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