readcell.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * readcell.c - reads an entire cell layer into a buffer
  3. *
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <grass/gis.h>
  13. #include <grass/raster.h>
  14. #include <grass/glocale.h>
  15. #include "r.proj.h"
  16. struct cache *readcell(int fdi, const char *size)
  17. {
  18. FCELL *tmpbuf;
  19. struct cache *c;
  20. int nrows;
  21. int ncols;
  22. int row;
  23. int nx, ny;
  24. int nblocks;
  25. int i;
  26. G_srand48(0);
  27. nrows = Rast_input_window_rows();
  28. ncols = Rast_input_window_cols();
  29. ny = (nrows + BDIM - 1) / BDIM;
  30. nx = (ncols + BDIM - 1) / BDIM;
  31. if (size)
  32. nblocks = atoi(size) * ((1 << 20) / sizeof(block));
  33. else
  34. nblocks = (nx + ny) * 2; /* guess */
  35. if (nblocks > nx * ny)
  36. nblocks = nx * ny;
  37. c = G_malloc(sizeof(struct cache));
  38. c->stride = nx;
  39. c->nblocks = nblocks;
  40. c->grid = (block **) G_calloc(nx * ny, sizeof(block *));
  41. c->blocks = (block *) G_malloc(nblocks * sizeof(block));
  42. c->refs = (int *)G_calloc(nblocks, sizeof(int));
  43. if (nblocks < nx * ny) {
  44. /* Temporary file must be created in output location */
  45. G_switch_env();
  46. c->fname = G_tempfile();
  47. G_switch_env();
  48. c->fd = open(c->fname, O_RDWR | O_CREAT | O_EXCL, 0600);
  49. if (c->fd < 0)
  50. G_fatal_error(_("Unable to open temporary file"));
  51. }
  52. else {
  53. c->fd = -1;
  54. c->fname = NULL;
  55. }
  56. G_verbose_message("%.2f percent are kept in memory", 100.0 * nblocks / (nx * ny));
  57. G_important_message(_("Allocating memory and reading input raster map..."));
  58. for (i = 0; i < c->nblocks; i++)
  59. c->refs[i] = -1;
  60. tmpbuf = (FCELL *) G_malloc(nx * sizeof(block));
  61. for (row = 0; row < nrows; row += BDIM) {
  62. int x, y;
  63. for (y = 0; y < BDIM; y++) {
  64. G_percent(row + y, nrows, 5);
  65. if (row + y >= nrows)
  66. break;
  67. Rast_get_f_row(fdi, &tmpbuf[y * nx * BDIM], row + y);
  68. }
  69. for (x = 0; x < nx; x++)
  70. for (y = 0; y < BDIM; y++)
  71. if (c->fd >= 0) {
  72. if (write
  73. (c->fd, &tmpbuf[(y * nx + x) * BDIM],
  74. BDIM * sizeof(FCELL)) < 0)
  75. G_fatal_error(_("Error writing segment file"));
  76. }
  77. else
  78. memcpy(&c->blocks[BKIDX(c, HI(row), x)][LO(y)][0],
  79. &tmpbuf[(y * nx + x) * BDIM],
  80. BDIM * sizeof(FCELL));
  81. }
  82. G_free(tmpbuf);
  83. if (c->fd < 0) {
  84. for (i = 0; i < c->nblocks; i++) {
  85. c->grid[i] = &c->blocks[i];
  86. c->refs[i] = i;
  87. }
  88. }
  89. else {
  90. close(c->fd);
  91. c->fd = -1;
  92. }
  93. return c;
  94. }
  95. block *get_block(struct cache * c, int idx)
  96. {
  97. int fd;
  98. int replace = G_lrand48() % c->nblocks;
  99. block *p = &c->blocks[replace];
  100. int ref = c->refs[replace];
  101. off_t offset = (off_t) idx * sizeof(FCELL) << L2BSIZE;
  102. if (c->fname == NULL)
  103. G_fatal_error(_("Internal error: cache miss on fully-cached map"));
  104. fd = open(c->fname, O_RDONLY, 0600);
  105. if (fd < 0)
  106. G_fatal_error(_("Unable to open temporary file"));
  107. if (ref >= 0)
  108. c->grid[ref] = NULL;
  109. c->grid[idx] = p;
  110. c->refs[replace] = idx;
  111. if (lseek(fd, offset, SEEK_SET) < 0)
  112. G_fatal_error(_("Error seeking on segment file"));
  113. if (read(fd, p, sizeof(block)) < 0)
  114. G_fatal_error(_("Error reading segment file"));
  115. close(fd);
  116. return p;
  117. }
  118. void release_cache(struct cache *c)
  119. {
  120. G_free(c->grid);
  121. G_free(c->blocks);
  122. G_free(c->refs);
  123. remove(c->fname);
  124. G_free(c);
  125. }