source: branches/port5/ARBDB/adsystem.c

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