source: trunk/ARBDB/adTest.cxx

Last change on this file was 19437, checked in by westram, 17 months ago
  • fix bogus warning
    adTest.cxx:154: warning: '%s' directive argument is null [-Wformat-overflow=]
    adTest.cxx:154: warning: '%s' directive argument is null [-Wformat-overflow=]
    
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 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                if (!prefix || !buffer) { gb_assert(0); break; } // condition should never happen. code is just here to silence a bogus warning
154                printf("%s'%s'\n", prefix, buffer);
155                if (lines_allowed && --(*lines_allowed) <= 0) break;
156                if (!cleared) { memset(prefix, ' ', strlen(prefix)); cleared = 1; }
157            }
158            free(buffer);
159        }
160        free(prefix);
161        free(toFree);
162    }
163
164    if (gbd->is_container() && showChildren) {
165        GBCONTAINER *gbc = gbd->as_container();
166
167        if (gbd->flags2.folded_container) gb_unfold(gbc, -1, -1);
168        for (GBDATA *gbp = GB_child(gbd); gbp; gbp = GB_nextChild(gbp)) {
169            ++indent;
170            dump_internal(gbp, lines_allowed);
171            --indent;
172            if (lines_allowed && (*lines_allowed)<0) break;
173        }
174    }
175
176    if (gb_show_later) {
177        if (!lines_allowed || (*lines_allowed)>0) {
178            printf("%*s Showing %s:\n", indent, "", whatto_show_later);
179            freenull(whatto_show_later);
180            ++indent;
181            dump_internal(gb_show_later, lines_allowed);
182            --indent;
183        }
184    }
185}
186
187NOT4PERL void GB_dump(GBDATA *gbd) { // used for debugging
188    int max_lines = 2500;
189    dump_internal(gbd, &max_lines);
190    if (max_lines <= 0) {
191        printf("Warning: Dump has been aborted (too many lines)\n"
192               "[use GB_dump_no_limit() if you really want to dump all]\n");
193    }
194}
195
196NOT4PERL void GB_dump_no_limit(GBDATA *gbd) { // used for debugging
197    dump_internal(gbd, NULp);
198}
199
200// ---------------------
201//      Fix database
202
203static GB_ERROR gb_fix_recursive(GBDATA *gbd) {
204    if (gbd->is_container()) {
205        for (GBDATA *gbp = GB_child(gbd); gbp; gbp = GB_nextChild(gbp)) {
206            gb_fix_recursive(gbp);
207        }
208    }
209    else {
210        GBQUARK key_quark = GB_KEY_QUARK(gbd);
211        if (key_quark == 0) {
212            GB_MAIN_TYPE *Main         = GB_MAIN(gbd);
213            const char   *new_key_try  = GBS_global_string("illegal_zero_key_%s", GB_get_type_name(gbd));
214            char         *new_key_name = GBS_string_2_key(new_key_try);
215            GBQUARK       keyq         = gb_find_or_create_quark(Main, new_key_name);
216
217            printf("new_key_name='%s'\n", new_key_name);
218
219            gb_assert(keyq != 0);
220            {
221                long gbm_index    = quark2gbmindex(Main, keyq);
222                GB_GBM_INDEX(gbd) = gbm_index;      // set new index
223
224                // @@@ FIXME: above command has no effect
225
226                printf("Fixed zero key_quark of GBDATA at %p\n", gbd);
227                GB_dump_db_path(gbd);
228            }
229
230            free(new_key_name);
231        }
232    }
233
234    return NULp;
235}
236
237GB_ERROR GB_fix_database(GBDATA *gb_main) {
238    GB_ERROR err  = GB_begin_transaction(gb_main);
239    if (!err) err = gb_fix_recursive(gb_main);
240    return GB_end_transaction(gb_main, err);
241}
242
243// --------------------------------------------------------------------------------
244
245#ifdef UNIT_TESTS
246#ifndef TEST_UNIT_H
247#include <test_unit.h>
248#endif
249
250void TEST_DB_path() {
251    GB_shell shell;
252
253#define ACC_PATH "species_data/species/acc"
254
255    for (int ascii = 0; ascii<=1; ++ascii) {
256        TEST_ANNOTATE(GBS_global_string("ascii=%i", ascii));
257
258        GBDATA *gb_main = GB_open(ascii ? "TEST_loadsave_ascii.arb" : "TEST_loadsave.arb", "r");
259        TEST_REJECT_NULL(gb_main);
260
261        {
262            GB_transaction ta(gb_main);
263
264            GBDATA *gb_acc = GB_search(gb_main, ACC_PATH, GB_STRING);
265            TEST_REJECT_NULL(gb_acc);
266
267            // Ascii- and binary-DBs differ in name of root-node.
268            // Make sure reported DB path does not depend on it:
269            TEST_EXPECT_EQUAL(GB_get_db_path(gb_acc), "/" ACC_PATH);
270        }
271
272        GB_close(gb_main);
273    }
274}
275TEST_PUBLISH(TEST_DB_path);
276
277#endif // UNIT_TESTS
278
279
280// --------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.