worker.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /**
  2. * \file worker.c
  3. *
  4. * \brief Implementation of the client for parallel
  5. * computing of r.li raster analysis
  6. *
  7. * This program is free software under the GPL (>=v2)
  8. * Read the COPYING file that comes with GRASS for details.
  9. *
  10. * \author Claudio Porta & Lucio Davide Spano
  11. *
  12. * \version 1.0
  13. *
  14. */
  15. #include <stdlib.h>
  16. #include <stddef.h>
  17. #include <fcntl.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <dirent.h>
  21. #include <errno.h>
  22. #include <math.h>
  23. #ifdef __MINGW32__
  24. #include <process.h>
  25. #else
  26. #include <sys/wait.h>
  27. #endif
  28. #include <grass/gis.h>
  29. #include <grass/raster.h>
  30. #include <grass/glocale.h>
  31. #include "daemon.h"
  32. #include "defs.h"
  33. #define CACHESIZE 4194304
  34. static int fd, aid;
  35. static int erease_mask = 0, data_type = 0;
  36. static int cache_rows, used = 0;
  37. static struct area_entry * ad;
  38. static double result;
  39. static struct Cell_head hd;
  40. static cell_manager cm;
  41. static dcell_manager dm;
  42. static fcell_manager fm;
  43. static char *raster;
  44. static char **parameters;
  45. static int (*func) (int, char **, struct area_entry *, double *);
  46. void worker_init(char *r, int f(int, char **, struct area_entry *, double *), char **p)
  47. {
  48. cm = G_malloc(sizeof(struct cell_memory_entry));
  49. fm = G_malloc(sizeof(struct fcell_memory_entry));
  50. dm = G_malloc(sizeof(struct dcell_memory_entry));
  51. ad = G_malloc(sizeof(struct area_entry));
  52. raster = r;
  53. parameters = p;
  54. func = f;
  55. /* open raster map */
  56. fd = Rast_open_old(raster, "");
  57. Rast_get_cellhd(raster, "", &hd);
  58. /* read data type to allocate cache */
  59. data_type = Rast_map_type(raster, "");
  60. /* calculate rows in cache */
  61. switch (data_type) {
  62. case CELL_TYPE:{
  63. cache_rows = CACHESIZE / (hd.cols * sizeof(CELL));
  64. cm->cache = G_malloc(cache_rows * sizeof(CELL *));
  65. cm->contents = G_malloc(cache_rows * sizeof(int));
  66. cm->used = 0;
  67. cm->contents[0] = -1;
  68. } break;
  69. case DCELL_TYPE:{
  70. cache_rows = CACHESIZE / (hd.cols * sizeof(DCELL));
  71. dm->cache = G_malloc(cache_rows * sizeof(DCELL *));
  72. dm->contents = G_malloc(cache_rows * sizeof(int));
  73. dm->used = 0;
  74. dm->contents[0] = -1;
  75. } break;
  76. case FCELL_TYPE:{
  77. cache_rows = CACHESIZE / (hd.cols * sizeof(FCELL));
  78. fm->cache = G_malloc(cache_rows * sizeof(FCELL *));
  79. fm->contents = G_malloc(cache_rows * sizeof(int));
  80. fm->used = 0;
  81. fm->contents[0] = -1;
  82. } break;
  83. }
  84. ad->data_type = data_type;
  85. ad->cm = cm;
  86. ad->fm = fm;
  87. ad->dm = dm;
  88. }
  89. void worker_process(msg * ret, msg * m)
  90. {
  91. switch (m->type) {
  92. case AREA:
  93. aid = m->f.f_a.aid;
  94. ad->x = m->f.f_a.x;
  95. ad->y = m->f.f_a.y;
  96. ad->rl = m->f.f_a.rl;
  97. ad->cl = m->f.f_a.cl;
  98. ad->raster = raster;
  99. ad->mask = -1;
  100. break;
  101. case MASKEDAREA:
  102. aid = m->f.f_ma.aid;
  103. ad->x = m->f.f_ma.x;
  104. ad->y = m->f.f_ma.y;
  105. ad->rl = m->f.f_ma.rl;
  106. ad->cl = m->f.f_ma.cl;
  107. ad->raster = raster;
  108. /* mask preprocessing */
  109. ad->mask_name = mask_preprocessing(m->f.f_ma.mask,
  110. raster, ad->rl, ad->cl);
  111. if (ad->mask_name == NULL) {
  112. G_message(_("unable to open <%s> mask ... continuing without!"),
  113. m->f.f_ma.mask);
  114. ad->mask = -1;
  115. }
  116. else {
  117. if (strcmp(m->f.f_ma.mask, ad->mask_name) != 0)
  118. /* temporary mask created */
  119. erease_mask = 1;
  120. ad->mask = open(ad->mask_name, O_WRONLY, 0755);
  121. if (ad->mask == -1) {
  122. G_message(_("unable to open <%s> mask ... continuing without!"),
  123. m->f.f_ma.mask);
  124. }
  125. }
  126. break;
  127. default:
  128. G_fatal_error("Program error, worker() type=%d", m->type);
  129. break;
  130. }
  131. /* memory menagement */
  132. if (ad->rl > used) {
  133. /* allocate cache */
  134. int i;
  135. switch (data_type) {
  136. case CELL_TYPE:{
  137. for (i = 0; i < (ad->rl - used); i++) {
  138. cm->cache[used + i] = Rast_allocate_c_buf();
  139. }
  140. }
  141. break;
  142. case DCELL_TYPE:{
  143. for (i = 0; i < ad->rl - used; i++) {
  144. dm->cache[used + i] = Rast_allocate_d_buf();
  145. }
  146. }
  147. break;
  148. case FCELL_TYPE:{
  149. for (i = 0; i < ad->rl - used; i++) {
  150. fm->cache[used + i] = Rast_allocate_f_buf();
  151. }
  152. }
  153. break;
  154. }
  155. cm->used = ad->rl;
  156. dm->used = ad->rl;
  157. fm->used = ad->rl;
  158. used = ad->rl;
  159. }
  160. /* calculate function */
  161. if (func(fd, parameters, ad, &result) == RLI_OK) {
  162. /* success */
  163. ret->type = DONE;
  164. ret->f.f_d.aid = aid;
  165. ret->f.f_d.pid = 0;
  166. ret->f.f_d.res = result;
  167. }
  168. else {
  169. /* fail */
  170. ret->type = ERROR;
  171. ret->f.f_e.aid = aid;
  172. ret->f.f_e.pid = 0;
  173. }
  174. if (erease_mask == 1) {
  175. erease_mask = 0;
  176. unlink(ad->mask_name);
  177. }
  178. }
  179. void worker_end(void)
  180. {
  181. /* close raster map */
  182. Rast_close(fd);
  183. }
  184. char *mask_preprocessing(char *mask, char *raster, int rl, int cl)
  185. {
  186. const char *tmp_file;
  187. struct Cell_head cell, oldcell;
  188. int mask_fd, old_fd, *buf, i, j;
  189. CELL *old;
  190. double add_row, add_col;
  191. buf = G_malloc(cl * sizeof(int));
  192. G_debug(3, "daemon mask preproc: raster=[%s] mask=[%s] rl=%d cl=%d",
  193. raster, mask, rl, cl);
  194. /* open raster */
  195. Rast_get_cellhd(raster, "", &cell);
  196. /* open raster */
  197. Rast_get_cellhd(mask, "", &oldcell);
  198. add_row = 1.0 * oldcell.rows / rl;
  199. add_col = 1.0 * oldcell.cols / cl;
  200. tmp_file = G_tempfile();
  201. mask_fd = open(tmp_file, O_RDWR | O_CREAT, 0755);
  202. old_fd = Rast_open_old(mask, "");
  203. old = Rast_allocate_c_buf();
  204. for (i = 0; i < rl; i++) {
  205. int riga;
  206. riga = (int)rint(i * add_row);
  207. Rast_get_c_row_nomask(old_fd, old, riga);
  208. for (j = 0; j < cl; j++) {
  209. int colonna;
  210. colonna = (int)rint(j * add_col);
  211. buf[j] = old[colonna];
  212. }
  213. if (write(mask_fd, buf, cl * sizeof(int)) < 0)
  214. return NULL;
  215. }
  216. close(mask_fd);
  217. return G_store(tmp_file);
  218. }
  219. CELL *RLI_get_cell_raster_row(int fd, int row, struct area_entry *ad)
  220. {
  221. int hash;
  222. hash = row % ad->rl;
  223. if (ad->cm->contents[hash] == row)
  224. return ad->cm->cache[hash];
  225. else {
  226. Rast_get_row(fd, ad->cm->cache[hash], row, CELL_TYPE);
  227. ad->cm->contents[hash] = row;
  228. return ad->cm->cache[hash];
  229. }
  230. }
  231. DCELL *RLI_get_dcell_raster_row(int fd, int row, struct area_entry *ad)
  232. {
  233. int hash;
  234. hash = row % ad->rl;
  235. if (ad->dm->contents[hash] == row)
  236. return ad->dm->cache[hash];
  237. else {
  238. Rast_get_row(fd, ad->dm->cache[hash], row, DCELL_TYPE);
  239. ad->dm->contents[hash] = row;
  240. return ad->dm->cache[hash];
  241. }
  242. }
  243. FCELL *RLI_get_fcell_raster_row(int fd, int row, struct area_entry *ad)
  244. {
  245. int hash;
  246. hash = row % ad->rl;
  247. if (ad->fm->contents[hash] == row)
  248. return ad->fm->cache[hash];
  249. else {
  250. Rast_get_row(fd, ad->fm->cache[hash], row, FCELL_TYPE);
  251. ad->fm->contents[hash] = row;
  252. return ad->fm->cache[hash];
  253. }
  254. }