source: branches/help/ARBDB/adTest.cxx

Last change on this file was 16763, checked in by westram, 7 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adTest.cxx                                        //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "gb_key.h"
12#include <arb_misc.h>
13
14const char *GB_get_db_path(GBDATA *gbd) {
15    GBDATA *gb_father = GB_FATHER(gbd);
16    if (gb_father) {
17        const char *father_path = GB_get_db_path(gb_father);
18        if (father_path) {
19            const char *key = GB_KEY(gbd);
20            RETURN_LOCAL_ALLOC(GBS_global_string_copy("%s/%s", father_path, key ? key : "<unknown>"));
21        }
22        return ""; // DB-root-node
23    }
24    return NULp; // node above DB-root-node
25}
26
27void GB_dump_db_path(GBDATA *gbd) {
28    printf("Path to GBDATA %p (type=%s) is '%s'\n", gbd, GB_get_type_name(gbd), GB_get_db_path(gbd));
29}
30
31static void dump_internal(GBDATA *gbd, int *lines_allowed) {
32    static int     indent            = 0;
33    const char    *type_name         = GB_get_type_name(gbd);
34    const char    *key_name          = NULp;
35    const char    *content           = NULp;
36    unsigned long  content_len       = 0;
37    GBCONTAINER   *father            = GB_FATHER(gbd);
38    GBDATA        *gb_show_later     = NULp;
39    char          *whatto_show_later = NULp;
40    bool           showChildren      = true;
41
42    if (father) {
43        int             index_pos = (int)gbd->index; // my index position in father
44        gb_header_list *hls       = &(GB_DATA_LIST_HEADER(father->d)[index_pos]);
45
46        if (!hls) {
47            key_name = GBS_global_string("<no gb_header_list found for index_pos=%i>", index_pos);
48            father   = NULp; // otherwise crash below
49        }
50        else {
51            GBDATA *gb_self = GB_HEADER_LIST_GBD(*hls);
52            if (gb_self != gbd) {
53                key_name = GBS_global_string("<element not linked in parent>");
54                if (gb_self) {
55                    gb_show_later     = gb_self;
56                    whatto_show_later = GBS_global_string_copy("Element linked at index pos of %p", gbd);
57                }
58                father = NULp; // otherwise crash below
59            }
60            // otherwise father looks fine
61        }
62    }
63
64    if (father) {
65        bool is_db_server = GB_is_server(gbd);
66
67        if (is_db_server && gbd->server_id != GBTUM_MAGIC_NUMBER) {
68            key_name = GBS_global_string("<element with illegal server-id %p>", (void*)gbd->server_id);
69        }
70        else if (is_db_server && father->server_id != GBTUM_MAGIC_NUMBER) {
71            key_name = GBS_global_string("<elements parent has illegal server-id %p>", (void*)father->server_id);
72            father   = NULp; // avoids crashes below
73        }
74        else {
75            key_name = GB_KEY_QUARK(gbd) ? GB_KEY(gbd) : "<illegal quark=0>";
76        }
77    }
78
79    if (!father && !key_name) {
80        key_name     = "<unknown quark - element w/o father>";
81        showChildren = false;
82    }
83    else {                                          // test if we need a transaction
84        if (GB_MAIN(gbd)->get_transaction_level() == 0) {
85            GB_push_transaction(gbd);
86            dump_internal(gbd, lines_allowed);
87            GB_pop_transaction(gbd);
88            return;
89        }
90    }
91
92    if (indent == 0) {
93        printf("\nGB_dump of '%s':\n", father ? GB_get_db_path(gbd) : "<no DB-path - father missing or not inspected>");
94        if (lines_allowed) (*lines_allowed)--;
95    }
96
97    if (father) {
98        if (GB_ARRAY_FLAGS(gbd).changed == GB_DELETED) {
99            content = "<can't examine - entry is deleted>";
100        }
101        else {
102            switch (gbd->type()) {
103                case GB_INT:    { content = GBS_global_string("%li", GB_read_int(gbd)); break; }
104                case GB_FLOAT:  { content = ARB_float_2_ascii(GB_read_float(gbd)); break; }
105                case GB_BYTE:   { content = GBS_global_string("%i", GB_read_byte(gbd)); break; }
106                case GB_STRING: { content = GB_read_char_pntr(gbd); content_len = GB_read_count(gbd); break; }
107                case GB_BITS:   { break; }
108                case GB_BYTES:  { break; }
109                case GB_INTS:   { break; }
110                case GB_FLOATS: { break; }
111                case GB_DB:     { content = "see below"; break; }
112                default:        { content = ""; break; }
113            }
114        }
115    }
116
117    if (!content) {
118        if (GB_have_error()) {
119            content = GBS_global_string("<failed to read content (error is '%s')>", GB_await_error());
120        }
121        else {
122            content = "<illegal zero content, but no error - severe bug?!>";
123        }
124    }
125    if (content_len == 0) content_len = strlen(content);
126
127    {
128        char     *prefix  = GBS_global_string_copy("%*s %-15s gbd=%p type=%s content=", indent, "", key_name, gbd, type_name);
129        unsigned  wrappos = 500;
130        char     *toFree  = NULp;
131
132        if (content_len > wrappos) {
133            toFree      = ARB_strdup(content);
134            content     = toFree;
135            content_len = GBS_shorten_repeated_data(toFree);
136        }
137
138        if (content_len <= wrappos) {
139            printf("%s'%s'\n", prefix, content);
140            if (lines_allowed) (*lines_allowed)--;
141        }
142        else {
143            char          *buffer  = ARB_alloc<char>(wrappos+1);
144            unsigned long  rest    = content_len;
145            const char    *from    = content;
146            int            cleared = 0;
147
148            buffer[wrappos] = 0;
149            while (rest) {
150                memcpy(buffer, from, wrappos);
151                rest  = rest>wrappos ? rest-wrappos : 0;
152                from += wrappos;
153                printf("%s'%s'\n", prefix, buffer);
154                if (lines_allowed && --(*lines_allowed) <= 0) break;
155                if (!cleared) { memset(prefix, ' ', strlen(prefix)); cleared = 1; }
156            }
157            free(buffer);
158        }
159        free(prefix);
160        free(toFree);
161    }
162
163    if (gbd->is_container() && showChildren) {
164        GBCONTAINER *gbc = gbd->as_container();
165
166        if (gbd->flags2.folded_container) gb_unfold(gbc, -1, -1);
167        for (GBDATA *gbp = GB_child(gbd); gbp; gbp = GB_nextChild(gbp)) {
168            ++indent;
169            dump_internal(gbp, lines_allowed);
170            --indent;
171            if (lines_allowed && (*lines_allowed)<0) break;
172        }
173    }
174
175    if (gb_show_later) {
176        if (!lines_allowed || (*lines_allowed)>0) {
177            printf("%*s Showing %s:\n", indent, "", whatto_show_later);
178            freenull(whatto_show_later);
179            ++indent;
180            dump_internal(gb_show_later, lines_allowed);
181            --indent;
182        }
183    }
184}
185
186NOT4PERL void GB_dump(GBDATA *gbd) { // used for debugging
187    int max_lines = 2500;
188    dump_internal(gbd, &max_lines);
189    if (max_lines <= 0) {
190        printf("Warning: Dump has been aborted (too many lines)\n"
191               "[use GB_dump_no_limit() if you really want to dump all]\n");
192    }
193}
194
195NOT4PERL void GB_dump_no_limit(GBDATA *gbd) { // used for debugging
196    dump_internal(gbd, NULp);
197}
198
199// ---------------------
200//      Fix database
201
202static GB_ERROR gb_fix_recursive(GBDATA *gbd) {
203    if (gbd->is_container()) {
204        for (GBDATA *gbp = GB_child(gbd); gbp; gbp = GB_nextChild(gbp)) {
205            gb_fix_recursive(gbp);
206        }
207    }
208    else {
209        GBQUARK key_quark = GB_KEY_QUARK(gbd);
210        if (key_quark == 0) {
211            GB_MAIN_TYPE *Main         = GB_MAIN(gbd);
212            const char   *new_key_try  = GBS_global_string("illegal_zero_key_%s", GB_get_type_name(gbd));
213            char         *new_key_name = GBS_string_2_key(new_key_try);
214            GBQUARK       keyq         = gb_find_or_create_quark(Main, new_key_name);
215
216            printf("new_key_name='%s'\n", new_key_name);
217
218            gb_assert(keyq != 0);
219            {
220                long gbm_index    = quark2gbmindex(Main, keyq);
221                GB_GBM_INDEX(gbd) = gbm_index;      // set new index
222
223                // @@@ FIXME: above command has no effect
224
225                printf("Fixed zero key_quark of GBDATA at %p\n", gbd);
226                GB_dump_db_path(gbd);
227            }
228
229            free(new_key_name);
230        }
231    }
232
233    return NULp;
234}
235
236GB_ERROR GB_fix_database(GBDATA *gb_main) {
237    GB_ERROR err  = GB_begin_transaction(gb_main);
238    if (!err) err = gb_fix_recursive(gb_main);
239    return GB_end_transaction(gb_main, err);
240}
241
242// --------------------------------------------------------------------------------
243
244#ifdef UNIT_TESTS
245#ifndef TEST_UNIT_H
246#include <test_unit.h>
247#endif
248
249void TEST_DB_path() {
250    GB_shell shell;
251
252#define ACC_PATH "species_data/species/acc"
253
254    for (int ascii = 0; ascii<=1; ++ascii) {
255        TEST_ANNOTATE(GBS_global_string("ascii=%i", ascii));
256
257        GBDATA *gb_main = GB_open(ascii ? "TEST_loadsave_ascii.arb" : "TEST_loadsave.arb", "r");
258        TEST_REJECT_NULL(gb_main);
259
260        {
261            GB_transaction ta(gb_main);
262
263            GBDATA *gb_acc = GB_search(gb_main, ACC_PATH, GB_STRING);
264            TEST_REJECT_NULL(gb_acc);
265
266            // Ascii- and binary-DBs differ in name of root-node.
267            // Make sure reported DB path does not depend on it:
268            TEST_EXPECT_EQUAL(GB_get_db_path(gb_acc), "/" ACC_PATH);
269        }
270
271        GB_close(gb_main);
272    }
273}
274TEST_PUBLISH(TEST_DB_path);
275
276#endif // UNIT_TESTS
277
278
279// --------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.