source: tags/svn.1.5.4/ARBDB/adsystem.cxx

Last change on this file was 8309, checked in by westram, 14 years ago
  • moved much code into static scope

(partly reverted by [8310])

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