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  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 
186 NOT4PERL 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 
195 NOT4PERL void GB_dump_no_limit(GBDATA *gbd) { // used for debugging
196  dump_internal(gbd, NULp);
197 }
198 
199 // ---------------------
200 // Fix database
201 
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 
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 
249 void 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 }
274 TEST_PUBLISH(TEST_DB_path);
275 
276 #endif // UNIT_TESTS
277 
278 
279 // --------------------------------------------------------------------------------
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2516
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:723
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:186
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:2549
const char * GB_get_type_name(GBDATA *gbd)
Definition: arbdb.cxx:66
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
size_t GBS_shorten_repeated_data(char *data)
Definition: adstring.cxx:358
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
bool GB_have_error()
Definition: arb_msg.cxx:349
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:1666
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:2482
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:1485
static GB_ERROR gb_fix_recursive(GBDATA *gbd)
Definition: adTest.cxx:202
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
GB_ERROR gb_unfold(GBCONTAINER *gbc, long deep, int index_pos)
Definition: arbdb.cxx:580
Definition: arbdb.h:67
long GB_read_count(GBDATA *gbd)
Definition: arbdb.cxx:752
Definition: arbdb.h:78
bool is_container() const
Definition: gb_data.h:147
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1310
float GB_read_float(GBDATA *gbd)
Definition: arbdb.cxx:738
#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:236
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2512
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:728
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:195
#define NULp
Definition: cxxforward.h:97
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:898
GBDATA * gb_main
Definition: adname.cxx:33
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:1283
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:649
Definition: arbdb.h:66