root/trunk/ARBDB/adsystem.cxx

Revision 8621, 10.2 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8340] [8341] [8342] [8343] [8344] [8345] [8346] [8347] [8348] [8349] [8350] [8353] [8354] [8362] [8370] [8371] [8372] [8373] [8374] [8375]

  • changed refresh behavior
    • refresh_all_windows
      • call via timer (every 2 sec)
      • replaced by refresh-requests where needed
      • added ED4_trigger_instant_refresh
    • set_refresh -> request_refresh
    • removed duplicated refresh-request in ED4_consensus_definition_changed
    • replaced ED4_refresh_window by ED4_request_full_refresh
      • some callers now request fewer refreshes
      • all callers now cause refresh of ALL windows
    • ED4_cursor::ShowCursor no longer updates global AWARs when used for display only
    • refresh_window does not handle updates (it is only used to quickly draw the cursor)
      • renamed into special_window_refresh() to disencourage usage
    • removed implicit clearing of refresh flags previously done when refresh propagated down through windows, areas and hierarchy. Instead refresh_all_windows explicitely calls clear_refresh when done.
  • cleaned up resize requests
  • removed extra sync in ED4_resize_cb
  • removed special handling of 1st call to ED4_expose_cb (no idea why, but this fixes an ancient bug: "save props in hide-all-gaps mode")
    • no longer abuse ED4_expose_cb
  • trigger relayout
    • when helix/seq spacing is changed
  • ED4_WinContext
    • missing when NDS changed
    • expect one in ED4_root::special_window_refresh
    • provide from ED4_cursor::delete_cursor
  • EDIT4 scrolling
    • scrollbar code refactored
    • SLIDER_OFFSET was missing in calculation of lower/right folding lines (fixed)
    • picture size announced by ED4_window::update_scrolled_rectangle was off by 1
    • fixed scroll/resize bugs introduced in [8618]
  • added debug code
    • print backtrace on negative folding line dimension
    • print mismatch if slider postions and folding line dimensions are out of sync
  • sequence color mapping
    • fixed broken window layout
    • increased number of sets to 8
      • added symbolic ambiguity set as default
    • hide default value '=0'
  • group name generation (index-safety)
  • execute callback-guards and post-useraction-callback whenever an awar change is directly triggered by a widget
  • moved (ARB_)strNULLcmp to global header
  • doc/fix unexpectable behavior (NULL is bigger that any text) with a test
  • dont use magics for system folder
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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
19static GB_CSTR gb_read_dict_data(GBDATA *gb_dict, long *size) {
20    GB_CSTR data = 0;
21    if (gb_dict->flags.compressed_data) {
22        GB_internal_error("Dictionary is compressed");
23        data = GB_read_bytes(gb_dict);
24    }
25    else {
26        data = GB_read_bytes_pntr(gb_dict);
27    }
28    *size = GB_read_bytes_count(gb_dict);
29    return data;
30}
31
32GB_ERROR gb_load_dictionary_data(GBDATA *gb_main, const char *key, char **dict_data, long *size) {
33    /* returns dictionary data (like saved in DB)
34     * in a block allocated by gbm_get_mem(.., GBM_DICT_INDEX)
35     */
36    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
37    GB_ERROR      error = 0;
38
39    *dict_data = 0;
40    *size      = -1;
41    gb_main    = (GBDATA *)Main->data;
42
43    if (key[0] == '@') {
44        error = GB_export_error("No dictionaries for system fields");
45    }
46    else {
47        GBDATA *gb_key_data = Main->gb_key_data;
48        GBDATA *gb_name;
49
50        GB_push_my_security(gb_main);
51        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        GB_pop_my_security(gb_main);
64    }
65    return error;
66}
67
68static GB_DICTIONARY *gb_create_dict(GBDATA *gb_dict) {
69    GB_DICTIONARY *dict = (GB_DICTIONARY *)GB_calloc(sizeof(GB_DICTIONARY), 1);
70    const char    *data;
71    GB_NINT       *idata;
72    long           size;
73
74    data = gb_read_dict_data(gb_dict, &size);
75    GB_write_security_write(gb_dict, 7);
76
77    idata = (GB_NINT *)data;
78    dict->words = ntohl(*idata++);
79    dict->textlen = (int)(size - sizeof(GB_NINT)*(1+dict->words*2));
80
81    dict->offsets = idata;
82    dict->resort =  idata+dict->words;
83    dict->text = (unsigned char*)(idata+2*dict->words);
84
85    return dict;
86}
87
88static void delete_gb_dictionary(GB_DICTIONARY *dict) {
89    free(dict);
90}
91
92static void gb_system_key_changed_cb(GBDATA *gbd, int *cl, GB_CB_TYPE type) {
93    GBQUARK q = (GBQUARK)(long) cl;
94
95    if (type == GB_CB_DELETE) {
96        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
97
98        delete_gb_dictionary(Main->keys[q].dictionary);
99        Main->keys[q].dictionary = 0;
100        Main->keys[q].gb_key     = 0;
101    }
102    else {
103        gb_load_single_key_data(gbd, q);
104    }
105}
106
107static void gb_system_master_changed_cb(GBDATA *gbd, int *cl, GB_CB_TYPE type) {
108    GBQUARK q = (GBQUARK)(long) cl;
109    if (type == GB_CB_DELETE) {
110        GB_MAIN_TYPE *Main = gb_get_main_during_cb();
111        Main->keys[q].gb_master_ali = 0;
112    }
113    else {
114        gb_load_single_key_data(gbd, q);
115    }
116}
117
118void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q) {
119    GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
120    gb_Key       *ks   = &Main->keys[q];
121    const char   *key  = ks->key;
122
123    if (!Main->gb_key_data) {
124        ks->compression_mask = -1;
125        return;
126    }
127
128    gb_main = (GBDATA *)Main->data;
129    if (key[0] == '@') {
130        ks->compression_mask = 0;
131        ks->dictionary       = 0;
132        ks->gb_key_disabled  = 1;
133        ks->gb_master_ali    = 0;
134    }
135    else {
136        GBDATA *gb_key_data = Main->gb_key_data;
137        GBDATA *gb_key, *gb_name, *gb_dict;
138        GB_push_my_security(gb_main);
139        gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
140        if (gb_name) {
141            gb_key = GB_get_father(gb_name);
142        }
143        else {
144            gb_key = gb_create_container(gb_key_data, "@key");
145            gb_name = gb_create(gb_key, "@name", GB_STRING);
146            GB_write_string(gb_name, key);
147        }
148
149        GB_ensure_callback(gb_key, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), gb_system_key_changed_cb, (int *)q);
150
151        if (ks->dictionary) {
152            delete_gb_dictionary(ks->dictionary);
153            ks->dictionary = 0;
154        }
155
156        ks->compression_mask = *GBT_readOrCreate_int(gb_key, "compression_mask", -1);
157        gb_dict              = GB_entry(gb_key, "@dictionary");
158        ks->dictionary       = gb_dict ? gb_create_dict(gb_dict) : 0;
159        ks->gb_key           = gb_key;
160
161        {
162            char buffer[256];
163            memset(buffer, 0, 256);
164            sprintf(buffer, "%s/@master_data/@%s", GB_SYSTEM_FOLDER, key);
165            ks->gb_master_ali = GB_search(gb_main, buffer, GB_FIND);
166            if (ks->gb_master_ali) {
167                GB_remove_callback(ks->gb_master_ali, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), gb_system_master_changed_cb, (int *)q);
168                GB_add_callback   (ks->gb_master_ali, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), gb_system_master_changed_cb, (int *)q);
169            }
170        }
171        GB_pop_my_security(gb_main);
172    }
173}
174
175GB_ERROR gb_save_dictionary_data(GBDATA *gb_main, const char *key, const char *dict, int size) {
176    // if 'dict' is NULL, an existing directory gets deleted
177    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
178    GB_ERROR      error = 0;
179    gb_main             = (GBDATA *)Main->data;
180    if (key[0] == '@') {
181        error = GB_export_error("No dictionaries for system fields");
182    }
183    else {
184        GBDATA *gb_key_data = Main->gb_key_data;
185        GBDATA *gb_key, *gb_name, *gb_dict;
186        GB_push_my_security(gb_main);
187        gb_name = GB_find_string(gb_key_data, "@name", key, GB_MIND_CASE, SEARCH_GRANDCHILD);
188        if (gb_name) {
189            gb_key = GB_get_father(gb_name);
190        }
191        else {
192            gb_key = gb_create_container(gb_key_data, "@key");
193            gb_name = gb_create(gb_key, "@name", GB_STRING);
194            GB_write_string(gb_name, key);
195        }
196        if (dict) {
197            gb_dict = gb_search(gb_key, "@dictionary", GB_BYTES, 1);
198            error   = GB_write_bytes(gb_dict, dict, size);
199        }
200        else {
201            gb_dict = GB_entry(gb_key, "@dictionary");
202            if (gb_dict) {
203                GB_delete(gb_dict); // delete existing dictionary
204            }
205        }
206        GB_pop_my_security(gb_main);
207    }
208    if (!error) {
209        GBQUARK q = gb_find_or_create_quark(Main, key);
210        gb_load_single_key_data(gb_main, q);
211    }
212    return error;
213}
214
215GB_ERROR gb_load_key_data_and_dictionaries(GBDATA *gb_main) { // goes to header: __ATTR__USERESULT
216    GB_MAIN_TYPE *Main  = GB_MAIN(gb_main);
217    GB_ERROR      error = NULL;
218
219    GBDATA *gb_key_data = gb_search(gb_main, GB_SYSTEM_FOLDER "/" GB_SYSTEM_KEY_DATA, GB_CREATE_CONTAINER, 1);
220    if (!gb_key_data) {
221        error = GB_await_error();
222    }
223    else {
224        Main->gb_key_data = gb_key_data;
225        if (Main->local_mode) { // do not create anything at the client side
226            GB_push_my_security(gb_main);
227
228            // search unused keys and delete them
229            for (GBDATA *gb_key = GB_entry(gb_key_data, "@key"); gb_key && !error;) {
230                GBDATA *gb_next_key = GB_nextEntry(gb_key);
231                GBDATA *gb_name     = GB_entry(gb_key, "@name");
232                if (!gb_name) error = GB_await_error();
233                else {
234                    const char *name = GB_read_char_pntr(gb_name);
235                    if (!name) error = GB_await_error();
236                    else {
237                        GBQUARK quark = gb_find_or_create_quark(Main, name);
238                        if (quark<=0 || quark >= Main->sizeofkeys || !Main->keys[quark].key) {
239                            error = GB_delete(gb_key);  // delete unused key
240                        }
241                    }
242                }
243                gb_key = gb_next_key;
244            }
245
246            if (!error) error = GB_create_index(gb_key_data, "@name", GB_MIND_CASE, Main->sizeofkeys*2); // create key index
247            if (!error) {
248                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@name"));
249                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@key"));
250                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "@dictionary"));
251                ASSERT_RESULT_PREDICATE(isAbove<int>(0), gb_find_or_create_quark(Main, "compression_mask"));
252
253                for (int key=1; key<Main->sizeofkeys; key++) {
254                    char *k = Main->keys[key].key;
255                    if (!k) continue;
256                    gb_load_single_key_data(gb_main, key);
257                }
258            }
259            GB_pop_my_security(gb_main);
260        }
261    }
262    RETURN_ERROR(error);
263}
264
265/* gain access to allow repair of broken compression
266 * (see NT_fix_dict_compress)
267 */
268
269struct DictData {
270    char *data;
271    long  size;
272};
273
274static void GB_free_dictionary(DictData *dd) {
275    if (dd) {
276        if (dd->data) gbm_free_mem(dd->data, dd->size, GBM_DICT_INDEX);
277        free(dd);
278    }
279}
280
281DictData *GB_get_dictionary(GBDATA *gb_main, const char *key) {
282    /* return DictData or
283     * NULL if no dictionary or error occurred
284     */
285    DictData *dd    = (DictData*)GB_calloc(1, sizeof(*dd));
286    GB_ERROR  error = gb_load_dictionary_data(gb_main, key, &dd->data, &dd->size);
287
288    if (error || !dd->data) {
289        GB_free_dictionary(dd);
290        dd = NULL;
291        if (error) GB_export_error(error);
292    }
293
294    return dd;
295}
296
297GB_ERROR GB_set_dictionary(GBDATA *gb_main, const char *key, const DictData *dd) {
298    // if 'dd' == NULL -> delete dictionary
299    GB_ERROR error;
300    if (dd) {
301        error = gb_save_dictionary_data(gb_main, key, dd->data, dd->size);
302    }
303    else {
304        error = gb_save_dictionary_data(gb_main, key, NULL, 0);
305    }
306    return error;
307}
Note: See TracBrowser for help on using the browser.