source: branches/help/ARBDB/gb_data.h

Last change on this file was 16763, checked in by westram, 7 years ago
File size: 11.2 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
105CONSTEXPR_INLINE 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(knownNonNull(this));
141        return GB_TYPES(flags.type);
142    }
143
144    bool is_a_string() const { return type() == GB_STRING; }
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_assert(knownNonNull(this)); // use GBDATA::as_entry() instead
152        gb_strict_assert(is_entry());
153        return (GBENTRY*)this;
154    }
155    GBCONTAINER *as_container() const {
156        gb_assert(knownNonNull(this)); // use GBDATA::as_container() instead
157        gb_strict_assert(is_container());
158        return (GBCONTAINER*)this;
159    }
160
161    static GBCONTAINER *as_container(GBDATA *gbd) { return gbd ? gbd->as_container() : NULp; }
162    static GBENTRY     *as_entry    (GBDATA *gbd) { return gbd ? gbd->as_entry()     : NULp; }
163
164    // meant to be used in client interface (i.e. on any GBDATA* passed from outside)
165    GBENTRY *expect_entry() const {
166        if (!is_entry()) GBK_terminate("expected a DB entry, got a container");
167        return as_entry();
168    }
169    GBCONTAINER *expect_container() const {
170        if (!is_container()) GBK_terminate("expected a DB container, got an entry");
171        return as_container();
172    }
173
174    inline GBCONTAINER *get_father();
175
176    void create_extended() {
177        if (!ext) {
178            ext = (gb_db_extended *)gbm_get_mem(sizeof(gb_db_extended), GB_GBM_INDEX(this));
179        }
180    }
181    void destroy_extended() {
182        if (ext) {
183            gbm_free_mem(ext, sizeof(gb_db_extended), GB_GBM_INDEX(this));
184            ext = NULp;
185        }
186    }
187
188    void touch_creation(long cdate)           { ext->creation_date = cdate; }
189    void touch_update(long udate)             { ext->update_date   = udate; }
190    void touch_creation_and_update(long date) { ext->creation_date = ext->update_date = date; }
191
192    long creation_date() const { return ext ? ext->creation_date : 0; }
193    long update_date()   const { return ext ? ext->update_date   : 0; }
194
195    gb_callback_list *get_callbacks() const { return ext ? ext->callback : NULp; }
196    gb_transaction_save *get_oldData() const { return ext ? ext->old : NULp; }
197};
198
199class GBENTRY : public GBDATA {
200    // calls that make no sense:
201    bool is_entry() const;
202    GBENTRY *as_entry() const;
203public:
204    gb_data_base_type_union info;
205
206    int cache_index;
207
208    void mark_as_intern() { flags2.extern_data = 0; }
209    void mark_as_extern() { flags2.extern_data = 1; }
210
211    bool stored_external() const { return flags2.extern_data; }
212    bool stored_internal() const { return !stored_external(); }
213
214    size_t size()    const { return stored_external() ? info.ex.size    : info.istr.size; }
215    size_t memsize() const { return stored_external() ? info.ex.memsize : info.istr.memsize; }
216
217    inline size_t uncompressed_size() const;
218
219    char *data() { return stored_external() ? info.ex.get_data() : &(info.istr.data[0]); }
220
221    inline char *alloc_data(long Size, long Memsize);
222    inline void insert_data(const char *Data, long Size, long Memsize);
223    void free_data() {
224        index_check_out();
225        if (stored_external()) {
226            char *exdata = info.ex.get_data();
227            if (exdata) {
228                gbm_free_mem(exdata, (size_t)(info.ex.memsize), GB_GBM_INDEX(this));
229                info.ex.set_data(NULp);
230            }
231        }
232    }
233
234    void index_check_in();
235    void index_re_check_in() { if (flags2.should_be_indexed) index_check_in(); }
236
237    void index_check_out();
238};
239
240class GBCONTAINER : public GBDATA {
241    // calls that make no sense:
242    bool is_container() const;
243    GBCONTAINER *as_container() const;
244public:
245    gb_flag_types3 flags3;
246    gb_data_list   d;
247
248    long index_of_touched_one_son;  /* index of modified son
249                                     * in case of a single mod. son
250                                     * -1 more than one (or one with ind = 0)
251                                     *  0    no son
252                                     * >0   index */
253    long header_update_date;
254
255    GB_MAIN_IDX main_idx;
256    GB_REL_IFS  rel_ifs;
257
258    void set_touched_idx(int idx) {
259        if (!index_of_touched_one_son || index_of_touched_one_son == idx+1) {
260            index_of_touched_one_son = idx+1;
261        }
262        else {
263            index_of_touched_one_son = -1;
264        }
265    }
266};
267
268// ----------------------
269//      parent access
270
271CONSTEXPR_INLINE GBCONTAINER* GB_FATHER(GBDATA *gbd)  { return GB_RESOLVE(GBCONTAINER*, gbd, rel_father); }
272CONSTEXPR_INLINE GBCONTAINER* GB_GRANDPA(GBDATA *gbd) { return GB_FATHER(GB_FATHER(gbd)); }
273
274CONSTEXPR_INLINE_Cxx14 void SET_GB_FATHER(GBDATA *gbd, GBCONTAINER *father) { GB_SETREL(gbd, rel_father, father); }
275
276GBCONTAINER *GBDATA::get_father() {
277    // like GB_FATHER, but returns NULp for root_container
278    GBCONTAINER *father = GB_FATHER(this);
279    if (father && !GB_FATHER(father)) return NULp;
280    return father;
281}
282
283
284// -----------------------
285//      GB_MAIN access
286
287extern GB_MAIN_TYPE *gb_main_array[];
288
289inline GB_MAIN_TYPE *GBCONTAINER_MAIN(GBCONTAINER *gbc) { return gb_main_array[gbc->main_idx]; }
290
291inline GB_MAIN_TYPE *GB_MAIN(GBDATA *gbd)               { return GBCONTAINER_MAIN(GB_FATHER(gbd)); }
292inline GB_MAIN_TYPE *GB_MAIN(GBCONTAINER *gbc)          { return GBCONTAINER_MAIN(gbc); }
293
294inline GB_MAIN_TYPE *GB_MAIN_NO_FATHER(GBDATA *gbd) {
295    return gbd->is_container() ? GBCONTAINER_MAIN(gbd->as_container()) : GB_MAIN(gbd->as_entry());
296}
297
298// -----------------------
299//      security flags
300
301#define GB_GET_SECURITY_READ(gb)   ((gb)->flags.security_read)
302#define GB_GET_SECURITY_WRITE(gb)  ((gb)->flags.security_write)
303#define GB_GET_SECURITY_DELETE(gb) ((gb)->flags.security_delete)
304
305#define GB_PUT_SECURITY_READ(gb, i)  ((gb)->flags.security_read   = (i))
306#define GB_PUT_SECURITY_WRITE(gb, i) ((gb)->flags.security_write  = (i))
307#define GB_PUT_SECURITY_DELETE(gb, i) ((gb)->flags.security_delete = (i))
308
309// ---------------------------------------------------------
310//      strictly-aliased forwarders for some functions:
311
312inline __ATTR__USERESULT GB_ERROR gb_commit_transaction_local_rek(GBCONTAINER*& gbc, long mode, int *pson_created) {
313    return gb_commit_transaction_local_rek(StrictlyAliased_BasePtrRef<GBCONTAINER,GBDATA>(gbc).forward(), mode, pson_created);
314}
315
316inline void gb_abort_transaction_local_rek(GBCONTAINER*& gbc) {
317    gb_abort_transaction_local_rek(StrictlyAliased_BasePtrRef<GBCONTAINER,GBDATA>(gbc).forward());
318}
319
320// --------------------------------------------------------------------------------
321
322#ifndef GB_STORAGE_H
323#include "gb_storage.h"
324#endif
325
326#else
327#error gb_data.h included twice
328#endif // GB_DATA_H
329
330
331
Note: See TracBrowser for help on using the repository browser.