ARB
arbdb.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : arbdb.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 "gb_comm.h"
13 #include "gb_compress.h"
14 #include "gb_localdata.h"
15 #include "gb_ta.h"
16 #include "gb_ts.h"
17 #include "gb_index.h"
18 #include "adperl.h"
19 
20 #include <arb_misc.h>
21 
22 #if defined(DARWIN)
23 // including types.h was never necessary under linux.
24 // Under SuSE Leap 15.3 it does fail (file not found).
25 // => made this OSX-only
26 # include <rpc/types.h>
27 # warning "Please remove the above include if it works w/o under OSX"
28 #endif
29 #include <rpc/xdr.h>
30 
31 #include <set>
32 
34 
35 #define INIT_TYPE_NAME(t) GB_TYPES_name[t] = #t
36 
37 static const char *GB_TYPES_2_name(GB_TYPES type) {
38  static const char *GB_TYPES_name[GB_TYPE_MAX];
39  static bool initialized = false;
40 
41  if (!initialized) {
42  memset(GB_TYPES_name, 0, sizeof(GB_TYPES_name));
56 
57  GB_TYPES_name[GB_OBSOLETE] = "GB_LINK (obsolete)";
58 
59  initialized = true;
60  }
61 
62  const char *name = NULp;
63  if (type >= 0 && type<GB_TYPE_MAX) name = GB_TYPES_name[type];
64  if (!name) {
65  static char *unknownType = NULp;
66  freeset(unknownType, GBS_global_string_copy("<invalid-type=%i>", type));
67  name = unknownType;
68  }
69  return name;
70 }
71 
72 const char *GB_get_type_name(GBDATA *gbd) {
73  return GB_TYPES_2_name(gbd->type());
74 }
75 
78  if (GB_MAIN(gbd)->get_transaction_level() == 0) {
79  error = "No transaction running";
80  }
81  else if (GB_ARRAY_FLAGS(gbd).changed == GB_DELETED) {
82  error = "Entry has been deleted";
83  }
84  else {
85  GB_TYPES gb_type = gbd->type();
86  if (gb_type != type && (type != GB_STRING || gb_type != GB_OBSOLETE)) {
87  char *rtype = ARB_strdup(GB_TYPES_2_name(type));
88  char *rgb_type = ARB_strdup(GB_TYPES_2_name(gb_type));
89 
90  error = GBS_global_string("type mismatch (want='%s', got='%s') in '%s'", rtype, rgb_type, GB_get_db_path(gbd));
91 
92  free(rgb_type);
93  free(rtype);
94  }
95  }
96  if (error) {
97  GBK_dump_backtrace(stderr, error); // it's a bug: none of the above errors should ever happen
98  gb_assert(0);
99  }
100  return error;
101 }
102 
104  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
105  const char *error = GBS_global_string("Protection: Attempt to change a level-%i-'%s'-entry,\n"
106  "but your current security level is only %i",
108  GB_read_key_pntr(gbd),
109  Main->security_level);
110 #if defined(DEBUG)
111  fprintf(stderr, "%s\n", error);
112 #endif // DEBUG
113  return error;
114 }
115 
117  GB_ERROR error = gb_transactable_type(type, gbd);
118  if (!error) {
119  if (GB_GET_SECURITY_WRITE(gbd) > GB_MAIN(gbd)->security_level) {
120  error = gb_security_error(gbd);
121  }
122  }
123  return error;
124 }
126  return gb_transactable_type(type, gbd);
127 }
128 
129 inline GB_ERROR error_with_dbentry(const char *action, GBDATA *gbd, GB_ERROR error) {
130  if (error) {
131  char *error_copy = ARB_strdup(error);
132  const char *path = GB_get_db_path(gbd);
133  error = GBS_global_string("Can't %s '%s':\n%s", action, path, error_copy);
134  free(error_copy);
135  }
136  return error;
137 }
138 
139 
140 #define RETURN_ERROR_IF_NOT_WRITEABLE_AS_TYPE(gbd,type) \
141  do { \
142  GB_ERROR error = gb_type_writeable_to(type, gbd); \
143  if (error) { \
144  return error_with_dbentry("write", gbd, error); \
145  } \
146  } while(0)
147 
148 #define EXPORT_ERROR_AND_RETURN_RES_IF_NOT_READABLE_AS_TYPE(gbd,res,type) \
149  do { \
150  GB_ERROR error = gb_type_readable_from(type, gbd); \
151  if (error) { \
152  error = error_with_dbentry("read", gbd, error); \
153  GB_export_error(error); \
154  return res; \
155  } \
156  } while(0) \
157 
158 
159 // @@@ replace GB_TEST_READ_NUM, GB_TEST_READ_PTR and GB_TEST_READ by new names
160 
161 #define GB_TEST_READ_NUM(gbd,type,ignored) EXPORT_ERROR_AND_RETURN_RES_IF_NOT_READABLE_AS_TYPE(gbd,0,type)
162 #define GB_TEST_READ_PTR(gbd,type,ignored) EXPORT_ERROR_AND_RETURN_RES_IF_NOT_READABLE_AS_TYPE(gbd,NULp,type)
163 #define GB_TEST_WRITE(gbd,type,ignored) RETURN_ERROR_IF_NOT_WRITEABLE_AS_TYPE(gbd, type)
164 
165 #define GB_TEST_NON_BUFFER(x, gerror) \
166  do { \
167  if (GB_is_in_buffer(x)) { \
168  GBK_terminatef("%s: you are not allowed to write any data, which you get by pntr", gerror); \
169  } \
170  } while (0)
171 
172 
173 static GB_ERROR GB_safe_atof(const char *str, float *res) {
174  GB_ERROR error = NULp;
175 
176  char *end;
177  *res = strtof(str, &end);
178 
179  if (end == str || end[0] != 0) {
180  if (!str[0]) {
181  *res = 0.0;
182  }
183  else {
184  error = GBS_global_string("cannot convert '%s' to float", str);
185  }
186  }
187  return error;
188 }
189 
190 float GB_atof(const char *str) {
191  // convert ASCII to float
192  float res = 0;
193  GB_ERROR err = GB_safe_atof(str, &res);
194  if (err) {
195  // expected float in 'str'- better use GB_safe_atof()
196  GBK_terminatef("GB_safe_atof(\"%s\", ..) returns error: %s", str, err);
197  }
198  return res;
199 }
200 
201 // ---------------------------
202 // compression tables
203 
205  GB_COMPRESSION_NONE, // GB_NONE 0
206  GB_COMPRESSION_NONE, // GB_BIT 1
207  GB_COMPRESSION_NONE, // GB_BYTE 2
208  GB_COMPRESSION_NONE, // GB_INT 3
209  GB_COMPRESSION_NONE, // GB_FLOAT 4
210  GB_COMPRESSION_NONE, // GB_?? 5
211  GB_COMPRESSION_BITS, // GB_BITS 6
212  GB_COMPRESSION_NONE, // GB_?? 7
216  GB_COMPRESSION_NONE, // GB_LINK 11
218  GB_COMPRESSION_NONE, // GB_STRS 13
219  GB_COMPRESSION_NONE, // GB?? 14
220  GB_COMPRESSION_NONE // GB_DB 15
221 };
222 
223 int gb_convert_type_2_sizeof[] = { /* contains the unit-size of data stored in DB,
224  * i.e. realsize = unit_size * size()
225  */
226  0, // GB_NONE 0
227  0, // GB_BIT 1
228  sizeof(char), // GB_BYTE 2
229  sizeof(int), // GB_INT 3
230  sizeof(float), // GB_FLOAT 4
231  0, // GB_?? 5
232  0, // GB_BITS 6
233  0, // GB_?? 7
234  sizeof(char), // GB_BYTES 8
235  sizeof(int), // GB_INTS 9
236  sizeof(float), // GB_FLTS 10
237  sizeof(char), // GB_LINK 11
238  sizeof(char), // GB_STR 12
239  sizeof(char), // GB_STRS 13
240  0, // GB_?? 14
241  0, // GB_DB 15
242 };
243 
244 int gb_convert_type_2_appendix_size[] = { /* contains the size of the suffix (aka terminator element)
245  * size is in bytes
246  */
247 
248  0, // GB_NONE 0
249  0, // GB_BIT 1
250  0, // GB_BYTE 2
251  0, // GB_INT 3
252  0, // GB_FLOAT 4
253  0, // GB_?? 5
254  0, // GB_BITS 6
255  0, // GB_?? 7
256  0, // GB_BYTES 8
257  0, // GB_INTS 9
258  0, // GB_FLTS 10
259  1, // GB_LINK 11 (zero terminated)
260  1, // GB_STR 12 (zero terminated)
261  1, // GB_STRS 13 (zero terminated)
262  0, // GB_?? 14
263  0, // GB_DB 15
264 };
265 
266 
267 // ---------------------------------
268 // local buffer management
269 
270 static void init_buffer(gb_buffer *buf, size_t initial_size) {
271  buf->size = initial_size;
272  buf->mem = buf->size ? ARB_alloc<char>(buf->size) : NULp;
273 }
274 
275 static char *check_out_buffer(gb_buffer *buf) {
276  char *checkOut = buf->mem;
277 
278  buf->mem = NULp;
279  buf->size = 0;
280 
281  return checkOut;
282 }
283 
284 static void alloc_buffer(gb_buffer *buf, size_t size) {
285  free(buf->mem);
286  buf->size = size;
287 #if (MEMORY_TEST==1)
288  ARB_alloc(buf->mem, buf->size);
289 #else
290  ARB_calloc(buf->mem, buf->size);
291 #endif
292 }
293 
294 static GB_BUFFER give_buffer(gb_buffer *buf, size_t size) {
295 #if (MEMORY_TEST==1)
296  alloc_buffer(buf, size); // do NOT reuse buffer if testing memory
297 #else
298  if (size >= buf->size) {
299  alloc_buffer(buf, size);
300  }
301 #endif
302  return buf->mem;
303 }
304 
305 static int is_in_buffer(gb_buffer *buf, GB_CBUFFER ptr) {
306  return ptr >= buf->mem && ptr < buf->mem+buf->size;
307 }
308 
309 // ------------------------------
310 
311 GB_BUFFER GB_give_buffer(size_t size) {
312  // return a pointer to a static piece of memory at least size bytes long
313  return give_buffer(&gb_local->buf1, size);
314 }
315 
317  if (size < gb_local->buf1.size) {
318  char *old_buffer = gb_local->buf1.mem;
319  size_t old_size = gb_local->buf1.size;
320 
321  gb_local->buf1.mem = NULp;
322  alloc_buffer(&gb_local->buf1, size);
323  memcpy(gb_local->buf1.mem, old_buffer, old_size);
324 
325  free(old_buffer);
326  }
327  return gb_local->buf1.mem;
328 }
329 
331  return gb_local->buf1.size;
332 }
333 
335  return give_buffer(&gb_local->buf2, size);
336 }
337 
338 static int GB_is_in_buffer(GB_CBUFFER ptr) {
339  /* returns 1 or 2 if 'ptr' points to gb_local->buf1/buf2
340  * returns 0 otherwise
341  */
342  int buffer = 0;
343 
344  if (is_in_buffer(&gb_local->buf1, ptr)) buffer = 1;
345  else if (is_in_buffer(&gb_local->buf2, ptr)) buffer = 2;
346 
347  return buffer;
348 }
349 
351  /* Check a piece of memory out of the buffer management
352  * after it is checked out, the user has the full control to use and free it
353  * Returns a pointer to the start of the buffer (even if 'buffer' points inside the buffer!)
354  */
355  char *old = NULp;
356 
357  if (is_in_buffer(&gb_local->buf1, buffer)) old = check_out_buffer(&gb_local->buf1);
358  else if (is_in_buffer(&gb_local->buf2, buffer)) old = check_out_buffer(&gb_local->buf2);
359 
360  return old;
361 }
362 
364  return is_in_buffer(&gb_local->buf1, buffer)
365  ? GB_give_buffer2(size)
366  : GB_give_buffer(size);
367 }
368 
369 static unsigned char GB_BIT_compress_data[] = {
370  0x1d, GB_CS_OK, 0, 0,
371  0x04, GB_CS_OK, 0, 1,
372  0x0a, GB_CS_OK, 0, 2,
373  0x0b, GB_CS_OK, 0, 3,
374  0x0c, GB_CS_OK, 0, 4,
375  0x1a, GB_CS_OK, 0, 5,
376  0x1b, GB_CS_OK, 0, 6,
377  0x1c, GB_CS_OK, 0, 7,
378  0xf0, GB_CS_OK, 0, 8,
379  0xf1, GB_CS_OK, 0, 9,
380  0xf2, GB_CS_OK, 0, 10,
381  0xf3, GB_CS_OK, 0, 11,
382  0xf4, GB_CS_OK, 0, 12,
383  0xf5, GB_CS_OK, 0, 13,
384  0xf6, GB_CS_OK, 0, 14,
385  0xf7, GB_CS_OK, 0, 15,
386  0xf8, GB_CS_SUB, 0, 16,
387  0xf9, GB_CS_SUB, 0, 32,
388  0xfa, GB_CS_SUB, 0, 48,
389  0xfb, GB_CS_SUB, 0, 64,
390  0xfc, GB_CS_SUB, 0, 128,
391  0xfd, GB_CS_SUB, 1, 0,
392  0xfe, GB_CS_SUB, 2, 0,
393  0xff, GB_CS_SUB, 4, 0,
394  0
395 };
396 
397 struct gb_exitfun {
398  void (*exitfun)();
400 };
401 
402 void GB_atexit(void (*exitfun)()) {
403  // called when GB_shell is destroyed (use similar to atexit())
404  //
405  // Since the program does not necessarily terminate, your code calling
406  // GB_atexit() may run multiple times. Make sure everything is completely reset by your 'exitfun'
407 
408  gb_exitfun *fun = new gb_exitfun;
409  fun->exitfun = exitfun;
410 
411  fun->next = gb_local->atgbexit;
412  gb_local->atgbexit = fun;
413 }
414 
416  if (fun) {
417  fun->exitfun();
419  delete fun;
420  }
421 }
422 
423 static void GB_exit_gb() {
425 
426  if (gb_local) {
427  gb_local->~gb_local_data(); // inplace-dtor
428  gbm_free_mem(gb_local, sizeof(*gb_local), 0);
429  gb_local = NULp;
430  gbm_flush_mem();
431  }
432 }
433 
435  gb_assert(openedDBs == closedDBs);
436 
438 
439  free(bitcompress);
441  free(write_buffer);
442 
443  free(check_out_buffer(&buf2));
444  free(check_out_buffer(&buf1));
445  free(open_gb_mains);
446 }
447 
448 // -----------------
449 // GB_shell
450 
451 
453 
455  if (inside_shell) GBK_terminate("only one GB_shell allowed");
456  inside_shell = this;
457 }
459  gb_assert(inside_shell == this);
460  GB_exit_gb();
461  inside_shell = NULp;
462 }
463 void GB_shell::ensure_inside() { if (!inside_shell) GBK_terminate("Not inside GB_shell"); }
464 
465 bool GB_shell::in_shell() { // used by code based on ARBDB (Kai IIRC)
466  return inside_shell;
467 }
468 
470  SmartPtr<GB_shell> one_global_shell;
471 
472 public:
475  if (GB_shell::in_shell()) { // leave that call
476  inside_shell->~GB_shell(); // call dtor
477  }
478  }
479 
481  // allows to workaround using a global GB_shell variable
482  // (see #508 for problem arising when such a variable used)
483  one_global_shell = new GB_shell;
484  }
486  if (one_global_shell.isSet()) {
488  one_global_shell.setNull(); // =destroy
489  }
490  }
491 };
493 
495  shell_manager.open_global_shell();
496 }
498  shell_manager.close_global_shell();
499 }
500 
501 #if defined(UNIT_TESTS)
502 static bool closed_open_shell_for_unit_tests() {
503  bool was_open = inside_shell;
504  if (was_open) {
505  if (gb_local) gb_local->fake_closed_DBs();
506  inside_shell->~GB_shell(); // just call dtor (not delete)
507  }
508  return was_open;
509 }
510 #endif
511 
512 void GB_init_gb() {
514  if (!gb_local) {
515  GBK_install_SIGSEGV_handler(true); // never uninstalled
516  gbm_init_mem();
517  gb_local = (gb_local_data *)gbm_get_mem(sizeof(gb_local_data), 0);
518  ::new(gb_local) gb_local_data(); // inplace-ctor
519  }
520 }
521 
522 int GB_open_DBs() { return gb_local ? gb_local->open_dbs() : 0; }
523 
525  init_buffer(&buf1, 4000);
526  init_buffer(&buf2, 4000);
527 
530 
533 
534  bituncompress = gb_build_uncompress_tree(GB_BIT_compress_data, 1, NULp);
535  bitcompress = gb_build_compress_list(GB_BIT_compress_data, 1, &(bc_size));
536 
537  openedDBs = 0;
538  closedDBs = 0;
539 
540  open_gb_mains = NULp;
541  open_gb_alloc = 0;
542 
543  atgbexit = NULp;
544 
545  iamclient = false;
546  search_system_folder = false;
548 }
549 
551  gb_assert(Main);
552  int idx = open_dbs();
553  if (idx >= open_gb_alloc) {
554  int new_alloc = open_gb_alloc + 10;
555  ARB_recalloc(open_gb_mains, open_gb_alloc, new_alloc);
556  open_gb_alloc = new_alloc;
557  }
558  open_gb_mains[idx] = Main;
559  openedDBs++;
560 }
561 
563  gb_assert(Main);
564  int open = open_dbs();
565  int idx;
566  for (idx = 0; idx<open; ++idx) if (open_gb_mains[idx] == Main) break;
567 
568  gb_assert(idx<open); // passed gb_main is unknown
569  if (idx<open) {
570  if (idx<(open-1)) { // not last
571  open_gb_mains[idx] = open_gb_mains[open-1];
572  }
573  closedDBs++;
574  }
575  if (closedDBs == openedDBs) {
576  GB_exit_gb(); // free most memory allocated by ARBDB library
577  // Caution: calling GB_exit_gb() frees 'this'!
578  }
579 }
580 
582  GB_MAIN_TYPE *Main = gb_local ? gb_local->get_any_open_db() : NULp;
583  return Main ? Main->gb_main() : NULp;
584 }
585 
586 GB_ERROR gb_unfold(GBCONTAINER *gbc, long deep, int index_pos) {
598  GB_ERROR error;
599  gb_header_list *header = GB_DATA_LIST_HEADER(gbc->d);
600 
601  if (!gbc->flags2.folded_container) return NULp;
602  if (index_pos> gbc->d.nheader) gb_create_header_array(gbc, index_pos + 1);
603  if (index_pos >= 0 && GB_HEADER_LIST_GBD(header[index_pos])) return NULp;
604 
605  if (GBCONTAINER_MAIN(gbc)->is_server()) {
606  GB_internal_error("Cannot unfold in server");
607  return NULp;
608  }
609 
610  do {
611  if (index_pos<0) break;
612  if (index_pos >= gbc->d.nheader) break;
613  if (header[index_pos].flags.changed >= GB_DELETED) {
614  GB_internal_error("Tried to unfold a deleted item");
615  return NULp;
616  }
617  if (GB_HEADER_LIST_GBD(header[index_pos])) return NULp; // already unfolded
618  } while (0);
619 
620  error = gbcm_unfold_client(gbc, deep, index_pos);
621  if (error) {
622  GB_print_error();
623  return error;
624  }
625 
626  if (index_pos<0) {
627  gb_untouch_children(gbc);
628  gbc->flags2.folded_container = 0;
629  }
630  else {
631  GBDATA *gb2 = GBCONTAINER_ELEM(gbc, index_pos);
632  if (gb2) {
633  if (gb2->is_container()) {
635  }
636  else {
637  gb_untouch_me(gb2->as_entry());
638  }
639  }
640  }
641  return NULp;
642 }
643 
644 // -----------------------
645 // close database
646 
648  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
649  gb_assert(Main->gb_main() == gb_main);
650  if (Main->close_callbacks) {
651  Main->close_callbacks->call(gb_main, GB_CB_DELETE);
652  }
653 }
654 
655 void GB_close(GBDATA *gbd) {
656  GB_ERROR error = NULp;
657  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
658 
659  gb_assert(Main->get_transaction_level() <= 0); // transaction running - you can't close DB yet!
660 
661  Main->forget_hierarchy_cbs();
662 
663  gb_assert(Main->gb_main() == gbd);
664  run_close_callbacks(gbd);
665  Main->close_callbacks = NULp;
666 
667  bool quick_exit = Main->mapped;
668  if (Main->is_client()) {
670  if (result != GBCM_SERVER_OK) error = GBS_global_string("close failed (with %i:%s)", result, GB_await_error());
671 
672  gb_assert(!quick_exit); // client cannot be mapped
673  }
674 
675  gbcm_logout(Main, NULp); // logout default user
676 
677  if (!error) {
678  gb_assert(!Main->close_callbacks);
679 
680 #if defined(LEAKS_SANITIZED)
681  quick_exit = false;
682 #endif
683 
684  if (quick_exit) {
685  // fake some data to allow quick-exit
686  Main->dummy_father = NULp;
687  Main->cache.entries = NULp;
688  }
689  else {
690  // proper cleanup of DB (causes unwanted behavior described in #649)
692  }
693  Main->root_container = NULp;
694 
695  /* ARBDB applications using awars easily crash in call_pending_callbacks(),
696  * if AWARs are still bound to elements in the closed database.
697  *
698  * To unlink awars call AW_root::unlink_awars_from_DB().
699  * If that doesn't help, test Main->data (often aka as gb_main)
700  */
701  Main->call_pending_callbacks(); // do all callbacks
702  delete Main;
703  }
704 
705  if (error) {
706  GB_warningf("Error in GB_close: %s", error);
707  }
708 }
709 
711  GBDATA *gb_main;
712  while ((gb_main = gb_remembered_db())) {
713  // abort any open transactions
714  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
715  while (Main->get_transaction_level()>0) {
716  GB_ERROR error = Main->abort_transaction();
717  if (error) {
718  fprintf(stderr, "Error in gb_abort_and_close_all_DBs: %s\n", error);
719  }
720  }
721  // and close DB
722  GB_close(gb_main);
723  }
724 }
725 
726 // ------------------
727 // read data
728 
729 long GB_read_int(GBDATA *gbd) {
730  GB_TEST_READ_NUM(gbd, GB_INT, "GB_read_int");
731  return gbd->as_entry()->info.i;
732 }
733 
734 int GB_read_byte(GBDATA *gbd) {
735  GB_TEST_READ_NUM(gbd, GB_BYTE, "GB_read_byte");
736  return gbd->as_entry()->info.i;
737 }
738 
740  GB_TEST_READ_PTR(gbd, GB_POINTER, "GB_read_pointer");
741  return gbd->as_entry()->info.ptr;
742 }
743 
744 float GB_read_float(GBDATA *gbd) {
745  XDR xdrs;
746  float f;
747 
748  GB_TEST_READ_NUM(gbd, GB_FLOAT, "GB_read_float");
749  xdrmem_create(&xdrs, &gbd->as_entry()->info.in.data[0], SIZOFINTERN, XDR_DECODE);
750  xdr_float(&xdrs, &f);
751  xdr_destroy(&xdrs);
752 
753  gb_assert(f == f); // !nan
754 
755  return f;
756 }
757 
758 long GB_read_count(GBDATA *gbd) {
759  return gbd->as_entry()->size();
760 }
761 
762 long GB_read_memuse(GBDATA *gbd) {
763  return gbd->as_entry()->memsize();
764 }
765 
766 #if defined(DEBUG)
767 
768 #define MIN_CBLISTNODE_SIZE 48 // minimum (found) callbacklist-elementsize
769 
770 #if defined(DARWIN)
771 
772 #define CBLISTNODE_SIZE MIN_CBLISTNODE_SIZE // assume known minimum (doesnt really matter; only used in db-browser)
773 
774 #else // linux:
775 
776 typedef std::_List_node<gb_callback_list::cbtype> CBLISTNODE_TYPE;
777 const size_t CBLISTNODE_SIZE = sizeof(CBLISTNODE_TYPE);
778 
779 #if defined(ARB_64)
780 // ignore smaller 32-bit implementations
781 STATIC_ASSERT_ANNOTATED(MIN_CBLISTNODE_SIZE<=CBLISTNODE_SIZE, "MIN_CBLISTNODE_SIZE too big (smaller implementation detected)");
782 #endif
783 
784 #endif
785 
786 inline long calc_size(gb_callback_list *gbcbl) {
787  return gbcbl
788  ? sizeof(*gbcbl) + gbcbl->callbacks.size()* CBLISTNODE_SIZE
789  : 0;
790 }
791 inline long calc_size(gb_transaction_save *gbts) {
792  return gbts
793  ? sizeof(*gbts)
794  : 0;
795 }
796 inline long calc_size(gb_if_entries *gbie) {
797  return gbie
798  ? sizeof(*gbie) + calc_size(GB_IF_ENTRIES_NEXT(gbie))
799  : 0;
800 }
801 inline long calc_size(GB_REL_IFES *gbri, int table_size) {
802  long size = 0;
803 
804  gb_if_entries *ifes;
805  for (int idx = 0; idx<table_size; ++idx) {
806  for (ifes = GB_ENTRIES_ENTRY(gbri, idx);
807  ifes;
808  ifes = GB_IF_ENTRIES_NEXT(ifes))
809  {
810  size += calc_size(ifes);
811  }
812  }
813  return size;
814 }
815 inline long calc_size(gb_index_files *gbif) {
816  return gbif
817  ? sizeof(*gbif) + calc_size(GB_INDEX_FILES_NEXT(gbif)) + calc_size(GB_INDEX_FILES_ENTRIES(gbif), gbif->hash_table_size)
818  : 0;
819 }
820 inline long calc_size(gb_db_extended *gbe) {
821  return gbe
822  ? sizeof(*gbe) + calc_size(gbe->callback) + calc_size(gbe->old)
823  : 0;
824 }
825 inline long calc_size(GBENTRY *gbe) {
826  return gbe
827  ? sizeof(*gbe) + calc_size(gbe->ext)
828  : 0;
829 }
830 inline long calc_size(GBCONTAINER *gbc) {
831  return gbc
832  ? sizeof(*gbc) + calc_size(gbc->ext) + calc_size(GBCONTAINER_IFS(gbc))
833  : 0;
834 }
835 
837  long size = 0;
838  if (gbd->is_container()) {
839  size = calc_size(gbd->as_container());
840  }
841  else {
842  size = calc_size(gbd->as_entry());
843  }
844  return size;
845 }
846 
847 void GB_SizeInfo::collect(GBDATA *gbd) {
848  if (gbd->is_container()) {
849  ++containers;
850  for (GBDATA *gb_child = GB_child(gbd); gb_child; gb_child = GB_nextChild(gb_child)) {
851  collect(gb_child);
852  }
853  }
854  else {
855  ++terminals;
856  mem += GB_read_memuse(gbd);
857 
858  long size;
859  switch (gbd->type()) {
860  case GB_INT: size = sizeof(int); break;
861  case GB_FLOAT: size = sizeof(float); break;
862  case GB_BYTE: size = sizeof(char); break;
863  case GB_POINTER: size = sizeof(GBDATA*); break;
864  case GB_STRING: size = GB_read_count(gbd); break; // accept 0 sized data for strings
865 
866  default:
867  size = GB_read_count(gbd);
868  gb_assert(size>0); // terminal w/o data - really?
869  break;
870  }
871  data += size;
872  }
873  structure += GB_calc_structure_size(gbd);
874 }
875 #endif
876 
878  GBENTRY *gbe = gbd->as_entry();
879  const char *data = gbe->data();
880 
881  if (data) {
882  if (gbe->flags.compressed_data) { // uncompressed data return pntr to database entry
883  char *ca = gb_read_cache(gbe);
884 
885  if (!ca) {
886  size_t size = gbe->uncompressed_size();
887  const char *da = gb_uncompress_data(gbe, data, size);
888 
889  if (da) {
890  ca = gb_alloc_cache_index(gbe, size);
891  memcpy(ca, da, size);
892  }
893  }
894  data = ca;
895  }
896  }
897  return data;
898 }
899 
900 int gb_read_nr(GBDATA *gbd) {
901  return gbd->index;
902 }
903 
905  GB_TEST_READ_PTR(gbd, GB_STRING, "GB_read_char_pntr");
906  return GB_read_pntr(gbd);
907 }
908 
909 char *GB_read_string(GBDATA *gbd) {
910  GB_TEST_READ_PTR(gbd, GB_STRING, "GB_read_string");
911  const char *d = GB_read_pntr(gbd);
912  if (!d) return NULp;
913  return GB_memdup(d, gbd->as_entry()->size()+1);
914 }
915 
917  GB_TEST_READ_NUM(gbd, GB_STRING, "GB_read_string_count");
918  return gbd->as_entry()->size();
919 }
920 
922  GB_TEST_READ_NUM(gbd, GB_BITS, "GB_read_bits_count");
923  return gbd->as_entry()->size();
924 }
925 
926 GB_CSTR GB_read_bits_pntr(GBDATA *gbd, char c_0, char c_1) {
927  GB_TEST_READ_PTR(gbd, GB_BITS, "GB_read_bits_pntr");
928  GBENTRY *gbe = gbd->as_entry();
929  long size = gbe->size();
930  if (size) {
931  // Note: the first 2 bytes of the cached entry contain the currently used encoding (c_0 and c_1)
932 
933  char *ca = gb_read_cache(gbe);
934  if (ca) {
935  // check if encoding was the same during last read
936  if (ca[0] == c_0 && ca[1] == c_1) { // yes -> reuse
937  return ca+2;
938  }
939  // no -> re-read from DB
940  GB_flush_cache(gbe);
941  ca = NULp;
942  }
943 
944  const char *data = gbe->data();
945  char *da = gb_uncompress_bits(data, size, c_0, c_1);
946 
947  if (da) {
948  ca = gb_alloc_cache_index(gbe, size+3); // 2 byte encoding + stored data + terminal '\0'
949  ca[0] = c_0;
950  ca[1] = c_1;
951  memcpy(ca+2, da, size+1);
952  return ca+2;
953  }
954  }
955  return NULp;
956 }
957 
958 char *GB_read_bits(GBDATA *gbd, char c_0, char c_1) {
959  GB_CSTR d = GB_read_bits_pntr(gbd, c_0, c_1);
960  return d ? GB_memdup(d, gbd->as_entry()->size()+1) : NULp;
961 }
962 
963 
965  GB_TEST_READ_PTR(gbd, GB_BYTES, "GB_read_bytes_pntr");
966  return GB_read_pntr(gbd);
967 }
968 
970  GB_TEST_READ_NUM(gbd, GB_BYTES, "GB_read_bytes_count");
971  return gbd->as_entry()->size();
972 }
973 
974 char *GB_read_bytes(GBDATA *gbd) {
975  GB_CSTR d = GB_read_bytes_pntr(gbd);
976  return d ? GB_memdup(d, gbd->as_entry()->size()) : NULp;
977 }
978 
980  GB_TEST_READ_PTR(gbd, GB_INTS, "GB_read_ints_pntr");
981  GBENTRY *gbe = gbd->as_entry();
982 
983  GB_UINT4 *res;
984  if (gbe->flags.compressed_data) {
985  res = (GB_UINT4 *)GB_read_pntr(gbe);
986  }
987  else {
988  res = (GB_UINT4 *)gbe->data();
989  }
990  if (!res) return NULp;
991 
992  if (0x01020304U == htonl(0x01020304U)) {
993  return res;
994  }
995  else {
996  int size = gbe->size();
997  char *buf2 = GB_give_other_buffer((char *)res, size<<2);
998  GB_UINT4 *s = (GB_UINT4 *)res;
999  GB_UINT4 *d = (GB_UINT4 *)buf2;
1000 
1001  for (long i=size; i; i--) {
1002  *(d++) = htonl(*(s++));
1003  }
1004  return (GB_UINT4 *)buf2;
1005  }
1006 }
1007 
1008 long GB_read_ints_count(GBDATA *gbd) { // used by ../PERL_SCRIPTS/SAI/SAI.pm@read_ints_count
1009  GB_TEST_READ_NUM(gbd, GB_INTS, "GB_read_ints_count");
1010  return gbd->as_entry()->size();
1011 }
1012 
1014  GB_CUINT4 *i = GB_read_ints_pntr(gbd);
1015  if (!i) return NULp;
1016  return (GB_UINT4 *)GB_memdup((char *)i, gbd->as_entry()->size()*sizeof(GB_UINT4));
1017 }
1018 
1020  GB_TEST_READ_PTR(gbd, GB_FLOATS, "GB_read_floats_pntr");
1021  GBENTRY *gbe = gbd->as_entry();
1022  char *res;
1023  if (gbe->flags.compressed_data) {
1024  res = (char *)GB_read_pntr(gbe);
1025  }
1026  else {
1027  res = (char *)gbe->data();
1028  }
1029  if (res) {
1030  long size = gbe->size();
1031  long full_size = size*sizeof(float);
1032 
1033  XDR xdrs;
1034  xdrmem_create(&xdrs, res, (int)(full_size), XDR_DECODE);
1035 
1036  char *buf2 = GB_give_other_buffer(res, full_size);
1037  float *d = (float *)(void*)buf2;
1038  for (long i=size; i; i--) {
1039  xdr_float(&xdrs, d);
1040  d++;
1041  }
1042  xdr_destroy(&xdrs);
1043  return (float *)(void*)buf2;
1044  }
1045  return NULp;
1046 }
1047 
1048 static long GB_read_floats_count(GBDATA *gbd) {
1049  GB_TEST_READ_NUM(gbd, GB_FLOATS, "GB_read_floats_count");
1050  return gbd->as_entry()->size();
1051 }
1052 
1053 float *GB_read_floats(GBDATA *gbd) { // @@@ only used in unittest - check usage of floats
1054  GB_CFLOAT *f;
1055  f = GB_read_floats_pntr(gbd);
1056  if (!f) return NULp;
1057  return (float *)GB_memdup((char *)f, gbd->as_entry()->size()*sizeof(float));
1058 }
1059 
1065  switch (gbd->type()) {
1066  case GB_STRING: return GB_read_string(gbd);
1067  case GB_BYTE: return GBS_global_string_copy("%i", GB_read_byte(gbd));
1068  case GB_INT: return GBS_global_string_copy("%li", GB_read_int(gbd));
1069  case GB_FLOAT: return ARB_strdup(ARB_float_2_ascii(GB_read_float(gbd)));
1070  case GB_BITS: return GB_read_bits(gbd, '0', '1');
1071  /* Be careful : When adding new types here, you have to make sure that
1072  * GB_write_autoconv_string is able to write them back and that this makes sense.
1073  */
1074  default:
1076  return NULp;
1077  }
1078 }
1079 
1082  return GB_TYPE_readable_as_string(gbd->type());
1083 }
1084 
1085 
1086 inline GB_ERROR cannot_use_fun4entry(const char *fun, GBDATA *gb_entry) {
1087  return GBS_global_string("Error: Cannot use %s() with a field of type %i (field=%s)",
1088  fun,
1089  GB_read_type(gb_entry),
1090  GB_read_key_pntr(gb_entry));
1091 }
1092 
1099  gb_assert(!error);
1101  uint8_t result;
1102  switch (gbd->type()) {
1103  case GB_BYTE:
1104  result = GB_read_byte(gbd);
1105  break;
1106 
1107  case GB_INT:
1108  result = GB_read_int(gbd);
1109  break;
1110 
1111  case GB_FLOAT:
1112  result = GB_read_float(gbd)+.5;
1113  break;
1114 
1115  case GB_STRING:
1116  result = atoi(GB_read_char_pntr(gbd));
1117  break;
1118 
1119  default:
1120  error = cannot_use_fun4entry("GB_read_lossless_byte", gbd);
1121  result = 0;
1122  break;
1123  }
1124 
1125  if (!error) error = GB_incur_error();
1126  return result;
1127 }
1134  gb_assert(!error);
1136  int32_t result;
1137  switch (gbd->type()) {
1138  case GB_INT:
1139  result = GB_read_int(gbd);
1140  break;
1141 
1142  case GB_STRING:
1143  result = atoi(GB_read_char_pntr(gbd));
1144  break;
1145 
1146  default:
1147  error = cannot_use_fun4entry("GB_read_lossless_int", gbd);
1148  result = 0;
1149  break;
1150  }
1151 
1152  if (!error) error = GB_incur_error();
1153  return result;
1154 }
1161  gb_assert(!error);
1163  float result;
1164  switch (gbd->type()) {
1165  case GB_FLOAT:
1166  result = GB_read_float(gbd);
1167  break;
1168 
1169  case GB_STRING:
1170  result = GB_atof(GB_read_char_pntr(gbd));
1171  break;
1172 
1173  default:
1174  error = cannot_use_fun4entry("GB_read_lossless_float", gbd);
1175  result = 0;
1176  break;
1177  }
1178 
1179  if (!error) error = GB_incur_error();
1180  return result;
1181 }
1182 
1183 // ------------------------------------------------------------
1184 // array type access functions (intended for perl use)
1185 
1186 long GB_read_from_ints(GBDATA *gbd, long index) { // used by ../PERL_SCRIPTS/SAI/SAI.pm@read_from_ints
1187  static GBDATA *last_gbd = NULp;
1188  static long count = 0;
1189  static GB_CUINT4 *i = NULp;
1190 
1191  if (gbd != last_gbd) {
1192  count = GB_read_ints_count(gbd);
1193  i = GB_read_ints_pntr(gbd);
1194  last_gbd = gbd;
1195  }
1196 
1197  if (index >= 0 && index < count) {
1198  return i[index];
1199  }
1200  return -1;
1201 }
1202 
1203 double GB_read_from_floats(GBDATA *gbd, long index) { // @@@ unused
1204  static GBDATA *last_gbd = NULp;
1205  static long count = 0;
1206  static GB_CFLOAT *f = NULp;
1207 
1208  if (gbd != last_gbd) {
1209  count = GB_read_floats_count(gbd);
1210  f = GB_read_floats_pntr(gbd);
1211  last_gbd = gbd;
1212  }
1213 
1214  if (index >= 0 && index < count) {
1215  return f[index];
1216  }
1217  return -1;
1218 }
1219 
1220 // -------------------
1221 // write data
1222 
1223 static void gb_do_callbacks(GBDATA *gbd) {
1224  gb_assert(GB_MAIN(gbd)->get_transaction_level() < 0); // only use in NO_TRANSACTION_MODE!
1225 
1226  while (gbd) {
1227  GBDATA *gbdn = GB_get_father(gbd);
1228  gb_callback_list *cbl = gbd->get_callbacks();
1229  if (cbl && cbl->call(gbd, GB_CB_CHANGED)) {
1231  }
1232  gbd = gbdn;
1233  }
1234 }
1235 
1236 #define GB_DO_CALLBACKS(gbd) do { if (GB_MAIN(gbd)->get_transaction_level() < 0) gb_do_callbacks(gbd); } while (0)
1237 
1239  GB_TEST_WRITE(gbd, GB_BYTE, "GB_write_byte");
1240  GBENTRY *gbe = gbd->as_entry();
1241  if (gbe->info.i != i) {
1243  gbe->info.i = i & 0xff;
1245  GB_DO_CALLBACKS(gbe);
1246  }
1247  return NULp;
1248 }
1249 
1251  // @@@ GB_write_int should be GB_ERROR GB_write_int(GBDATA *gbd,int32_t i)
1252 
1253  GB_TEST_WRITE(gbd, GB_INT, "GB_write_int");
1254  if ((long)((int32_t)i) != i) {
1255  gb_assert(0);
1256  GB_warningf("Warning: 64bit incompatibility detected\nNo data written to '%s'\n", GB_get_db_path(gbd));
1257  return "GB_INT out of range (signed, 32bit)";
1258  }
1259  GBENTRY *gbe = gbd->as_entry();
1260  if (gbe->info.i != (int32_t)i) {
1262  gbe->info.i = i;
1264  GB_DO_CALLBACKS(gbe);
1265  }
1266  return NULp;
1267 }
1268 
1270  GB_TEST_WRITE(gbd, GB_POINTER, "GB_write_pointer");
1271  GBENTRY *gbe = gbd->as_entry();
1272  if (gbe->info.ptr != pointer) {
1274  gbe->info.ptr = pointer;
1276  GB_DO_CALLBACKS(gbe);
1277  }
1278  return NULp;
1279 }
1280 
1282  gb_assert(f == f); // !nan
1283  GB_TEST_WRITE(gbd, GB_FLOAT, "GB_write_float");
1284 
1285  if (GB_read_float(gbd) != f) {
1286  GBENTRY *gbe = gbd->as_entry();
1288 
1289  XDR xdrs;
1290  xdrmem_create(&xdrs, &gbe->info.in.data[0], SIZOFINTERN, XDR_ENCODE);
1291  xdr_float(&xdrs, &f);
1292  xdr_destroy(&xdrs);
1293 
1295  GB_DO_CALLBACKS(gbe);
1296  }
1297  return NULp;
1298 }
1299 
1301  // order of the following commands is important:
1302  // gb_save_extern_data_in_ts may recreate a cache-entry under the following conditions:
1303  // - gbe is indexed AND
1304  // - gbe is stored compressed (and compression really takes place)
1305  //
1306  // Calling these commands in reversed order (as done until [15622])
1307  // had the following effects:
1308  // - writing modified data to an entry had no effect (cache still contained old value)
1309  // - after saving and reloading the database, the modified value was effective
1310  //
1311  // Happened e.g. when copying an SAI (if dictionary compression occurred for SAI/name). See #742.
1312 
1313  gb_save_extern_data_in_ts(gbe); // Warning: might undo effect of gb_uncache if called afterwards
1314  gb_uncache(gbe);
1315 }
1316 
1317 GB_ERROR gb_write_compressed_pntr(GBENTRY *gbe, const char *s, long memsize, long stored_size) {
1319 
1320  gbe->flags.compressed_data = 1;
1321 
1322  gb_assert(!gbe->cache_index); // insert_data() will recreate the cache-entry (if entry is_indexed)
1323  gbe->insert_data((char *)s, stored_size, (size_t)memsize);
1325 
1326  return NULp;
1327 }
1328 
1329 int gb_get_compression_mask(GB_MAIN_TYPE *Main, GBQUARK key, int gb_type) {
1330  gb_Key *ks = &Main->keys[key];
1331  int compression_mask;
1332 
1333  if (ks->gb_key_disabled) {
1334  compression_mask = 0;
1335  }
1336  else {
1337  if (!ks->gb_key) gb_load_single_key_data(Main->gb_main(), key);
1338  compression_mask = gb_convert_type_2_compression_flags[gb_type] & ks->compression_mask;
1339  }
1340 
1341  return compression_mask;
1342 }
1343 
1344 GB_ERROR GB_write_pntr(GBDATA *gbd, const char *s, size_t bytes_size, size_t stored_size) {
1345  // 'bytes_size' is the size of what 's' points to.
1346  // 'stored_size' is the size-information written into the DB
1347  //
1348  // e.g. for strings : stored_size = bytes_size-1, cause stored_size is string len,
1349  // but bytes_size includes zero byte.
1350 
1351  GBENTRY *gbe = gbd->as_entry();
1352  GB_MAIN_TYPE *Main = GB_MAIN(gbe);
1353  GBQUARK key = GB_KEY_QUARK(gbe);
1354  GB_TYPES type = gbe->type();
1355 
1356  gb_assert(implicated(type == GB_STRING, stored_size == bytes_size-1)); // size constraint for strings not fulfilled!
1357 
1359 
1360  int compression_mask = gb_get_compression_mask(Main, key, type);
1361 
1362  const char *d;
1363  size_t memsize;
1364  if (compression_mask) {
1365  d = gb_compress_data(gbe, key, s, bytes_size, &memsize, compression_mask, false);
1366  }
1367  else {
1368  d = NULp;
1369  }
1370  if (d) {
1371  gbe->flags.compressed_data = 1;
1372  }
1373  else {
1374  d = s;
1375  gbe->flags.compressed_data = 0;
1376  memsize = bytes_size;
1377  }
1378 
1379  gb_assert(!gbe->cache_index); // insert_data() will recreate the cache-entry (if entry is_indexed)
1380  gbe->insert_data(d, stored_size, memsize);
1382  GB_DO_CALLBACKS(gbe);
1383 
1384  return NULp;
1385 }
1386 
1387 GB_ERROR GB_write_string(GBDATA *gbd, const char *s) {
1388  GBENTRY *gbe = gbd->as_entry();
1389  GB_TEST_WRITE(gbe, GB_STRING, "GB_write_string");
1390  GB_TEST_NON_BUFFER(s, "GB_write_string"); // compress would destroy the other buffer
1391 
1392  if (!s) s = "";
1393  size_t size = strlen(s);
1394 
1395  // no zero len strings allowed
1396  if (gbe->memsize() && (size == gbe->size())) {
1397  if (!strcmp(s, GB_read_pntr(gbe))) return NULp;
1398  }
1399 #if defined(DEBUG) && 0
1400  // check for error (in compression)
1401  {
1402  GB_ERROR error = GB_write_pntr(gbe, s, size+1, size);
1403  if (!error) {
1404  char *check = GB_read_string(gbe);
1405 
1406  gb_assert(check);
1407  gb_assert(strcmp(check, s) == 0);
1408 
1409  free(check);
1410  }
1411  return error;
1412  }
1413 #else
1414  return GB_write_pntr(gbe, s, size+1, size);
1415 #endif // DEBUG
1416 }
1417 
1418 GB_ERROR GB_write_bits(GBDATA *gbd, const char *bits, long size, const char *c_0) {
1419  GBENTRY *gbe = gbd->as_entry();
1420  GB_TEST_WRITE(gbe, GB_BITS, "GB_write_bits");
1421  GB_TEST_NON_BUFFER(bits, "GB_write_bits"); // compress would destroy the other buffer
1423 
1424  long memsize;
1425  char *d = gb_compress_bits(bits, size, (const unsigned char *)c_0, &memsize);
1426 
1427  gbe->flags.compressed_data = 1;
1428  gbe->insert_data(d, size, memsize);
1430  GB_DO_CALLBACKS(gbe);
1431  return NULp;
1432 }
1433 
1434 GB_ERROR GB_write_bytes(GBDATA *gbd, const char *s, long size) {
1435  GB_TEST_WRITE(gbd, GB_BYTES, "GB_write_bytes");
1436  return GB_write_pntr(gbd, s, size, size);
1437 }
1438 
1439 GB_ERROR GB_write_ints(GBDATA *gbd, const GB_UINT4 *i, long size) {
1440  GB_TEST_WRITE(gbd, GB_INTS, "GB_write_ints");
1441  GB_TEST_NON_BUFFER((char *)i, "GB_write_ints"); // compress would destroy the other buffer
1442 
1443  if (0x01020304 != htonl((GB_UINT4)0x01020304)) {
1444  long j;
1445  char *buf2 = GB_give_other_buffer((char *)i, size<<2);
1446  GB_UINT4 *s = (GB_UINT4 *)i;
1447  GB_UINT4 *d = (GB_UINT4 *)buf2;
1448 
1449  for (j=size; j; j--) {
1450  *(d++) = htonl(*(s++));
1451  }
1452  i = (GB_UINT4 *)buf2;
1453  }
1454  return GB_write_pntr(gbd, (char *)i, size* 4 /* sizeof(long4) */, size);
1455 }
1456 
1457 GB_ERROR GB_write_floats(GBDATA *gbd, const float *f, long size) {
1458  long fullsize = size * sizeof(float);
1459  GB_TEST_WRITE(gbd, GB_FLOATS, "GB_write_floats");
1460  GB_TEST_NON_BUFFER((char *)f, "GB_write_floats"); // compress would destroy the other buffer
1461 
1462  {
1463  XDR xdrs;
1464  long i;
1465  char *buf2 = GB_give_other_buffer((char *)f, fullsize);
1466  float *s = (float *)f;
1467 
1468  xdrmem_create(&xdrs, buf2, (int)fullsize, XDR_ENCODE);
1469  for (i=size; i; i--) {
1470  xdr_float(&xdrs, s);
1471  s++;
1472  }
1473  xdr_destroy (&xdrs);
1474  f = (float*)(void*)buf2;
1475  }
1476  return GB_write_pntr(gbd, (char *)f, size*sizeof(float), size);
1477 }
1478 
1479 GB_ERROR GB_write_autoconv_string(GBDATA *gbd, const char *val) {
1490  switch (gbd->type()) {
1491  case GB_STRING: return GB_write_string(gbd, val);
1492  case GB_BYTE: return GB_write_byte(gbd, atoi(val));
1493  case GB_INT: return GB_write_int(gbd, atoi(val));
1494  case GB_FLOAT: {
1495  float f;
1496  GB_ERROR error = GB_safe_atof(val, &f);
1497  return error ? error : GB_write_float(gbd, f);
1498  }
1499  case GB_BITS: return GB_write_bits(gbd, val, strlen(val), "0");
1500  default: return GBS_global_string("Error: You cannot use GB_write_autoconv_string on this type of entry (%s)", GB_read_key_pntr(gbd));
1501  }
1502 }
1503 
1509  switch (gbd->type()) {
1510  case GB_BYTE: return GB_write_byte(gbd, byte);
1511  case GB_INT: return GB_write_int(gbd, byte);
1512  case GB_FLOAT: return GB_write_float(gbd, byte);
1513  case GB_STRING: {
1514  char buffer[4];
1515  sprintf(buffer, "%u", unsigned(byte));
1516  return GB_write_string(gbd, buffer);
1517  }
1518 
1519  default: return cannot_use_fun4entry("GB_write_lossless_byte", gbd);
1520  }
1521 }
1522 
1529  switch (gbd->type()) {
1530  case GB_INT: return GB_write_int(gbd, i);
1531  case GB_STRING: {
1532  const int BUFSIZE = 30;
1533  char buffer[BUFSIZE];
1534 #if defined(ASSERTION_USED)
1535  int printed =
1536 #endif
1537  sprintf(buffer, "%i", i);
1538  gb_assert(printed<BUFSIZE);
1539  return GB_write_string(gbd, buffer);
1540  }
1541 
1542  default: return cannot_use_fun4entry("GB_write_lossless_int", gbd);
1543  }
1544 }
1545 
1552  switch (gbd->type()) {
1553  case GB_FLOAT: return GB_write_float(gbd, f);
1554  case GB_STRING: {
1555  const int BUFSIZE = 30;
1556  char buffer[BUFSIZE];
1557 #if defined(ASSERTION_USED)
1558  int printed =
1559 #endif
1560  sprintf(buffer, "%e", f);
1561  gb_assert(printed<BUFSIZE);
1562  return GB_write_string(gbd, buffer);
1563  }
1564 
1565  default: return cannot_use_fun4entry("GB_write_lossless_float", gbd);
1566  }
1567 }
1568 
1569 // ---------------------------
1570 // security functions
1571 
1573  GB_test_transaction(gbd);
1574  return GB_GET_SECURITY_WRITE(gbd);
1575 }
1577  GB_test_transaction(gbd);
1578  return GB_GET_SECURITY_READ(gbd);
1579 }
1581  GB_test_transaction(gbd);
1582  return GB_GET_SECURITY_DELETE(gbd);
1583 }
1584 GB_ERROR GB_write_security_write(GBDATA *gbd, unsigned long level) {
1585  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1586  GB_test_transaction(Main);
1587 
1588  if (GB_GET_SECURITY_WRITE(gbd)>Main->security_level) return gb_security_error(gbd);
1589  if (GB_GET_SECURITY_WRITE(gbd) == level) return NULp;
1590  GB_PUT_SECURITY_WRITE(gbd, level);
1592  GB_DO_CALLBACKS(gbd);
1593  return NULp;
1594 }
1595 GB_ERROR GB_write_security_read(GBDATA *gbd, unsigned long level) { // @@@ unused
1596  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1597  GB_test_transaction(Main);
1598  if (GB_GET_SECURITY_WRITE(gbd)>Main->security_level) return gb_security_error(gbd);
1599  if (GB_GET_SECURITY_READ(gbd) == level) return NULp;
1600  GB_PUT_SECURITY_READ(gbd, level);
1602  GB_DO_CALLBACKS(gbd);
1603  return NULp;
1604 }
1605 GB_ERROR GB_write_security_delete(GBDATA *gbd, unsigned long level) {
1606  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1607  GB_test_transaction(Main);
1608  if (GB_GET_SECURITY_WRITE(gbd)>Main->security_level) return gb_security_error(gbd);
1609  if (GB_GET_SECURITY_DELETE(gbd) == level) return NULp;
1610  GB_PUT_SECURITY_DELETE(gbd, level);
1612  GB_DO_CALLBACKS(gbd);
1613  return NULp;
1614 }
1615 GB_ERROR GB_write_security_levels(GBDATA *gbd, unsigned long readlevel, unsigned long writelevel, unsigned long deletelevel) { // @@@ unused
1616  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1617  GB_test_transaction(Main);
1618  if (GB_GET_SECURITY_WRITE(gbd)>Main->security_level) return gb_security_error(gbd);
1619  GB_PUT_SECURITY_WRITE(gbd, writelevel);
1620  GB_PUT_SECURITY_READ(gbd, readlevel);
1621  GB_PUT_SECURITY_DELETE(gbd, deletelevel);
1623  GB_DO_CALLBACKS(gbd);
1624  return NULp;
1625 }
1626 
1627 void GB_change_my_security(GBDATA *gbd, int level) {
1628  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1629  Main->security_level = level<0 ? 0 : (level>7 ? 7 : level);
1630 }
1631 
1632 int GB_securityLevel::whats_my_security() const {
1633  GB_MAIN_TYPE *Main = GB_MAIN(gbdata);
1634  return Main->security_level;
1635 }
1636 void GB_securityLevel::change_my_security(int level) {
1637  GB_change_my_security(gbdata, level);
1638 }
1639 
1640 // ------------------------
1641 // Key information
1642 
1644  GB_test_transaction(gbd);
1645  return gbd->type();
1646 }
1647 
1649  return gbd && gbd->is_container();
1650 }
1651 
1652 char *GB_read_key(GBDATA *gbd) {
1653  return ARB_strdup(GB_read_key_pntr(gbd));
1654 }
1655 
1657  GB_CSTR k;
1658  GB_test_transaction(gbd);
1659  k = GB_KEY(gbd);
1660  if (!k) k = GBS_global_string("<invalid key (quark=%i)>", GB_KEY_QUARK(gbd));
1661  return k;
1662 }
1663 
1665  return GB_KEY(gbd);
1666 }
1667 
1670  GBQUARK quark = key2quark(Main, key);
1671  if (!quark) {
1672  if (!key[0]) GBK_terminate("Attempt to create quark from empty key");
1673  quark = gb_create_key(Main, key, true);
1674  }
1675  return quark;
1676 }
1677 
1679  // similar to gb_find_or_create_quark,
1680  // but if 'key' is NULp, quark 0 will be returned.
1681  //
1682  // Use this function with care.
1683  //
1684  // Known good use:
1685  // - create main entry and its dummy father via gb_make_container()
1686 
1687  return key ? gb_find_or_create_quark(Main, key) : 0;
1688 }
1689 
1690 GBQUARK GB_find_existing_quark(GBDATA *gbd, const char *key) {
1692  return key2quark(GB_MAIN(gbd), key);
1693 }
1694 
1695 GBQUARK GB_find_or_create_quark(GBDATA *gbd, const char *key) {
1697  return gb_find_or_create_quark(GB_MAIN(gbd), key);
1698 }
1699 
1700 
1701 // ---------------------------------------------
1702 
1704  return GB_KEY_QUARK(gbd);
1705 }
1706 
1707 bool GB_has_key(GBDATA *gbd, const char *key) {
1708  GBQUARK quark = GB_find_existing_quark(gbd, key);
1709  return quark && (quark == GB_get_quark(gbd));
1710 }
1711 
1712 // ---------------------------------------------
1713 
1714 long GB_read_clock(GBDATA *gbd) {
1715  if (GB_ARRAY_FLAGS(gbd).changed) return GB_MAIN(gbd)->clock;
1716  return gbd->update_date();
1717 }
1718 
1719 // ---------------------------------------------
1720 // Get and check the database hierarchy
1721 
1723  // Get the father of an entry
1724  GB_test_transaction(gbd);
1725  return gbd->get_father();
1726 }
1727 
1729  GB_test_transaction(gbd);
1730 
1731  GBDATA *gb_grandpa = GB_FATHER(gbd);
1732  if (gb_grandpa) {
1733  gb_grandpa = GB_FATHER(gb_grandpa);
1734  if (gb_grandpa && !GB_FATHER(gb_grandpa)) gb_grandpa = NULp; // never return dummy_father of root container
1735  }
1736  return gb_grandpa;
1737 }
1738 
1739 // Get the root entry (gb_main)
1740 GBDATA *GB_get_root(GBDATA *gbd) { return GB_MAIN(gbd)->gb_main(); }
1743 
1744 bool GB_is_ancestor_of(GBDATA *gb_ancestor, GBDATA *gb_descendant) {
1745  // Test whether 'gb_descendant' is a subentry of 'gb_ancestor'.
1746  // Note: returns false if gb_descendant == gb_ancestor!
1747 
1748  GB_test_transaction(gb_descendant);
1749  if (gb_ancestor->is_container()) { // otherwise it contains nothing!
1750  for (GBDATA *gb_up = gb_descendant->get_father();
1751  gb_up;
1752  gb_up = gb_up->get_father())
1753  {
1754  if (gb_up == gb_ancestor) return true;
1755  }
1756  }
1757  return false;
1758 }
1759 
1760 // --------------------------
1761 // create and rename
1762 
1764  GBENTRY *gbe = gb_make_entry(father, key, -1, 0, type);
1765  gb_touch_header(GB_FATHER(gbe));
1766  gb_touch_entry(gbe, GB_CREATED);
1767 
1768  gb_assert(GB_ARRAY_FLAGS(gbe).changed < GB_DELETED); // happens sometimes -> needs debugging
1769 
1770  return gbe;
1771 }
1772 
1774  // Create a container, do not check anything
1775  GBCONTAINER *gbc = gb_make_container(father, key, -1, 0);
1776  gb_touch_header(GB_FATHER(gbc));
1777  gb_touch_entry(gbc, GB_CREATED);
1778  return gbc;
1779 }
1780 
1781 GBDATA *GB_create(GBDATA *father, const char *key, GB_TYPES type) {
1795  gb_assert(!GB_have_error()); // illegal to enter this function when an error is exported!
1796 
1797  if (GB_ERROR keyerr = GB_check_key(key)) {
1798  GB_export_error(keyerr);
1799  return NULp;
1800  }
1801 
1802  if (type == GB_DB) {
1803  gb_assert(type != GB_DB); // you like to use GB_create_container!
1804  GB_export_error("GB_create: can't create containers");
1805  return NULp;
1806  }
1807 
1808  if (!father) {
1809  GB_internal_errorf("GB_create error in GB_create:\nno father (key = '%s')", key);
1810  return NULp;
1811  }
1812  GB_test_transaction(father);
1813  if (father->is_entry()) {
1814  GB_export_errorf("while creating '%s': father (%s) is not of GB_DB type (%i)",
1815  key, GB_read_key_pntr(father), father->type());
1816  return NULp;
1817  }
1818 
1819  if (type == GB_POINTER) {
1820  if (!GB_in_temporary_branch(father)) {
1821  GB_export_error("GB_create: pointers only allowed in temporary branches");
1822  return NULp;
1823  }
1824  }
1825 
1826  return gb_create(father->expect_container(), key, type);
1827 }
1828 
1842  gb_assert(!GB_have_error()); // illegal to enter this function when an error is exported!
1843 
1844  if (GB_ERROR keyerr = GB_check_key(key)) {
1845  GB_export_error(keyerr);
1846  return NULp;
1847  }
1848 
1849  if ((*key == '\0')) {
1850  GB_export_error("GB_create error: empty key");
1851  return NULp;
1852  }
1853  if (!father) {
1854  GB_internal_errorf("GB_create error in GB_create:\nno father (key = '%s')", key);
1855  return NULp;
1856  }
1857 
1858  GB_test_transaction(father);
1859  return gb_create_container(father->expect_container(), key);
1860 }
1861 
1862 // ----------------------
1863 // recompression
1864 
1865 
1867  // @@@ rename gb_set_compression into gb_recompress (misleading name)
1868 
1869  GB_ERROR error = NULp;
1870  GB_test_transaction(source);
1871 
1872  switch (source->type()) {
1873  case GB_STRING: {
1874  char *str = GB_read_string(source);
1875  GB_write_string(source, "");
1876  GB_write_string(source, str);
1877  free(str);
1878  break;
1879  }
1880  case GB_BITS:
1881  case GB_BYTES:
1882  case GB_INTS:
1883  case GB_FLOATS:
1884  break;
1885  case GB_DB:
1886  for (GBDATA *gb_child = GB_child(source); gb_child && !error; gb_child = GB_nextChild(gb_child)) {
1887  error = gb_set_compression(gb_child);
1888  }
1889  break;
1890  default:
1891  break;
1892  }
1893  return error;
1894 }
1895 
1896 bool GB_allow_compression(GBDATA *gb_main, bool allow_compression) {
1897  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
1898  int prev_mask = Main->compression_mask;
1899  Main->compression_mask = allow_compression ? -1 : 0;
1900 
1901  return prev_mask == 0 ? false : true;
1902 }
1903 
1905  GB_test_transaction(gb_obj);
1906  int sec_obj = GB_GET_SECURITY_DELETE(gb_obj);
1907  int sec_main = GB_MAIN(gb_obj)->security_level;
1908  if (sec_obj > sec_main) {
1909  return GBS_global_string("Security error: deleting entry '%s' not permitted\n"
1910  "(entry has security level %i, your security level is only %i)",
1911  GB_read_key_pntr(gb_obj), sec_obj, sec_main);
1912  }
1913  return NULp;
1914 }
1915 
1922  if (!error) {
1923  GBDATA *gb_main = GB_get_root(source);
1924 
1925  if (source->flags.compressed_data) {
1926  bool was_allowed = GB_allow_compression(gb_main, false);
1927  gb_set_compression(source); // write data w/o compression (otherwise GB_read_old_value... won't work)
1928  GB_allow_compression(gb_main, was_allowed);
1929  }
1930 
1931  {
1932  GB_MAIN_TYPE *Main = GB_MAIN(source);
1933  if (Main->get_transaction_level() < 0) { // no transaction mode
1934  gb_delete_entry(source);
1935  Main->call_pending_callbacks();
1936  }
1937  else {
1938  gb_touch_entry(source, GB_DELETED);
1939  }
1940  }
1941  }
1942  RETURN_ERROR(error);
1943 }
1944 
1946  // delete always
1947  gb_touch_entry(source, GB_DELETED);
1948  return NULp;
1949 }
1950 
1951 
1952 // ------------------
1953 // Copy data
1954 
1955 enum CopyMode {
1956  // bit values:
1957  CM_DROP_PROTECTION = 1, // -> reset protection (use current default?).
1958  CM_DROP_MARKS = 2, // -> clear marks of copied entries (other user flags are always dropped, e.g. query flag). this only affects containers!
1959  CM_SKIP_TEMP = 4, // -> do not copy temporarily entries (and their subentries).
1960  CM_DROP_TEMPSTATE = 8, // w/o effect if CM_SKIP_TEMP; otherwise clear temporary state of copied entries if set.
1961  CM_OVERWRITE_EXISTING = 16, // -> overwrite existing sub-entries (otherwise keeps existing sub-entries + adds new entries)
1962 
1963  // convenience definitions:
1964  CM_COPY_TRADITIONAL = CM_DROP_PROTECTION|CM_DROP_MARKS|CM_DROP_TEMPSTATE, // traditional behavior of GB_copy_dropProtectMarksAndTempstate
1965  CM_COPY_WITHPROTECT = CM_COPY_TRADITIONAL & ~CM_DROP_PROTECTION, // like traditional, but dont drop protection (note: not dropping protection was the first attempt to fix copying)
1967  CM_COPY_FULL = 0, // copy everything
1968 };
1969 
1970 static GB_ERROR gb_copy_explicit(GBDATA *dest, GBDATA *source, CopyMode mode);
1971 
1972 static GBDATA *gb_clone_explicit(GBCONTAINER *gb_destCont, GBDATA *gb_source, CopyMode mode) {
1976  GB_test_transaction(gb_source);
1977  gb_assert(!GB_have_error()); // illegal to enter this function when an error is exported!
1978  gb_assert(!gb_destCont->flags2.folded_container); // please unfold in caller!
1979 
1980  if (mode&CM_SKIP_TEMP && GB_is_temporary(gb_source)) return NULp; // skip temporaries (as GB_save does)
1981 
1982  const char *key = GB_read_key_pntr(gb_source);
1983  GBDATA *gb_clone;
1984  if (gb_source->is_container()) {
1985  gb_assert(!GB_is_ancestor_of(gb_source, gb_destCont)); // (for performance reasons this has to be guaranteed by caller)
1986 
1987  if (strcmp(GB_SYSTEM_FOLDER, key) == 0) return NULp; // never ever clone system folder
1988 
1989  gb_clone = GB_create_container(gb_destCont, key);
1990  if (gb_clone) gb_create_header_array(gb_clone->as_container(), gb_source->as_container()->d.size);
1991  else GB_export_errorf("failed to clone container (Reason: %s)", GB_await_error());
1992  }
1993  else gb_clone = GB_create(gb_destCont, key, gb_source->type());
1994 
1995  if (gb_clone) {
1996  // target is a basic field or an empty container -> behavior of normal copy and overlay-copy is identical
1997  mode = CopyMode(mode&~CM_OVERWRITE_EXISTING); // -> drop overwrite mode
1998 
1999  GB_ERROR error = gb_copy_explicit(gb_clone, gb_source, mode);
2000  if (error) {
2001  IF_ASSERTION_USED(GB_ERROR derror =)GB_delete(gb_clone);
2002  gb_assert(!derror);
2003  gb_clone = NULp;
2004  GB_export_error(error);
2005  }
2006  }
2007 
2008  gb_assert(contradicted(gb_clone, GB_have_error()));
2009  return gb_clone;
2010 }
2011 
2012 static GB_ERROR gb_copy_explicit(GBDATA *dest, GBDATA *source, CopyMode mode) {
2013  GB_ERROR error = NULp;
2014  GB_test_transaction(source);
2015 
2016  if (mode&CM_SKIP_TEMP) {
2017  if (GB_is_temporary(source)) {
2018  return "logic error: it's too late to skip copy of temporary entry"; // has to be done by caller!
2019  }
2020 #if defined(ASSERTION_USED)
2021  bool overwriteTempTarget = GB_is_temporary(dest) && (mode&CM_OVERWRITE_EXISTING);
2022  gb_assert(!overwriteTempTarget); // currently is permitted. may be problematic.
2023 #endif
2024  }
2025 
2026  GB_TYPES type = source->type();
2027  if (dest->type() != type) {
2028  return GB_export_errorf("incompatible types in gb_copy_explicit (source %s:%u != %s:%u",
2029  GB_read_key_pntr(source), type, GB_read_key_pntr(dest), dest->type());
2030  }
2031 
2032  switch (type) {
2033  case GB_INT:
2034  error = GB_write_int(dest, GB_read_int(source));
2035  break;
2036  case GB_FLOAT:
2037  error = GB_write_float(dest, GB_read_float(source));
2038  break;
2039  case GB_BYTE:
2040  error = GB_write_byte(dest, GB_read_byte(source));
2041  break;
2042  case GB_STRING: // No local compression
2043  error = GB_write_string(dest, GB_read_char_pntr(source));
2044  break;
2045  case GB_OBSOLETE:
2046  error = GB_set_temporary(dest); // exclude obsolete type from next save
2047  break;
2048  case GB_BITS: // only local compressions for the following types
2049  case GB_BYTES:
2050  case GB_INTS:
2051  case GB_FLOATS: {
2052  GBENTRY *source_entry = source->as_entry();
2053  GBENTRY *dest_entry = dest->as_entry();
2054 
2055  gb_save_extern_data_in_ts(dest_entry);
2056  dest_entry->insert_data(source_entry->data(), source_entry->size(), source_entry->memsize());
2057 
2058  dest->flags.compressed_data = source->flags.compressed_data;
2059  break;
2060  }
2061  case GB_DB: {
2062  if (!dest->is_container()) {
2063  GB_ERROR err = GB_export_errorf("GB_COPY Type conflict %s:%i != %s:%i",
2064  GB_read_key_pntr(dest), dest->type(), GB_read_key_pntr(source), GB_DB);
2065  GB_internal_error(err);
2066  return err;
2067  }
2068 
2069  GBCONTAINER *destc = dest->as_container();
2070  GBCONTAINER *sourcec = source->as_container();
2071 
2072  if (!(mode&CM_DROP_MARKS)) GB_write_flag(destc, GB_read_flag(sourcec)); // preserve mark flags
2073 
2074  if (sourcec->flags2.folded_container) gb_unfold(sourcec, -1, -1);
2075  if (destc->flags2.folded_container) gb_unfold(destc, 0, -1);
2076 
2077  gb_assert(!GB_is_ancestor_of(source, dest)); // (for performance reasons this has to be guaranteed by caller, use gb_copy_checked?)
2078 
2079  if (mode&CM_OVERWRITE_EXISTING) { // overlay childs of destination with childs of source
2080  std::set<GBQUARK> keyHandled;
2081  for (GBDATA *gb_child = GB_child(sourcec); gb_child && !error; gb_child = GB_nextChild(gb_child)) {
2082  GBQUARK quark = GB_KEY_QUARK(gb_child);
2083  if (keyHandled.find(quark) == keyHandled.end()) { // handle each quark once
2084  GBDATA *gb_entry = gb_child;
2085  const char *key = GB_KEY(gb_entry);
2086  GBDATA *gb_exist = GB_entry(destc, key);
2087 
2088  while (gb_entry && gb_exist && !error) {
2089  // @@@ skip over temporary entries here?
2090 
2091  // overlay subentries pairwise:
2092  error = gb_copy_explicit(gb_exist, gb_entry, mode);
2093  if (!error) {
2094  gb_exist = GB_nextEntry(gb_exist);
2095  gb_entry = GB_nextEntry(gb_entry);
2096  }
2097  }
2098 
2099  while (gb_entry && !error) {
2100  error = GB_incur_error_if(!gb_clone_explicit(destc, gb_entry, mode));
2101  if (!error) gb_entry = GB_nextEntry(gb_entry);
2102  }
2103 
2104  gb_assert(implicated(gb_entry, error));
2105 
2106  keyHandled.insert(quark);
2107  }
2108  }
2109  }
2110  else { // copy all childs to destination
2111  for (GBDATA *gb_child = GB_child(sourcec); gb_child && !error; gb_child = GB_nextChild(gb_child)) {
2112  error = GB_incur_error_if(!gb_clone_explicit(destc, gb_child, mode));
2113  }
2114  }
2115 
2116  destc->flags3 = sourcec->flags3;
2117  break;
2118  }
2119  default:
2120  error = GB_export_error("error in gb_copy_explicit: unhandled type");
2121  }
2122 
2123  if (!error) {
2125 
2126  dest->flags.security_read = source->flags.security_read; // (note: read security generally has no effect)
2127  if (!(mode&CM_DROP_PROTECTION)) { // preserve protection
2128  dest->flags.security_write = source->flags.security_write;
2129  dest->flags.security_delete = source->flags.security_delete;
2130  }
2131 
2132  if (!(mode&CM_DROP_TEMPSTATE)) { // preserve tempstate
2133  bool source_is_temp = GB_is_temporary(source);
2134  if (GB_is_temporary(dest) != source_is_temp) {
2135  error = source_is_temp ? GB_set_temporary(dest) : GB_clear_temporary(dest);
2136  }
2137  }
2138  }
2139  return error;
2140 }
2141 
2142 inline GB_ERROR gb_copy_checked(GBDATA *dest, GBDATA *source, CopyMode mode) {
2146  if (GB_is_ancestor_of(source, dest)) {
2147  return "infinite copy not permitted (destination may not be part of source)";
2148  }
2149  return gb_copy_explicit(dest, source, mode);
2150 }
2151 
2161  return gb_copy_checked(dest, source, CM_COPY_TRADITIONAL);
2162 }
2172  return gb_copy_checked(dest, source, CM_COPY_WITHPROTECT);
2173 }
2179  return gb_copy_checked(dest, source, CM_COPY_STANDARD);
2180 }
2181 
2188 }
2189 
2193  return gb_copy_checked(dest, source, CM_COPY_FULL);
2194 }
2195 
2196 GBDATA *GB_clone(GBDATA *gb_destCont, GBDATA *gb_source) {
2201  gb_assert(!GB_have_error()); // illegal to enter this function when an error is exported!
2202 
2203  GB_ERROR error = NULp;
2204  if (gb_destCont->is_container()) {
2205  GBCONTAINER *destc = gb_destCont->as_container();
2206  if (destc->flags2.folded_container) gb_unfold(destc, 0, -1);
2207  if (!GB_is_ancestor_of(gb_source, gb_destCont)) {
2208  return gb_clone_explicit(destc, gb_source, CM_COPY_STANDARD);
2209  }
2210  error = "GB_clone destination cannot be part of source.";
2211  }
2212  else {
2213  error = "GB_clone destination has to be a container.";
2214  }
2215  GB_export_error(error);
2216  return NULp;
2217 }
2218 
2219 
2220 static char *gb_stpcpy(char *dest, const char *source) {
2221  while ((*dest++=*source++)) ;
2222  return dest-1; // return pointer to last copied character (which is \0)
2223 }
2224 
2231  GB_test_transaction(gbd);
2232 
2233  char *result = NULp;
2234  if (gbd->is_container()) {
2235  GBCONTAINER *gbc = gbd->as_container();
2236  int result_length = 0;
2237 
2238  if (gbc->flags2.folded_container) {
2239  gb_unfold(gbc, -1, -1);
2240  }
2241 
2242  for (GBDATA *gbp = GB_child(gbd); gbp; gbp = GB_nextChild(gbp)) {
2243  const char *key = GB_read_key_pntr(gbp);
2244  int keylen = strlen(key);
2245 
2246  if (result) {
2247  char *neu_result = ARB_alloc<char>(result_length+keylen+1+1);
2248 
2249  if (neu_result) {
2250  char *p = gb_stpcpy(neu_result, result);
2251  p = gb_stpcpy(p, key);
2252  *p++ = ';';
2253  p[0] = 0;
2254 
2255  freeset(result, neu_result);
2256  result_length += keylen+1;
2257  }
2258  else {
2259  gb_assert(0);
2260  }
2261  }
2262  else {
2263  ARB_alloc(result, 1+keylen+1+1);
2264  result[0] = ';';
2265  strcpy(result+1, key);
2266  result[keylen+1] = ';';
2267  result[keylen+2] = 0;
2268  result_length = keylen+2;
2269  }
2270  }
2271  }
2272  else {
2273  result = ARB_strdup(";");
2274  }
2275 
2276  return result;
2277 }
2278 
2279 // --------------------------
2280 // temporary entries
2281 
2282 GB_ERROR GB_set_temporary(GBDATA *gbd) { // goes to header: __ATTR__USERESULT
2288  if (!error) {
2289  gbd->flags.temporary = 1;
2291  }
2292  RETURN_ERROR(error);
2293 }
2294 
2295 GB_ERROR GB_clear_temporary(GBDATA *gbd) { // @@@ used in ptpan branch - do not remove
2297 
2298  GB_test_transaction(gbd);
2299  gbd->flags.temporary = 0;
2301  return NULp;
2302 }
2303 
2306  GB_test_transaction(gbd);
2307  return (long)gbd->flags.temporary;
2308 }
2309 
2315  if (GB_is_temporary(gbd)) return true;
2316 
2317  GBDATA *gb_parent = GB_get_father(gbd);
2318  if (!gb_parent) return false;
2319 
2320  return GB_in_temporary_branch(gb_parent);
2321 }
2322 
2323 // ---------------------
2324 // transactions
2325 
2326 GB_ERROR GB_MAIN_TYPE::initial_client_transaction() {
2327  // the first client transaction ever
2328  transaction_level = 1;
2330  if (!error) ++clock;
2331  return error;
2332 }
2333 
2334 inline GB_ERROR GB_MAIN_TYPE::start_transaction() {
2335  gb_assert(transaction_level == 0);
2336 
2337  transaction_level = 1;
2338  aborted_transaction = 0;
2339 
2340  GB_ERROR error = NULp;
2341  if (is_client()) {
2342  error = gbcmc_begin_transaction(gb_main());
2343  if (!error) {
2344  error = gb_commit_transaction_local_rek(gb_main_ref(), 0, NULp); // init structures
2346  }
2347  }
2348 
2349  if (!error) {
2350  /* do all callbacks
2351  * cb that change the db are no problem, because it's the beginning of a ta
2352  */
2354  ++clock;
2355  }
2356  return error;
2357 }
2358 
2360  if (transaction_level>0) return GBS_global_string("attempt to start a NEW transaction (at transaction level %i)", transaction_level);
2361  if (transaction_level == 0) return start_transaction();
2362  return NULp; // NO_TRANSACTION_MODE
2363 }
2364 
2366  if (transaction_level<=0) {
2367  if (transaction_level<0) return "GB_abort_transaction: Attempt to abort transaction in no-transaction-mode";
2368  return "GB_abort_transaction: No transaction running";
2369  }
2370  if (transaction_level>1) {
2371  aborted_transaction = 1;
2372  return pop_transaction();
2373  }
2374 
2375  gb_abort_transaction_local_rek(gb_main_ref());
2376  if (is_client()) {
2378  if (error) return error;
2379  }
2380  clock--;
2382  transaction_level = 0;
2384  return NULp;
2385 }
2386 
2388  GB_ERROR error = NULp;
2389  GB_CHANGE flag;
2390 
2391  if (!transaction_level) {
2392  return "commit_transaction: No transaction running";
2393  }
2394  if (transaction_level>1) {
2395  return GBS_global_string("attempt to commit at transaction level %i", transaction_level);
2396  }
2397  if (aborted_transaction) {
2398  aborted_transaction = 0;
2399  return abort_transaction();
2400  }
2401  if (is_server()) {
2402  char *error1 = gb_set_undo_sync(gb_main());
2403 
2404  int warn_deadlock = 100;
2405  int loop_count = 0;
2406  while (1) {
2407  flag = (GB_CHANGE)GB_ARRAY_FLAGS(gb_main()).changed;
2408  if (!flag) break; // nothing to do
2409  error = gb_commit_transaction_local_rek(gb_main_ref(), 0, NULp);
2411  if (error) break;
2413 
2414  ++loop_count;
2415  if (loop_count>warn_deadlock) {
2416  fprintf(stderr, "possible deadlock in commit_transaction (callback triggered by callback?). looped %i times.\n", warn_deadlock);
2417  warn_deadlock *= 10;
2418  }
2419  }
2421  if (error1) {
2422  transaction_level = 0;
2423  gb_assert(error); // maybe return error1?
2424  return error; // @@@ huh? why not return error1
2425  }
2426  }
2427  else {
2429  while (1) {
2430  flag = (GB_CHANGE)GB_ARRAY_FLAGS(gb_main()).changed;
2431  if (!flag) break; // nothing to do
2432 
2433  error = gbcmc_begin_sendupdate(gb_main()); if (error) break;
2434  error = gb_commit_transaction_local_rek(gb_main_ref(), 1, NULp); if (error) break;
2435  error = gbcmc_end_sendupdate(gb_main()); if (error) break;
2436 
2439  }
2440  if (!error) error = gbcmc_commit_transaction(gb_main());
2441 
2442  }
2443  transaction_level = 0;
2444  return error;
2445 }
2446 
2448  if (transaction_level == 0) return start_transaction();
2449  if (transaction_level>0) ++transaction_level;
2450  // transaction<0 is NO_TRANSACTION_MODE
2451  return NULp;
2452 }
2453 
2455  if (transaction_level==0) return "attempt to pop nested transaction while none running";
2456  if (transaction_level<0) return NULp; // NO_TRANSACTION_MODE
2457  if (transaction_level==1) return commit_transaction();
2458  transaction_level--;
2459  return NULp;
2460 }
2461 
2463  if (is_client()) return "Tried to disable transactions in a client";
2464  transaction_level = -1;
2465  return NULp;
2466 }
2467 
2469  GB_ERROR error = NULp;
2470 
2471  if (!transaction_level) error = "send_update_to_server: no transaction running";
2472  else if (is_server()) error = "send_update_to_server: only possible from clients (not from server itself)";
2473  else {
2474  const gb_triggered_callback *chg_cbl_old = changeCBs.pending.get_tail();
2475  const gb_triggered_callback *del_cbl_old = deleteCBs.pending.get_tail();
2476 
2477  error = gbcmc_begin_sendupdate(gb_main());
2478  if (!error) error = gb_commit_transaction_local_rek(gbd, 2, NULp);
2479  if (!error) error = gbcmc_end_sendupdate(gb_main());
2480 
2481  if (!error &&
2482  (chg_cbl_old != changeCBs.pending.get_tail() ||
2483  del_cbl_old != deleteCBs.pending.get_tail()))
2484  {
2485  error = "send_update_to_server triggered a callback (this is not allowed)";
2486  }
2487  }
2488  return error;
2489 }
2490 
2491 // --------------------------------------
2492 // client transaction interface
2493 
2521  return GB_MAIN(gbd)->push_transaction();
2522 }
2523 
2526  return GB_MAIN(gbd)->pop_transaction();
2527 }
2533  return GB_MAIN(gbd)->begin_transaction();
2534 }
2535 GB_ERROR GB_no_transaction(GBDATA *gbd) { // goes to header: __ATTR__USERESULT
2536  return GB_MAIN(gbd)->no_transaction();
2537 }
2538 
2548  return GB_MAIN(gbd)->abort_transaction();
2549 }
2550 
2558  return GB_MAIN(gbd)->commit_transaction();
2559 }
2560 
2574  if (GB_get_transaction_level(gbd)<0) {
2576  }
2577  else {
2578  if (error) GB_abort_transaction(gbd);
2579  else error = GB_pop_transaction(gbd);
2580  }
2581  return error;
2582 }
2583 
2584 void GB_end_transaction_show_error(GBDATA *gbd, GB_ERROR error, void (*error_handler)(GB_ERROR)) {
2586  error = GB_end_transaction(gbd, error);
2587  if (error) error_handler(error);
2588 }
2589 
2597  return GB_MAIN(gbd)->get_transaction_level();
2598 }
2599 
2605  GBCONTAINER *gbc;
2606  GBDATA *gb;
2607  int index;
2608  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
2609 
2610  GB_test_transaction(gbd);
2611  if (Main->is_server()) return NULp;
2612  if (GB_ARRAY_FLAGS(gbd).changed && !gbd->flags2.update_in_server) {
2613  GB_ERROR error = Main->send_update_to_server(gbd);
2614  if (error) return error;
2615  }
2616  if (gbd->type() != GB_DB) {
2617  GB_ERROR error = GB_export_errorf("You cannot release non container (%s)",
2618  GB_read_key_pntr(gbd));
2619  GB_internal_error(error);
2620  return error;
2621  }
2622  if (gbd->flags2.folded_container) return NULp;
2623  gbc = (GBCONTAINER *)gbd;
2624 
2625  for (index = 0; index < gbc->d.nheader; index++) {
2626  if ((gb = GBCONTAINER_ELEM(gbc, index))) {
2627  gb_delete_entry(gb);
2628  }
2629  }
2630 
2631  gbc->flags2.folded_container = 1;
2632  Main->call_pending_callbacks();
2633  return NULp;
2634 }
2635 
2636 int GB_nsons(GBDATA *gbd) {
2642  return gbd->is_container()
2643  ? gbd->as_container()->d.size
2644  : 0;
2645 }
2646 
2647 void GB_disable_quicksave(GBDATA *gbd, const char *reason) {
2652  freedup(GB_MAIN(gbd)->qs.quick_save_disabled, reason);
2653 }
2654 
2655 GB_ERROR GB_resort_data_base(GBDATA *gb_main, GBDATA **new_order_list, long listsize) {
2656  {
2657  long client_count = GB_read_clients(gb_main);
2658  if (client_count<0) {
2659  return "Sorry: this program is not the arbdb server, you cannot resort your data";
2660  }
2661  if (client_count>0) {
2662  // resort will do a big amount of client update callbacks => disallow clients here
2663  bool called_from_macro = GB_inside_remote_action(gb_main);
2664  if (!called_from_macro) { // accept macro clients
2665  return GBS_global_string("There are %li clients (editors, tree programs) connected to this server.\n"
2666  "You need to close these clients before you can run this operation.",
2667  client_count);
2668  }
2669  }
2670  }
2671 
2672  if (listsize <= 0) return NULp;
2673 
2674  GBCONTAINER *father = GB_FATHER(new_order_list[0]);
2675  GB_disable_quicksave(gb_main, "some entries in the database got a new order");
2676 
2677  gb_header_list *hl = GB_DATA_LIST_HEADER(father->d);
2678  for (long new_index = 0; new_index< listsize; new_index++) {
2679  long old_index = new_order_list[new_index]->index;
2680 
2681  if (old_index < new_index) {
2682  GB_warningf("Warning at resort database: entry exists twice: %li and %li",
2683  old_index, new_index);
2684  }
2685  else {
2686  GBDATA *ogb = GB_HEADER_LIST_GBD(hl[old_index]);
2687  GBDATA *ngb = GB_HEADER_LIST_GBD(hl[new_index]);
2688 
2689  gb_header_list h = hl[new_index];
2690  hl[new_index] = hl[old_index];
2691  hl[old_index] = h; // Warning: Relative Pointers are incorrect !!!
2692 
2693  SET_GB_HEADER_LIST_GBD(hl[old_index], ngb);
2694  SET_GB_HEADER_LIST_GBD(hl[new_index], ogb);
2695 
2696  if (ngb) ngb->index = old_index;
2697  if (ogb) ogb->index = new_index;
2698  }
2699  }
2700 
2702  return NULp;
2703 }
2704 
2706  if (GB_read_clients(gb_main)<0) {
2707  return NULp; // we are not server
2708  }
2709 
2710  GBDATA *gb_system = GB_entry(gb_main, GB_SYSTEM_FOLDER);
2711  if (!gb_system) {
2712  return GB_export_error("System databaseentry does not exist");
2713  }
2714 
2715  GBDATA *gb_first = GB_child(gb_main);
2716  if (gb_first == gb_system) {
2717  return NULp;
2718  }
2719 
2720  int len = GB_number_of_subentries(gb_main);
2721  GBDATA **new_order_list = ARB_calloc<GBDATA*>(len);
2722 
2723  new_order_list[0] = gb_system;
2724  for (int i=1; i<len; i++) {
2725  new_order_list[i] = gb_first;
2726  do gb_first = GB_nextChild(gb_first); while (gb_first == gb_system);
2727  }
2728 
2729  GB_ERROR error = GB_resort_data_base(gb_main, new_order_list, len);
2730  free(new_order_list);
2731 
2732  return error;
2733 }
2734 
2735 // ------------------------------
2736 // private(?) user flags
2737 
2738 STATIC_ASSERT_ANNOTATED(((GB_USERFLAG_ANY+1)&GB_USERFLAG_ANY) == 0, "not all bits set in GB_USERFLAG_ANY");
2739 
2740 #if defined(ASSERTION_USED)
2741 inline bool legal_user_bitmask(unsigned char bitmask) {
2742  return bitmask>0 && bitmask<=GB_USERFLAG_ANY;
2743 }
2744 #endif
2745 
2747  return gbd->expect_container()->flags2;
2748 }
2749 
2750 bool GB_user_flag(GBDATA *gbd, unsigned char user_bit) {
2751  gb_assert(legal_user_bitmask(user_bit));
2752  return get_user_flags(gbd).user_bits & user_bit;
2753 }
2754 
2755 void GB_raise_user_flag(GBDATA *gbd, unsigned char user_bit) {
2756  gb_assert(legal_user_bitmask(user_bit));
2758  flags.user_bits |= user_bit;
2759 }
2760 void GB_clear_user_flag(GBDATA *gbd, unsigned char user_bit) {
2761  gb_assert(legal_user_bitmask(user_bit));
2763  flags.user_bits &= (user_bit^GB_USERFLAG_ANY);
2764 }
2765 void GB_write_user_flag(GBDATA *gbd, unsigned char user_bit, bool state) {
2766  (state ? GB_raise_user_flag : GB_clear_user_flag)(gbd, user_bit);
2767 }
2768 
2769 
2770 // ------------------------
2771 // mark DB entries
2772 
2773 void GB_write_flag(GBDATA *gbd, long flag) {
2774  GBCONTAINER *gbc = gbd->expect_container();
2775  GB_MAIN_TYPE *Main = GB_MAIN(gbc);
2776 
2777  GB_test_transaction(Main);
2778 
2779  int ubit = Main->users[0]->userbit;
2780  int prev = GB_ARRAY_FLAGS(gbc).flags;
2781  gbc->flags.saved_flags = prev;
2782 
2783  if (flag) {
2784  GB_ARRAY_FLAGS(gbc).flags |= ubit;
2785  }
2786  else {
2787  GB_ARRAY_FLAGS(gbc).flags &= ~ubit;
2788  }
2789  if (prev != (int)GB_ARRAY_FLAGS(gbc).flags) {
2791  gb_touch_header(GB_FATHER(gbc));
2792  GB_DO_CALLBACKS(gbc);
2793  }
2794 }
2795 
2797  GB_test_transaction(gbd);
2798  if (GB_ARRAY_FLAGS(gbd).flags & GB_MAIN(gbd)->users[0]->userbit) return 1;
2799  else return 0;
2800 }
2801 
2802 void GB_touch(GBDATA *gbd) {
2803  GB_test_transaction(gbd);
2805  GB_DO_CALLBACKS(gbd);
2806 }
2807 
2808 
2810  const char *type2char = "-bcif-B-CIFlSS-%";
2811  return type2char[type];
2812 }
2813 
2814 void GB_print_debug_information(struct Unfixed_cb_parameter *, GBDATA *gb_main) {
2815  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
2816  GB_push_transaction(gb_main);
2817  for (int i=0; i<Main->keycnt; i++) {
2818  gb_Key& KEY = Main->keys[i];
2819  if (KEY.key) {
2820  printf("%3i %20s nref %li\n", i, KEY.key, KEY.nref);
2821  }
2822  else {
2823  printf(" %3i unused key, next free key = %li\n", i, KEY.next_free_key);
2824  }
2825  }
2826  gbm_debug_mem();
2827  GB_pop_transaction(gb_main);
2828 }
2829 
2830 static int GB_info_deep = 15;
2831 
2832 
2833 static int gb_info(GBDATA *gbd, int deep) {
2834  if (!gbd) { printf("NULp\n"); return -1; }
2835  GB_push_transaction(gbd);
2836 
2837  GB_TYPES type = gbd->type();
2838 
2839  if (deep) {
2840  printf(" ");
2841  }
2842 
2843  printf("(GBDATA*)0x%lx (GBCONTAINER*)0x%lx ", (long)gbd, (long)gbd);
2844 
2845  if (gbd->rel_father==0) { printf("father=NULp\n"); return -1; }
2846 
2847  GBCONTAINER *gbc;
2848  GB_MAIN_TYPE *Main;
2849  if (type==GB_DB) { gbc = gbd->as_container(); Main = GBCONTAINER_MAIN(gbc); }
2850  else { gbc = NULp; Main = GB_MAIN(gbd); }
2851 
2852  if (!Main) { printf("Oops - I have no main entry!!!\n"); return -1; }
2853  if (gbd==Main->dummy_father) { printf("dummy_father!\n"); return -1; }
2854 
2855  printf("%10s Type '%c' ", GB_read_key_pntr(gbd), GB_type_2_char(type));
2856 
2857  switch (type) {
2858  case GB_DB: {
2859  int size = gbc->d.size;
2860  printf("Size %i nheader %i hmemsize %i", gbc->d.size, gbc->d.nheader, gbc->d.headermemsize);
2861  printf(" father=(GBDATA*)0x%lx\n", (long)GB_FATHER(gbd));
2862  if (size < GB_info_deep) {
2863  int index;
2864  gb_header_list *header;
2865 
2866  header = GB_DATA_LIST_HEADER(gbc->d);
2867  for (index = 0; index < gbc->d.nheader; index++) {
2868  GBDATA *gb_sub = GB_HEADER_LIST_GBD(header[index]);
2869  GBQUARK quark = header[index].flags.key_quark;
2870  printf("\t\t%10s (GBDATA*)0x%lx (GBCONTAINER*)0x%lx\n", quark2key(Main, quark), (long)gb_sub, (long)gb_sub);
2871  }
2872  }
2873  break;
2874  }
2875  default: {
2876  char *data = GB_read_as_string(gbd);
2877  if (data) { printf("%s", data); free(data); }
2878  printf(" father=(GBDATA*)0x%lx\n", (long)GB_FATHER(gbd));
2879  }
2880  }
2881 
2882 
2883  GB_pop_transaction(gbd);
2884 
2885  return 0;
2886 }
2887 
2888 int GB_info(GBDATA *gbd) { // unused - intended to be used in debugger
2889  return gb_info(gbd, 0);
2890 }
2891 
2893  GBCONTAINER *gbc = gbd->expect_container();
2894  gb_header_list *header = GB_DATA_LIST_HEADER(gbc->d);
2895 
2896  long subentries = 0;
2897  int end = gbc->d.nheader;
2898 
2899  for (int index = 0; index<end; index++) {
2900  if (header[index].flags.changed < GB_DELETED) subentries++;
2901  }
2902  return subentries;
2903 }
2904 
2905 // --------------------------------------------------------------------------------
2906 
2907 #ifdef UNIT_TESTS
2908 
2909 #include <arb_diff.h>
2910 #include <arb_file.h>
2911 #include <test_unit.h>
2912 #include <locale.h>
2913 #include "arbdbt.h"
2914 
2915 void TEST_GB_atof() {
2916  // arb depends on locale for floating-point conversion!
2917  // see ../SOURCE_TOOLS/arb_main.h@setlocale
2918  TEST_EXPECT_SIMILAR(GB_atof("0.031"), 0.031, 0.0001); // fails if LC_NUMERIC is set to "de_DE..."
2919 }
2920 
2921 #if !defined(DARWIN)
2922 // @@@ TEST_DISABLED_OSX: test fails to compile for OSX on build server
2923 // @@@ re-activate test later; see missing libs http://bugs.arb-home.de/changeset/11664#file2
2924 void TEST_999_strtod_replacement() {
2925  // caution: if it fails -> locale is not reset (therefore call with low priority 999)
2926  const char *old = setlocale(LC_NUMERIC, "de_DE.UTF-8");
2927  {
2928  // TEST_EXPECT_SIMILAR__BROKEN(strtod("0.031", NULp), 0.031, 0.0001);
2929  TEST_EXPECT_SIMILAR(g_ascii_strtod("0.031", NULp), 0.031, 0.0001);
2930  }
2931  setlocale(LC_NUMERIC, old);
2932 }
2933 #endif
2934 
2935 #if defined(ENABLE_CRASH_TESTS)
2936 static void test_another_shell() { delete new GB_shell; }
2937 #endif
2938 static void test_opendb() { GB_close(GB_open("no.arb", "c")); }
2939 
2940 void TEST_GB_shell__crashtest() {
2941  {
2942  GB_shell *shell = new GB_shell;
2943  TEST_EXPECT_SEGFAULT(test_another_shell);
2944  test_opendb(); // no SEGV here
2945  delete shell;
2946  }
2947 
2948  TEST_EXPECT_SEGFAULT(test_opendb); // should be impossible to open db w/o shell
2949 }
2950 
2951 void TEST_GB_number_of_subentries() {
2952  GB_shell shell;
2953  GBDATA *gb_main = GB_open("no.arb", "c");
2954 
2955  {
2956  GB_transaction ta(gb_main);
2957 
2958  GBDATA *gb_cont = GB_create_container(gb_main, "container");
2960 
2961  TEST_EXPECT_RESULT__NOERROREXPORTED(GB_create(gb_cont, "entry", GB_STRING));
2963 
2964  {
2965  GBDATA *gb_entry;
2966  TEST_EXPECT_RESULT__NOERROREXPORTED(gb_entry = GB_create(gb_cont, "entry", GB_STRING));
2968 
2969  TEST_EXPECT_NO_ERROR(GB_delete(gb_entry));
2971  }
2972 
2973  TEST_EXPECT_RESULT__NOERROREXPORTED(GB_create(gb_cont, "entry", GB_STRING));
2975  }
2976 
2977  GB_close(gb_main);
2978 }
2979 
2980 
2981 void TEST_POSTCOND_arbdb() {
2982  GB_ERROR error = GB_incur_error(); // clears the error (to make further tests succeed)
2983  bool unclosed_GB_shell = closed_open_shell_for_unit_tests();
2984 
2985  TEST_REJECT(error); // your test finished with an exported error
2986  TEST_REJECT(unclosed_GB_shell); // your test finished w/o destroying GB_shell
2987 }
2988 
2989 // #define TEST_AUTO_UPDATE // uncomment to auto-update expected results
2990 
2991 static void saveAndCompare(GBDATA *gb_main, const char *expectedname, bool
2992 #if defined(TEST_AUTO_UPDATE)
2993  allowAutoUpdate
2994 #endif
2995  ) {
2996  const char *outputname = "copied.arb";
2997 
2998  TEST_EXPECT_NO_ERROR(GB_save(gb_main, outputname, "a"));
2999 
3000 #if defined(TEST_AUTO_UPDATE)
3001  if (allowAutoUpdate) {
3002  TEST_COPY_FILE(outputname, expectedname);
3003  }
3004 #endif
3005  TEST_EXPECT_TEXTFILE_DIFFLINES(outputname, expectedname, 0);
3007 }
3008 
3009 void TEST_AFTER_SLOW_copy() { // run after TEST_SLOW_loadsave!
3010  GB_shell shell;
3011  GBDATA *gb_main = GB_open("TEST_loadsave_ascii.arb", "rw"); // ../UNIT_TESTER/run/TEST_loadsave_ascii.arb
3012 
3013  // ---------------------------------------------------------
3014  // 1st step: copy root elements to container 'all'
3015  GBDATA *gb_all;
3016  {
3017  GB_transaction ta(gb_main);
3018 
3019  TEST_EXPECT_RESULT__NOERROREXPORTED(gb_all = GB_create_container(gb_main, "all"));
3020 
3021  // move everything into new container:
3022  GB_ERROR error = NULp;
3023  for (GBDATA *gb_child = GB_child(gb_main); gb_child && !error; ) {
3024  GBDATA *gb_next_child = GB_nextChild(gb_child);
3025  if (gb_child != gb_all) { // skip target container
3026  GBDATA *gb_clone = GB_clone(gb_all, gb_child);
3027  error = GB_incur_error_if(!gb_clone);
3028  if (gb_clone) {
3029  gb_assert(!error);
3030  error = GB_delete(gb_child);
3031  }
3032  }
3033  gb_child = gb_next_child;
3034  }
3035 
3036  TEST_EXPECT_NO_ERROR(error);
3037  }
3038 
3039  saveAndCompare(gb_main, "TEST_copy.arb", true);
3040 
3041  // -----------------------------------------------------------------------------
3042  // 2nd step: copy container 'gb_all' with traditional GB_copy_dropProtectMarksAndTempstate into the fresh container 'gb_copy' (also named 'all')
3043  GBDATA *gb_copy;
3044  {
3045  GB_transaction ta(gb_main);
3046 
3047  TEST_EXPECT_RESULT__NOERROREXPORTED(gb_copy = GB_create_container(gb_main, "all"));
3048  TEST_EXPECT_NO_ERROR(GB_copy_dropProtectMarksAndTempstate(gb_copy, gb_all)); // w/o protection
3049 
3050  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_all)); // do not save 'all'
3051  }
3052 
3053  saveAndCompare(gb_main, "TEST_copy_noProtect.arb", true); // ../UNIT_TESTER/run/TEST_copy_noProtect.arb
3054 
3055  // -----------------------------------------------------------------------------
3056  // 3rd step: copy container 'gb_all' with GB_copy_overlay to the fresh container 'gb_copy2' (also named 'all')
3057  GBDATA *gb_copy2;
3058  {
3059  GB_transaction ta(gb_main);
3060 
3062 
3063  TEST_EXPECT_RESULT__NOERROREXPORTED(gb_copy2 = GB_create_container(gb_main, "all"));
3064  TEST_EXPECT_NO_ERROR(GB_copy_overlay(gb_copy2, gb_all));
3065 
3066  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_copy)); // skip save of 'copy'
3067  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_all)); // skip save of 'all'
3068  }
3069 
3070  saveAndCompare(gb_main, "TEST_copy.arb", false);
3071 
3072  // -----------------------------------------------------------------------------
3073  // 4th step: copy container 'gb_all' with GB_copy_overlay over container 'gb_copy'
3074  // (Note: gb_copy lacks protection; it gets restored by overlay copy)
3075  {
3076  GB_transaction ta(gb_main);
3077 
3080 
3081  TEST_EXPECT_NO_ERROR(GB_copy_overlay(gb_copy, gb_all));
3082 
3083  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_copy2)); // skip save of 'copy2'
3084  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_all)); // skip save of 'all'
3085  }
3086 
3087  saveAndCompare(gb_main, "TEST_copy.arb", false);
3088 
3089  // ---------------------------------------------------------------------------------
3090  // 5th step: revert DB to original state by copying 'gb_all' back to DB-root
3091  {
3092  GB_transaction ta(gb_main);
3093 
3094  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_copy)); // skip save of 'copy'
3095  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_copy2)); // skip save of 'copy2'
3096 
3097  // copy all entries back to root-container:
3098  GBDATA *gb_tmp = GB_search(gb_all, "tmp", GB_FIND);
3099  TEST_EXPECT_NULL(gb_tmp); // did not clone temp entries (in 1st step)
3100 
3101  TEST_EXPECT_NO_ERROR(GB_clear_temporary(gb_all)); // all = permanent (to permit copy)
3102  TEST_EXPECT_NO_ERROR(GB_copy_std(gb_main, gb_all));
3103  TEST_EXPECT_NO_ERROR(GB_set_temporary(gb_all)); // all = temporary (to avoid save)
3104 
3106  "logic error: it's too late to skip copy of temporary entry");
3107 
3108  GBDATA *gb_description = GB_entry(gb_main, "description");
3109  TEST_EXPECT_NORESULT__ERROREXPORTED_CONTAINS(GB_clone(gb_description, gb_copy),
3110  "GB_clone destination has to be a container");
3111  }
3112 
3113  saveAndCompare(gb_main, "TEST_loadsave_ascii.arb", false);
3114 
3115  // ----------------------------------------------
3116  // copying container into itself fails:
3117  {
3118  GB_transaction ta(gb_main);
3119 
3120  GBDATA *gb_key_data = GB_search(gb_copy, "presets/key_data", GB_FIND);
3121  GBDATA *gb_key = GBT_find_item_rel_item_data(gb_key_data, "key_name", "full_name");
3122 
3123  TEST_REJECT_NULL(gb_key);
3124  TEST_EXPECT_NO_ERROR(GB_clear_temporary(gb_copy)); // allow to copy
3125  TEST_EXPECT(GB_is_ancestor_of(gb_copy, gb_key)); // expect copy is ancestor of key
3126 
3127  TEST_EXPECT_ERROR_CONTAINS(GB_copy_std(gb_key, gb_copy), "infinite copy not permitted");
3128  TEST_EXPECT_NORESULT__ERROREXPORTED_CONTAINS(GB_clone(gb_key, gb_copy), "GB_clone destination cannot be part of source");
3129  }
3130 
3131  GB_close(gb_main);
3132 }
3133 
3134 #endif // UNIT_TESTS
GB_ERROR GB_check_key(const char *key) __ATTR__USERESULT
Definition: adstring.cxx:85
NOT4PERL int32_t GB_read_lossless_int(GBDATA *gbd, GB_ERROR &error)
Definition: arbdb.cxx:1128
void gb_remove_callbacks_marked_for_deletion(GBDATA *gbd)
Definition: ad_cb.cxx:295
GB_CHANGE
Definition: gb_local.h:73
static GB_ERROR GB_safe_atof(const char *str, float *res)
Definition: arbdb.cxx:173
gb_buffer buf1
Definition: gb_localdata.h:51
size_t GB_read_string_count(GBDATA *gbd)
Definition: arbdb.cxx:916
const char * GB_ERROR
Definition: arb_core.h:25
#define GB_SYSTEM_FOLDER
Definition: arbdb.h:27
GB_ERROR GB_write_floats(GBDATA *gbd, const float *f, long size)
Definition: arbdb.cxx:1457
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2494
static void alloc_buffer(gb_buffer *buf, size_t size)
Definition: arbdb.cxx:284
STATIC_ASSERT_ANNOTATED(((GB_USERFLAG_ANY+1)&GB_USERFLAG_ANY)==0,"not all bits set in GB_USERFLAG_ANY")
bool legal_user_bitmask(unsigned char bitmask)
Definition: arbdb.cxx:2741
string result
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
GB_TYPES type
long update_date() const
Definition: gb_data.h:193
GB_CBUFFER gb_uncompress_data(GBDATA *gbd, GB_CBUFFER source, size_t size)
Definition: adcompr.cxx:990
NOT4PERL long GB_calc_structure_size(GBDATA *gbd)
#define GB_GET_SECURITY_READ(gb)
Definition: gb_data.h:301
GB_ERROR GB_write_security_delete(GBDATA *gbd, unsigned long level)
Definition: arbdb.cxx:1605
GB_ERROR GB_clear_temporary(GBDATA *gbd)
Definition: arbdb.cxx:2295
bool GB_TYPE_readable_as_string(GB_TYPES type)
Definition: arbdb.h:90
unsigned int saved_flags
Definition: gb_data.h:74
void GB_write_user_flag(GBDATA *gbd, unsigned char user_bit, bool state)
Definition: arbdb.cxx:2765
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1722
#define INIT_TYPE_NAME(t)
Definition: arbdb.cxx:35
GB_ERROR GB_commit_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2551
#define TEST_EXPECT_SIMILAR(expr, want, epsilon)
Definition: test_unit.h:1287
bool GB_is_temporary(GBDATA *gbd)
Definition: arbdb.cxx:2304
void gb_free_compress_tree(gb_compress_tree *tree)
Definition: adcompr.cxx:183
Definition: arbdb.h:65
GBDATA * GB_child(GBDATA *father)
Definition: adquery.cxx:322
GB_ERROR GB_incur_error()
Definition: arb_msg.h:49
char * GB_read_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1060
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
#define GB_TEST_READ_NUM(gbd, type, ignored)
Definition: arbdb.cxx:161
static GB_ERROR gb_copy_explicit(GBDATA *dest, GBDATA *source, CopyMode mode)
Definition: arbdb.cxx:2012
char data[SIZOFINTERN]
Definition: gb_data.h:43
unsigned int security_read
Definition: gb_data.h:69
GB_ERROR GB_save(GBDATA *gb, const char *path, const char *savetype)
__ATTR__USERESULT GB_ERROR send_update_to_server(GBDATA *gbd) __ATTR__USERESULT
Definition: arbdb.cxx:2468
Definition: arbdb.h:69
static char * check_out_buffer(gb_buffer *buf)
Definition: arbdb.cxx:275
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1916
GB_BUFFER gb_compress_data(GBDATA *gbd, int key, GB_CBUFFER source, size_t size, size_t *msize, GB_COMPRESSION_MASK max_compr, bool pre_compressed)
Definition: adcompr.cxx:923
#define GB_PUT_SECURITY_READ(gb, i)
Definition: gb_data.h:305
bool GB_is_container(GBDATA *gbd)
Definition: arbdb.cxx:1648
void gb_touch_header(GBCONTAINER *gbc)
Definition: ad_core.cxx:108
#define GB_GET_SECURITY_WRITE(gb)
Definition: gb_data.h:302
const char * quark2key(GB_MAIN_TYPE *Main, GBQUARK key_quark)
Definition: gb_key.h:45
char * GB_read_bytes(GBDATA *gbd)
Definition: arbdb.cxx:974
char * GB_get_subfields(GBDATA *gbd)
Definition: arbdb.cxx:2225
static GB_shell * inside_shell
Definition: arbdb.cxx:452
gb_flag_types2 flags2
Definition: gb_data.h:135
GBDATA * gb_key
Definition: gb_key.h:35
static long GB_read_floats_count(GBDATA *gbd)
Definition: arbdb.cxx:1048
gb_data_base_type_union info
Definition: gb_data.h:204
GB_MAIN_TYPE * GB_MAIN(GBDATA *gbd)
Definition: gb_data.h:291
long GB_read_count(GBDATA *gbd)
Definition: arbdb.cxx:758
void insert_data(const char *Data, long Size, long Memsize)
Definition: gb_storage.h:60
GBCONTAINER * expect_container() const
Definition: gb_data.h:169
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
GB_ERROR GB_copy_dropMarksAndTempstate(GBDATA *dest, GBDATA *source)
Definition: arbdb.cxx:2163
GBDATA * GB_get_root(GBDATA *gbd)
Definition: arbdb.cxx:1740
long nref
Definition: gb_key.h:31
long GB_read_from_ints(GBDATA *gbd, long index)
Definition: arbdb.cxx:1186
gb_user * users[GB_MAX_USERS]
Definition: gb_main.h:156
bool search_system_folder
Definition: gb_localdata.h:57
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
gb_compress_tree * bituncompress
Definition: gb_localdata.h:59
unsigned int folded_container
Definition: gb_data.h:82
double GB_read_from_floats(GBDATA *gbd, long index)
Definition: arbdb.cxx:1203
size_t memsize() const
Definition: gb_data.h:215
long gb_create_key(GB_MAIN_TYPE *Main, const char *key, bool create_gb_key)
Definition: ad_core.cxx:708
GB_CSTR GB_read_pntr(GBDATA *gbd)
Definition: arbdb.cxx:877
GB_ERROR GB_resort_data_base(GBDATA *gb_main, GBDATA **new_order_list, long listsize)
Definition: arbdb.cxx:2655
GB_ERROR gbcmc_end_sendupdate(GBDATA *gbd)
Definition: adcomm.cxx:1365
GB_ERROR GB_copy_full(GBDATA *dest, GBDATA *source)
Definition: arbdb.cxx:2190
bool GB_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2750
static int GB_is_in_buffer(GB_CBUFFER ptr)
Definition: arbdb.cxx:338
#define ASSERT_RESULT(Type, Expected, Expr)
Definition: arb_assert.h:336
GB_ERROR GB_write_ints(GBDATA *gbd, const GB_UINT4 *i, long size)
Definition: arbdb.cxx:1439
GBCONTAINER * gb_create_container(GBCONTAINER *father, const char *key)
Definition: arbdb.cxx:1773
gbcmc_comm * c_link
Definition: gb_main.h:117
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
static GB_BUFFER give_buffer(gb_buffer *buf, size_t size)
Definition: arbdb.cxx:294
void GB_internal_errorf(const char *templat,...)
Definition: arb_msg.cxx:445
GB_ERROR gbcmc_commit_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1596
int GB_nsons(GBDATA *gbd)
Definition: arbdb.cxx:2636
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:202
int GB_read_flag(GBDATA *gbd)
Definition: arbdb.cxx:2796
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2524
long GB_read_bytes_count(GBDATA *gbd)
Definition: arbdb.cxx:969
void GB_disable_quicksave(GBDATA *gbd, const char *reason)
Definition: arbdb.cxx:2647
GBDATA * GB_create(GBDATA *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1781
bool GB_have_error()
Definition: arb_msg.cxx:337
char * GB_read_bits(GBDATA *gbd, char c_0, char c_1)
Definition: arbdb.cxx:958
void GBK_terminatef(const char *templat,...)
Definition: arb_msg.cxx:464
GBDATA * GB_HEADER_LIST_GBD(gb_header_list &hl)
Definition: gb_header.h:42
int compression_mask
Definition: gb_main.h:129
CONSTEXPR_INLINE gb_header_list * GB_DATA_LIST_HEADER(gb_data_list &dl)
Definition: gb_data.h:105
GB_ERROR gb_commit_transaction_local_rek(GBDATA *&gbd, long mode, int *pson_created)
Definition: ad_core.cxx:818
gb_header_flags & GB_ARRAY_FLAGS(GBDATA *gbd)
Definition: gb_header.h:49
float GB_atof(const char *str)
Definition: arbdb.cxx:190
bool GB_has_key(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1707
GBQUARK gb_find_or_create_quark(GB_MAIN_TYPE *Main, const char *key)
Definition: arbdb.cxx:1668
long GB_read_memuse(GBDATA *gbd)
Definition: arbdb.cxx:762
gb_index_files * GB_INDEX_FILES_NEXT(gb_index_files *ixf)
Definition: gb_index.h:87
char * gb_read_cache(GBENTRY *gbe)
Definition: adcache.cxx:179
int GB_unlink(const char *path)
Definition: arb_file.cxx:188
GB_BUFFER GB_give_buffer2(long size)
Definition: arbdb.cxx:334
#define GB_GET_SECURITY_DELETE(gb)
Definition: gb_data.h:303
GB_TYPES type() const
Definition: gb_data.h:139
GB_MAIN_TYPE * GBCONTAINER_MAIN(GBCONTAINER *gbc)
Definition: gb_data.h:289
static void run_close_callbacks(GBDATA *gb_main)
Definition: arbdb.cxx:647
gb_flag_types2 & get_user_flags(GBDATA *gbd)
Definition: arbdb.cxx:2746
bool call(GBDATA *with, GB_CB_TYPE typemask)
Definition: gb_cb.h:144
GBCONTAINER * root_container
Definition: gb_main.h:120
char * gb_compress_bits(const char *source, long size, const unsigned char *c_0, long *msize)
Definition: adcompr.cxx:250
void forget_hierarchy_cbs()
Definition: ad_cb.cxx:100
GB_BUFFER GB_give_buffer(size_t size)
Definition: arbdb.cxx:311
static void gb_delete_entry(GBCONTAINER *&gbc)
Definition: ad_core.cxx:473
static void GB_exit_gb()
Definition: arbdb.cxx:423
void setNull()
set SmartPtr to NULp
Definition: smartptr.h:251
GB_ERROR gb_transactable_type(GB_TYPES type, GBDATA *gbd)
Definition: arbdb.cxx:76
GB_ERROR GB_write_security_read(GBDATA *gbd, unsigned long level)
Definition: arbdb.cxx:1595
Definition: gb_key.h:28
GB_ERROR GB_copy_dropProtectMarksAndTempstate(GBDATA *dest, GBDATA *source)
Definition: arbdb.cxx:2152
static unsigned char GB_BIT_compress_data[]
Definition: arbdb.cxx:369
long clock
Definition: gb_main.h:151
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
GB_CFLOAT * GB_read_floats_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1019
const char * ARB_float_2_ascii(const float f)
Definition: arb_misc.cxx:66
#define NOT4PERL
Definition: arbdb_base.h:23
GBENTRY * gb_create(GBCONTAINER *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1763
GB_ERROR GB_incur_error_if(bool error_may_occur)
Definition: arb_msg.h:56
void GB_end_transaction_show_error(GBDATA *gbd, GB_ERROR error, void(*error_handler)(GB_ERROR))
Definition: arbdb.cxx:2584
static bool initialized
Definition: AW_advice.cxx:36
POS_TREE1 * father
Definition: probe_tree.h:39
static int gb_info(GBDATA *gbd, int deep)
Definition: arbdb.cxx:2833
void SET_GB_HEADER_LIST_GBD(gb_header_list &hl, GBDATA *gbd)
Definition: gb_header.h:45
int gb_get_compression_mask(GB_MAIN_TYPE *Main, GBQUARK key, int gb_type)
Definition: arbdb.cxx:1329
unsigned int GB_UINT4
Definition: arbdb_base.h:37
void GB_raise_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2755
GB_ERROR GB_export_error(const char *error)
Definition: arb_msg.cxx:256
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1656
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2561
uchar flags
Definition: probe_tree.h:38
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:341
char * GB_memdup(const char *source, size_t len)
Definition: adstring.cxx:56
GB_ERROR gb_unfold(GBCONTAINER *gbc, long deep, int index_pos)
Definition: arbdb.cxx:586
gb_flag_types flags
Definition: gb_data.h:134
#define TEST_EXPECT(cond)
Definition: test_unit.h:1313
Definition: arbdb.h:67
Definition: arbdb.h:78
GBCM_ServerResult
Definition: gb_local.h:93
char * gb_set_undo_sync(GBDATA *gb_main)
Definition: adindex.cxx:579
void GB_warningf(const char *templat,...)
Definition: arb_msg.cxx:477
TYPE * ARB_alloc(size_t nelem)
Definition: arb_mem.h:56
void gb_untouch_children_and_me(GBCONTAINER *gbc)
Definition: ad_core.cxx:159
NOT4PERL float GB_read_lossless_float(GBDATA *gbd, GB_ERROR &error)
Definition: arbdb.cxx:1155
GB_ERROR gbcmc_init_transaction(GBCONTAINER *gbc)
Definition: adcomm.cxx:1549
gb_cache_entry * entries
Definition: gb_main.h:61
void GBK_install_SIGSEGV_handler(bool dump_backtrace)
Definition: arb_signal.cxx:47
GB_ERROR GB_write_bits(GBDATA *gbd, const char *bits, long size, const char *c_0)
Definition: arbdb.cxx:1418
bool isSet() const
test if SmartPtr is not NULp
Definition: smartptr.h:245
GB_ERROR error_with_dbentry(const char *action, GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:129
NOT4PERL uint8_t GB_read_lossless_byte(GBDATA *gbd, GB_ERROR &error)
Definition: arbdb.cxx:1093
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2892
char * mem
Definition: gb_localdata.h:27
char * gb_alloc_cache_index(GBENTRY *gbe, size_t size)
Definition: adcache.cxx:260
void GBK_terminate(const char *error) __ATTR__NORETURN
Definition: arb_msg.cxx:450
#define GB_TEST_NON_BUFFER(x, gerror)
Definition: arbdb.cxx:165
GB_ERROR gbcm_unfold_client(GBCONTAINER *gbc, long deep, long index_pos)
Definition: adcomm.cxx:1305
GBQUARK GB_find_existing_quark(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1690
static char * gb_stpcpy(char *dest, const char *source)
Definition: arbdb.cxx:2220
bool is_server() const
Definition: gb_main.h:203
~GB_shell()
Definition: arbdb.cxx:458
int gb_convert_type_2_appendix_size[]
Definition: arbdb.cxx:244
static const char * GB_TYPES_2_name(GB_TYPES type)
Definition: arbdb.cxx:37
GB_ERROR GB_write_bytes(GBDATA *gbd, const char *s, long size)
Definition: arbdb.cxx:1434
Definition: arbdb.h:64
NOT4PERL int GB_give_buffer_size()
Definition: arbdb.cxx:330
GB_shell()
Definition: arbdb.cxx:454
GB_ERROR begin_transaction() __ATTR__USERESULT
Definition: arbdb.cxx:2359
#define RETURN_ERROR(err)
Definition: arb_msg.h:27
void gb_abort_transaction_local_rek(GBDATA *&gbd)
Definition: ad_core.cxx:787
unsigned int user_bits
Definition: gb_data.h:80
float * GB_read_floats(GBDATA *gbd)
Definition: arbdb.cxx:1053
GBQUARK key2quark(GB_MAIN_TYPE *Main, const char *key)
Definition: gb_key.h:42
static void ensure_inside()
Definition: arbdb.cxx:463
unsigned int key_quark
Definition: gb_header.h:21
char * gb_disable_undo(GBDATA *gb_main)
Definition: adindex.cxx:607
bool is_container() const
Definition: gb_data.h:147
int GB_read_security_read(GBDATA *gbd)
Definition: arbdb.cxx:1576
void announce_db_close(GB_MAIN_TYPE *Main)
Definition: arbdb.cxx:562
static GB_test_shell_closed shell_manager
Definition: arbdb.cxx:492
void gbm_debug_mem()
Definition: admalloc.cxx:549
#define TEST_REJECT(cond)
Definition: test_unit.h:1315
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1310
GB_ERROR push_transaction() __ATTR__USERESULT
Definition: arbdb.cxx:2447
bool GB_in_temporary_branch(GBDATA *gbd)
Definition: arbdb.cxx:2310
GB_BUFFER gb_uncompress_bits(const char *source, long size, char c_0, char c_1)
Definition: adcompr.cxx:294
char GB_type_2_char(GB_TYPES type)
Definition: arbdb.cxx:2809
static void error(const char *msg)
Definition: mkptypes.cxx:96
GBDATA * GB_clone(GBDATA *gb_destCont, GBDATA *gb_source)
Definition: arbdb.cxx:2196
bool is_client() const
Definition: gb_main.h:204
GB_ERROR gb_delete_force(GBDATA *source)
Definition: arbdb.cxx:1945
void GB_flush_cache(GBDATA *gbd)
Definition: adcache.cxx:226
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1829
gb_flag_types3 flags3
Definition: gb_data.h:245
GB_ERROR GB_write_byte(GBDATA *gbd, int i)
Definition: arbdb.cxx:1238
void GB_clear_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2760
void GB_print_debug_information(struct Unfixed_cb_parameter *, GBDATA *gb_main)
Definition: arbdb.cxx:2814
gb_compress_list * bitcompress
Definition: gb_localdata.h:60
#define GB_PUT_SECURITY_WRITE(gb, i)
Definition: gb_data.h:306
#define SIZOFINTERN
Definition: gb_data.h:25
GB_ERROR GB_write_lossless_int(GBDATA *gbd, int32_t i)
Definition: arbdb.cxx:1523
void gb_save_extern_data_in_ts__and_uncache(GBENTRY *gbe)
Definition: arbdb.cxx:1300
long GB_read_int(GBDATA *gbd)
Definition: arbdb.cxx:729
bool GB_inside_remote_action(GBDATA *gbd)
Definition: adcomm.cxx:1668
size_t size
Definition: gb_localdata.h:28
void GB_init_gb()
Definition: arbdb.cxx:512
gb_db_extended * ext
Definition: gb_data.h:132
const int gb_convert_type_2_compression_flags[]
Definition: arbdb.cxx:204
unsigned int update_in_server
Definition: gb_data.h:83
unsigned int security_delete
Definition: gb_data.h:67
int gb_key_disabled
Definition: gb_key.h:37
void gb_untouch_me(GBENTRY *gbe)
Definition: ad_core.cxx:149
long GB_read_clients(GBDATA *gbd)
Definition: adcomm.cxx:1682
static void gb_uncache(GBCONTAINER *gbc)
Definition: adcache.cxx:221
GBCONTAINER * as_container() const
Definition: gb_data.h:155
GB_ERROR GB_copy_overlay(GBDATA *dest, GBDATA *source)
Definition: arbdb.cxx:2182
int open_dbs() const
Definition: gb_localdata.h:71
void ARB_recalloc(TYPE *&tgt, size_t oelem, size_t nelem)
Definition: arb_mem.h:49
#define TEST_EXPECT_ZERO_OR_SHOW_ERRNO(iocond)
Definition: test_unit.h:1079
void * gbm_get_mem(size_t size, long index)
Definition: gb_memory.h:130
void gb_create_header_array(GBCONTAINER *gbc, int size)
Definition: ad_core.cxx:176
GB_ERROR GB_write_lossless_float(GBDATA *gbd, float f)
Definition: arbdb.cxx:1546
GB_ERROR GB_write_autoconv_string(GBDATA *gbd, const char *val)
Definition: arbdb.cxx:1479
GB_UINT4 * GB_read_ints(GBDATA *gbd)
Definition: arbdb.cxx:1013
void GB_touch(GBDATA *gbd)
Definition: arbdb.cxx:2802
GB_CSTR GB_read_bytes_pntr(GBDATA *gbd)
Definition: arbdb.cxx:964
int compression_mask
Definition: gb_key.h:38
CONSTEXPR_INLINE GBCONTAINER * GB_FATHER(GBDATA *gbd)
Definition: gb_data.h:271
int cache_index
Definition: gb_data.h:206
GB_ERROR GB_set_temporary(GBDATA *gbd)
Definition: arbdb.cxx:2282
gb_exitfun * atgbexit
Definition: gb_localdata.h:66
GB_ERROR GB_release(GBDATA *gbd)
Definition: arbdb.cxx:2600
static GB_ERROR gb_set_compression(GBDATA *source)
Definition: arbdb.cxx:1866
char * key
Definition: gb_key.h:29
GBDATA * GB_get_grandfather(GBDATA *gbd)
Definition: arbdb.cxx:1728
GBDATA * gb_main() const
Definition: gb_main.h:179
Definition: arbdb.h:86
GB_ERROR GB_write_int(GBDATA *gbd, long i)
Definition: arbdb.cxx:1250
static bool in_shell()
Definition: arbdb.cxx:465
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2528
GB_ERROR GB_write_pntr(GBDATA *gbd, const char *s, size_t bytes_size, size_t stored_size)
Definition: arbdb.cxx:1344
gb_index_files * GBCONTAINER_IFS(GBCONTAINER *gbc)
Definition: gb_index.h:94
GBQUARK GB_find_or_create_quark(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1695
void gbm_flush_mem()
Definition: admalloc.cxx:198
GB_ERROR gbcmc_begin_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1469
GB_ERROR cannot_use_fun4entry(const char *fun, GBDATA *gb_entry)
Definition: arbdb.cxx:1086
static GBDATA * gb_remembered_db()
Definition: arbdb.cxx:581
unsigned int temporary
Definition: gb_data.h:73
void gb_untouch_children(GBCONTAINER *gbc)
Definition: ad_core.cxx:114
char * write_buffer
Definition: gb_localdata.h:52
gb_if_entries * GB_IF_ENTRIES_NEXT(gb_if_entries *ie)
Definition: gb_index.h:29
ARB_TRANS_TYPE running_client_transaction
Definition: gb_localdata.h:64
gb_exitfun * next
Definition: arbdb.cxx:399
GB_ERROR pop_transaction() __ATTR__USERESULT
Definition: arbdb.cxx:2454
int gb_read_nr(GBDATA *gbd)
Definition: arbdb.cxx:900
GB_ERROR GB_print_error()
Definition: arb_msg.cxx:323
int get_transaction_level() const
Definition: gb_main.h:177
GBENTRY * gb_make_entry(GBCONTAINER *father, const char *key, long index_pos, GBQUARK keyq, GB_TYPES type)
Definition: ad_core.cxx:353
char * write_ptr
Definition: gb_localdata.h:53
long int flag
Definition: f2c.h:39
int GB_get_transaction_level(GBDATA *gbd)
Definition: arbdb.cxx:2590
static void init_buffer(gb_buffer *buf, size_t initial_size)
Definition: arbdb.cxx:270
GB_ERROR GB_no_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2535
void GB_test_transaction(GB_MAIN_TYPE *Main)
Definition: gb_ta.h:21
char * data()
Definition: gb_data.h:219
const float GB_CFLOAT
Definition: arbdb_base.h:43
Definition: arbdb.h:72
GBQUARK gb_find_or_create_NULL_quark(GB_MAIN_TYPE *Main, const char *key)
Definition: arbdb.cxx:1678
GB_ERROR GB_copy_std(GBDATA *dest, GBDATA *source)
Definition: arbdb.cxx:2174
gb_callback_list * callback
Definition: gb_data.h:59
long write_bufsize
Definition: gb_localdata.h:54
unsigned int security_level
Definition: gb_main.h:150
Definition: arbdb.h:63
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1387
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:261
static void gb_do_callbacks(GBDATA *gbd)
Definition: arbdb.cxx:1223
void GB_internal_error(const char *message)
Definition: arb_msg.cxx:422
GBQUARK GB_KEY_QUARK(GBDATA *gbd)
Definition: gb_key.h:48
GBDATA * GB_read_pointer(GBDATA *gbd)
Definition: arbdb.cxx:739
long GB_read_clock(GBDATA *gbd)
Definition: arbdb.cxx:1714
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
#define IF_ASSERTION_USED(x)
Definition: arb_assert.h:308
GBCONTAINER * gb_make_container(GBCONTAINER *father, const char *key, long index_pos, GBQUARK keyq)
Definition: ad_core.cxx:414
bool mapped
Definition: gb_main.h:137
#define TEST_EXPECT_NULL(n)
Definition: test_unit.h:1307
#define gb_assert(cond)
Definition: arbdbt.h:11
GB_TYPES GB_read_type(GBDATA *gbd)
Definition: arbdb.cxx:1643
void open_global_shell()
Definition: arbdb.cxx:480
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2773
#define GB_DO_CALLBACKS(gbd)
Definition: arbdb.cxx:1236
int userbit
Definition: gb_comm.h:24
GB_ERROR commit_transaction() __ATTR__USERESULT
Definition: arbdb.cxx:2387
char * GB_read_key(GBDATA *gbd)
Definition: arbdb.cxx:1652
static __ATTR__USERESULT GB_ERROR gb_security_error(GBDATA *gbd)
Definition: arbdb.cxx:103
long GB_REL_IFES
Definition: gb_memory.h:59
gb_callback_list * close_callbacks
Definition: gb_main.h:154
size_t uncompressed_size() const
Definition: gb_compress.h:48
void gb_save_extern_data_in_ts(GBENTRY *gbe)
Definition: ad_core.cxx:639
GB_CUINT4 * GB_read_ints_pntr(GBDATA *gbd)
Definition: arbdb.cxx:979
static void run_and_destroy_exit_functions(gb_exitfun *fun)
Definition: arbdb.cxx:415
GB_ERROR GB_write_security_write(GBDATA *gbd, unsigned long level)
Definition: arbdb.cxx:1584
bool is_entry() const
Definition: gb_data.h:148
long index
Definition: gb_data.h:133
#define __ATTR__USERESULT
Definition: attributes.h:58
GB_CSTR gb_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1664
char * GB_read_string(GBDATA *gbd)
Definition: arbdb.cxx:909
int GB_info(GBDATA *gbd)
Definition: arbdb.cxx:2888
GB_ERROR gb_copy_checked(GBDATA *dest, GBDATA *source, CopyMode mode)
Definition: arbdb.cxx:2142
GB_ERROR gb_write_compressed_pntr(GBENTRY *gbe, const char *s, long memsize, long stored_size)
Definition: arbdb.cxx:1317
gb_transaction_save * old
Definition: gb_data.h:60
listtype callbacks
Definition: gb_cb.h:67
void GB_change_my_security(GBDATA *gbd, int level)
Definition: arbdb.cxx:1627
GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname)
Definition: adcomm.cxx:1934
GB_BUFFER GB_increase_buffer(size_t size)
Definition: arbdb.cxx:316
void GBK_dump_backtrace(FILE *out, const char *message)
Definition: arb_msg.cxx:415
GB_ERROR gb_resort_system_folder_to_top(GBCONTAINER *gb_main)
Definition: arbdb.cxx:2705
static int GB_info_deep
Definition: arbdb.cxx:2830
gb_compress_list * gb_build_compress_list(const unsigned char *data, long short_flag, long *size)
Definition: adcompr.cxx:193
GB_ERROR GB_test_delete_possible(GBDATA *gb_obj)
Definition: arbdb.cxx:1904
GB_ERROR GB_write_float(GBDATA *gbd, float f)
Definition: arbdb.cxx:1281
unsigned int changed
Definition: gb_header.h:22
~gb_local_data()
Definition: arbdb.cxx:434
#define GB_TEST_READ_PTR(gbd, type, ignored)
Definition: arbdb.cxx:162
#define GB_PUT_SECURITY_DELETE(gb, i)
Definition: gb_data.h:307
GB_ERROR gb_type_readable_from(GB_TYPES type, GBDATA *gbd)
Definition: arbdb.cxx:125
const char * GB_get_db_path(GBDATA *gbd)
Definition: adTest.cxx:14
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1107
long GB_read_ints_count(GBDATA *gbd)
Definition: arbdb.cxx:1008
#define TEST_EXPECT_SEGFAULT(cb)
Definition: test_unit.h:1244
gb_compress_tree * gb_build_uncompress_tree(const unsigned char *data, long short_flag, char **end)
Definition: adcompr.cxx:120
gb_Key * keys
Definition: gb_main.h:134
void announce_db_open(GB_MAIN_TYPE *Main)
Definition: arbdb.cxx:550
GBENTRY * as_entry() const
Definition: gb_data.h:150
GBDATA * GBCONTAINER_ELEM(GBCONTAINER *gbc, int idx)
Definition: gb_header.h:57
gb_buffer buf2
Definition: gb_localdata.h:51
#define NULp
Definition: cxxforward.h:114
gb_data_list d
Definition: gb_data.h:246
size_t size() const
Definition: gb_data.h:214
#define TEST_EXPECT_ERROR_CONTAINS(call, part)
Definition: test_unit.h:1103
int keycnt
Definition: gb_main.h:131
gb_header_flags flags
Definition: gb_header.h:35
#define GB_USERFLAG_ANY
Definition: arbdb.h:54
GB_ERROR GB_write_pointer(GBDATA *gbd, GBDATA *pointer)
Definition: arbdb.cxx:1269
#define TEST_EXPECT_TEXTFILE_DIFFLINES(fgot, fwant, diff)
Definition: test_unit.h:1401
GB_ERROR abort_transaction() __ATTR__USERESULT
Definition: arbdb.cxx:2365
bool GB_is_ancestor_of(GBDATA *gb_ancestor, GBDATA *gb_descendant)
Definition: arbdb.cxx:1744
int GB_read_security_write(GBDATA *gbd)
Definition: arbdb.cxx:1572
GB_TYPES
Definition: arbdb.h:62
GB_ERROR gb_type_writeable_to(GB_TYPES type, GBDATA *gbd)
Definition: arbdb.cxx:116
const char * GB_CBUFFER
Definition: arbdb_base.h:27
const char * GB_get_type_name(GBDATA *gbd)
Definition: arbdb.cxx:72
const int GBCM_BUFFER
Definition: adtune.cxx:16
GBDATA * GB_nextChild(GBDATA *child)
Definition: adquery.cxx:326
GB_REL_IFES * GB_INDEX_FILES_ENTRIES(gb_index_files *ifs)
Definition: gb_index.h:80
int GB_open_DBs()
Definition: arbdb.cxx:522
GB_ERROR GB_write_security_levels(GBDATA *gbd, unsigned long readlevel, unsigned long writelevel, unsigned long deletelevel)
Definition: arbdb.cxx:1615
GBDATA * GBT_find_item_rel_item_data(GBDATA *gb_item_data, const char *id_field, const char *id_value)
Definition: aditem.cxx:74
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:904
GB_ERROR GB_abort_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2539
void(* exitfun)()
Definition: arbdb.cxx:398
GB_transaction ta(gb_var)
#define BUFSIZE
GBDATA * gb_main
Definition: adname.cxx:33
void gbm_free_mem(void *block, size_t size, long index)
Definition: gb_memory.h:131
int GB_read_byte(GBDATA *gbd)
Definition: arbdb.cxx:734
GB_ERROR GB_write_lossless_byte(GBDATA *gbd, uint8_t byte)
Definition: arbdb.cxx:1504
Definition: arbdb.h:71
void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q)
Definition: adsystem.cxx:112
long hash_table_size
Definition: gb_index.h:50
GB_MAIN_TYPE * get_any_open_db()
Definition: gb_localdata.h:75
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
GB_ERROR gbcmc_abort_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1615
GB_BUFFER GB_give_other_buffer(GB_CBUFFER buffer, long size)
Definition: arbdb.cxx:363
int nheader
Definition: gb_data.h:102
static GBDATA * gb_clone_explicit(GBCONTAINER *gb_destCont, GBDATA *gb_source, CopyMode mode)
Definition: arbdb.cxx:1972
void gbm_init_mem()
Definition: admalloc.cxx:219
void gb_touch_entry(GBDATA *gbd, GB_CHANGE val)
Definition: ad_core.cxx:83
bool GB_readable_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1080
int gb_convert_type_2_sizeof[]
Definition: arbdb.cxx:223
#define GB_ENTRIES_ENTRY(entries, idx)
Definition: gb_index.h:64
GBCM_ServerResult gbcmc_close(gbcmc_comm *link)
Definition: adcomm.cxx:1916
void close_global_shell()
Definition: arbdb.cxx:485
void gb_abort_and_close_all_DBs()
Definition: arbdb.cxx:710
GB_ERROR no_transaction()
Definition: arbdb.cxx:2462
const unsigned int GB_CUINT4
Definition: arbdb_base.h:40
gb_cache cache
Definition: gb_main.h:128
void GB_atexit(void(*exitfun)())
Definition: arbdb.cxx:402
const char * GB_CSTR
Definition: arbdb_base.h:25
bool GB_allow_compression(GBDATA *gb_main, bool allow_compression)
Definition: arbdb.cxx:1896
void call_pending_callbacks()
Definition: ad_cb.cxx:86
GBQUARK GB_get_quark(GBDATA *gbd)
Definition: arbdb.cxx:1703
int GB_read_security_delete(GBDATA *gbd)
Definition: arbdb.cxx:1580
GBCONTAINER * gb_get_root(GBENTRY *gbe)
Definition: arbdb.cxx:1741
int GBQUARK
Definition: arbdb_base.h:30
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
char * GB_BUFFER
Definition: arbdb_base.h:26
static int is_in_buffer(gb_buffer *buf, GB_CBUFFER ptr)
Definition: arbdb.cxx:305
gb_local_data * gb_local
Definition: arbdb.cxx:33
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
unsigned int security_write
Definition: gb_data.h:68
GBCONTAINER * get_father()
Definition: gb_data.h:276
GB_ERROR gbcmc_begin_sendupdate(GBDATA *gbd)
Definition: adcomm.cxx:1356
unsigned int compressed_data
Definition: gb_data.h:70
gb_callback_list * get_callbacks() const
Definition: gb_data.h:195
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:193
long next_free_key
Definition: gb_key.h:32
float GB_read_float(GBDATA *gbd)
Definition: arbdb.cxx:744
GB_CSTR GB_read_bits_pntr(GBDATA *gbd, char c_0, char c_1)
Definition: arbdb.cxx:926
GBCONTAINER * dummy_father
Definition: gb_main.h:119
int headermemsize
Definition: gb_data.h:100
Definition: arbdb.h:66
~GB_shell4perl()
Definition: arbdb.cxx:497
char * GB_check_out_buffer(GB_CBUFFER buffer)
Definition: arbdb.cxx:350
CopyMode
Definition: arbdb.cxx:1955
void gb_delete_dummy_father(GBCONTAINER *&gbc)
Definition: ad_core.cxx:542
unsigned int flags
Definition: gb_header.h:20
long GB_read_bits_count(GBDATA *gbd)
Definition: arbdb.cxx:921
#define GB_TEST_WRITE(gbd, type, ignored)
Definition: arbdb.cxx:163
GB_write_int const char s
Definition: AW_awar.cxx:154