source: branches/profile/ARBDB/adsystem.cxx

Last change on this file was 11053, checked in by westram, 10 years ago
  • predefine and use common GB_CB_TYPE combinations
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.1 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adsystem.cxx                                      //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <sys/types.h>
12#include <netinet/in.h>
13
14#include <arbdbt.h>
15#include <ad_cb.h>
16
17#include "gb_key.h"
18#include "gb_dict.h"
19
20static GB_CSTR gb_read_dict_data(GBDATA *gb_dict, long *size) {
21    GB_CSTR data = 0;
22    if (gb_dict->flags.compressed_data) {
23        GB_internal_error("Dictionary is compressed");
24        data = GB_read_bytes(gb_dict);
25    }
26    else {
27        data = GB_read_bytes_pntr(gb_dict);
28    }
29    *size = GB_read_bytes_count(gb_dict);
30    return data;
31}
32
33GB_ERROR gb_load_dictionary_data(GBDATA *gb_main, const char *key, char **dict_data, long *size) {
34    /* returns dictionary data (like saved in DB)
35     * in a block allocated by gbm_get_mem(.., GBM_DICT_INDEX)
36     */
37    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
38    GB_ERROR      error = 0;
39
40    *dict_data = 0;
41    *size      = -1;
42    gb_main    = Main->gb_main();
43
44    if (key[0] == '@') {
45        error = GB_export_error("No dictionaries for system fields");
46    }
47    else {
48        GBDATA *gb_key_data = Main->gb_key_data;
49        GBDATA *gb_name;
50
51        GB_push_my_security(gb_main);
52        gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
53
54        if (gb_name) {
55            GBDATA *gb_key  = GB_get_father(gb_name);
56            GBDATA *gb_dict = GB_entry(gb_key, "@dictionary");
57            if (gb_dict) {
58                const char *data = gb_read_dict_data(gb_dict, size);
59                char       *copy = (char*)gbm_get_mem(*size, GBM_DICT_INDEX);
60                memcpy(copy, data, *size);
61                *dict_data       = copy;
62            }
63        }
64        GB_pop_my_security(gb_main);
65    }
66    return error;
67}
68
69static GB_DICTIONARY *gb_create_dict(GBDATA *gb_dict) {
70    GB_DICTIONARY *dict = (GB_DICTIONARY *)GB_calloc(sizeof(GB_DICTIONARY), 1);
71    const char    *data;
72    GB_NINT       *idata;
73    long           size;
74
75    data = gb_read_dict_data(gb_dict, &size);
76    GB_write_security_write(gb_dict, 7);
77
78    idata = (GB_NINT *)data;
79    dict->words = ntohl(*idata++);
80    dict->textlen = (int)(size - sizeof(GB_NINT)*(1+dict->words*2));
81
82    dict->offsets = idata;
83    dict->resort =  idata+dict->words;
84    dict->text = (unsigned char*)(idata+2*dict->words);
85
86    return dict;
87}
88
89static void delete_gb_dictionary(GB_DICTIONARY *dict) {
90    free(dict);
91}
92
93static void gb_system_key_changed_cb(GBDATA *gbd, GBQUARK q, GB_CB_TYPE type) {
94    if (type == GB_CB_DELETE) {
95        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
96
97        delete_gb_dictionary(Main->keys[q].dictionary);
98        Main->keys[q].dictionary = 0;
99        Main->keys[q].gb_key     = 0;
100    }
101    else {
102        gb_load_single_key_data(gbd, q);
103    }
104}
105
106static void gb_system_master_changed_cb(GBDATA *gbd, GBQUARK q, GB_CB_TYPE type) {
107    if (type == GB_CB_DELETE) {
108        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
109        Main->keys[q].gb_master_ali = 0;
110    }
111    else {
112        gb_load_single_key_data(gbd, q);
113    }
114}
115
116void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q) {
117    GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
118    gb_Key       *ks   = &Main->keys[q];
119    const char   *key  = ks->key;
120
121    if (!Main->gb_key_data) {
122        ks->compression_mask = -1;
123        return;
124    }
125
126    gb_main = Main->gb_main();
127    if (key[0] == '@') {
128        ks->compression_mask = 0;
129        ks->dictionary       = 0;
130        ks->gb_key_disabled  = 1;
131        ks->gb_master_ali    = 0;
132    }
133    else {
134        GBCONTAINER *gb_key_data = Main->gb_key_data;
135        GB_push_my_security(gb_main);
136
137        GBDATA      *gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
138        GBCONTAINER *gb_key;
139        if (gb_name) {
140            gb_key = GB_FATHER(gb_name);
141        }
142        else {
143            gb_key  = gb_create_container(gb_key_data, "@key");
144            gb_name = gb_create(gb_key, "@name", GB_STRING);
145            GB_write_string(gb_name, key);
146        }
147
148        GB_ensure_callback(gb_key, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(gb_system_key_changed_cb, q));
149
150        if (ks->dictionary) {
151            delete_gb_dictionary(ks->dictionary);
152            ks->dictionary = 0;
153        }
154
155        ks->compression_mask = *GBT_readOrCreate_int(gb_key, "compression_mask", -1);
156        GBDATA *gb_dict      = GB_entry(gb_key, "@dictionary");
157        ks->dictionary       = gb_dict ? gb_create_dict(gb_dict) : 0;
158        ks->gb_key           = gb_key;
159
160        {
161            char buffer[256];
162            sprintf(buffer, "%s/@master_data/@%s", GB_SYSTEM_FOLDER, key);
163            ks->gb_master_ali = GB_search(gb_main, buffer, GB_FIND)->as_container();
164            if (ks->gb_master_ali) {
165                GB_ensure_callback(ks->gb_master_ali, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(gb_system_master_changed_cb, q));
166            }
167        }
168        GB_pop_my_security(gb_main);
169    }
170}
171
172GB_ERROR gb_save_dictionary_data(GBDATA *gb_main, const char *key, const char *dict, int size) {
173    // if 'dict' is NULL, an existing directory gets deleted
174    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
175    GB_ERROR      error = 0;
176    gb_main             = Main->gb_main();
177    if (key[0] == '@') {
178        error = GB_export_error("No dictionaries for system fields");
179    }
180    else {
181        GBCONTAINER *gb_key_data = Main->gb_key_data;
182        GB_push_my_security(gb_main);
183
184        GBDATA      *gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
185        GBCONTAINER *gb_key;
186        if (gb_name) {
187            gb_key = GB_FATHER(gb_name);
188        }
189        else {
190            gb_key = gb_create_container(gb_key_data, "@key");
191            gb_name = gb_create(gb_key, "@name", GB_STRING);
192            GB_write_string(gb_name, key);
193        }
194        GBDATA *gb_dict;
195        if (dict) {
196            gb_dict = gb_search(gb_key, "@dictionary", GB_BYTES, 1);
197            error   = GB_write_bytes(gb_dict, dict, size);
198        }
199        else {
200            gb_dict = GB_entry(gb_key, "@dictionary");
201            if (gb_dict) {
202                GB_delete(gb_dict); // delete existing dictionary
203            }
204        }
205        GB_pop_my_security(gb_main);
206    }
207    if (!error) {
208        GBQUARK q = gb_find_or_create_quark(Main, key);
209        gb_load_single_key_data(gb_main, q);
210    }
211    return error;
212}
213
214GB_ERROR gb_load_key_data_and_dictionaries(GB_MAIN_TYPE *Main) { // goes to header: __ATTR__USERESULT
215    GBCONTAINER *gb_main = Main->root_container;
216    GB_ERROR     error   = NULL;
217
218    GBCONTAINER *gb_key_data = gb_search(gb_main, GB_SYSTEM_FOLDER "/" GB_SYSTEM_KEY_DATA, GB_CREATE_CONTAINER, 1)->as_container();
219    if (!gb_key_data) {
220        error = GB_await_error();
221    }
222    else {
223        Main->gb_key_data = gb_key_data;
224        if (Main->is_server()) { // do not create anything at the client side
225            GB_push_my_security(gb_main);
226
227            // search unused keys and delete them
228            for (GBDATA *gb_key = GB_entry(gb_key_data, "@key"); gb_key && !error;) {
229                GBDATA *gb_next_key = GB_nextEntry(gb_key);
230                GBDATA *gb_name     = GB_entry(gb_key, "@name");
231                if (!gb_name) error = GB_await_error();
232                else {
233                    const char *name = GB_read_char_pntr(gb_name);
234                    if (!name) error = GB_await_error();
235                    else {
236                        GBQUARK quark = gb_find_or_create_quark(Main, name);
237                        if (quark<=0 || quark >= Main->sizeofkeys || !Main->keys[quark].key) {
238                            error = GB_delete(gb_key);  // delete unused key
239                        }
240                    }
241                }
242                gb_key = gb_next_key;
243            }
244
245            if (!error) error = GB_create_index(gb_key_data, "@name", GB_MIND_CASE, Main->sizeofkeys*2); // create key index
246            if (!error) {
247                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@name"));
248                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@key"));
249                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@dictionary"));
250                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "compression_mask"));
251
252                for (int key=1; key<Main->sizeofkeys; key++) {
253                    char *k = Main->keys[key].key;
254                    if (!k) continue;
255                    gb_load_single_key_data(gb_main, key);
256                }
257            }
258            GB_pop_my_security(gb_main);
259        }
260    }
261    RETURN_ERROR(error);
262}
263
264/* gain access to allow repair of broken compression
265 * (see NT_fix_dict_compress)
266 */
267
268struct DictData {
269    char *data;
270    long  size;
271};
272
273static void GB_free_dictionary(DictData *dd) {
274    if (dd) {
275        if (dd->data) gbm_free_mem(dd->data, dd->size, GBM_DICT_INDEX);
276        free(dd);
277    }
278}
279
280DictData *GB_get_dictionary(GBDATA *gb_main, const char *key) {
281    /* return DictData or
282     * NULL if no dictionary or error occurred
283     */
284    DictData *dd    = (DictData*)GB_calloc(1, sizeof(*dd));
285    GB_ERROR  error = gb_load_dictionary_data(gb_main, key, &dd->data, &dd->size);
286
287    if (error || !dd->data) {
288        GB_free_dictionary(dd);
289        dd = NULL;
290        if (error) GB_export_error(error);
291    }
292
293    return dd;
294}
295
296GB_ERROR GB_set_dictionary(GBDATA *gb_main, const char *key, const DictData *dd) {
297    // if 'dd' == NULL -> delete dictionary
298    GB_ERROR error;
299    if (dd) {
300        error = gb_save_dictionary_data(gb_main, key, dd->data, dd->size);
301    }
302    else {
303        error = gb_save_dictionary_data(gb_main, key, NULL, 0);
304    }
305    return error;
306}
307
Note: See TracBrowser for help on using the repository browser.