source: tags/arb_5.1/ARBDB/ad_core.c

Last change on this file was 6099, checked in by westram, 15 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_internal_error → GB_internal_error/GB_internal_errorf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
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
11void ad_use(int dummy, ...)  {
12    dummy = 0;
13}
14#endif
15
16/********************************************************************************************
17                    GB data manangement
18********************************************************************************************/
19void 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
58void gb_touch_header(GBCONTAINER *gbc)
59{
60    gbc->flags2.header_changed = 1;
61    gb_touch_entry((GBDATA*)gbc, gb_changed);
62}
63
64
65void
66gb_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
105void 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
114void 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
129void 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
166void 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
213void 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
231void 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
240struct 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
254char *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 */
264GBDATA   *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
284void
285gb_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 */
303GBDATA *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 */
350GBCONTAINER   *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
371GBCONTAINER *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 */
409void 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
444void 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
485void 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 ********************/
518struct 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
542void gb_add_ref_gb_transaction_save(struct gb_transaction_save *ts){
543    if (!ts) return;
544    ts->refcount ++;
545}
546
547void 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 */
565void 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
572void 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
600void 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
622void 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
659void 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
673void 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
696long 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
731void 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
746char *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
772int 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
811GB_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
Note: See TracBrowser for help on using the repository browser.