io.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /****************************************************************************
  2. * MODULE: R-Tree library
  3. *
  4. * AUTHOR(S): Antonin Guttman - original code
  5. * Daniel Green (green@superliminal.com) - major clean-up
  6. * and implementation of bounding spheres
  7. * Markus Metz - file-based and memory-based R*-tree
  8. *
  9. * PURPOSE: Multidimensional index
  10. *
  11. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *****************************************************************************/
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <unistd.h>
  21. #include <assert.h>
  22. #include <grass/config.h>
  23. #include "index.h"
  24. /* add new free node position for recycling */
  25. void RTreeAddNodePos(off_t pos, int level, struct RTree *t)
  26. {
  27. int which;
  28. if (t->free_nodes.avail >= t->free_nodes.alloc) {
  29. size_t size;
  30. t->free_nodes.alloc += 100;
  31. size = t->free_nodes.alloc * sizeof(off_t);
  32. t->free_nodes.pos = (off_t *)realloc((void *)t->free_nodes.pos, size);
  33. assert(t->free_nodes.pos);
  34. }
  35. t->free_nodes.pos[t->free_nodes.avail++] = pos;
  36. which = (pos == t->nb[level][2].pos ? 2 : pos == t->nb[level][1].pos);
  37. t->nb[level][which].pos = -1;
  38. t->nb[level][which].dirty = 0;
  39. /* make it lru */
  40. if (t->used[level][0] == which) {
  41. t->used[level][0] = t->used[level][1];
  42. t->used[level][1] = t->used[level][2];
  43. t->used[level][2] = which;
  44. }
  45. else if (t->used[level][1] == which) {
  46. t->used[level][1] = t->used[level][2];
  47. t->used[level][2] = which;
  48. }
  49. }
  50. /* looks for free node position, sets file pointer, returns position */
  51. off_t RTreeGetNodePos(struct RTree *t)
  52. {
  53. if (t->free_nodes.avail > 0) {
  54. t->free_nodes.avail--;
  55. return lseek(t->fd, t->free_nodes.pos[t->free_nodes.avail], SEEK_SET);
  56. }
  57. else {
  58. return lseek(t->fd, 0, SEEK_END);
  59. }
  60. }
  61. /* read branch from file */
  62. size_t RTreeReadBranch(struct RTree_Branch *b, struct RTree *t)
  63. {
  64. size_t size = 0;
  65. size += read(t->fd, b->rect.boundary, t->nsides * sizeof(RectReal));
  66. size += read(t->fd, &(b->child), sizeof(union RTree_Child));
  67. return size;
  68. }
  69. /* read node from file */
  70. size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  71. {
  72. int i;
  73. size_t size = 0;
  74. lseek(t->fd, nodepos, SEEK_SET);
  75. size += read(t->fd, &(n->count), sizeof(int));
  76. size += read(t->fd, &(n->level), sizeof(int));
  77. for (i = 0; i < MAXCARD; i++) {
  78. size += RTreeReadBranch(&(n->branch[i]), t);
  79. }
  80. return size;
  81. }
  82. /* get node from buffer or file */
  83. void RTreeGetNode(struct RTree_Node *n, off_t nodepos, int level, struct RTree *t)
  84. {
  85. int which = (nodepos == t->nb[level][2].pos ? 2 : nodepos == t->nb[level][1].pos);
  86. if (t->nb[level][which].pos != nodepos) {
  87. /* replace least recently used (fastest method of lru, pseudo-lru, mru) */
  88. which = t->used[level][2];
  89. /* rewrite node in buffer */
  90. if (t->nb[level][which].dirty) {
  91. RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
  92. t->nb[level][which].dirty = 0;
  93. }
  94. RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
  95. t->nb[level][which].pos = nodepos;
  96. }
  97. /* make it mru */
  98. if (t->used[level][2] == which) {
  99. t->used[level][2] = t->used[level][1];
  100. t->used[level][1] = t->used[level][0];
  101. t->used[level][0] = which;
  102. }
  103. else if (t->used[level][1] == which) {
  104. t->used[level][1] = t->used[level][0];
  105. t->used[level][0] = which;
  106. }
  107. /* copy node */
  108. RTreeCopyNode(n, &(t->nb[level][which].n), t);
  109. }
  110. /* write branch to file */
  111. size_t RTreeWriteBranch(struct RTree_Branch *b, struct RTree *t)
  112. {
  113. size_t size = 0;
  114. size += write(t->fd, b->rect.boundary, t->nsides * sizeof(RectReal));
  115. size += write(t->fd, &(b->child), sizeof(union RTree_Child));
  116. return size;
  117. }
  118. /* write new node to file */
  119. size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
  120. {
  121. int i;
  122. size_t size = 0;
  123. /* file position must be set first with RTreeGetFNodePos() */
  124. size += write(t->fd, &(n->count), sizeof(int));
  125. size += write(t->fd, &(n->level), sizeof(int));
  126. for (i = 0; i < MAXCARD; i++) {
  127. size += RTreeWriteBranch(&(n->branch[i]), t);
  128. }
  129. return size;
  130. }
  131. /* rewrite updated node to file */
  132. size_t RTreeRewriteNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  133. {
  134. lseek(t->fd, nodepos, SEEK_SET);
  135. return write(t->fd, n, t->nodesize);
  136. }
  137. /* update node in buffer */
  138. void RTreePutNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  139. {
  140. int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
  141. /* copy node */
  142. RTreeCopyNode(&(t->nb[n->level][which].n), n, t);
  143. t->nb[n->level][which].dirty = 1;
  144. /* make it mru */
  145. if (t->used[n->level][2] == which) {
  146. t->used[n->level][2] = t->used[n->level][1];
  147. t->used[n->level][1] = t->used[n->level][0];
  148. t->used[n->level][0] = which;
  149. }
  150. else if (t->used[n->level][1] == which) {
  151. t->used[n->level][1] = t->used[n->level][0];
  152. t->used[n->level][0] = which;
  153. }
  154. }
  155. /* update rectangle */
  156. void RTreeUpdateRect(struct RTree_Rect *r, struct RTree_Node *n, off_t nodepos, int b, struct RTree *t)
  157. {
  158. int i;
  159. int which = (nodepos == t->nb[n->level][2].pos ?
  160. 2 : nodepos == t->nb[n->level][1].pos);
  161. for (i = 0; i < t->nsides; i++) {
  162. t->nb[n->level][which].n.branch[b].rect.boundary[i] =
  163. n->branch[b].rect.boundary[i] = r->boundary[i];
  164. }
  165. t->nb[n->level][which].dirty = 1;
  166. /* make it mru */
  167. if (t->used[n->level][2] == which) {
  168. t->used[n->level][2] = t->used[n->level][1];
  169. t->used[n->level][1] = t->used[n->level][0];
  170. t->used[n->level][0] = which;
  171. }
  172. else if (t->used[n->level][1] == which) {
  173. t->used[n->level][1] = t->used[n->level][0];
  174. t->used[n->level][0] = which;
  175. }
  176. }
  177. /* flush pending changes to file */
  178. void RTreeFlushBuffer(struct RTree *t)
  179. {
  180. int i;
  181. for (i = 0; i <= t->rootlevel; i++) {
  182. if (t->nb[i][0].dirty)
  183. RTreeRewriteNode(&(t->nb[i][0].n), t->nb[i][0].pos, t);
  184. if (t->nb[i][1].dirty)
  185. RTreeRewriteNode(&(t->nb[i][1].n), t->nb[i][1].pos, t);
  186. if (t->nb[i][2].dirty)
  187. RTreeRewriteNode(&(t->nb[i][2].n), t->nb[i][2].pos, t);
  188. }
  189. }