GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
io.c
Go to the documentation of this file.
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
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21#include <sys/types.h>
22#include <unistd.h>
23#include <assert.h>
24#include <errno.h>
25
26#include <grass/gis.h>
27#include <grass/glocale.h>
28
29#include "index.h"
30
31/* #define USAGE_SWAP */
32
33/* add new free node position for recycling */
34void RTreeAddNodePos(off_t pos, int level, struct RTree *t)
35{
36 int which, i;
37
38 if (t->free_nodes.avail >= t->free_nodes.alloc) {
39 size_t size;
40
41 t->free_nodes.alloc += 100;
42 size = t->free_nodes.alloc * sizeof(off_t);
43 t->free_nodes.pos = (off_t *)realloc((void *)t->free_nodes.pos, size);
44 assert(t->free_nodes.pos);
45 }
46 t->free_nodes.pos[t->free_nodes.avail++] = pos;
47
48 /* check mru first */
49 i = 0;
50 while (t->nb[level][t->used[level][i]].pos != pos && i < NODE_BUFFER_SIZE)
51 i++;
52
53 /* is it possible that this node is not in the buffer? */
55 which = t->used[level][i];
56 t->nb[level][which].pos = -1;
57 t->nb[level][which].dirty = 0;
58
59 /* make it lru */
60 if (i < NODE_BUFFER_SIZE -
61 1) { /* which != t->used[level][NODE_BUFFER_SIZE - 1] */
62 /* simple swap does not work here */
63 while (i < NODE_BUFFER_SIZE - 1 &&
64 t->nb[level][t->used[level][i + 1]].pos != -1) {
65 t->used[level][i] = t->used[level][i + 1];
66 i++;
67 }
69 t->used[level][i] = which;
70 }
71}
72
73/* look for free node position, set file pointer, return position */
75{
76 if (t->free_nodes.avail > 0) {
77 t->free_nodes.avail--;
78 return lseek(t->fd, t->free_nodes.pos[t->free_nodes.avail], SEEK_SET);
79 }
80 else {
81 return lseek(t->fd, 0, SEEK_END);
82 }
83}
84
85/* read branch from file */
86size_t RTreeReadBranch(struct RTree_Branch *b, struct RTree *t)
87{
88 size_t size = 0;
89
90 size += read(t->fd, b->rect.boundary, t->rectsize);
91 size += read(t->fd, &(b->child), sizeof(union RTree_Child));
92
93 return size;
94}
95
96/* read node from file */
97size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
98{
99 int i;
100 size_t size = 0;
101
102 if (lseek(t->fd, nodepos, SEEK_SET) == -1) {
103 int err = errno;
104 G_fatal_error(_("File read/write operation failed: %s (%d)"),
105 strerror(err), err);
106 }
107 size += read(t->fd, &(n->count), sizeof(int));
108 size += read(t->fd, &(n->level), sizeof(int));
109
110 for (i = 0; i < MAXCARD; i++) {
111 size += RTreeReadBranch(&(n->branch[i]), t);
112 }
113
114 return size;
115}
116
117/* get node from buffer or file */
119{
120 int which, i = 0;
121
122 /* check mru first */
123 while (t->nb[level][t->used[level][i]].pos != nodepos &&
124 t->nb[level][t->used[level][i]].pos >= 0 && i < NODE_BUFFER_SIZE - 1)
125 i++;
126
127 which = t->used[level][i];
128
129 if (t->nb[level][which].pos != nodepos) {
130 /* rewrite node in buffer */
131 if (t->nb[level][which].dirty) {
132 RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos,
133 t);
134 t->nb[level][which].dirty = 0;
135 }
136 RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
137 t->nb[level][which].pos = nodepos;
138 }
139 /* make it mru */
140 if (i) { /* t->used[level][0] != which */
141#ifdef USAGE_SWAP
142 t->used[level][i] = t->used[level][0];
143 t->used[level][0] = which;
144#else
145 while (i) {
146 t->used[level][i] = t->used[level][i - 1];
147 i--;
148 }
149 t->used[level][0] = which;
150#endif
151 }
152
153 /* RTreeCopyNode(n, &(t->nb[level][which].n), t); */
154
155 return &(t->nb[level][which].n);
156}
157
158/* write branch to file */
159size_t RTreeWriteBranch(struct RTree_Branch *b, struct RTree *t)
160{
161 size_t size = 0;
162
163 if (write(t->fd, b->rect.boundary, t->rectsize) != t->rectsize)
164 G_fatal_error("RTreeWriteBranch(): Unable to write (%s)",
165 strerror(errno));
166 size += t->rectsize;
167 if (write(t->fd, &(b->child), sizeof(union RTree_Child)) !=
168 sizeof(union RTree_Child))
169 G_fatal_error("RTreeWriteBranch(): Unable to write (%s)",
170 strerror(errno));
171 size += sizeof(union RTree_Child);
172
173 return size;
174}
175
176/* write new node to file */
177size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
178{
179 int i;
180 size_t size = 0;
181
182 /* file position must be set first with RTreeGetFNodePos() */
183 if (write(t->fd, &(n->count), sizeof(int)) != sizeof(int))
184 G_fatal_error("RTreeWriteNode(): Unable to write (%s)",
185 strerror(errno));
186 size += sizeof(int);
187 if (write(t->fd, &(n->level), sizeof(int)) != sizeof(int))
188 G_fatal_error("RTreeWriteNode(): Unable to write (%s)",
189 strerror(errno));
190 size += sizeof(int);
191
192 for (i = 0; i < MAXCARD; i++) {
193 size += RTreeWriteBranch(&(n->branch[i]), t);
194 }
195
196 return size;
197}
198
199/* rewrite updated node to file */
200size_t RTreeRewriteNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
201{
202 if (lseek(t->fd, nodepos, SEEK_SET) == -1) {
203 int err = errno;
204 G_fatal_error(_("File read/write operation failed: %s (%d)"),
205 strerror(err), err);
206 }
207
208 return RTreeWriteNode(n, t);
209}
210
211/* mark node in buffer as changed */
213{
214 int which, i = 0;
215
216 /* check mru first */
217 while (t->nb[n->level][t->used[n->level][i]].pos != nodepos &&
219 i++;
220
222 /* as it is used, it should always be mru */
223 assert(i == 0);
224 which = t->used[n->level][i];
225
226 t->nb[n->level][which].dirty = 1;
227
228 /* make it mru */
229 if (i) { /* t->used[level][0] != which */
230#ifdef USAGE_SWAP
231 t->used[n->level][i] = t->used[n->level][0];
232 t->used[n->level][0] = which;
233#else
234 while (i) {
235 t->used[n->level][i] = t->used[n->level][i - 1];
236 i--;
237 }
238 t->used[n->level][0] = which;
239#endif
240 }
241}
242
243/* flush pending changes to file */
245{
246 int i, j;
247
248 for (i = 0; i <= t->rootlevel; i++) {
249 for (j = 0; j < NODE_BUFFER_SIZE; j++) {
250 if (t->nb[i][j].dirty) {
251 RTreeRewriteNode(&(t->nb[i][j].n), t->nb[i][j].pos, t);
252 t->nb[i][j].dirty = 0;
253 }
254 }
255 }
256}
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define _(str)
Definition glocale.h:10
off_t RTreeGetNodePos(struct RTree *t)
Definition io.c:74
void RTreeNodeChanged(struct RTree_Node *n, off_t nodepos, struct RTree *t)
Definition io.c:212
size_t RTreeWriteBranch(struct RTree_Branch *b, struct RTree *t)
Definition io.c:159
size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
Definition io.c:97
void RTreeFlushBuffer(struct RTree *t)
Definition io.c:244
size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
Definition io.c:177
size_t RTreeRewriteNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
Definition io.c:200
struct RTree_Node * RTreeGetNode(off_t nodepos, int level, struct RTree *t)
Definition io.c:118
void RTreeAddNodePos(off_t pos, int level, struct RTree *t)
Definition io.c:34
size_t RTreeReadBranch(struct RTree_Branch *b, struct RTree *t)
Definition io.c:86
#define assert(condition)
Definition lz4.c:291
double b
Definition r_raster.c:39
double t
Definition r_raster.c:39
#define MAXCARD
Definition rtree.h:44
#define NODE_BUFFER_SIZE
Definition rtree.h:52
int count
Definition rtree.h:74
int level
Definition rtree.h:75
struct RTree_Branch * branch
Definition rtree.h:76
Definition rtree.h:123
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
#define read
Definition unistd.h:5
#define write
Definition unistd.h:6