1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | |
---|
4 | #include <string.h> |
---|
5 | /* #include <malloc.h> */ |
---|
6 | |
---|
7 | /*#include "arbdb.h"*/ |
---|
8 | #include "adlocal.h" |
---|
9 | |
---|
10 | #ifndef __cplusplus |
---|
11 | void ad_use(int dummy, ...) { |
---|
12 | dummy = 0; |
---|
13 | } |
---|
14 | #endif |
---|
15 | |
---|
16 | /******************************************************************************************** |
---|
17 | GB data manangement |
---|
18 | ********************************************************************************************/ |
---|
19 | void gb_touch_entry(GBDATA * gbd, GB_CHANGED val) { |
---|
20 | GBCONTAINER *gbc; |
---|
21 | GBCONTAINER *gbc_father; |
---|
22 | |
---|
23 | gbd->flags2.update_in_server = 0; |
---|
24 | if ( val > (GB_CHANGED)(int)GB_ARRAY_FLAGS(gbd).changed) { |
---|
25 | GB_ARRAY_FLAGS(gbd).changed = val; |
---|
26 | GB_ARRAY_FLAGS(gbd).ever_changed = 1; |
---|
27 | } |
---|
28 | gbc = GB_FATHER(gbd); |
---|
29 | |
---|
30 | if ((!gbc->index_of_touched_one_son) || gbc->index_of_touched_one_son == gbd->index+1) { |
---|
31 | gbc->index_of_touched_one_son = gbd->index+1; |
---|
32 | }else{ |
---|
33 | gbc->index_of_touched_one_son = -1; |
---|
34 | } |
---|
35 | |
---|
36 | while ((gbc_father=GB_FATHER(gbc))!=NULL) |
---|
37 | { |
---|
38 | if ( (!gbc_father->index_of_touched_one_son) || gbc_father->index_of_touched_one_son == gbc->index+1 ) { |
---|
39 | gbc_father->index_of_touched_one_son = gbc->index+1; |
---|
40 | }else{ |
---|
41 | gbc_father->index_of_touched_one_son = -1; |
---|
42 | } |
---|
43 | |
---|
44 | if (gbc->flags2.update_in_server) { |
---|
45 | gbc->flags2.update_in_server = 0; |
---|
46 | } else { |
---|
47 | if (GB_ARRAY_FLAGS(gbc).changed >= (unsigned int)gb_son_changed) |
---|
48 | return; |
---|
49 | } |
---|
50 | if (gb_son_changed > (int)GB_ARRAY_FLAGS(gbc).changed) { |
---|
51 | GB_ARRAY_FLAGS(gbc).changed = gb_son_changed; |
---|
52 | GB_ARRAY_FLAGS(gbc).ever_changed = 1; |
---|
53 | } |
---|
54 | gbc = gbc_father; |
---|
55 | } |
---|
56 | } |
---|
57 | |
---|
58 | void gb_touch_header(GBCONTAINER *gbc) |
---|
59 | { |
---|
60 | gbc->flags2.header_changed = 1; |
---|
61 | gb_touch_entry((GBDATA*)gbc, gb_changed); |
---|
62 | } |
---|
63 | |
---|
64 | |
---|
65 | void |
---|
66 | gb_untouch_children(GBCONTAINER * gbc) |
---|
67 | { |
---|
68 | GBDATA *gbd; |
---|
69 | int index, start, end; |
---|
70 | GB_CHANGED changed; |
---|
71 | |
---|
72 | struct gb_header_list_struct *header = GB_DATA_LIST_HEADER(gbc->d); |
---|
73 | |
---|
74 | if (gbc->index_of_touched_one_son > 0) { |
---|
75 | start = (int)gbc->index_of_touched_one_son-1; |
---|
76 | end = start + 1; |
---|
77 | } else { |
---|
78 | if (!gbc->index_of_touched_one_son){ |
---|
79 | start = end = 0; |
---|
80 | }else{ |
---|
81 | start = 0; |
---|
82 | end = gbc->d.nheader; |
---|
83 | } |
---|
84 | } |
---|
85 | |
---|
86 | for (index = start; index < end; index++) |
---|
87 | { |
---|
88 | if ((gbd = GB_HEADER_LIST_GBD(header[index]))!=NULL) |
---|
89 | { |
---|
90 | if ( (changed = (GB_CHANGED)header[index].flags.changed) && |
---|
91 | (changed < gb_deleted) ) |
---|
92 | { |
---|
93 | header[index].flags.changed = gb_not_changed; |
---|
94 | if (GB_TYPE(gbd) == GB_DB) |
---|
95 | { |
---|
96 | gb_untouch_children((GBCONTAINER *) gbd); |
---|
97 | } |
---|
98 | } |
---|
99 | gbd->flags2.update_in_server = 0; |
---|
100 | } |
---|
101 | } |
---|
102 | gbc->index_of_touched_one_son = 0; |
---|
103 | } |
---|
104 | |
---|
105 | void gb_untouch_me(GBDATA * gbc) |
---|
106 | { |
---|
107 | GB_DATA_LIST_HEADER(GB_FATHER(gbc)->d)[gbc->index].flags.changed = gb_not_changed; |
---|
108 | if (GB_TYPE(gbc) == GB_DB){ |
---|
109 | gbc->flags2.header_changed = 0; |
---|
110 | ((GBCONTAINER *)gbc)->index_of_touched_one_son = 0; |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | void gb_set_update_in_server_flags(GBCONTAINER * gbc) |
---|
115 | { |
---|
116 | int index; |
---|
117 | GBDATA *gbd; |
---|
118 | |
---|
119 | for (index = 0; index < gbc->d.nheader; index++) { |
---|
120 | if ((gbd = GBCONTAINER_ELEM(gbc,index))!=NULL) { |
---|
121 | if (GB_TYPE(gbd) == GB_DB) { |
---|
122 | gb_set_update_in_server_flags((GBCONTAINER *) gbd); |
---|
123 | } |
---|
124 | gbd->flags2.update_in_server = 1; |
---|
125 | } |
---|
126 | } |
---|
127 | } |
---|
128 | |
---|
129 | void gb_create_header_array(GBCONTAINER *gbc, int size){ |
---|
130 | /* creates or resizes an old array to children */ |
---|
131 | struct gb_header_list_struct *nl, *ol; |
---|
132 | |
---|
133 | if (size <= gbc->d.headermemsize) return; |
---|
134 | if (!size) return; |
---|
135 | if (size > 10) size++; |
---|
136 | if (size > 30) size = size*3/2; |
---|
137 | nl = (struct gb_header_list_struct *) |
---|
138 | gbm_get_mem(sizeof(struct gb_header_list_struct)*size,GBM_HEADER_INDEX); |
---|
139 | |
---|
140 | if ((ol=GB_DATA_LIST_HEADER(gbc->d))!=NULL) |
---|
141 | { |
---|
142 | int idx, |
---|
143 | maxidx = gbc->d.headermemsize; /* ???: oder ->d.nheader */ |
---|
144 | |
---|
145 | for (idx=0; idx<maxidx; idx++) |
---|
146 | { |
---|
147 | GBDATA *gbd = GB_HEADER_LIST_GBD(ol[idx]); |
---|
148 | nl[idx].flags = ol[idx].flags; |
---|
149 | |
---|
150 | if (gbd) |
---|
151 | { |
---|
152 | ad_assert(gbd->server_id==GBTUM_MAGIC_NUMBER || GB_read_clients(gbd)<0); /* or I am a client */ |
---|
153 | SET_GB_HEADER_LIST_GBD(nl[idx],gbd); |
---|
154 | } |
---|
155 | } |
---|
156 | |
---|
157 | gbm_free_mem((char *)ol, |
---|
158 | sizeof(struct gb_header_list_struct)*gbc->d.headermemsize, |
---|
159 | GBM_HEADER_INDEX ); |
---|
160 | } |
---|
161 | |
---|
162 | gbc->d.headermemsize = size; |
---|
163 | SET_GB_DATA_LIST_HEADER(gbc->d,nl); |
---|
164 | } |
---|
165 | |
---|
166 | void gb_link_entry(GBCONTAINER* father, GBDATA * gbd, long index_pos) |
---|
167 | { |
---|
168 | /* if index_pos == -1 -> to end of data; |
---|
169 | else special index position; error when data already exists in index pos */ |
---|
170 | |
---|
171 | SET_GB_FATHER(gbd,father); |
---|
172 | if (father == NULL) { /* 'main' entry in GB */ |
---|
173 | return; |
---|
174 | } |
---|
175 | |
---|
176 | if (GB_TYPE(father) != GB_DB) { |
---|
177 | GB_internal_errorf("to read a database into a non database keyword %s," |
---|
178 | "probably %%%% is missing\n", GB_read_key_pntr((GBDATA*)father)); |
---|
179 | return; |
---|
180 | } |
---|
181 | if ( index_pos < 0) { |
---|
182 | index_pos = father->d.nheader++; |
---|
183 | }else{ |
---|
184 | if ( index_pos >= father->d.nheader){ |
---|
185 | father->d.nheader = (int)index_pos+1; |
---|
186 | } |
---|
187 | } |
---|
188 | |
---|
189 | gb_create_header_array(father, (int)index_pos+1); |
---|
190 | |
---|
191 | if ( GBCONTAINER_ELEM(father,index_pos) ) { |
---|
192 | GB_internal_error("Index of Databaseentry used twice"); |
---|
193 | index_pos = father->d.nheader++; |
---|
194 | gb_create_header_array(father, (int)index_pos+1); |
---|
195 | } |
---|
196 | |
---|
197 | /* the following code skips just-deleted index position, while searching for an unused |
---|
198 | index position. I'm unsure whether this works w/o problems (ralf 2004-Oct-08) */ |
---|
199 | |
---|
200 | while (GB_DATA_LIST_HEADER(father->d)[index_pos].flags.changed >= gb_deleted) { |
---|
201 | #if defined(DEBUG) |
---|
202 | fprintf(stderr, "Warning: index_pos %li of father(%p) contains just-deleted entry -> using next index_pos..\n", index_pos, father); |
---|
203 | #endif /* DEBUG */ |
---|
204 | index_pos = father->d.nheader++; |
---|
205 | gb_create_header_array(father, (int)index_pos+1); |
---|
206 | } |
---|
207 | |
---|
208 | gbd->index = index_pos; |
---|
209 | SET_GBCONTAINER_ELEM(father,index_pos,gbd); |
---|
210 | father->d.size++; |
---|
211 | } |
---|
212 | |
---|
213 | void gb_unlink_entry(GBDATA * gbd) |
---|
214 | { |
---|
215 | GBCONTAINER *father = GB_FATHER(gbd); |
---|
216 | |
---|
217 | if (father) |
---|
218 | { |
---|
219 | int index_pos = (int)gbd->index; |
---|
220 | struct gb_header_list_struct *hls = &(GB_DATA_LIST_HEADER(father->d)[index_pos]); |
---|
221 | |
---|
222 | SET_GB_HEADER_LIST_GBD(*hls,NULL); |
---|
223 | hls->flags.key_quark = 0; |
---|
224 | hls->flags.changed = gb_deleted; |
---|
225 | hls->flags.ever_changed = 1; |
---|
226 | father->d.size--; |
---|
227 | SET_GB_FATHER(gbd,NULL); |
---|
228 | } |
---|
229 | } |
---|
230 | |
---|
231 | void gb_create_extended(GBDATA *gbd){ |
---|
232 | int index; |
---|
233 | if (gbd->ext) return; |
---|
234 | index = GB_GBM_INDEX(gbd); |
---|
235 | gbd->ext = (struct gb_db_extended *)gbm_get_mem( |
---|
236 | sizeof(struct gb_db_extended), |
---|
237 | index); |
---|
238 | } |
---|
239 | |
---|
240 | struct gb_main_type *gb_make_gb_main_type(const char *path) |
---|
241 | { |
---|
242 | struct gb_main_type *Main; |
---|
243 | |
---|
244 | Main = (struct gb_main_type *)gbm_get_mem(sizeof(struct gb_main_type),0); |
---|
245 | if (path) Main->path = strdup((char*)path); |
---|
246 | Main->key_2_index_hash = GBS_create_hash(20000, GB_MIND_CASE); |
---|
247 | Main->compression_mask = -1; /* allow all compressions */ |
---|
248 | gb_init_cache(Main); |
---|
249 | gb_init_undo_stack(Main); |
---|
250 | gb_init_ctype_table(); |
---|
251 | return Main; |
---|
252 | } |
---|
253 | |
---|
254 | char *gb_destroy_main(struct gb_main_type *Main) |
---|
255 | { |
---|
256 | if (Main->path) free(Main->path); |
---|
257 | gb_free_undo_stack(Main); |
---|
258 | gbm_free_mem((char *)Main,sizeof(struct gb_main_type),0); |
---|
259 | |
---|
260 | return 0; |
---|
261 | } |
---|
262 | |
---|
263 | /* inserts an object into the dabase hierarchy */ |
---|
264 | GBDATA *gb_make_pre_defined_entry( GBCONTAINER * father, GBDATA *gbd, |
---|
265 | long index_pos, GBQUARK keyq) |
---|
266 | { |
---|
267 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(father); |
---|
268 | |
---|
269 | SET_GB_FATHER(gbd,father); |
---|
270 | if (Main->local_mode) { |
---|
271 | gbd->server_id = GBTUM_MAGIC_NUMBER; |
---|
272 | } |
---|
273 | if (Main->clock) { |
---|
274 | GB_CREATE_EXT(gbd); |
---|
275 | gbd->ext->creation_date = Main->clock; |
---|
276 | } |
---|
277 | |
---|
278 | gb_link_entry(father, gbd, index_pos); |
---|
279 | gb_write_index_key(father,gbd->index,keyq); |
---|
280 | |
---|
281 | return gbd; |
---|
282 | } |
---|
283 | |
---|
284 | void |
---|
285 | gb_rename_entry(GBCONTAINER *gbc, const char *new_key) { |
---|
286 | GBCONTAINER *gb_father = GB_FATHER(gbc); |
---|
287 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gb_father); |
---|
288 | GBQUARK new_keyq; |
---|
289 | long new_gbm_index; |
---|
290 | |
---|
291 | gb_unlink_entry((GBDATA*)gbc); |
---|
292 | |
---|
293 | new_keyq = gb_key_2_quark(Main, new_key); |
---|
294 | new_gbm_index = GB_QUARK_2_GBMINDEX(Main, new_keyq); |
---|
295 | GB_GBM_INDEX(gbc) = new_gbm_index; |
---|
296 | |
---|
297 | gb_link_entry(gb_father, (GBDATA*)gbc, -1); |
---|
298 | gb_write_key((GBDATA*)gbc, new_key); |
---|
299 | } |
---|
300 | |
---|
301 | |
---|
302 | /* creates a terminal database object */ |
---|
303 | GBDATA *gb_make_entry(GBCONTAINER * father, const char *key, long index_pos, GBQUARK keyq, GB_TYPES type) { |
---|
304 | GBDATA *gbd; |
---|
305 | long gbm_index; |
---|
306 | static char *buffer = 0; |
---|
307 | char *p; |
---|
308 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(father); |
---|
309 | |
---|
310 | if (!keyq) keyq = gb_key_2_quark(Main,key); |
---|
311 | gbm_index = GB_QUARK_2_GBMINDEX(Main, keyq); |
---|
312 | gbd = (GBDATA *) gbm_get_mem(sizeof(GBDATA), gbm_index); |
---|
313 | GB_GBM_INDEX(gbd) = gbm_index; |
---|
314 | SET_GB_FATHER(gbd,father); |
---|
315 | |
---|
316 | switch(type) |
---|
317 | { |
---|
318 | case GB_STRING_SHRT: type = GB_STRING; |
---|
319 | case GB_STRING: |
---|
320 | if (!buffer) buffer = strdup("1234"); |
---|
321 | p = buffer; |
---|
322 | while ( !(++(*p) )) { (*p)++;p++; if (!(*p)) break; } |
---|
323 | GB_SETSMDMALLOC(gbd,5,5,buffer); |
---|
324 | break; |
---|
325 | case GB_LINK: |
---|
326 | buffer[0] = ':'; |
---|
327 | buffer[1] = 0; |
---|
328 | GB_SETSMDMALLOC(gbd,0,0,buffer); |
---|
329 | break; |
---|
330 | default: break; |
---|
331 | } |
---|
332 | gbd->flags.type = type; |
---|
333 | |
---|
334 | if (Main->local_mode) { |
---|
335 | gbd->server_id = GBTUM_MAGIC_NUMBER; |
---|
336 | } |
---|
337 | if (Main->clock) { |
---|
338 | GB_CREATE_EXT(gbd); |
---|
339 | gbd->ext->creation_date = Main->clock; |
---|
340 | } |
---|
341 | |
---|
342 | gb_link_entry(father, gbd, index_pos); |
---|
343 | if (key) gb_write_key(gbd, key); |
---|
344 | else gb_write_index_key(father,gbd->index,keyq); |
---|
345 | |
---|
346 | return gbd; |
---|
347 | } |
---|
348 | |
---|
349 | /* inserts an object into the dabase hierarchy */ |
---|
350 | GBCONTAINER *gb_make_pre_defined_container( GBCONTAINER * father, GBCONTAINER *gbd, |
---|
351 | long index_pos, GBQUARK keyq) |
---|
352 | { |
---|
353 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(father); |
---|
354 | |
---|
355 | SET_GB_FATHER(gbd,father); |
---|
356 | gbd->main_idx = father->main_idx; |
---|
357 | |
---|
358 | if (Main->local_mode) gbd->server_id = GBTUM_MAGIC_NUMBER; |
---|
359 | if (Main->clock) |
---|
360 | { |
---|
361 | GB_CREATE_EXT((GBDATA *) gbd); |
---|
362 | gbd->ext->creation_date = Main->clock; |
---|
363 | } |
---|
364 | gb_link_entry(father, (GBDATA *) gbd, index_pos); |
---|
365 | gb_write_index_key(father,gbd->index,keyq); |
---|
366 | |
---|
367 | return gbd; |
---|
368 | } |
---|
369 | |
---|
370 | |
---|
371 | GBCONTAINER *gb_make_container(GBCONTAINER * father, const char *key, long index_pos, GBQUARK keyq) |
---|
372 | { |
---|
373 | GBCONTAINER *gbd; |
---|
374 | long gbm_index; |
---|
375 | |
---|
376 | if (father) |
---|
377 | { |
---|
378 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(father); |
---|
379 | |
---|
380 | if (!keyq) keyq = gb_key_2_quark(Main,key); |
---|
381 | gbm_index = GB_QUARK_2_GBMINDEX(Main, keyq); |
---|
382 | gbd = (GBCONTAINER *) gbm_get_mem(sizeof(GBCONTAINER), gbm_index); |
---|
383 | GB_GBM_INDEX(gbd) = gbm_index; |
---|
384 | SET_GB_FATHER(gbd,father); |
---|
385 | gbd->flags.type = GB_DB; |
---|
386 | gbd->main_idx = father->main_idx; |
---|
387 | if (Main->local_mode) gbd->server_id = GBTUM_MAGIC_NUMBER; |
---|
388 | if (Main->clock) |
---|
389 | { |
---|
390 | GB_CREATE_EXT((GBDATA *) gbd); |
---|
391 | gbd->ext->creation_date = Main->clock; |
---|
392 | } |
---|
393 | gb_link_entry(father, (GBDATA *) gbd, index_pos); |
---|
394 | if (key) gb_write_key((GBDATA *)gbd, key); |
---|
395 | else gb_write_index_key(father,gbd->index,keyq); |
---|
396 | |
---|
397 | return gbd; |
---|
398 | } |
---|
399 | else /* main entry */ |
---|
400 | { |
---|
401 | gbd = (GBCONTAINER *) gbm_get_mem(sizeof(GBCONTAINER), 0); |
---|
402 | gbd->flags.type = GB_DB; |
---|
403 | } |
---|
404 | |
---|
405 | return gbd; |
---|
406 | } |
---|
407 | |
---|
408 | /** Reduce an entry to its absolute minimum and remove it from database */ |
---|
409 | void gb_pre_delete_entry(GBDATA *gbd){ |
---|
410 | GB_MAIN_TYPE *Main = GB_MAIN(gbd); |
---|
411 | long type = GB_TYPE(gbd); |
---|
412 | |
---|
413 | struct gb_callback *cb, *cb2; |
---|
414 | long gbm_index; |
---|
415 | gbm_index = GB_GBM_INDEX(gbd); |
---|
416 | for (cb = GB_GET_EXT_CALLBACKS(gbd); cb; cb = cb2) { |
---|
417 | gbd->ext->callback = 0; |
---|
418 | cb2 = cb->next; |
---|
419 | if (!gbd->ext->old && type != GB_DB){ |
---|
420 | gb_save_extern_data_in_ts(gbd); |
---|
421 | } |
---|
422 | if (cb->type & GB_CB_DELETE) { |
---|
423 | gb_add_delete_callback_list(gbd, gbd->ext->old, cb->func, cb->clientdata); |
---|
424 | } |
---|
425 | gbm_free_mem((char *) cb, sizeof(struct gb_callback), gbm_index); |
---|
426 | } |
---|
427 | gb_write_key(gbd, 0); |
---|
428 | gb_unlink_entry(gbd); |
---|
429 | |
---|
430 | /* as soon as an entry is deleted, there is |
---|
431 | no need to keep track of the database entry |
---|
432 | within the server at the client side */ |
---|
433 | if (!Main->local_mode && gbd->server_id) { |
---|
434 | GBS_write_hashi(Main->remote_hash, gbd->server_id, 0); |
---|
435 | } |
---|
436 | |
---|
437 | if (type>= GB_BITS && type < GB_DB) { |
---|
438 | gb_free_cache(Main,gbd); |
---|
439 | } |
---|
440 | GB_FREE_TRANSACTION_SAVE(gbd); |
---|
441 | _GB_DELETE_EXT(gbd, gbm_index); |
---|
442 | } |
---|
443 | |
---|
444 | void gb_delete_entry(GBDATA **gbd_ptr) { |
---|
445 | GBDATA *gbd = *gbd_ptr; |
---|
446 | long gbm_index; |
---|
447 | long type = GB_TYPE(gbd); |
---|
448 | |
---|
449 | gbm_index = GB_GBM_INDEX(gbd); |
---|
450 | |
---|
451 | if (type == GB_DB) { |
---|
452 | int index; |
---|
453 | GBDATA *gbd2; |
---|
454 | GBCONTAINER *gbc = ((GBCONTAINER *) gbd); |
---|
455 | |
---|
456 | for (index = 0; index < gbc->d.nheader; index++) { |
---|
457 | if ((gbd2 = GBCONTAINER_ELEM(gbc,index))!=NULL) { |
---|
458 | gb_delete_entry(&gbd2); |
---|
459 | } |
---|
460 | }; |
---|
461 | } |
---|
462 | gb_pre_delete_entry(gbd); |
---|
463 | |
---|
464 | /* Now what is left is the core database entry !!! */ |
---|
465 | |
---|
466 | if (type == GB_DB) { |
---|
467 | GBCONTAINER *gbc = ((GBCONTAINER *) gbd); |
---|
468 | struct gb_header_list_struct *hls; |
---|
469 | |
---|
470 | if ((hls=GB_DATA_LIST_HEADER(gbc->d))!=NULL){ |
---|
471 | gbm_free_mem((char *)hls, |
---|
472 | sizeof(struct gb_header_list_struct) * gbc->d.headermemsize, |
---|
473 | GBM_HEADER_INDEX); |
---|
474 | } |
---|
475 | gbm_free_mem((char *) gbd, sizeof(GBCONTAINER), gbm_index); |
---|
476 | } |
---|
477 | else { |
---|
478 | if (type >= GB_BITS) GB_FREEDATA(gbd); |
---|
479 | gbm_free_mem((char *) gbd, sizeof(GBDATA), gbm_index); |
---|
480 | } |
---|
481 | |
---|
482 | *gbd_ptr = 0; // avoid further usage |
---|
483 | } |
---|
484 | |
---|
485 | void gb_delete_main_entry(GBDATA **gbd_ptr) { |
---|
486 | GBDATA *gbd = *gbd_ptr; |
---|
487 | long type = GB_TYPE(gbd); |
---|
488 | |
---|
489 | ad_assert(type == GB_DB); |
---|
490 | if (type == GB_DB) { |
---|
491 | int index; |
---|
492 | int pass; |
---|
493 | GBDATA *gbd2; |
---|
494 | GBCONTAINER *gbc = ((GBCONTAINER *) gbd); |
---|
495 | |
---|
496 | int sys_quark = GB_key_2_quark(gbd, GB_SYSTEM_FOLDER); |
---|
497 | |
---|
498 | for (pass = 1; pass <= 2; pass++) { |
---|
499 | for (index = 0; index < gbc->d.nheader; index++) { |
---|
500 | if ((gbd2 = GBCONTAINER_ELEM(gbc,index)) != NULL) { |
---|
501 | if (pass == 2 || GB_KEY_QUARK(gbd2) != sys_quark) { // delay deletion of system folder to pass 2 |
---|
502 | #if defined(DEBUG) |
---|
503 | fprintf(stderr, "Deleting root node '%s'\n", GB_get_db_path(gbd2)); |
---|
504 | #endif /* DEBUG */ |
---|
505 | gb_delete_entry(&gbd2); |
---|
506 | } |
---|
507 | } |
---|
508 | } |
---|
509 | } |
---|
510 | gb_delete_entry(gbd_ptr); |
---|
511 | } |
---|
512 | } |
---|
513 | |
---|
514 | /******************************************************************************************** |
---|
515 | Data Storage |
---|
516 | ********************************************************************************************/ |
---|
517 | /******************** Does not increment the refcounter ********************/ |
---|
518 | struct gb_transaction_save *gb_new_gb_transaction_save(GBDATA *gbd){ |
---|
519 | struct gb_transaction_save *ts; |
---|
520 | |
---|
521 | ts = (struct gb_transaction_save *)gbm_get_mem(sizeof(struct gb_transaction_save),GBM_CB_INDEX); |
---|
522 | |
---|
523 | ts->flags = gbd->flags; |
---|
524 | ts->flags2 = gbd->flags2; |
---|
525 | |
---|
526 | if (gbd->flags2.extern_data) |
---|
527 | { |
---|
528 | ts->info.ex.data = GB_EXTERN_DATA_DATA(gbd->info.ex); |
---|
529 | ts->info.ex.memsize = gbd->info.ex.memsize; |
---|
530 | ts->info.ex.size = gbd->info.ex.size; |
---|
531 | } |
---|
532 | else |
---|
533 | { |
---|
534 | memcpy(&(ts->info), &(gbd->info), sizeof(gbd->info)); |
---|
535 | } |
---|
536 | |
---|
537 | ts->refcount = 1; |
---|
538 | |
---|
539 | return ts; |
---|
540 | } |
---|
541 | |
---|
542 | void gb_add_ref_gb_transaction_save(struct gb_transaction_save *ts){ |
---|
543 | if (!ts) return; |
---|
544 | ts->refcount ++; |
---|
545 | } |
---|
546 | |
---|
547 | void gb_del_ref_gb_transaction_save(struct gb_transaction_save *ts){ |
---|
548 | if (!ts) return; |
---|
549 | ts->refcount --; |
---|
550 | if (ts->refcount <=0) { /* no more references !!!! */ |
---|
551 | if (ts->flags2.extern_data) { |
---|
552 | if (ts->info.ex.data) { |
---|
553 | gbm_free_mem(ts->info.ex.data, |
---|
554 | ts->info.ex.memsize, |
---|
555 | ts->flags2.gbm_index); |
---|
556 | } |
---|
557 | } |
---|
558 | gbm_free_mem((char*)ts, |
---|
559 | sizeof(struct gb_transaction_save), |
---|
560 | GBM_CB_INDEX); |
---|
561 | } |
---|
562 | } |
---|
563 | |
---|
564 | /* remove reference to undo entry and set extern pointer to zero */ |
---|
565 | void gb_del_ref_and_extern_gb_transaction_save(struct gb_transaction_save *ts){ |
---|
566 | if (ts->flags2.extern_data) { |
---|
567 | ts->info.ex.data = 0; |
---|
568 | } |
---|
569 | gb_del_ref_gb_transaction_save(ts); |
---|
570 | } |
---|
571 | |
---|
572 | void gb_abortdata(GBDATA *gbd) |
---|
573 | { |
---|
574 | struct gb_transaction_save *old; |
---|
575 | |
---|
576 | GB_INDEX_CHECK_OUT(gbd); |
---|
577 | old = gbd->ext->old; |
---|
578 | ad_assert(old!=0); |
---|
579 | |
---|
580 | gbd->flags = old->flags; |
---|
581 | gbd->flags2 = old->flags2; |
---|
582 | |
---|
583 | if (old->flags2.extern_data) |
---|
584 | { |
---|
585 | SET_GB_EXTERN_DATA_DATA(gbd->info.ex,old->info.ex.data); |
---|
586 | gbd->info.ex.memsize = old->info.ex.memsize; |
---|
587 | gbd->info.ex.size = old->info.ex.size; |
---|
588 | } |
---|
589 | else |
---|
590 | { |
---|
591 | memcpy(&(gbd->info), &(old->info),sizeof(old->info)); |
---|
592 | } |
---|
593 | gb_del_ref_and_extern_gb_transaction_save(old); |
---|
594 | gbd->ext->old = NULL; |
---|
595 | |
---|
596 | GB_INDEX_CHECK_IN(gbd); |
---|
597 | } |
---|
598 | |
---|
599 | |
---|
600 | void gb_save_extern_data_in_ts(GBDATA *gbd){ |
---|
601 | /* Saves gbd->info into gbd->ext->old |
---|
602 | * destroys gbd->info !!!! |
---|
603 | * dont call with GBCONTAINER */ |
---|
604 | GB_CREATE_EXT(gbd); |
---|
605 | GB_INDEX_CHECK_OUT(gbd); |
---|
606 | if (gbd->ext->old || (GB_ARRAY_FLAGS(gbd).changed == gb_created)){ |
---|
607 | GB_FREEDATA(gbd); |
---|
608 | }else{ |
---|
609 | gbd->ext->old = gb_new_gb_transaction_save(gbd); |
---|
610 | SET_GB_EXTERN_DATA_DATA(gbd->info.ex,0); |
---|
611 | } |
---|
612 | } |
---|
613 | |
---|
614 | |
---|
615 | /******************************************************************************************** |
---|
616 | Key Management |
---|
617 | ********************************************************************************************/ |
---|
618 | |
---|
619 | /********** set the key quark of an database field |
---|
620 | check for indexing data field ***********/ |
---|
621 | |
---|
622 | void gb_write_index_key(GBCONTAINER *father, long index, GBQUARK new_index) { |
---|
623 | GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(father); |
---|
624 | struct gb_header_list_struct *hls = GB_DATA_LIST_HEADER(father->d); |
---|
625 | GBQUARK old_index = hls[index].flags.key_quark; |
---|
626 | |
---|
627 | GBCONTAINER *gfather; |
---|
628 | Main->keys[old_index].nref--; |
---|
629 | Main->keys[new_index].nref++; |
---|
630 | |
---|
631 | if (Main->local_mode) |
---|
632 | { |
---|
633 | GBDATA *gbd = GB_HEADER_LIST_GBD(hls[index]); |
---|
634 | |
---|
635 | if (gbd && (GB_TYPE(gbd) == GB_STRING || GB_TYPE(gbd) == GB_LINK)) |
---|
636 | { |
---|
637 | struct gb_index_files_struct *ifs = 0; |
---|
638 | |
---|
639 | GB_INDEX_CHECK_OUT(gbd); |
---|
640 | gbd->flags2.tisa_index = 0; |
---|
641 | if ( (gfather = GB_FATHER(father))) |
---|
642 | { |
---|
643 | for ( ifs = GBCONTAINER_IFS(gfather); ifs; |
---|
644 | ifs = GB_INDEX_FILES_NEXT(ifs)) |
---|
645 | { |
---|
646 | if (ifs->key == new_index) break; |
---|
647 | } |
---|
648 | } |
---|
649 | hls[index].flags.key_quark = new_index; |
---|
650 | if (ifs) gb_index_check_in(gbd); |
---|
651 | |
---|
652 | return; |
---|
653 | } |
---|
654 | } |
---|
655 | |
---|
656 | hls[index].flags.key_quark = new_index; |
---|
657 | } |
---|
658 | |
---|
659 | void gb_write_key(GBDATA *gbd,const char *s) { |
---|
660 | GBQUARK new_index = 0; |
---|
661 | |
---|
662 | if (s) { |
---|
663 | GB_MAIN_TYPE *Main = GB_MAIN(gbd); |
---|
664 | new_index = (int)GBS_read_hash(Main->key_2_index_hash,s); |
---|
665 | |
---|
666 | if (!new_index) { /* create new index */ |
---|
667 | new_index = (int)gb_create_key(Main,s,GB_TRUE); |
---|
668 | } |
---|
669 | } |
---|
670 | gb_write_index_key(GB_FATHER(gbd), gbd->index, new_index); |
---|
671 | } |
---|
672 | |
---|
673 | void gb_create_key_array(GB_MAIN_TYPE *Main, int index){ |
---|
674 | if (index >= Main->sizeofkeys) { |
---|
675 | Main->sizeofkeys = index*3/2+1; |
---|
676 | if (Main->keys) { |
---|
677 | int i; |
---|
678 | Main->keys = (struct gb_key_struct *) |
---|
679 | realloc((MALLOC_T)Main->keys, |
---|
680 | sizeof(struct gb_key_struct) * (size_t)Main->sizeofkeys); |
---|
681 | memset( (char *)&(Main->keys[Main->keycnt]), |
---|
682 | 0, |
---|
683 | sizeof(struct gb_key_struct) * (size_t) |
---|
684 | (Main->sizeofkeys - Main->keycnt)); |
---|
685 | for (i= Main->keycnt; i < Main->sizeofkeys; i++){ |
---|
686 | Main->keys[i].compression_mask = -1; |
---|
687 | } |
---|
688 | }else{ |
---|
689 | Main->sizeofkeys = 1000; |
---|
690 | Main->keys = (struct gb_key_struct *) |
---|
691 | GB_calloc(sizeof(struct gb_key_struct) ,(size_t)Main->sizeofkeys); |
---|
692 | } |
---|
693 | } |
---|
694 | } |
---|
695 | |
---|
696 | long gb_create_key(GB_MAIN_TYPE *Main, const char *s, GB_BOOL create_gb_key) { |
---|
697 | long index; |
---|
698 | if ( Main->first_free_key ) { |
---|
699 | index = Main->first_free_key; |
---|
700 | Main->first_free_key = Main->keys[index].next_free_key; |
---|
701 | Main->keys[index].next_free_key = 0; |
---|
702 | }else{ |
---|
703 | index = Main->keycnt++; |
---|
704 | gb_create_key_array(Main,(int)index+1); |
---|
705 | } |
---|
706 | if (!Main->local_mode) { |
---|
707 | long test_index = gbcmc_key_alloc((GBDATA *)Main->data,s); |
---|
708 | if (test_index != index) { |
---|
709 | GBK_terminatef("Database corrupt (allocating quark '%s' in server failed)",s); |
---|
710 | } |
---|
711 | } |
---|
712 | Main->keys[index].nref = 0; |
---|
713 | |
---|
714 | if (s){ |
---|
715 | Main->keys[index].key = strdup(s); |
---|
716 | GBS_write_hash(Main->key_2_index_hash,s,index); |
---|
717 | if (Main->gb_key_data && create_gb_key){ |
---|
718 | gb_load_single_key_data((GBDATA *)Main->data,(GBQUARK)index); |
---|
719 | /* Warning: starts a big recursion */ |
---|
720 | if (!Main->local_mode){ /* send new gb_key to server, needed for searching */ |
---|
721 | GB_update_server((GBDATA *)Main->data); |
---|
722 | } |
---|
723 | } |
---|
724 | } |
---|
725 | |
---|
726 | |
---|
727 | Main->key_clock = Main->clock; |
---|
728 | return index; |
---|
729 | } |
---|
730 | |
---|
731 | void gb_free_all_keys(GB_MAIN_TYPE *Main) { |
---|
732 | long index; |
---|
733 | if (!Main->keys) return; |
---|
734 | for (index = 1; index < Main->keycnt; index++) { |
---|
735 | if (Main->keys[index].key){ |
---|
736 | GBS_write_hash(Main->key_2_index_hash, Main->keys[index].key, 0); |
---|
737 | freeset(Main->keys[index].key, 0); |
---|
738 | } |
---|
739 | Main->keys[index].nref = 0; |
---|
740 | Main->keys[index].next_free_key = 0; |
---|
741 | } |
---|
742 | Main->first_free_key = 0; |
---|
743 | Main->keycnt = 1; |
---|
744 | } |
---|
745 | |
---|
746 | char *gb_abort_entry(GBDATA *gbd){ |
---|
747 | int type = GB_TYPE(gbd); |
---|
748 | GB_ARRAY_FLAGS(gbd).flags = gbd->flags.saved_flags; |
---|
749 | if (type == GB_DB){ |
---|
750 | return 0; |
---|
751 | }else{ |
---|
752 | if (GB_GET_EXT_OLD_DATA(gbd)) { |
---|
753 | if ( (type >= GB_BITS) ) { |
---|
754 | gb_free_cache(GB_MAIN(gbd),gbd); |
---|
755 | GB_FREEDATA(gbd); |
---|
756 | } |
---|
757 | gb_abortdata(gbd); |
---|
758 | } |
---|
759 | } |
---|
760 | return 0; |
---|
761 | } |
---|
762 | |
---|
763 | /******************************************************************************************** |
---|
764 | Transactions |
---|
765 | ********************************************************************************************/ |
---|
766 | |
---|
767 | #if defined(DEVEL_RALF) |
---|
768 | #warning change param for gb_abort_transaction_local_rek to GBDATA ** |
---|
769 | #warning remove param 'mode' (unused!) |
---|
770 | #endif /* DEVEL_RALF */ |
---|
771 | |
---|
772 | int gb_abort_transaction_local_rek(GBDATA *gbd, long mode) { |
---|
773 | /* delete created, undo changed */ |
---|
774 | GBDATA *gb; |
---|
775 | enum gb_key_types type; |
---|
776 | GB_CHANGED change = (GB_CHANGED)GB_ARRAY_FLAGS(gbd).changed; |
---|
777 | |
---|
778 | switch (change) { |
---|
779 | case gb_not_changed: |
---|
780 | return 0; |
---|
781 | |
---|
782 | case gb_created: |
---|
783 | GB_PUT_SECURITY_DELETE(gbd,0); |
---|
784 | gb_delete_entry(&gbd); |
---|
785 | return 1; |
---|
786 | |
---|
787 | case gb_deleted: |
---|
788 | GB_ARRAY_FLAGS(gbd).changed = gb_not_changed; |
---|
789 | // fall-through |
---|
790 | default: |
---|
791 | type = (GB_TYPES)GB_TYPE(gbd); |
---|
792 | if (type == GB_DB) |
---|
793 | { |
---|
794 | int index; |
---|
795 | GBCONTAINER *gbc = (GBCONTAINER *)gbd; |
---|
796 | struct gb_header_list_struct *hls = GB_DATA_LIST_HEADER(gbc->d); |
---|
797 | |
---|
798 | for (index = 0; index < gbc->d.nheader; index++) |
---|
799 | { |
---|
800 | if ((gb = GB_HEADER_LIST_GBD(hls[index]))!=NULL) |
---|
801 | { |
---|
802 | gb_abort_transaction_local_rek(gb,mode); |
---|
803 | } |
---|
804 | } |
---|
805 | } |
---|
806 | gb_abort_entry(gbd); |
---|
807 | } |
---|
808 | return 0; |
---|
809 | } |
---|
810 | |
---|
811 | GB_ERROR gb_commit_transaction_local_rek(GBDATA * gbd, long mode,int *pson_created) |
---|
812 | /* |
---|
813 | * commit created |
---|
814 | * delete deleted |
---|
815 | * mode 0 local = server or begin trans in client or commit_client_in_server |
---|
816 | * mode 1 remote = client |
---|
817 | * mode 2 remote = client send only updated data |
---|
818 | */ |
---|
819 | { |
---|
820 | GBDATA *gb; |
---|
821 | GB_MAIN_TYPE *Main = GB_MAIN(gbd); |
---|
822 | GB_TYPES type; |
---|
823 | GB_ERROR error; |
---|
824 | struct gb_callback *cb; |
---|
825 | GB_CHANGED change = (GB_CHANGED)GB_ARRAY_FLAGS(gbd).changed; |
---|
826 | int send_header; |
---|
827 | int son_created = 0; |
---|
828 | |
---|
829 | type = (GB_TYPES)GB_TYPE(gbd); |
---|
830 | switch (change) { |
---|
831 | case gb_not_changed: |
---|
832 | return 0; |
---|
833 | case gb_deleted: |
---|
834 | GB_PUT_SECURITY_DELETE(gbd, 0); |
---|
835 | if (mode) { |
---|
836 | if (!gbd->flags2.update_in_server) { |
---|
837 | error = gbcmc_sendupdate_delete(gbd); |
---|
838 | if (error) |
---|
839 | return error; |
---|
840 | gbd->flags2.update_in_server = 1; |
---|
841 | } |
---|
842 | if (mode == 2) return 0; |
---|
843 | } else { |
---|
844 | gbcms_add_to_delete_list(gbd); |
---|
845 | _GB_CHECK_IN_UNDO_DELETE(Main,gbd); |
---|
846 | return 0; |
---|
847 | } |
---|
848 | gb_delete_entry(&gbd); |
---|
849 | return 0; |
---|
850 | case gb_created: |
---|
851 | if (mode) { |
---|
852 | if (!gbd->flags2.update_in_server) { |
---|
853 | if (gbd->server_id) goto gb_changed_label; |
---|
854 | /* already created, do only a change */ |
---|
855 | error = gbcmc_sendupdate_create(gbd); |
---|
856 | if (type == GB_DB) { |
---|
857 | gb_set_update_in_server_flags(((GBCONTAINER *)gbd)); |
---|
858 | /* set all childrens update_in_server flags */ |
---|
859 | } |
---|
860 | gbd->flags2.update_in_server = 1; |
---|
861 | if (error) return error; |
---|
862 | } |
---|
863 | if (mode == 2) return 0; |
---|
864 | }else{ |
---|
865 | _GB_CHECK_IN_UNDO_CREATE(Main,gbd); |
---|
866 | } |
---|
867 | if (pson_created) { |
---|
868 | *pson_created = 1; |
---|
869 | } |
---|
870 | |
---|
871 | if (gbd->flags2.header_changed == 1) { |
---|
872 | ((GBCONTAINER*)gbd)->header_update_date = Main->clock; |
---|
873 | } |
---|
874 | goto gb_commit_do_callbacks; |
---|
875 | |
---|
876 | case gb_changed: |
---|
877 | if (mode) { |
---|
878 | if (!gbd->flags2.update_in_server) { |
---|
879 | gb_changed_label:; |
---|
880 | send_header = 0; |
---|
881 | if (gbd->flags2.header_changed) send_header = 1; |
---|
882 | error = gbcmc_sendupdate_update(gbd,send_header); |
---|
883 | if (error) return error; |
---|
884 | gbd->flags2.update_in_server = 1; |
---|
885 | } |
---|
886 | }else{ |
---|
887 | _GB_CHECK_IN_UNDO_MODIFY(Main,gbd); |
---|
888 | } |
---|
889 | default: /* means gb_son_changed + changed */ |
---|
890 | |
---|
891 | if (type == GB_DB) |
---|
892 | { |
---|
893 | GBCONTAINER *gbc = (GBCONTAINER *)gbd; |
---|
894 | int index, start, end; |
---|
895 | struct gb_header_list_struct *hls = GB_DATA_LIST_HEADER(gbc->d); |
---|
896 | |
---|
897 | if (gbc->index_of_touched_one_son>0) { |
---|
898 | start = (int)gbc->index_of_touched_one_son-1; |
---|
899 | end = start+1; |
---|
900 | }else{ if (!gbc->index_of_touched_one_son){ start = end = 0; |
---|
901 | }else{ start = 0; end = gbc->d.nheader; } |
---|
902 | } |
---|
903 | |
---|
904 | for (index = start; index < end; index++) |
---|
905 | { |
---|
906 | if ((gb = GB_HEADER_LIST_GBD(hls[index]))!=NULL) |
---|
907 | { |
---|
908 | if (!hls[index].flags.changed) continue; |
---|
909 | error = gb_commit_transaction_local_rek(gb,mode,&son_created); |
---|
910 | if (error) return error; |
---|
911 | } |
---|
912 | } |
---|
913 | |
---|
914 | if (mode) gbd->flags2.update_in_server = 1; |
---|
915 | } |
---|
916 | gb_commit_do_callbacks: |
---|
917 | if (mode == 2) { /* update server; no callbacks */ |
---|
918 | gbd->flags2.update_in_server = 1; |
---|
919 | }else{ |
---|
920 | GB_CB_TYPE gbtype = GB_CB_CHANGED; |
---|
921 | if (son_created) { |
---|
922 | gbtype = (GB_CB_TYPE)(GB_CB_SON_CREATED | GB_CB_CHANGED); |
---|
923 | } |
---|
924 | GB_CREATE_EXT(gbd); |
---|
925 | gbd->ext->update_date = Main->clock; |
---|
926 | if (gbd->flags2.header_changed ) { |
---|
927 | ((GBCONTAINER*)gbd)->header_update_date = Main->clock; |
---|
928 | } |
---|
929 | |
---|
930 | for (cb = GB_GET_EXT_CALLBACKS(gbd); cb; cb = cb->next) { |
---|
931 | if (cb->type & (GB_CB_CHANGED|GB_CB_SON_CREATED)) { |
---|
932 | gb_add_changed_callback_list(gbd,gbd->ext->old,gbtype,cb->func,cb->clientdata); |
---|
933 | } |
---|
934 | } |
---|
935 | |
---|
936 | GB_FREE_TRANSACTION_SAVE(gbd); |
---|
937 | } |
---|
938 | }/*switch*/ |
---|
939 | return 0; |
---|
940 | } |
---|
941 | |
---|