source: branches/help/ARBDB/adsystem.cxx

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