root/trunk/ARBDB/ad_core.cxx

Revision 8607, 29.8 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8135] [8136] [8137] [8138] [8139] [8140] [8141] [8142] [8143] [8144] [8222]
this revives the reverted patches [8129] [8130] [8131] [8132]

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