source: branches/profile/ARBDB/gb_data.h

Last change on this file was 11778, checked in by westram, 10 years ago
File size: 10.8 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : gb_data.h                                         //
4//   Purpose   : GBDATA/GBCONTAINER                                //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef GB_DATA_H
12#define GB_DATA_H
13
14#ifndef GB_LOCAL_H
15#include "gb_local.h"
16#endif
17#ifndef GB_MEMORY_H
18#include "gb_memory.h"
19#endif
20
21struct gb_callback_list;
22
23// --------------------------------------------------------------------------------
24
25#define SIZOFINTERN 10
26
27struct gb_extern_data {
28    GB_REL_STRING rel_data;
29    long          memsize;
30    long          size;
31
32    char *get_data() { return GB_RESOLVE(char*, this, rel_data); }
33    void set_data(char *data) { GB_SETREL(this, rel_data, data); }
34};
35
36struct GB_INTern_strings {
37    char          data[SIZOFINTERN];
38    unsigned char memsize;
39    unsigned char size;
40};
41
42struct GB_INTern {
43    char data[SIZOFINTERN];
44};
45
46union gb_data_base_type_union {
47    int32_t            i;
48    GBDATA            *ptr;
49    GB_INTern_strings  istr;
50    GB_INTern          in;
51    gb_extern_data     ex;
52};
53
54// --------------------------------------------------------------------------------
55
56struct gb_db_extended {
57    long                 creation_date;
58    long                 update_date;
59    gb_callback_list    *callback;
60    gb_transaction_save *old;
61};
62
63// --------------------------------------------------------------------------------
64
65struct gb_flag_types {                                                  // public flags
66    unsigned int type : 4;
67    unsigned int security_delete : 3;
68    unsigned int security_write : 3;
69    unsigned int security_read : 3;
70    unsigned int compressed_data : 1;
71    unsigned int unused : 1;                                            // last bit saved!
72    unsigned int user_flags : 8;
73    unsigned int temporary : 1;                                         // ==1 -> don't save entry
74    unsigned int saved_flags : 8;
75};
76
77struct gb_flag_types2 { // private flags (DB server and each client have their own copy!), abortable
78    // uncritical section, undoable
79    unsigned int last_updated : 8;
80    unsigned int user_bits : 7;                                         // user flags (see GB_USERFLAG_...)
81    // critic section, do not update any below
82    unsigned int folded_container : 1;
83    unsigned int update_in_server : 1;                                  // already informed
84    unsigned int extern_data : 1;                                       // data ref. by pntr
85    unsigned int header_changed : 1;                                    // used by container
86    unsigned int gbm_index : 8;                                         // memory section
87    unsigned int should_be_indexed : 1;                                 // this should be indexed
88    unsigned int is_indexed : 1;                                        // this db. field is indexed
89};
90
91struct gb_flag_types3 {                                                 // user and project flags (public); not abortable !!!
92    unsigned int project : 8;
93    unsigned int unused : 24;
94};
95
96// --------------------------------------------------------------------------------
97
98struct gb_data_list {
99    GB_REL_HLS rel_header;
100    int        headermemsize; // array size (allocated entries)
101    int        size;          // number of valid (non-deleted) items - not valid in transaction mode
102    int        nheader;       // index of next new entry
103};
104
105inline gb_header_list *GB_DATA_LIST_HEADER(gb_data_list& dl) {
106    return GB_RESOLVE(gb_header_list *, (&(dl)), rel_header);
107}
108inline void SET_GB_DATA_LIST_HEADER(gb_data_list& dl, gb_header_list *head) {
109    GB_SETREL(&dl, rel_header, head);
110}
111
112// --------------------------------------------------------------------------------
113
114#if defined(DEBUG)
115#define ASSERT_STRICT_GBDATA_TYPES // just for refactoring/debugging (slow)
116#endif
117
118#if defined(ASSERT_STRICT_GBDATA_TYPES)
119#define gb_strict_assert(cond) gb_assert(cond)
120#else
121#define gb_strict_assert(cond)
122#endif
123
124struct GBENTRY;
125struct GBCONTAINER;
126
127#define GB_GBM_INDEX(gbd) ((gbd)->flags2.gbm_index)
128
129struct GBDATA {
130    long              server_id;
131    GB_REL_CONTAINER  rel_father;
132    gb_db_extended   *ext;
133    long              index;
134    gb_flag_types     flags;
135    gb_flag_types2    flags2;
136
137    // ----------------------------------------
138
139    GB_TYPES type() const {
140        gb_assert(this);
141        return GB_TYPES(flags.type);
142    }
143
144    bool is_a_string() const { return type() == GB_STRING || type() == GB_LINK; }
145    bool is_indexable() const { return is_a_string(); }
146
147    bool is_container() const { return type() == GB_DB; }
148    bool is_entry() const { return !is_container(); }
149
150    GBENTRY *as_entry() const {
151        gb_strict_assert(!this || is_entry());
152        return (GBENTRY*)this;
153    }
154    GBCONTAINER *as_container() const {
155        gb_strict_assert(!this || is_container());
156        return (GBCONTAINER*)this;
157    }
158
159    // meant to be used in client interface (i.e. on any GBDATA* passed from outside)
160    GBENTRY *expect_entry() const {
161        if (!is_entry()) GBK_terminate("expected a DB entry, got a container");
162        return as_entry();
163    }
164    GBCONTAINER *expect_container() const {
165        if (!is_container()) GBK_terminate("expected a DB container, got an entry");
166        return as_container();
167    }
168
169    inline GBCONTAINER *get_father();
170
171    void create_extended() {
172        if (!ext) {
173            ext = (gb_db_extended *)gbm_get_mem(sizeof(gb_db_extended), GB_GBM_INDEX(this));
174        }
175    }
176    void destroy_extended() {
177        if (ext) {
178            gbm_free_mem(ext, sizeof(gb_db_extended), GB_GBM_INDEX(this));
179            ext = NULL;
180        }
181    }
182
183    void touch_creation(long cdate)           { ext->creation_date = cdate; }
184    void touch_update(long udate)             { ext->update_date   = udate; }
185    void touch_creation_and_update(long date) { ext->creation_date = ext->update_date = date; }
186
187    long creation_date() const { return ext ? ext->creation_date : 0; }
188    long update_date()   const { return ext ? ext->update_date   : 0; }
189
190    gb_callback_list *get_callbacks() const { return ext ? ext->callback : NULL; }
191    gb_transaction_save *get_oldData() const { return ext ? ext->old : 0; }
192};
193
194class GBENTRY : public GBDATA {
195    // calls that make no sense:
196    bool is_entry() const;
197    GBENTRY *as_entry() const;
198public:
199    gb_data_base_type_union info;
200
201    int cache_index;
202
203    void mark_as_intern() { flags2.extern_data = 0; }
204    void mark_as_extern() { flags2.extern_data = 1; }
205
206    bool stored_external() const { return flags2.extern_data; }
207    bool stored_internal() const { return !stored_external(); }
208
209    size_t size()    const { return stored_external() ? info.ex.size    : info.istr.size; }
210    size_t memsize() const { return stored_external() ? info.ex.memsize : info.istr.memsize; }
211
212    inline size_t uncompressed_size() const;
213
214    char *data() { return stored_external() ? info.ex.get_data() : &(info.istr.data[0]); }
215
216    inline char *alloc_data(long Size, long Memsize);
217    inline void insert_data(const char *Data, long Size, long Memsize);
218    void free_data() {
219        index_check_out();
220        if (stored_external()) {
221            char *exdata = info.ex.get_data();
222            if (exdata) {
223                gbm_free_mem(exdata, (size_t)(info.ex.memsize), GB_GBM_INDEX(this));
224                info.ex.set_data(0);
225            }
226        }
227    }
228
229    void index_check_in();
230    void index_re_check_in() { if (flags2.should_be_indexed) index_check_in(); }
231
232    void index_check_out();
233};
234
235class GBCONTAINER : public GBDATA {
236    // calls that make no sense:
237    bool is_container() const;
238    GBCONTAINER *as_container() const;
239public:
240    gb_flag_types3 flags3;
241    gb_data_list   d;
242
243    long index_of_touched_one_son;  /* index of modified son
244                                     * in case of a single mod. son
245                                     * -1 more than one (or one with ind = 0)
246                                     *  0    no son
247                                     * >0   index */
248    long header_update_date;
249
250    GB_MAIN_IDX main_idx;
251    GB_REL_IFS  rel_ifs;
252
253    void set_touched_idx(int idx) {
254        if (!index_of_touched_one_son || index_of_touched_one_son == idx+1) {
255            index_of_touched_one_son = idx+1;
256        }
257        else {
258            index_of_touched_one_son = -1;
259        }
260    }
261};
262
263// ----------------------
264//      parent access
265
266inline GBCONTAINER* GB_FATHER(GBDATA *gbd)  { return GB_RESOLVE(GBCONTAINER*, gbd, rel_father); }
267inline GBCONTAINER* GB_GRANDPA(GBDATA *gbd) { return GB_FATHER(GB_FATHER(gbd)); }
268
269inline void SET_GB_FATHER(GBDATA *gbd, GBCONTAINER *father) { GB_SETREL(gbd, rel_father, father); }
270
271GBCONTAINER *GBDATA::get_father() {
272    // like GB_FATHER, but returns NULL for root_container
273    GBCONTAINER *father = GB_FATHER(this);
274    if (father && !GB_FATHER(father)) return NULL;
275    return father;
276}
277
278
279// -----------------------
280//      GB_MAIN access
281
282extern GB_MAIN_TYPE *gb_main_array[];
283
284inline GB_MAIN_TYPE *GBCONTAINER_MAIN(GBCONTAINER *gbc) { return gb_main_array[gbc->main_idx]; }
285
286inline GB_MAIN_TYPE *GB_MAIN(GBDATA *gbd)               { return GBCONTAINER_MAIN(GB_FATHER(gbd)); }
287inline GB_MAIN_TYPE *GB_MAIN(GBCONTAINER *gbc)          { return GBCONTAINER_MAIN(gbc); }
288
289inline GB_MAIN_TYPE *GB_MAIN_NO_FATHER(GBDATA *gbd) {
290    return gbd->is_container() ? GBCONTAINER_MAIN(gbd->as_container()) : GB_MAIN(gbd->as_entry());
291}
292
293// -----------------------
294//      security flags
295
296#define GB_GET_SECURITY_READ(gb)   ((gb)->flags.security_read)
297#define GB_GET_SECURITY_WRITE(gb)  ((gb)->flags.security_write)
298#define GB_GET_SECURITY_DELETE(gb) ((gb)->flags.security_delete)
299
300#define GB_PUT_SECURITY_READ(gb, i)  ((gb)->flags.security_read   = (i))
301#define GB_PUT_SECURITY_WRITE(gb, i) ((gb)->flags.security_write  = (i))
302#define GB_PUT_SECURITY_DELETE(gb, i) ((gb)->flags.security_delete = (i))
303
304// ---------------------------------------------------------
305//      strictly-aliased forwarders for some functions:
306
307inline GB_ERROR gb_commit_transaction_local_rek(GBCONTAINER*& gbc, long mode, int *pson_created) {
308    return gb_commit_transaction_local_rek(StrictlyAliased_BasePtrRef<GBCONTAINER,GBDATA>(gbc).forward(), mode, pson_created);
309}
310
311inline void gb_abort_transaction_local_rek(GBCONTAINER*& gbc) {
312    gb_abort_transaction_local_rek(StrictlyAliased_BasePtrRef<GBCONTAINER,GBDATA>(gbc).forward());
313}
314
315// --------------------------------------------------------------------------------
316
317#ifndef GB_STORAGE_H
318#include "gb_storage.h"
319#endif
320
321#else
322#error gb_data.h included twice
323#endif // GB_DATA_H
324
325
326
Note: See TracBrowser for help on using the repository browser.