io.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 node from file */
  62. size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  63. {
  64. lseek(t->fd, nodepos, SEEK_SET);
  65. return read(t->fd, n, t->nodesize);
  66. }
  67. /* get node from buffer or file */
  68. void RTreeGetNode(struct RTree_Node *n, off_t nodepos, int level, struct RTree *t)
  69. {
  70. int which = (nodepos == t->nb[level][2].pos ? 2 : nodepos == t->nb[level][1].pos);
  71. if (t->nb[level][which].pos != nodepos) {
  72. /* replace least recently used (fastest method of lru, pseudo-lru, mru) */
  73. which = t->used[level][2];
  74. /* rewrite node in buffer */
  75. if (t->nb[level][which].dirty) {
  76. RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
  77. t->nb[level][which].dirty = 0;
  78. }
  79. RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
  80. t->nb[level][which].pos = nodepos;
  81. }
  82. /* make it mru */
  83. if (t->used[level][2] == which) {
  84. t->used[level][2] = t->used[level][1];
  85. t->used[level][1] = t->used[level][0];
  86. t->used[level][0] = which;
  87. }
  88. else if (t->used[level][1] == which) {
  89. t->used[level][1] = t->used[level][0];
  90. t->used[level][0] = which;
  91. }
  92. *n = t->nb[level][which].n;
  93. }
  94. /* write new node to file */
  95. size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
  96. {
  97. /* file position must be set first with RTreeGetFNodePos() */
  98. return write(t->fd, n, t->nodesize);
  99. }
  100. /* rewrite updated node to file */
  101. size_t RTreeRewriteNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  102. {
  103. lseek(t->fd, nodepos, SEEK_SET);
  104. return write(t->fd, n, t->nodesize);
  105. }
  106. /* update node in buffer */
  107. void RTreePutNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
  108. {
  109. int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
  110. t->nb[n->level][which].n = *n;
  111. t->nb[n->level][which].dirty = 1;
  112. /* make it mru */
  113. if (t->used[n->level][2] == which) {
  114. t->used[n->level][2] = t->used[n->level][1];
  115. t->used[n->level][1] = t->used[n->level][0];
  116. t->used[n->level][0] = which;
  117. }
  118. else if (t->used[n->level][1] == which) {
  119. t->used[n->level][1] = t->used[n->level][0];
  120. t->used[n->level][0] = which;
  121. }
  122. }
  123. /* update rectangle */
  124. void RTreeUpdateRect(struct RTree_Rect *r, struct RTree_Node *n, off_t nodepos, int b, struct RTree *t)
  125. {
  126. int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
  127. t->nb[n->level][which].n.branch[b].rect = n->branch[b].rect = *r;
  128. t->nb[n->level][which].dirty = 1;
  129. /* make it mru */
  130. if (t->used[n->level][2] == which) {
  131. t->used[n->level][2] = t->used[n->level][1];
  132. t->used[n->level][1] = t->used[n->level][0];
  133. t->used[n->level][0] = which;
  134. }
  135. else if (t->used[n->level][1] == which) {
  136. t->used[n->level][1] = t->used[n->level][0];
  137. t->used[n->level][0] = which;
  138. }
  139. }
  140. /* flush pending changes to file */
  141. void RTreeFlushBuffer(struct RTree *t)
  142. {
  143. int i;
  144. for (i = 0; i <= t->rootlevel; i++) {
  145. if (t->nb[i][0].dirty)
  146. RTreeRewriteNode(&(t->nb[i][0].n), t->nb[i][0].pos, t);
  147. if (t->nb[i][1].dirty)
  148. RTreeRewriteNode(&(t->nb[i][1].n), t->nb[i][1].pos, t);
  149. if (t->nb[i][2].dirty)
  150. RTreeRewriteNode(&(t->nb[i][2].n), t->nb[i][2].pos, t);
  151. }
  152. }