io.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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][1].pos;
  37. t->nb[level][which].pos = -1;
  38. t->nb[level][which].dirty = 0;
  39. t->mru[level] = which == 0;
  40. }
  41. /* looks for free node position, sets file pointer, returns position */
  42. off_t RTreeGetNodePos(struct RTree *t)
  43. {
  44. if (t->free_nodes.avail > 0) {
  45. t->free_nodes.avail--;
  46. return lseek(t->fd, t->free_nodes.pos[t->free_nodes.avail], SEEK_SET);
  47. }
  48. else {
  49. return lseek(t->fd, 0, SEEK_END);
  50. }
  51. }
  52. /* read node from file */
  53. size_t RTreeReadNode(struct Node *n, off_t nodepos, struct RTree *t)
  54. {
  55. lseek(t->fd, nodepos, SEEK_SET);
  56. return read(t->fd, n, t->nodesize);
  57. }
  58. /* get node from buffer or file */
  59. void RTreeGetNode(struct Node *n, off_t nodepos, int level, struct RTree *t)
  60. {
  61. int which = nodepos == t->nb[level][1].pos;
  62. if (t->nb[level][which].pos != nodepos) {
  63. /* which is 0 */
  64. /* replace least recently used */
  65. /* least recently used is faster than most recently used */
  66. if (t->nb[level][which].pos != -1)
  67. which = t->mru[level] == 0;
  68. /* rewrite node in buffer */
  69. if (t->nb[level][which].dirty) {
  70. RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
  71. t->nb[level][which].dirty = 0;
  72. }
  73. RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
  74. t->nb[level][which].pos = nodepos;
  75. }
  76. t->mru[level] = which;
  77. *n = t->nb[level][which].n;
  78. }
  79. /* write new node to file */
  80. size_t RTreeWriteNode(struct Node *n, struct RTree *t)
  81. {
  82. /* file position must be set first with RTreeGetFNodePos() */
  83. return write(t->fd, n, t->nodesize);
  84. }
  85. /* rewrite updated node to file */
  86. size_t RTreeRewriteNode(struct Node *n, off_t nodepos, struct RTree *t)
  87. {
  88. lseek(t->fd, nodepos, SEEK_SET);
  89. return write(t->fd, n, t->nodesize);
  90. }
  91. /* update node in buffer */
  92. void RTreePutNode(struct Node *n, off_t nodepos, struct RTree *t)
  93. {
  94. int which = nodepos == t->nb[n->level][1].pos;
  95. t->nb[n->level][which].n = *n;
  96. t->nb[n->level][which].dirty = 1;
  97. t->mru[n->level] = which;
  98. }
  99. /* update rectangle */
  100. void RTreeUpdateRect(struct Rect *r, struct Node *n, off_t nodepos, int b, struct RTree *t)
  101. {
  102. int which = nodepos == t->nb[n->level][1].pos;
  103. t->nb[n->level][which].n.branch[b].rect = n->branch[b].rect = *r;
  104. t->nb[n->level][which].dirty = 1;
  105. t->mru[n->level] = which;
  106. }
  107. void RTreeFlushBuffer(struct RTree *t)
  108. {
  109. int i;
  110. for (i = 0; i <= t->rootlevel; i++) {
  111. if (t->nb[i][0].dirty)
  112. RTreeRewriteNode(&(t->nb[i][0].n), t->nb[i][0].pos, t);
  113. if (t->nb[i][1].dirty)
  114. RTreeRewriteNode(&(t->nb[i][1].n), t->nb[i][1].pos, t);
  115. }
  116. }