source: tags/ms_r17q3/ARBDB/adsystem.cxx

Last change on this file was 15176, checked in by westram, 8 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 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 = ARB_calloc<GB_DICTIONARY>(1);
71
72    long size;
73    const char *data = gb_read_dict_data(gb_dict, &size);
74    GB_write_security_write(gb_dict, 7);
75
76    GB_NINT *idata = (GB_NINT *)data;
77    dict->words = ntohl(*idata++);
78    dict->textlen = (int)(size - sizeof(GB_NINT)*(1+dict->words*2));
79
80    dict->offsets = idata;
81    dict->resort =  idata+dict->words;
82    dict->text = (unsigned char*)(idata+2*dict->words);
83
84    return dict;
85}
86
87static void delete_gb_dictionary(GB_DICTIONARY *dict) {
88    free(dict);
89}
90
91static void gb_system_key_changed_cb(GBDATA *gbd, GBQUARK q, GB_CB_TYPE type) {
92    if (type == GB_CB_DELETE) {
93        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
94
95        delete_gb_dictionary(Main->keys[q].dictionary);
96        Main->keys[q].dictionary = 0;
97        Main->keys[q].gb_key     = 0;
98    }
99    else {
100        gb_load_single_key_data(gbd, q);
101    }
102}
103
104static void gb_system_master_changed_cb(GBDATA *gbd, GBQUARK q, GB_CB_TYPE type) {
105    if (type == GB_CB_DELETE) {
106        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
107        Main->keys[q].gb_master_ali = 0;
108    }
109    else {
110        gb_load_single_key_data(gbd, q);
111    }
112}
113
114void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q) {
115    GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
116    gb_Key       *ks   = &Main->keys[q];
117    const char   *key  = ks->key;
118
119    if (!Main->gb_key_data) {
120        ks->compression_mask = -1;
121        return;
122    }
123
124    gb_main = Main->gb_main();
125    if (key[0] == '@') {
126        ks->compression_mask = 0;
127        ks->dictionary       = 0;
128        ks->gb_key_disabled  = 1;
129        ks->gb_master_ali    = 0;
130    }
131    else {
132        GBCONTAINER *gb_key_data = Main->gb_key_data;
133        GB_push_my_security(gb_main);
134
135        GBDATA      *gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
136        GBCONTAINER *gb_key;
137        if (gb_name) {
138            gb_key = GB_FATHER(gb_name);
139        }
140        else {
141            gb_key  = gb_create_container(gb_key_data, "@key");
142            gb_name = gb_create(gb_key, "@name", GB_STRING);
143            GB_write_string(gb_name, key);
144        }
145
146        GB_ensure_callback(gb_key, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(gb_system_key_changed_cb, q));
147
148        if (ks->dictionary) {
149            delete_gb_dictionary(ks->dictionary);
150            ks->dictionary = 0;
151        }
152
153        ks->compression_mask = *GBT_readOrCreate_int(gb_key, "compression_mask", -1);
154        GBDATA *gb_dict      = GB_entry(gb_key, "@dictionary");
155        ks->dictionary       = gb_dict ? gb_create_dict(gb_dict) : 0;
156        ks->gb_key           = gb_key;
157
158        {
159            char buffer[256];
160            sprintf(buffer, "%s/@master_data/@%s", GB_SYSTEM_FOLDER, key);
161
162            ks->gb_master_ali = GBDATA::as_container(GB_search(gb_main, buffer, GB_FIND));
163            if (ks->gb_master_ali) {
164                GB_ensure_callback(ks->gb_master_ali, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(gb_system_master_changed_cb, q));
165            }
166        }
167        GB_pop_my_security(gb_main);
168    }
169}
170
171GB_ERROR gb_save_dictionary_data(GBDATA *gb_main, const char *key, const char *dict, int size) {
172    // if 'dict' is NULL, an existing directory gets deleted
173    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
174    GB_ERROR      error = 0;
175    gb_main             = Main->gb_main();
176    if (key[0] == '@') {
177        error = GB_export_error("No dictionaries for system fields");
178    }
179    else {
180        GBCONTAINER *gb_key_data = Main->gb_key_data;
181        GB_push_my_security(gb_main);
182
183        GBDATA      *gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
184        GBCONTAINER *gb_key;
185        if (gb_name) {
186            gb_key = GB_FATHER(gb_name);
187        }
188        else {
189            gb_key = gb_create_container(gb_key_data, "@key");
190            gb_name = gb_create(gb_key, "@name", GB_STRING);
191            GB_write_string(gb_name, key);
192        }
193        GBDATA *gb_dict;
194        if (dict) {
195            gb_dict = gb_search(gb_key, "@dictionary", GB_BYTES, 1);
196            error   = GB_write_bytes(gb_dict, dict, size);
197        }
198        else {
199            gb_dict = GB_entry(gb_key, "@dictionary");
200            if (gb_dict) {
201                GB_delete(gb_dict); // delete existing dictionary
202            }
203        }
204        GB_pop_my_security(gb_main);
205    }
206    if (!error) {
207        GBQUARK q = gb_find_or_create_quark(Main, key);
208        gb_load_single_key_data(gb_main, q);
209    }
210    return error;
211}
212
213GB_ERROR gb_load_key_data_and_dictionaries(GB_MAIN_TYPE *Main) { // goes to header: __ATTR__USERESULT
214    GBCONTAINER *gb_main = Main->root_container;
215    GB_ERROR     error   = NULL;
216
217    GBCONTAINER *gb_key_data = gb_search(gb_main, GB_SYSTEM_FOLDER "/" GB_SYSTEM_KEY_DATA, GB_CREATE_CONTAINER, 1)->as_container();
218    if (!gb_key_data) {
219        error = GB_await_error();
220    }
221    else {
222        Main->gb_key_data = gb_key_data;
223        if (Main->is_server()) { // do not create anything at the client side
224            GB_push_my_security(gb_main);
225
226            // search unused keys and delete them
227            for (GBDATA *gb_key = GB_entry(gb_key_data, "@key"); gb_key && !error;) {
228                GBDATA *gb_next_key = GB_nextEntry(gb_key);
229                GBDATA *gb_name     = GB_entry(gb_key, "@name");
230                if (!gb_name) error = GB_await_error();
231                else {
232                    const char *name = GB_read_char_pntr(gb_name);
233                    if (!name) error = GB_await_error();
234                    else {
235                        if (!name[0]) {
236                            error = GB_delete(gb_key);  // delete invalid empty key
237                        }
238                        else {
239                            GBQUARK quark = gb_find_or_create_quark(Main, name);
240                            if (quark<=0 || quark >= Main->sizeofkeys || !quark2key(Main, quark)) {
241                                error = GB_delete(gb_key);  // delete unused key
242                            }
243                        }
244                    }
245                }
246                gb_key = gb_next_key;
247            }
248
249            if (!error) error = GB_create_index(gb_key_data, "@name", GB_MIND_CASE, Main->sizeofkeys*2); // create key index
250            if (!error) {
251                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@name"));
252                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@key"));
253                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@dictionary"));
254                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "compression_mask"));
255
256                for (int key=1; key<Main->sizeofkeys; key++) {
257                    if (quark2key(Main, key)) {
258                        gb_load_single_key_data(gb_main, key);
259                    }
260                }
261            }
262            GB_pop_my_security(gb_main);
263        }
264    }
265    RETURN_ERROR(error);
266}
267
268/* gain access to allow repair of broken compression
269 * (see NT_fix_dict_compress)
270 */
271
272struct DictData {
273    char *data;
274    long  size;
275};
276
277static void GB_free_dictionary(DictData *dd) {
278    if (dd) {
279        if (dd->data) gbm_free_mem(dd->data, dd->size, GBM_DICT_INDEX);
280        free(dd);
281    }
282}
283
284DictData *GB_get_dictionary(GBDATA *gb_main, const char *key) {
285    /* return DictData or
286     * NULL if no dictionary or error occurred
287     */
288    DictData *dd    = ARB_calloc<DictData>(1);
289    GB_ERROR  error = gb_load_dictionary_data(gb_main, key, &dd->data, &dd->size);
290
291    if (error || !dd->data) {
292        GB_free_dictionary(dd);
293        dd = NULL;
294        if (error) GB_export_error(error);
295    }
296
297    return dd;
298}
299
300GB_ERROR GB_set_dictionary(GBDATA *gb_main, const char *key, const DictData *dd) {
301    // if 'dd' == NULL -> delete dictionary
302    GB_ERROR error;
303    if (dd) {
304        error = gb_save_dictionary_data(gb_main, key, dd->data, dd->size);
305    }
306    else {
307        error = gb_save_dictionary_data(gb_main, key, NULL, 0);
308    }
309    return error;
310}
311
Note: See TracBrowser for help on using the repository browser.