ARB
adTest.cxx
Go to the documentation of this file.
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 
14 const 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 
27 void 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 
31 static 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;
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) {
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 
187 NOT4PERL 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 
196 NOT4PERL void GB_dump_no_limit(GBDATA *gbd) { // used for debugging
197  dump_internal(gbd, NULp);
198 }
199 
200 // ---------------------
201 // Fix database
202 
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 
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 
250 void 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 }
275 TEST_PUBLISH(TEST_DB_path);
276 
277 #endif // UNIT_TESTS
278 
279 
280 // --------------------------------------------------------------------------------
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2528
static void dump_internal(GBDATA *gbd, int *lines_allowed)
Definition: adTest.cxx:31
const char * GB_ERROR
Definition: arb_core.h:25
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
#define GB_GBM_INDEX(gbd)
Definition: gb_data.h:127
Definition: arbdb.h:65
long GB_read_int(GBDATA *gbd)
Definition: arbdb.cxx:729
GBDATA * GB_child(GBDATA *father)
Definition: adquery.cxx:322
bool GB_is_server(GBDATA *gbd)
Definition: adcomm.cxx:1697
Definition: arbdb.h:69
gb_flag_types2 flags2
Definition: gb_data.h:135
NOT4PERL void GB_dump(GBDATA *gbd)
Definition: adTest.cxx:187
GB_MAIN_TYPE * GB_MAIN(GBDATA *gbd)
Definition: gb_data.h:291
unsigned int folded_container
Definition: gb_data.h:82
long server_id
Definition: gb_data.h:130
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2561
const char * GB_get_type_name(GBDATA *gbd)
Definition: arbdb.cxx:72
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
size_t GBS_shorten_repeated_data(char *data)
Definition: adstring.cxx:357
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
bool GB_have_error()
Definition: arb_msg.cxx:338
GBDATA * GB_HEADER_LIST_GBD(gb_header_list &hl)
Definition: gb_header.h:42
CONSTEXPR_INLINE gb_header_list * GB_DATA_LIST_HEADER(gb_data_list &dl)
Definition: gb_data.h:105
gb_header_flags & GB_ARRAY_FLAGS(GBDATA *gbd)
Definition: gb_header.h:49
char * GBS_string_2_key(const char *str)
Definition: adstring.cxx:52
GBQUARK gb_find_or_create_quark(GB_MAIN_TYPE *Main, const char *key)
Definition: arbdb.cxx:1668
GB_TYPES type() const
Definition: gb_data.h:139
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2494
const char * ARB_float_2_ascii(const float f)
Definition: arb_misc.cxx:66
#define NOT4PERL
Definition: arbdb_base.h:23
POS_TREE1 * father
Definition: probe_tree.h:39
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1517
static GB_ERROR gb_fix_recursive(GBDATA *gbd)
Definition: adTest.cxx:203
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
GB_ERROR gb_unfold(GBCONTAINER *gbc, long deep, int index_pos)
Definition: arbdb.cxx:586
Definition: arbdb.h:67
long GB_read_count(GBDATA *gbd)
Definition: arbdb.cxx:758
Definition: arbdb.h:78
bool is_container() const
Definition: gb_data.h:147
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1325
float GB_read_float(GBDATA *gbd)
Definition: arbdb.cxx:744
#define RETURN_LOCAL_ALLOC(mallocation)
Definition: smartptr.h:310
GBCONTAINER * as_container() const
Definition: gb_data.h:155
CONSTEXPR_INLINE GBCONTAINER * GB_FATHER(GBDATA *gbd)
Definition: gb_data.h:271
GB_ERROR GB_fix_database(GBDATA *gb_main)
Definition: adTest.cxx:237
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2524
Definition: arbdb.h:72
GBQUARK GB_KEY_QUARK(GBDATA *gbd)
Definition: gb_key.h:48
#define GBTUM_MAGIC_NUMBER
Definition: gb_local.h:25
#define gb_assert(cond)
Definition: arbdbt.h:11
Definition: output.h:122
long index
Definition: gb_data.h:133
int GB_read_byte(GBDATA *gbd)
Definition: arbdb.cxx:734
long quark2gbmindex(GB_MAIN_TYPE *Main, GBQUARK key_quark)
Definition: gb_key.h:46
const char * GB_get_db_path(GBDATA *gbd)
Definition: adTest.cxx:14
NOT4PERL void GB_dump_no_limit(GBDATA *gbd)
Definition: adTest.cxx:196
#define NULp
Definition: cxxforward.h:116
gb_data_list d
Definition: gb_data.h:246
void GB_dump_db_path(GBDATA *gbd)
Definition: adTest.cxx:27
GBDATA * GB_nextChild(GBDATA *child)
Definition: adquery.cxx:326
GB_transaction ta(gb_var)
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:904
GBDATA * gb_main
Definition: adname.cxx:32
Definition: arbdb.h:71
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
const char * GB_KEY(GBDATA *gbd)
Definition: gb_key.h:49
int GBQUARK
Definition: arbdb_base.h:30
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
Definition: arbdb.h:66