daemon.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /**
  2. * \file daemon.c
  3. *
  4. * \brief Implementation of the server for parallel
  5. * computing of r.li raster analysis
  6. *
  7. * \author Claudio Porta & Lucio Davide Spano
  8. *
  9. * This program is free software under the GPL (>=v2)
  10. * Read the COPYING file that comes with GRASS for details.
  11. *
  12. * \version 1.0
  13. *
  14. * \include
  15. *
  16. */
  17. #include <stdlib.h>
  18. #include <stddef.h>
  19. #include <fcntl.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <dirent.h>
  23. #include <errno.h>
  24. #include <math.h>
  25. #ifdef __MINGW32__
  26. #include <process.h>
  27. #else
  28. #include <sys/wait.h>
  29. #endif
  30. #include <grass/gis.h>
  31. #include <grass/raster.h>
  32. #include <grass/glocale.h>
  33. #include "daemon.h"
  34. int calculateIndex(char *file, rli_func *f,
  35. char **parameters, char *raster, char *output)
  36. {
  37. char pathSetup[GPATH_MAX], out[GPATH_MAX], parsed;
  38. char *random_access_name;
  39. struct History history;
  40. struct g_area *g;
  41. int res;
  42. int i, doneDir, mv_fd, random_access;
  43. /* int mv_rows, mv_cols; */
  44. struct list *l;
  45. msg m, doneJob;
  46. g = (struct g_area *) G_malloc(sizeof(struct g_area));
  47. g->maskname = NULL;
  48. l = (struct list*) G_malloc(sizeof(struct list));
  49. l->head = NULL;
  50. l->tail = NULL;
  51. l->size = 0;
  52. worker_init(raster, f, parameters);
  53. /*#########################################################
  54. -----------------create area queue----------------------
  55. ######################################################### */
  56. /* strip off leading path if present */
  57. char rlipath[GPATH_MAX];
  58. char testpath[GPATH_MAX];
  59. /* conf files go into ~/.grass7/r.li/ */
  60. sprintf(rlipath, "%s%c%s%c", G_config_path(), HOST_DIRSEP, "r.li", HOST_DIRSEP);
  61. sprintf(testpath, "%s%c%s%c", G_config_path(), HOST_DIRSEP, "r.li", HOST_DIRSEP);
  62. if (strncmp(file, testpath, strlen(testpath)) == 0)
  63. file += strlen(testpath);
  64. /* TODO: check if this path is portable */
  65. /* TODO: use G_rc_path() */
  66. sprintf(pathSetup, "%s%s", rlipath, file);
  67. G_debug(1, "r.li.daemon pathSetup: [%s]", pathSetup);
  68. parsed = parseSetup(pathSetup, l, g, raster);
  69. /*########################################################
  70. -----------------open output file ---------------------
  71. ####################################################### */
  72. if (parsed == MVWIN) {
  73. /* struct Cell_head cellhd_r, cellhd_new;
  74. char *mapset; */
  75. /*creating new raster file */
  76. mv_fd = Rast_open_new(output, DCELL_TYPE);
  77. random_access_name = G_tempfile();
  78. random_access = open(random_access_name, O_RDWR | O_CREAT, 0755);
  79. if (random_access == -1)
  80. G_fatal_error(_("Cannot create random access file"));
  81. }
  82. else {
  83. /* text file output */
  84. /* check if ~/.grass7/ exists */
  85. sprintf(out, "%s", G_config_path());
  86. doneDir = G_mkdir(out);
  87. if (doneDir == -1 && errno != EEXIST)
  88. G_fatal_error(_("Cannot create %s directory"), out);
  89. /* check if ~/.grass7/r.li/ exists */
  90. sprintf(out, "%s", rlipath);
  91. doneDir = G_mkdir(out);
  92. if (doneDir == -1 && errno != EEXIST)
  93. G_fatal_error(_("Cannot create %s directory"), out);
  94. /* check if ~/.grass7/r.li/output exists */
  95. sprintf(out, "%s%s", rlipath, "output");
  96. doneDir = G_mkdir(out);
  97. if (doneDir == -1 && errno != EEXIST)
  98. G_fatal_error(_("Cannot create %s directory"), out);
  99. sprintf(out, "%s%s%c%s", rlipath, "output", HOST_DIRSEP, output);
  100. res = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  101. }
  102. i = 0;
  103. /*#######################################################
  104. ------------------analysis loop----------------------
  105. ####################################################### */
  106. /*body */
  107. while (next_Area(parsed, l, g, &m) != 0) {
  108. worker_process(&doneJob, &m);
  109. /*perc++; */
  110. /*G_percent (perc, WORKERS, 1); */
  111. if (doneJob.type == DONE) {
  112. double result;
  113. result = doneJob.f.f_d.res;
  114. /* output */
  115. if (parsed != MVWIN) {
  116. /* text file output */
  117. print_Output(res, doneJob);
  118. }
  119. else {
  120. /* raster output */
  121. raster_Output(random_access, doneJob.f.f_d.aid, g,
  122. doneJob.f.f_d.res);
  123. }
  124. }
  125. else {
  126. if (parsed != MVWIN) {
  127. /* text file output */
  128. error_Output(res, doneJob);
  129. }
  130. else {
  131. /* printf("todo"); fflush(stdout); */
  132. /* TODO write to raster NULL ??? */
  133. }
  134. }
  135. }
  136. worker_end();
  137. /*################################################
  138. --------------delete tmp files------------------
  139. ################################################ */
  140. if (parsed == MVWIN) {
  141. write_raster(mv_fd, random_access, g);
  142. close(random_access);
  143. unlink(random_access_name);
  144. Rast_close(mv_fd);
  145. Rast_short_history(output, "raster", &history);
  146. Rast_command_history(&history);
  147. Rast_write_history(output, &history);
  148. G_done_msg(_("Raster map <%s> created."), output);
  149. } else {
  150. /* text file output */
  151. G_done_msg("Result written to text file <%s>", out);
  152. }
  153. /* This is only return in this function, so the documented 1 is
  154. actually never returned. */
  155. return 0;
  156. }
  157. int parseSetup(char *path, struct list *l, struct g_area *g, char *raster)
  158. {
  159. struct stat s;
  160. struct Cell_head cellhd;
  161. char *buf;
  162. const char *token;
  163. int setup;
  164. int letti;
  165. double rel_x, rel_y, rel_rl, rel_cl;
  166. double sf_n, sf_s, sf_e, sf_w;
  167. int sf_x, sf_y, sf_rl, sf_cl;
  168. int sa_x, sa_y, sa_rl, sa_cl;
  169. int size;
  170. if (stat(path, &s) != 0)
  171. G_fatal_error(_("Cannot find configuration file <%s>"), path);
  172. size = s.st_size * sizeof(char);
  173. buf = G_malloc(size);
  174. setup = open(path, O_RDONLY, 0755);
  175. if (setup == -1)
  176. G_fatal_error(_("Cannot read setup file"));
  177. letti = read(setup, buf, s.st_size);
  178. if (letti < s.st_size)
  179. G_fatal_error(_("Cannot read setup file"));
  180. token = strtok(buf, " ");
  181. if (strcmp("SAMPLINGFRAME", token) != 0)
  182. G_fatal_error(_("Unable to parse configuration file (sampling frame)"));
  183. rel_x = atof(strtok(NULL, "|"));
  184. rel_y = atof(strtok(NULL, "|"));
  185. rel_rl = atof(strtok(NULL, "|"));
  186. rel_cl = atof(strtok(NULL, "\n"));
  187. /* use current region ! */
  188. Rast_get_window(&cellhd);
  189. /* calculate absolute sampling frame definition */
  190. sf_x = (int)rint(cellhd.cols * rel_x);
  191. sf_y = (int)rint(cellhd.rows * rel_y);
  192. sf_rl = (int)rint(cellhd.rows * rel_rl);
  193. sf_cl = (int)rint(cellhd.cols * rel_cl);
  194. /* sanity check */
  195. if (sf_x < 0)
  196. sf_x = 0;
  197. if (sf_y < 0)
  198. sf_y = 0;
  199. if (sf_x > cellhd.cols)
  200. sf_x = cellhd.cols;
  201. if (sf_y > cellhd.rows)
  202. sf_y = cellhd.rows;
  203. if (sf_rl > cellhd.rows - sf_y)
  204. sf_rl = cellhd.rows - sf_y;
  205. if (sf_cl > cellhd.cols - sf_x)
  206. sf_cl = cellhd.cols - sf_x;
  207. /* calculate sample frame boundaries */
  208. sf_n = cellhd.north - (cellhd.ns_res * sf_y);
  209. sf_s = sf_n - (cellhd.ns_res * sf_rl);
  210. sf_w = cellhd.west + (cellhd.ew_res * sf_x);
  211. sf_e = sf_w + (cellhd.ew_res * sf_cl);
  212. /* parse configuration file */
  213. token = strtok(NULL, " ");
  214. if (strcmp("SAMPLEAREA", token) == 0) {
  215. double rel_sa_x, rel_sa_y, rel_sa_rl, rel_sa_cl;
  216. int aid = 1, toReturn;
  217. do {
  218. rel_sa_x = atof(strtok(NULL, "|"));
  219. rel_sa_y = atof(strtok(NULL, "|"));
  220. rel_sa_rl = atof(strtok(NULL, "|"));
  221. rel_sa_cl = atof(strtok(NULL, "\n"));
  222. if (rel_sa_x == -1.0 && rel_sa_y == -1.0) {
  223. /* runtime disposition */
  224. sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
  225. sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
  226. /* sanity check */
  227. if (sa_rl > cellhd.rows - sf_y)
  228. sa_rl = cellhd.rows - sf_y;
  229. if (sa_cl > cellhd.cols - sf_x)
  230. sa_cl = cellhd.cols - sf_x;
  231. /* total sample area */
  232. g->rows = sf_rl;
  233. g->cols = sf_cl;
  234. g->x = sf_x;
  235. g->y = sf_y;
  236. /* current sample area (subset of total sample area) */
  237. g->rl = sa_rl;
  238. g->cl = sa_cl;
  239. g->sf_x = sf_x;
  240. g->sf_y = sf_y;
  241. g->count = 1;
  242. g->maskname = NULL;
  243. return disposeAreas(l, g, strtok(NULL, "\n"));
  244. }
  245. else {
  246. msg m;
  247. toReturn = NORMAL;
  248. /*read file and create list */
  249. m.type = AREA;
  250. /* current sample area (subset of total sample area) */
  251. sa_x = (int)rint(cellhd.cols * rel_sa_x);
  252. sa_y = (int)rint(cellhd.rows * rel_sa_y);
  253. sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
  254. sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
  255. /* sanity check */
  256. if (sa_x < 0)
  257. sa_x = 0;
  258. if (sa_y < 0)
  259. sa_y = 0;
  260. if (sa_x > cellhd.cols)
  261. sa_x = cellhd.cols;
  262. if (sa_y > cellhd.rows)
  263. sa_y = cellhd.rows;
  264. if (sa_rl > cellhd.rows - sa_y)
  265. sa_rl = cellhd.rows - sa_y;
  266. if (sa_cl > cellhd.cols - sa_x)
  267. sa_cl = cellhd.cols - sa_x;
  268. m.f.f_a.x = sa_x;
  269. m.f.f_a.y = sa_y;
  270. m.f.f_a.rl = sa_rl;
  271. m.f.f_a.cl = sa_cl;
  272. m.f.f_a.aid = aid;
  273. aid++;
  274. insertNode(l, m);
  275. }
  276. } while ((token = strtok(NULL, " ")) != NULL &&
  277. strcmp(token, "SAMPLEAREA") == 0);
  278. close(setup);
  279. return toReturn;
  280. }
  281. else if (strcmp("MASKEDSAMPLEAREA", token) == 0) {
  282. double rel_sa_x, rel_sa_y, rel_sa_rl, rel_sa_cl;
  283. int aid = 1;
  284. char maskname[GNAME_MAX] = {'\0'};
  285. do {
  286. rel_sa_x = atof(strtok(NULL, "|"));
  287. rel_sa_y = atof(strtok(NULL, "|"));
  288. rel_sa_rl = atof(strtok(NULL, "|"));
  289. rel_sa_cl = atof(strtok(NULL, "|"));
  290. strcpy(maskname, strtok(NULL, "\n"));
  291. if (rel_sa_x == -1 && rel_sa_y == -1) {
  292. /* runtime disposition */
  293. sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
  294. sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
  295. /* sanity check */
  296. if (sa_rl > cellhd.rows - sf_y)
  297. sa_rl = cellhd.rows - sf_y;
  298. if (sa_cl > cellhd.cols - sf_x)
  299. sa_cl = cellhd.cols - sf_x;
  300. /* total sample area */
  301. g->rows = sf_rl;
  302. g->cols = sf_cl;
  303. g->x = sf_x;
  304. g->y = sf_y;
  305. /* current sample area (subset of total sample area) */
  306. g->rl = sa_rl;
  307. g->cl = sa_cl;
  308. g->count = 1;
  309. g->maskname = maskname;
  310. return disposeAreas(l, g, strtok(NULL, "\n"));
  311. }
  312. else {
  313. /*read file and create list */
  314. msg m;
  315. m.type = MASKEDAREA;
  316. /* current sample area (subset of total sample area) */
  317. sa_x = (int)rint(cellhd.cols * rel_sa_x);
  318. sa_y = (int)rint(cellhd.rows * rel_sa_y);
  319. sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
  320. sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
  321. /* sanity check */
  322. if (sa_x < 0)
  323. sa_x = 0;
  324. if (sa_y < 0)
  325. sa_y = 0;
  326. if (sa_x > cellhd.cols)
  327. sa_x = cellhd.cols;
  328. if (sa_y > cellhd.rows)
  329. sa_y = cellhd.rows;
  330. if (sa_rl > cellhd.rows - sa_y)
  331. sa_rl = cellhd.rows - sa_y;
  332. if (sa_cl > cellhd.cols - sa_x)
  333. sa_cl = cellhd.cols - sa_x;
  334. m.f.f_ma.x = sa_x;
  335. m.f.f_ma.y = sa_y;
  336. m.f.f_ma.rl = sa_rl;
  337. m.f.f_ma.cl = sa_cl;
  338. m.f.f_ma.aid = aid;
  339. strcpy(m.f.f_ma.mask, maskname);
  340. aid++;
  341. insertNode(l, m);
  342. }
  343. }
  344. while ((token = strtok(NULL, " ")) != NULL &&
  345. strcmp(token, "MASKEDSAMPLEAREA") == 0);
  346. close(setup);
  347. return NORMAL;
  348. }
  349. else if (strcmp("MASKEDOVERLAYAREA", token) == 0) {
  350. double sa_n, sa_s, sa_w, sa_e;
  351. int aid = 1;
  352. char maskname[GNAME_MAX] = {'\0'};
  353. msg m;
  354. /* Get the window setting. g.region raster=<input raster> */
  355. /* ? same as cellhd above ? */
  356. /* no. the current window might be different */
  357. do {
  358. strcpy(maskname, strtok(NULL, "|"));
  359. sa_n = atof(strtok(NULL, "|"));
  360. sa_s = atof(strtok(NULL, "|"));
  361. sa_e = atof(strtok(NULL, "|"));
  362. sa_w = atof(strtok(NULL, "\n"));
  363. m.type = MASKEDAREA;
  364. /* Each input overlay area from input vector are converted to
  365. raster via v.to.rast. See r.li.setup/sample_area_vector.sh.
  366. This is used only for reading the region (NS, EW). */
  367. /* current sample area (subset of total sample area) */
  368. /* Get start x and y position of masked overlay raster with
  369. respect to current region.
  370. sa_n, sa_w are read from configuration file. */
  371. sa_x = (int)rint((sa_w - cellhd.west) / cellhd.ew_res);
  372. sa_y = (int)rint((cellhd.north - sa_n) / cellhd.ns_res);
  373. /* Get row count and column count of overlay raster */
  374. sa_rl = (int)rint((sa_n - sa_s) / cellhd.ns_res);
  375. sa_cl = (int)rint((sa_e - sa_w) / cellhd.ew_res);
  376. /* sanity check */
  377. if (sa_x < 0)
  378. sa_x = 0;
  379. if (sa_y < 0)
  380. sa_y = 0;
  381. if (sa_x > cellhd.cols)
  382. sa_x = cellhd.cols;
  383. if (sa_y > cellhd.rows)
  384. sa_y = cellhd.rows;
  385. if (sa_rl > cellhd.rows - sa_y)
  386. sa_rl = cellhd.rows - sa_y;
  387. if (sa_cl > cellhd.cols - sa_x)
  388. sa_cl = cellhd.cols - sa_x;
  389. m.f.f_ma.x = sa_x;
  390. m.f.f_ma.y = sa_y;
  391. m.f.f_ma.rl = sa_rl;
  392. m.f.f_ma.cl = sa_cl;
  393. m.f.f_ma.aid = aid;
  394. strcpy(m.f.f_ma.mask, maskname);
  395. aid++;
  396. insertNode(l, m);
  397. }
  398. while ((token = strtok(NULL, " ")) != NULL &&
  399. (strcmp(token, "MASKEDOVERLAYAREA") == 0));
  400. if (strcmp(token, "RASTERMAP") != 0)
  401. G_fatal_error(_("Irregular MASKEDOVERLAY areas definition"));
  402. token = strtok(NULL, "\n");
  403. if (strcmp(token, raster) != 0)
  404. G_fatal_error(_("The configuration file can only be used "
  405. "with the <%s> raster map"), token);
  406. close(setup);
  407. return NORMAL;
  408. }
  409. else
  410. G_fatal_error(_("Unable to parse configuration file (sample area)"));
  411. close(setup);
  412. return ERROR;
  413. }
  414. int disposeAreas(struct list *l, struct g_area *g, char *def)
  415. {
  416. char *token;
  417. token = strtok(def, " \n");
  418. if (strcmp(token, "MOVINGWINDOW") == 0) {
  419. g->count = 0;
  420. g->dist = 0;
  421. g->add_row = 1;
  422. g->add_col = 1;
  423. if (g->rl != 1)
  424. g->rows = g->rows - g->rl + 1;
  425. else
  426. g->rows = g->rows;
  427. if (g->cl != 1)
  428. g->cols = g->cols - g->cl + 1;
  429. return MVWIN;
  430. }
  431. else if (strcmp(token, "RANDOMNONOVERLAPPING") == 0) {
  432. int units, sf_rl, sf_cl, sa_rl, sa_cl, max_units, i;
  433. int *assigned;
  434. sscanf(strtok(NULL, "\n"), "%i", &units);
  435. sf_rl = g->rows;
  436. sf_cl = g->cols;
  437. sa_rl = g->rl;
  438. sa_cl = g->cl;
  439. max_units = (int)rint((sf_rl / sa_rl) * (sf_cl / sa_cl));
  440. if (units > max_units)
  441. G_fatal_error(_("Too many units to place"));
  442. assigned = G_malloc(units * sizeof(int));
  443. i = 0;
  444. G_srand48(0);
  445. while (i < units) {
  446. int j, position, found = FALSE;
  447. position = G_lrand48() % max_units;
  448. for (j = 0; j < i; j++) {
  449. if (assigned[j] == position)
  450. found = TRUE;
  451. }
  452. if (!found) {
  453. msg m;
  454. assigned[i] = position;
  455. i++;
  456. if (g->maskname == NULL) {
  457. int n_col = rint(sf_cl / sa_cl);
  458. m.type = AREA;
  459. m.f.f_a.aid = i;
  460. m.f.f_a.x = g->sf_x + (position % n_col) * sa_cl;
  461. m.f.f_a.y = g->sf_y + (position / n_col) * sa_rl;
  462. m.f.f_a.rl = sa_rl;
  463. m.f.f_a.cl = sa_cl;
  464. insertNode(l, m);
  465. }
  466. else {
  467. int n_col = sf_cl / sa_cl;
  468. m.type = MASKEDAREA;
  469. m.f.f_ma.aid = i;
  470. m.f.f_a.x = g->sf_x + (position % n_col) * sa_cl;
  471. m.f.f_a.y = g->sf_y + (position / n_col) * sa_rl;
  472. m.f.f_ma.rl = sa_rl;
  473. m.f.f_ma.cl = sa_cl;
  474. strcpy(m.f.f_ma.mask, g->maskname);
  475. insertNode(l, m);
  476. }
  477. }
  478. }
  479. return NORMAL;
  480. }
  481. else if (strcmp(token, "SYSTEMATICCONTIGUOUS") == 0) {
  482. g->dist = 0;
  483. g->add_row = g->rl;
  484. g->add_col = g->cl;
  485. return GEN;
  486. }
  487. else if (strcmp(token, "SYSTEMATICNONCONTIGUOUS") == 0) {
  488. int dist;
  489. dist = atoi(strtok(NULL, "\n"));
  490. g->dist = dist;
  491. g->add_row = g->rl + dist;
  492. g->add_col = g->cl + dist;
  493. g->x = g->sf_x + dist;
  494. g->y = g->sf_y + dist;
  495. return GEN;
  496. }
  497. else if (strcmp(token, "STRATIFIEDRANDOM") == 0) {
  498. int r_strat, c_strat, r_strat_len, c_strat_len, loop, i;
  499. r_strat = atoi(strtok(NULL, "|"));
  500. c_strat = atoi(strtok(NULL, "\n"));
  501. r_strat_len = (int)rint(g->rows / r_strat);
  502. c_strat_len = (int)rint(g->cols / c_strat);
  503. if (r_strat_len < g->rl || c_strat_len < g->cl)
  504. G_fatal_error(_("Too many stratified random sample for raster map"));
  505. loop = r_strat * c_strat;
  506. G_srand48(0);
  507. for (i = 0; i < loop; i++) {
  508. msg m;
  509. if (g->maskname == NULL) {
  510. m.type = AREA;
  511. m.f.f_a.aid = i;
  512. m.f.f_a.x = (int)g->sf_x + ((i % c_strat) * c_strat_len) +
  513. (G_lrand48() % (c_strat_len - g->cl));
  514. m.f.f_a.y = (int)g->sf_y + (rint(i / c_strat) * r_strat_len) +
  515. (G_lrand48() % (r_strat_len - g->rl));
  516. m.f.f_a.rl = g->rl;
  517. m.f.f_a.cl = g->cl;
  518. insertNode(l, m);
  519. }
  520. else {
  521. m.type = MASKEDAREA;
  522. m.f.f_ma.aid = i;
  523. m.f.f_ma.x = (int)g->sf_x + ((i % c_strat) * c_strat_len) +
  524. (G_lrand48() % (c_strat_len - g->cl));
  525. m.f.f_ma.y =
  526. (int)g->sf_y + (rint(i / c_strat) * r_strat_len) +
  527. (G_lrand48() % (r_strat_len - g->rl));
  528. m.f.f_ma.rl = g->rl;
  529. m.f.f_ma.cl = g->cl;
  530. strcpy(m.f.f_ma.mask, g->maskname);
  531. insertNode(l, m);
  532. }
  533. }
  534. return NORMAL;
  535. }
  536. else {
  537. G_fatal_error(_("Illegal areas disposition"));
  538. return NORMAL;
  539. }
  540. return ERROR;
  541. }
  542. int next_Area(int parsed, struct list *l, struct g_area *g, msg * m)
  543. {
  544. if (parsed == NORMAL) {
  545. if (l->size == 0)
  546. return 0;
  547. else {
  548. msg tmp;
  549. memcpy(&tmp, l->head->m, sizeof(msg));
  550. *m = tmp;
  551. removeNode(l);
  552. return 1;
  553. }
  554. }
  555. else {
  556. return next(g, m);
  557. }
  558. }
  559. int print_Output(int out, msg m)
  560. {
  561. if (m.type != DONE)
  562. return 0;
  563. else {
  564. char s[100];
  565. int len;
  566. if (Rast_is_d_null_value(&m.f.f_d.res))
  567. sprintf(s, "RESULT %i|NULL\n", m.f.f_d.aid);
  568. else
  569. sprintf(s, "RESULT %i|%.15g\n", m.f.f_d.aid, m.f.f_d.res);
  570. len = strlen(s);
  571. if (write(out, s, len) == len)
  572. return 1;
  573. else
  574. return 0;
  575. }
  576. }
  577. int error_Output(int out, msg m)
  578. {
  579. if (m.type != ERROR)
  580. return 0;
  581. else {
  582. char s[100];
  583. sprintf(s, "ERROR %i", m.f.f_d.aid);
  584. if (write(out, s, strlen(s)) == strlen(s))
  585. return 1;
  586. else
  587. return 0;
  588. }
  589. }
  590. int raster_Output(int fd, int aid, struct g_area *g, double res)
  591. {
  592. double toPut = res;
  593. off_t offset = (off_t) aid * sizeof(double);
  594. if (lseek(fd, offset, SEEK_SET) != offset) {
  595. G_message(_("Cannot make lseek"));
  596. return -1;
  597. }
  598. if (write(fd, &toPut, sizeof(double)) == 0)
  599. return 1;
  600. else
  601. return 0;
  602. }
  603. int write_raster(int mv_fd, int random_access, struct g_area *g)
  604. {
  605. int i = 0, j = 0, letti = 0;
  606. double *file_buf;
  607. DCELL *cell_buf;
  608. int cols, rows, center;
  609. cols = g->cols;
  610. rows = g->rows;
  611. center = g->sf_x + ((int)g->cl / 2);
  612. file_buf = G_malloc(cols * sizeof(double));
  613. lseek(random_access, 0, SEEK_SET);
  614. cell_buf = Rast_allocate_d_buf();
  615. Rast_set_d_null_value(cell_buf, Rast_window_cols() + 1);
  616. for (i = 0; i < g->sf_y + ((int)g->rl / 2); i++) {
  617. Rast_put_row(mv_fd, cell_buf, DCELL_TYPE);
  618. }
  619. for (i = 0; i < rows; i++) {
  620. letti = read(random_access, file_buf, (cols * sizeof(double)));
  621. if (letti == -1)
  622. G_message("%s", strerror(errno));
  623. for (j = 0; j < cols; j++) {
  624. cell_buf[j + center] = file_buf[j];
  625. }
  626. Rast_put_row(mv_fd, cell_buf, DCELL_TYPE);
  627. }
  628. Rast_set_d_null_value(cell_buf, Rast_window_cols() + 1);
  629. for (i = 0; i < Rast_window_rows() - g->sf_y - ((int)g->rl / 2) - g->rows; i++) {
  630. Rast_put_row(mv_fd, cell_buf, DCELL_TYPE);
  631. }
  632. G_free(file_buf);
  633. G_free(cell_buf);
  634. return 1;
  635. }