ARB
adcomm.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : adcomm.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include <unistd.h>
12 
13 #include <csignal>
14 #include <cerrno>
15 
16 #include <sys/socket.h>
17 
18 #include <netinet/in.h>
19 #include <netinet/tcp.h>
20 
21 #include "gb_key.h"
22 #include "gb_comm.h"
23 #include "gb_localdata.h"
24 
25 #include <SigHandler.h>
26 #include <arb_signal.h>
27 #include <arb_file.h>
28 
29 static GBCM_ServerResult gbcms_talking(int con, long *hs, void *sin);
30 
31 
32 #define FD_SET_TYPE
33 
34 #define debug_printf(a, b)
35 
36 #define GBCMS_TRANSACTION_TIMEOUT 60*60 // one hour timeout
37 #define MAX_QUEUE_LEN 5
38 
39 #define GBCM_COMMAND_UNFOLD (GBTUM_MAGIC_NUMBER)
40 #define GBCM_COMMAND_GET_UPDATA (GBTUM_MAGIC_NUMBER+1)
41 #define GBCM_COMMAND_PUT_UPDATE (GBTUM_MAGIC_NUMBER+2)
42 #define GBCM_COMMAND_UPDATED (GBTUM_MAGIC_NUMBER+3)
43 #define GBCM_COMMAND_BEGIN_TRANSACTION (GBTUM_MAGIC_NUMBER+4)
44 #define GBCM_COMMAND_COMMIT_TRANSACTION (GBTUM_MAGIC_NUMBER+5)
45 #define GBCM_COMMAND_ABORT_TRANSACTION (GBTUM_MAGIC_NUMBER+6)
46 #define GBCM_COMMAND_INIT_TRANSACTION (GBTUM_MAGIC_NUMBER+7)
47 #define GBCM_COMMAND_FIND (GBTUM_MAGIC_NUMBER+8)
48 #define GBCM_COMMAND_CLOSE (GBTUM_MAGIC_NUMBER+9)
49 #define GBCM_COMMAND_KEY_ALLOC (GBTUM_MAGIC_NUMBER+11)
50 #define GBCM_COMMAND_UNDO (GBTUM_MAGIC_NUMBER+12)
51 #define GBCM_COMMAND_DONT_WAIT (GBTUM_MAGIC_NUMBER+13)
52 
53 #define GBCM_COMMAND_SEND (GBTUM_MAGIC_NUMBER+0x1000)
54 #define GBCM_COMMAND_SEND_COUNT (GBTUM_MAGIC_NUMBER+0x2000)
55 #define GBCM_COMMAND_SETDEEP (GBTUM_MAGIC_NUMBER+0x3000)
56 #define GBCM_COMMAND_SETINDEX (GBTUM_MAGIC_NUMBER+0x4000)
57 #define GBCM_COMMAND_PUT_UPDATE_KEYS (GBTUM_MAGIC_NUMBER+0x5000)
58 #define GBCM_COMMAND_PUT_UPDATE_CREATE (GBTUM_MAGIC_NUMBER+0x6000)
59 #define GBCM_COMMAND_PUT_UPDATE_DELETE (GBTUM_MAGIC_NUMBER+0x7000)
60 #define GBCM_COMMAND_PUT_UPDATE_UPDATE (GBTUM_MAGIC_NUMBER+0x8000)
61 #define GBCM_COMMAND_PUT_UPDATE_END (GBTUM_MAGIC_NUMBER+0x9000)
62 #define GBCM_COMMAND_TRANSACTION_RETURN (GBTUM_MAGIC_NUMBER+0x100000)
63 #define GBCM_COMMAND_FIND_ERG (GBTUM_MAGIC_NUMBER+0x108000)
64 #define GBCM_COMMAND_KEY_ALLOC_RES (GBTUM_MAGIC_NUMBER+0x10b000)
65 #define GBCM_COMMAND_UNDO_CMD (GBTUM_MAGIC_NUMBER+0x10a0001)
66 
67 // --------------------------
68 // error generators
69 
70 inline GB_ERROR clientserver_error(const char *clientserver, const char *what_failed, int sourceLine) {
71  const char *rev_tag = GB_get_arb_revision_tag();
72  return GBS_global_string("ARBDB %s error: %s (errcode=%s#%i)", clientserver, what_failed, rev_tag, sourceLine);
73 }
74 
75 #define CLIENT_ERROR(reason) clientserver_error("client", reason, __LINE__)
76 #define SERVER_ERROR(reason) clientserver_error("server", reason, __LINE__)
77 #define COMM_ERROR(reason) clientserver_error("communication", reason, __LINE__)
78 
79 #define CLIENT_RECEIVE_ERROR() CLIENT_ERROR("receive failed")
80 #define SERVER_RECEIVE_ERROR() SERVER_ERROR("receive failed")
81 #define COMM_RECEIVE_ERROR() COMM_ERROR("receive failed")
82 
83 #define CLIENT_SEND_ERROR() CLIENT_ERROR("send failed")
84 #define SERVER_SEND_ERROR() SERVER_ERROR("send failed")
85 #define COMM_SEND_ERROR() COMM_ERROR("send failed")
86 
87 #define CLIENT_SEND_ERROR_AT_ITEM(gb_item) CLIENT_ERROR(GBS_global_string("send failed (entry='%s')", GB_KEY(gb_item)))
88 
89 static void dumpError(GB_ERROR error) {
90  fputc('\n', stderr);
91  fputs(error, stderr);
92  fputc('\n', stderr);
93  fflush(stderr);
94 }
95 
96 // ------------------------
97 // some structures
98 
99 struct gbcms_delete_list { // Store all deleted items in a list
104 };
105 
106 struct Socinf {
107  Socinf *next;
108  int socket;
109  gbcms_delete_list *dl; // point to last deleted item that is sent to this client
110  char *username;
111 };
112 
113 static void g_bcms_delete_Socinf(Socinf *THIS) {
114  freenull(THIS->username);
115  THIS->next = NULp;
116  free(THIS);
117 }
118 
120  int hso;
121  char *unix_name;
123  long nsoc;
124  long timeout;
128 
129  gbcms_delete_list *del_first; // All deleted items, that are yet unknown to at least one client
131 };
132 
133 
134 
135 struct gbcms_create {
139 };
140 
141 
142 // --------------------
143 // Panic save
144 
146 
147 static void gbcms_sighup(int) {
148  char *panic_file = NULp; // hang-up trigger file
149  char *db_panic = NULp; // file to save DB to
150  {
151  const char *ap = GB_getenv("ARB_PID");
152  if (!ap) ap = "";
153 
154  FILE *in = GB_fopen_tempfile(GBS_global_string("arb_panic_%s_%s", GB_getenvUSER(), ap), "rt", &panic_file);
155 
156  fprintf(stderr,
157  "**** ARB DATABASE SERVER received a HANGUP SIGNAL ****\n"
158  "- Looking for file '%s'\n",
159  panic_file);
160 
161  db_panic = GB_read_fp(in);
162  fclose(in);
163  }
164 
165  if (!db_panic) {
166  fprintf(stderr,
167  "- Could not read '%s' (Reason: %s)\n"
168  "[maybe retry]\n",
169  panic_file, GB_await_error());
170  }
171  else {
172  char *newline = strchr(db_panic, '\n');
173  if (newline) newline[0] = 0;
174 
175  fprintf(stderr, "- Trying to save DATABASE in ASCII mode into file '%s'\n", db_panic);
176 
177  GB_ERROR error = GBCONTAINER_MAIN(gbcms_gb_main)->panic_save(db_panic);
178 
179  if (error) fprintf(stderr, "Error while saving '%s': %s\n", db_panic, error);
180  else fprintf(stderr, "- DATABASE saved into '%s' (ASCII)\n", db_panic);
181 
182  unlink(panic_file);
183  free(db_panic);
184  }
185 }
186 
187 GB_ERROR GB_MAIN_TYPE::panic_save(const char *db_panic) {
188  const int org_transaction_level = transaction_level;
189 
190  transaction_level = 0;
191  GB_ERROR error = save_as(db_panic, "az"); // attempt zipped first
192  if (error) error = save_as(db_panic, "a"); // fallback to plain ascii on failure
193  transaction_level = org_transaction_level;
194 
195  return error;
196 }
197 
198 GB_ERROR GBCMS_open(const char *path, long timeout, GBDATA *gb_main) {
199  // server open
200 
201  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
202  GB_ERROR error = NULp;
203 
204  if (Main->server_data) {
205  error = "reopen of server not allowed";
206  }
207  else {
208  gbcmc_comm *comm = gbcmc_open(path);
209  if (comm) {
210  error = GBS_global_string("Socket '%s' already in use", path);
211  gbcmc_close(comm); // ignore result
212  }
213  else {
214  int socket;
215  char *unix_name = NULp;
216 
217  error = gbcm_open_socket(path, false, &socket, &unix_name);
218  if (!error) {
219  ASSERT_RESULT(SigHandler, SIG_DFL, INSTALL_SIGHANDLER(SIGHUP, gbcms_sighup, "GBCMS_open"));
220 
221  gbcms_gb_main = gb_main->as_container();
222 
223  if (listen(socket, MAX_QUEUE_LEN) < 0) {
224  error = GBS_global_string("could not listen (server; errno=%i)", errno);
225  }
226  else {
227  gb_server_data *hs = ARB_calloc<gb_server_data>(1);
228 
229  hs->timeout = timeout;
230  hs->gb_main = gb_main;
231  hs->hso = socket;
232  hs->unix_name = unix_name;
233 
234  Main->server_data = hs;
235  }
236  }
237  }
238  }
239 
240  if (error) {
241  error = GBS_global_string("ARB_DB_SERVER_ERROR: %s", error);
242  fprintf(stderr, "%s\n", error);
243  }
244  return error;
245 }
246 
247 void GBCMS_shutdown(GBDATA *gbd) {
248  // server close
249 
250  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
251  if (Main->server_data) {
252  gb_server_data *hs = Main->server_data;
253  Socinf *si;
254 
255  for (si=hs->soci; si; si=si->next) {
256  shutdown(si->socket, SHUT_RDWR);
257  close(si->socket);
258  }
259  shutdown(hs->hso, SHUT_RDWR);
260 
261  if (hs->unix_name) {
262  unlink(hs->unix_name);
263  freenull(hs->unix_name);
264  }
265  close(hs->hso);
266  freenull(Main->server_data);
267  }
268 }
269 
270 template<typename T>
271 inline void write_into_comm_buffer(long& buffer, T& t) {
272  STATIC_ASSERT(sizeof(t) <= sizeof(long));
273 
274  buffer = 0; // initialize (avoid to write uninitialized byte to avoid valgrind errors)
275  *(T*)(&buffer) = t;
276 }
277 
278 static __ATTR__USERESULT GB_ERROR gbcm_write_bin(int socket, GBDATA *gbd, long *buffer, long deep, int send_headera) {
279  /* send a database item to client/server
280  *
281  * mode =1 server
282  * =0 client
283  * buffer = buffer
284  * deep = 0 -> just send one item >0 send sub entries too
285  * send_headera = 1 -> if type = GB_DB send flag and key_quark array
286  */
287 
288  buffer[0] = GBCM_COMMAND_SEND;
289 
290  long i = 2;
291  buffer[i++] = (long)gbd;
292  buffer[i++] = gbd->index;
293 
294  write_into_comm_buffer(buffer[i++], gbd->flags);
295 
296  if (gbd->is_container()) {
297  GBCONTAINER *gbc = gbd->as_container();
298  int end = gbc->d.nheader;
299 
300  write_into_comm_buffer(buffer[i++], gbc->flags3);
301 
302  buffer[i++] = send_headera ? end : -1;
303  buffer[i++] = deep ? gbc->d.size : -1;
304  buffer[1] = i;
305 
306  if (gbcm_write(socket, (const char *)buffer, i* sizeof(long))) {
307  return COMM_SEND_ERROR();
308  }
309 
310  if (send_headera) {
311  gb_header_list *hdl = GB_DATA_LIST_HEADER(gbc->d);
313 
314  for (int index = 0; index < end; index++) {
315  buf2[index] = hdl[index].flags;
316  }
317  if (gbcm_write(socket, (const char *)buf2, end * sizeof(gb_header_flags))) {
318  return COMM_SEND_ERROR();
319  }
320  }
321 
322  if (deep) {
323  debug_printf("%i ", gbc->d.size);
324 
325  for (int index = 0; index < end; index++) {
326  GBDATA *gb2 = GBCONTAINER_ELEM(gbc, index);
327  if (gb2) {
328  debug_printf("%i ", index);
329  GB_ERROR error = gbcm_write_bin(socket, gb2, (long *)buffer, deep-1, send_headera);
330  if (error) return error;
331  }
332  }
333  debug_printf("\n", 0);
334  }
335  }
336  else {
337  GBENTRY *gbe = gbd->as_entry();
338  if (gbe->type() < GB_BITS) {
339  buffer[i++] = gbe->info.i;
340  buffer[1] = i;
341  if (gbcm_write(socket, (const char *)buffer, i*sizeof(long))) {
342  return COMM_SEND_ERROR();
343  }
344  }
345  else {
346  long memsize;
347  buffer[i++] = gbe->size();
348  memsize = buffer[i++] = gbe->memsize();
349  buffer[1] = i;
350  if (gbcm_write(socket, (const char *)buffer, i* sizeof(long))) {
351  return COMM_SEND_ERROR();
352  }
353  if (gbcm_write(socket, gbe->data(), memsize)) {
354  return COMM_SEND_ERROR();
355  }
356  }
357  }
358  return NULp;
359 }
360 
361 #define RETURN_SERVER_FAULT_ON_BAD_ADDRESS(ptr) \
362  do { \
363  GB_ERROR error = GBK_test_address((long*)(ptr), GBTUM_MAGIC_NUMBER); \
364  if (error) { \
365  GB_warningf("%s (%s, #%i)", error, __FILE__, __LINE__); \
366  return GBCM_SERVER_FAULT; \
367  } \
368  } while (0)
369 
370 static GBCM_ServerResult gbcm_read_bin(int socket, GBCONTAINER *gbc, long *buffer, long mode, GBDATA *gb_source, void *cs_main) {
371  /* read an entry into gbc
372  * mode == 1 server reads data
373  * mode == 0 client read all data
374  * mode == -1 client read but do not read subobjects -> folded cont
375  * mode == -2 client dummy read
376  */
377 
378  long size = gbcm_read(socket, (char *)buffer, sizeof(long) * 3);
379  if (size != sizeof(long) * 3) {
380  fprintf(stderr, "receive failed header size\n");
381  return GBCM_SERVER_FAULT;
382  }
383  if (buffer[0] != GBCM_COMMAND_SEND) {
384  fprintf(stderr, "receive failed wrong command\n");
385  return GBCM_SERVER_FAULT;
386  }
387 
388  long id = buffer[2];
389  long i = buffer[1];
390  i = sizeof(long) * (i - 3);
391 
392  size = gbcm_read(socket, (char *)buffer, i);
393  if (size != i) {
394  GB_internal_error("receive failed DB_NODE\n");
395  return GBCM_SERVER_FAULT;
396  }
397 
398  i = 0;
399  long index_pos = buffer[i++];
400  if (!gb_source && gbc && index_pos<gbc->d.nheader) {
401  gb_source = GBCONTAINER_ELEM(gbc, index_pos);
402  }
403 
404  gb_flag_types flags = *(gb_flag_types *)(&buffer[i++]);
405  GB_TYPES type = GB_TYPES(flags.type);
406 
407  GBDATA *gb2;
408  if (mode >= -1) { // real read data
409  if (gb_source) {
410  GB_TYPES stype = gb_source->type();
411  gb2 = gb_source;
412  if (stype != type) {
413  GB_internal_error("Type changed in client: Connection aborted\n");
414  return GBCM_SERVER_FAULT;
415  }
416  if (mode>0) { // transactions only in server
418  }
419  if (stype != GB_DB) {
421  }
423  }
424  else {
425  if (mode==-1) goto dont_create_in_a_folded_container;
426  if (type == GB_DB) {
427  gb2 = gb_make_container(gbc, NULp, index_pos, GB_DATA_LIST_HEADER(gbc->d)[index_pos].flags.key_quark);
428  }
429  else { // @@@ Header Transaction stimmt nicht
430  gb2 = gb_make_entry(gbc, NULp, index_pos, GB_DATA_LIST_HEADER(gbc->d)[index_pos].flags.key_quark, (GB_TYPES)type);
431  }
432  if (mode>0) { // transaction only in server
434  }
435  else {
436  gb2->server_id = id;
437  GBS_write_numhash(GB_MAIN(gb2)->remote_hash, id, (long) gb2);
438  }
439  if (cs_main) {
440  gbcms_create *cs = ARB_calloc<gbcms_create>(1);
441  cs->next = *((gbcms_create **) cs_main);
442  *((gbcms_create **) cs_main) = cs;
443  cs->server_id = gb2;
444  cs->client_id = (GBDATA *)id;
445  }
446  }
447  gb2->flags = flags;
448  if (type == GB_DB) {
449  gb2->as_container()->flags3 = *((gb_flag_types3 *)&(buffer[i++]));
450  }
451  }
452  else {
453  dont_create_in_a_folded_container :
454  if (type == GB_DB) {
455  // gb_flag_types3 flags3 = *((gb_flag_types3 *)&(buffer[i++]));
456  ++i;
457  }
458  gb2 = NULp;
459  }
460 
461  if (type == GB_DB) {
462  long nheader = buffer[i++];
463  long nitems = buffer[i++];
464 
465  if (nheader > 0) {
466  long realsize = nheader* sizeof(gb_header_flags);
467  gb_header_flags *buffer2 = (gb_header_flags *)GB_give_buffer2(realsize);
468 
469  size = gbcm_read(socket, (char *)buffer2, realsize);
470  if (size != realsize) {
471  GB_internal_error("receive failed data\n");
472  return GBCM_SERVER_FAULT;
473  }
474  if (gb2 && mode >= -1) {
475  GBCONTAINER *gbc2 = gb2->as_container();
476  GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gbc2);
477 
478  gb_create_header_array(gbc2, (int)nheader);
479  if (nheader < gbc2->d.nheader) {
480  GB_internal_error("Inconsistency Client-Server Cache");
481  }
482  gbc2->d.nheader = (int)nheader;
483  gb_header_list *hdl = GB_DATA_LIST_HEADER(gbc2->d);
484  for (long item = 0; item < nheader; item++) {
485  GBQUARK old_index = hdl->flags.key_quark;
486  GBQUARK new_index = buffer2->key_quark;
487  if (new_index && !old_index) { // a rename ...
488  gb_write_index_key(gbc2, item, new_index);
489  }
490  if (mode>0) { // server read data
491 
492 
493  }
494  else {
495  if (buffer2->changed >= GB_DELETED) {
497  }
498  }
499  hdl->flags.flags = buffer2->flags;
500  hdl++; buffer2++;
501  }
502  if (mode>0) { // transaction only in server
503  gb_touch_header(gbc2);
504  }
505  else {
506  gbc2->header_update_date = Main->clock;
507  }
508  }
509  }
510 
511  if (nitems >= 0) {
512  long newmod = mode;
513  if (mode>=0) {
514  if (mode==0 && nitems<=1) { // only a partial send
515  gb2->flags2.folded_container = 1;
516  }
517  }
518  else {
519  newmod = -2;
520  }
521  debug_printf("Client %i \n", nheader);
522  for (long item = 0; item < nitems; item++) {
523  debug_printf(" Client reading %i\n", item);
524  long irror = gbcm_read_bin(socket, gb2->as_container(), buffer, newmod, NULp, cs_main);
525  if (irror) {
526  return GBCM_SERVER_FAULT;
527  }
528  }
529  debug_printf("Client done\n", 0);
530  }
531  else {
532  if ((mode==0) && !gb_source) { // created GBDATA at client
533  gb2->flags2.folded_container = 1;
534  }
535  }
536  }
537  else {
538  if (mode >= 0) {
539  GBENTRY *ge2 = gb2->as_entry();
540  if (type < GB_BITS) {
541  ge2->info.i = buffer[i++];
542  }
543  else {
544  long realsize = buffer[i++];
545  long memsize = buffer[i++];
546 
547  ge2->index_check_out();
548  assert_or_exit(!(ge2->stored_external() && ge2->info.ex.get_data()));
549 
550  GBENTRY_memory storage(ge2, realsize, memsize);
551  size = gbcm_read(socket, storage, memsize);
552  if (size != memsize) {
553  fprintf(stderr, "receive failed data\n");
554  return GBCM_SERVER_FAULT;
555  }
556  }
557  }
558  else {
559  if (type >= GB_BITS) { // dummy read (e.g. updata in server && not cached in client
560  long memsize;
561  char *buffer2;
562  i++;
563  memsize = buffer[i++];
564  buffer2 = GB_give_buffer2(memsize);
565 
566  size = gbcm_read(socket, buffer2, memsize);
567  if (size != memsize) {
568  GB_internal_error("receive failed data\n");
569  return GBCM_SERVER_FAULT;
570  }
571  }
572  }
573  }
574 
575  return GBCM_SERVER_OK;
576 }
577 
578 
579 static void gbcms_shift_delete_list(void *hsi, void *soi) {
580  gb_server_data *hs = (gb_server_data *)hsi;
581  Socinf *socinf = (Socinf *)soi;
582 
583  if (!hs->del_first) return;
584  while ((!socinf->dl) || (socinf->dl->next)) {
585  if (!socinf->dl) socinf->dl = hs->del_first;
586  else socinf->dl = socinf->dl->next;
587  }
588 }
589 
590 static GBCM_ServerResult gbcms_write_deleted(int socket, long hsin, long client_clock, long *buffer) {
591  Socinf *socinf;
592  gb_server_data *hs;
593  gbcms_delete_list *dl;
594 
595  hs = (gb_server_data *)hsin;
596  for (socinf = hs->soci; socinf; socinf=socinf->next) {
597  if (socinf->socket == socket) break;
598  }
599  if (!socinf) return GBCM_SERVER_OK;
600  if (!hs->del_first) return GBCM_SERVER_OK;
601  while (!socinf->dl || (socinf->dl->next)) {
602  if (!socinf->dl) socinf->dl = hs->del_first;
603  else socinf->dl = socinf->dl->next;
604  if (socinf->dl->creation_date>client_clock) continue;
605  // created and deleted object
606  buffer[0] = GBCM_COMMAND_PUT_UPDATE_DELETE;
607  buffer[1] = (long)socinf->dl->gbd;
608  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
609  }
610  for (socinf = hs->soci; socinf; socinf=socinf->next) {
611  if (!socinf->dl) return GBCM_SERVER_OK;
612  }
613  while ((dl = hs->del_first)) {
614  for (socinf = hs->soci; socinf; socinf=socinf->next) {
615  if (socinf->dl == dl) return GBCM_SERVER_OK;
616  }
617  hs->del_first = dl->next;
619  }
620  return GBCM_SERVER_OK;
621 }
622 
623 static GBCM_ServerResult gbcms_write_updated(int socket, GBDATA *gbd, long hsin, long client_clock, long *buffer) {
624  if (gbd->update_date()<=client_clock) return GBCM_SERVER_OK;
625  if (gbd->creation_date() > client_clock) {
626  buffer[0] = GBCM_COMMAND_PUT_UPDATE_CREATE;
627  buffer[1] = (long)GB_FATHER(gbd);
628  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
629 
630  GB_ERROR error = gbcm_write_bin(socket, gbd, buffer, 0, 1);
631  if (error) {
632  dumpError(error);
633  return GBCM_SERVER_FAULT;
634  }
635  }
636  else { // send clients first
637  if (gbd->is_container()) {
638  GBCONTAINER *gbc = gbd->as_container();
639  int end = (int)gbc->d.nheader;
640  int send_header = (gbc->header_update_date > client_clock) ? 1 : 0;
641 
642  buffer[0] = GBCM_COMMAND_PUT_UPDATE_UPDATE;
643  buffer[1] = (long)gbd;
644  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
645 
646  GB_ERROR error = gbcm_write_bin(socket, gbd, buffer, 0, send_header);
647  if (error) {
648  dumpError(error);
649  return GBCM_SERVER_FAULT;
650  }
651 
652  for (int index = 0; index < end; index++) {
653  GBDATA *gb2 = GBCONTAINER_ELEM(gbc, index);
654  if (gb2 && gbcms_write_updated(socket, gb2, hsin, client_clock, buffer)) {
655  return GBCM_SERVER_FAULT;
656  }
657  }
658  }
659  else {
660  buffer[0] = GBCM_COMMAND_PUT_UPDATE_UPDATE;
661  buffer[1] = (long)gbd;
662  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
663 
664  const int SEND_HEADER = 0;
665  GB_ERROR error = gbcm_write_bin(socket, gbd, buffer, 0, SEND_HEADER);
666  if (error) {
667  dumpError(error);
668  return GBCM_SERVER_FAULT;
669  }
670  }
671  }
672 
673  return GBCM_SERVER_OK;
674 }
675 
676 static GBCM_ServerResult gbcms_write_keys(int socket, GBDATA *gbd) { // @@@ move into GB_MAIN_TYPE?
677  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
678 
679  long buffer[4];
680  buffer[0] = GBCM_COMMAND_PUT_UPDATE_KEYS;
681  buffer[1] = (long)gbd;
682  buffer[2] = Main->keycnt;
683  buffer[3] = Main->first_free_key;
684 
685  if (gbcm_write(socket, (const char *)buffer, 4*sizeof(long))) return GBCM_SERVER_FAULT;
686 
687  for (int i=1; i<Main->keycnt; i++) {
688  gb_Key &key = Main->keys[i];
689  buffer[0] = key.nref;
690  buffer[1] = key.next_free_key;
691  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
692  if (gbcm_write_string(socket, key.key)) return GBCM_SERVER_FAULT;
693  }
694  return GBCM_SERVER_OK;
695 }
696 
697 static GBCM_ServerResult gbcms_talking_unfold(int socket, long */*hsin*/, void */*sin*/, GBDATA *gb_in) {
698  // command: GBCM_COMMAND_UNFOLD
699 
700  GBCONTAINER *gbc = gb_in->expect_container();
701  GBDATA *gb2;
702  char *buffer;
703  long deep[1];
704  long index_pos[1];
705  int index, start, end;
706 
708  if (gbc->type() != GB_DB) return GBCM_SERVER_FAULT;
709  if (gbcm_read_two(socket, GBCM_COMMAND_SETDEEP, NULp, deep)) {
710  return GBCM_SERVER_FAULT;
711  }
712  if (gbcm_read_two(socket, GBCM_COMMAND_SETINDEX, NULp, index_pos)) {
713  return GBCM_SERVER_FAULT;
714  }
715 
716  gbcm_read_flush();
717  buffer = GB_give_buffer(1014);
718 
719  if (index_pos[0]==-2) {
720  GB_ERROR error = gbcm_write_bin(socket, gbc, (long *)buffer, deep[0]+1, 1);
721  if (error) {
722  dumpError(error);
723  return GBCM_SERVER_FAULT;
724  }
725  gbcm_write_flush(socket);
726  return GBCM_SERVER_OK;
727  }
728 
729  if (index_pos[0] >= 0) {
730  start = (int)index_pos[0];
731  end = start + 1;
732  if (gbcm_write_two(socket, GBCM_COMMAND_SEND_COUNT, 1)) {
733  return GBCM_SERVER_FAULT;
734  }
735  }
736  else {
737  start = 0;
738  end = gbc->d.nheader;
739  if (gbcm_write_two(socket, GBCM_COMMAND_SEND_COUNT, gbc->d.size)) {
740  return GBCM_SERVER_FAULT;
741  }
742  }
743  for (index = start; index < end; index++) {
744  if ((gb2 = GBCONTAINER_ELEM(gbc, index))) {
745  GB_ERROR error = gbcm_write_bin(socket, gb2, (long *)buffer, deep[0], 1);
746  if (error) {
747  dumpError(error);
748  return GBCM_SERVER_FAULT;
749  }
750  }
751  }
752 
753  gbcm_write_flush(socket);
754  return GBCM_SERVER_OK;
755 }
756 
757 static GBCM_ServerResult gbcms_talking_get_update(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
758  return GBCM_SERVER_OK;
759 }
760 
761 static GBCM_ServerResult gbcms_talking_put_update(int socket, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
762  /* Reads
763  * - the date
764  * - and all changed data
765  * from client.
766  *
767  * command: GBCM_COMMAND_PUT_UPDATE
768  */
769  long irror;
770  GBDATA *gbd;
771  gbcms_create *cs[1], *cs_main[1];
772  long *buffer;
773  bool end;
774 
775  cs_main[0] = NULp;
776  buffer = (long *) GB_give_buffer(1024);
777  end = false;
778  while (!end) {
779  if (gbcm_read(socket, (char *) buffer, sizeof(long) * 3) != sizeof(long) * 3) {
780  return GBCM_SERVER_FAULT;
781  }
782  gbd = (GBDATA *) buffer[2];
784  switch (buffer[0]) {
786  irror = gbcm_read_bin(socket, gbd->as_container(), buffer, 1, NULp, (void *)cs_main);
787  if (irror) return GBCM_SERVER_FAULT;
788  break;
790  gb_delete_force(gbd);
791  break;
793  irror = gbcm_read_bin(socket, NULp, buffer, 1, gbd, NULp);
794  if (irror) return GBCM_SERVER_FAULT;
795  break;
797  end = true;
798  break;
799  default:
800  return GBCM_SERVER_FAULT;
801  }
802  }
803  gbcm_read_flush(); // send all id's of newly created objects
804  for (cs[0] = cs_main[0]; cs[0]; cs[0]=cs_main[0]) {
805  cs_main[0] = cs[0]->next;
806  buffer[0] = (long)cs[0]->client_id;
807  buffer[1] = (long)cs[0]->server_id;
808  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
809  free(cs[0]);
810  }
811  buffer[0] = 0;
812  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
813  gbcm_write_flush(socket);
814  return GBCM_SERVER_OK;
815 }
816 
817 static GBCM_ServerResult gbcms_talking_updated(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
818  return GBCM_SERVER_OK;
819 }
820 
821 static GBCM_ServerResult gbcms_talking_init_transaction(int socket, long *hsin, void *sin, GBDATA */*gbd*/) {
822  /* begin client transaction
823  * sends clock
824  *
825  * command: GBCM_COMMAND_INIT_TRANSACTION
826  */
827 
828  gb_server_data *hs = (gb_server_data *)hsin;
829  Socinf *si = (Socinf *)sin;
830 
831  GBDATA *gb_main = hs->gb_main;
832  GB_MAIN_TYPE *Main = GB_MAIN(gb_main);
833  GBDATA *gbd = gb_main;
834  char *user = gbcm_read_string(socket);
835 
836  gbcm_read_flush();
837  if (gbcm_login(gbd->as_container(), user)) {
838  return GBCM_SERVER_FAULT;
839  }
840  si->username = user;
841 
843 
845  return GBCM_SERVER_FAULT;
846  }
847  if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, (long)gbd)) {
848  return GBCM_SERVER_FAULT;
849  }
850  if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, (long)Main->this_user->userid)) {
851  return GBCM_SERVER_FAULT;
852  }
853  gbcms_write_keys(socket, gbd);
854 
855  gbcm_write_flush(socket);
856  // send modified data to client
857 
860  fd_set set;
861  FD_ZERO(&set);
862  FD_SET(socket, &set);
863 
864  struct timeval timeout;
865  timeout.tv_sec = GBCMS_TRANSACTION_TIMEOUT;
866  timeout.tv_usec = 100000;
867 
868  long anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULp, NULp, &timeout);
869 
870  if (anz<0) continue;
871  if (anz==0) {
872  GB_export_errorf("ARB_DB ERROR CLIENT TRANSACTION TIMEOUT, CLIENT DISCONNECTED (I waited %lu seconds)", timeout.tv_sec);
873  GB_print_error();
876  return GBCM_SERVER_FAULT;
877  }
878  if (GBCM_SERVER_OK == gbcms_talking(socket, hsin, sin)) continue;
881  return GBCM_SERVER_FAULT;
882  }
885  gbcms_shift_delete_list(hsin, sin);
886  }
887  else {
889  }
890  return GBCM_SERVER_OK;
891 }
892 
893 static GBCM_ServerResult gbcms_talking_begin_transaction(int socket, long *hsin, void *sin, GBDATA *long_client_clock) {
894  /* begin client transaction
895  * sends clock
896  * deleted
897  * created+updated
898  *
899  * command: GBCM_COMMAND_BEGIN_TRANSACTION
900  */
901  long client_clock = (long)long_client_clock;
902  GBDATA *gb_main;
903  GBDATA *gbd;
904  gb_server_data *hs = (gb_server_data *)hsin;
905  long anz;
906  long *buffer;
907  fd_set set;
908  timeval timeout;
909 
910  gb_main = hs->gb_main;
911  gbd = gb_main;
912  gbcm_read_flush();
914 
915  if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, GB_MAIN(gbd)->clock)) {
916  return GBCM_SERVER_FAULT;
917  }
918 
919  // send modified data to client
920  buffer = (long *)GB_give_buffer(1024);
921  if (GB_MAIN(gb_main)->key_clock > client_clock) {
922  if (gbcms_write_keys(socket, gbd)) return GBCM_SERVER_FAULT;
923  }
924  if (gbcms_write_deleted(socket, (long)hs, client_clock, buffer)) return GBCM_SERVER_FAULT;
925  if (gbcms_write_updated(socket, gbd, (long)hs, client_clock, buffer)) return GBCM_SERVER_FAULT;
926  buffer[0] = GBCM_COMMAND_PUT_UPDATE_END;
927  buffer[1] = 0;
928  if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
929  if (gbcm_write_flush(socket)) return GBCM_SERVER_FAULT;
930 
933  FD_ZERO(&set);
934  FD_SET(socket, &set);
935 
936  timeout.tv_sec = GBCMS_TRANSACTION_TIMEOUT;
937  timeout.tv_usec = 0;
938 
939  anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULp, NULp, &timeout);
940 
941  if (anz<0) continue;
942  if (anz==0) {
943  GB_export_errorf("ARB_DB ERROR CLIENT TRANSACTION TIMEOUT, CLIENT DISCONNECTED (I waited %lu seconds)", timeout.tv_sec);
944  GB_print_error();
947  return GBCM_SERVER_FAULT;
948  }
949  if (GBCM_SERVER_OK == gbcms_talking(socket, hsin, sin)) continue;
952  return GBCM_SERVER_FAULT;
953  }
956  gbcms_shift_delete_list(hsin, sin);
957  }
958  else {
960  }
961  return GBCM_SERVER_OK;
962 }
963 
964 static GBCM_ServerResult commit_or_abort_transaction(int socket, GBDATA *gbd, ARB_TRANS_TYPE commit_or_abort) {
966 
967  gb_local->running_client_transaction = commit_or_abort;
968  gbcm_read_flush();
969 
971  return gbcm_write_flush(socket);
972 }
973 static GBCM_ServerResult gbcms_talking_commit_transaction(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
974  // command: GBCM_COMMAND_COMMIT_TRANSACTION
975  return commit_or_abort_transaction(socket, gbd, ARB_COMMIT);
976 }
977 
978 static GBCM_ServerResult gbcms_talking_abort_transaction(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
979  // command: GBCM_COMMAND_ABORT_TRANSACTION
980  return commit_or_abort_transaction(socket, gbd, ARB_ABORT);
981 }
982 
983 static GBCM_ServerResult gbcms_talking_close(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
984  // command: GBCM_COMMAND_CLOSE
985  return GBCM_SERVER_ABORTED;
986 }
987 
988 static GBCM_ServerResult gbcms_talking_undo(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
989  // command: GBCM_COMMAND_UNDO
990  long cmd;
991  GB_ERROR result = NULp;
992  char *to_free = NULp;
993  if (gbcm_read_two(socket, GBCM_COMMAND_UNDO_CMD, NULp, &cmd)) {
994  return GBCM_SERVER_FAULT;
995  }
996  gbcm_read_flush();
997  switch (cmd) {
999  result = GB_request_undo_type(gbd, GB_UNDO_NONE);
1000  break;
1002  result = GB_request_undo_type(gbd, GB_UNDO_KILL);
1003  break;
1005  result = GB_request_undo_type(gbd, GB_UNDO_UNDO);
1006  break;
1008  result = to_free = GB_undo_info(gbd, GB_UNDO_UNDO);
1009  break;
1011  result = to_free = GB_undo_info(gbd, GB_UNDO_REDO);
1012  break;
1013  case _GBCMC_UNDOCOM_UNDO:
1014  result = GB_undo(gbd, GB_UNDO_UNDO);
1015  break;
1016  case _GBCMC_UNDOCOM_REDO:
1017  result = GB_undo(gbd, GB_UNDO_REDO);
1018  break;
1019  default: result = GB_set_undo_mem(gbd, cmd);
1020  }
1021  if (gbcm_write_string(socket, result)) {
1022  if (to_free) free(to_free);
1023  return GBCM_SERVER_FAULT;
1024  }
1025  if (to_free) free(to_free);
1026  return gbcm_write_flush(socket);
1027 }
1028 
1029 static GBCM_ServerResult gbcms_talking_find(int socket, long */*hsin*/, void */*sin*/, GBDATA * gbd) {
1030  // command: GBCM_COMMAND_FIND
1031 
1032  char *key;
1033  char *val1 = NULp;
1034  GB_CASE case_sens = GB_CASE_UNDEFINED;
1035  long val2 = 0;
1036  GB_TYPES type;
1037  void *buffer[2];
1038 
1040 
1041  key = gbcm_read_string(socket);
1042  type = GB_TYPES(gbcm_read_long(socket));
1043 
1044  switch (type) {
1045  case GB_NONE:
1046  break;
1047 
1048  case GB_STRING:
1049  val1 = gbcm_read_string(socket);
1050  case_sens = GB_CASE(gbcm_read_long(socket));
1051  break;
1052 
1053  case GB_INT:
1054  val2 = gbcm_read_long(socket);
1055  break;
1056 
1057  default:
1058  gb_assert(0);
1059  GB_export_errorf("gbcms_talking_find: illegal data type (%i)", type);
1060  GB_print_error();
1061  return GBCM_SERVER_FAULT;
1062  }
1063 
1064  {
1066  gbcm_read_flush();
1067 
1068  if (type == GB_FIND) {
1069  gbd = GB_find(gbd, key, gbs);
1070  }
1071  else if (type == GB_STRING) {
1072  gbd = GB_find_string(gbd, key, val1, case_sens, gbs);
1073  free(val1);
1074  }
1075  else if (type == GB_INT) {
1076  gbd = GB_find_int(gbd, key, val2, gbs);
1077  }
1078  else {
1079  GB_internal_errorf("Searching DBtype %i not implemented", type);
1080  }
1081  }
1082 
1083  free(key);
1084 
1085  if (gbcm_write_two(socket, GBCM_COMMAND_FIND_ERG, (long) gbd)) {
1086  return GBCM_SERVER_FAULT;
1087  }
1088  if (gbd) {
1089  while (GB_GRANDPA(gbd)) {
1090  buffer[0] = (void *)gbd->index;
1091  buffer[1] = (void *)GB_FATHER(gbd);
1092  gbcm_write(socket, (const char *) buffer, sizeof(long) * 2);
1093  gbd = GB_FATHER(gbd);
1094  }
1095  }
1096  buffer[0] = NULp;
1097  buffer[1] = NULp;
1098  gbcm_write(socket, (const char *) buffer, sizeof(long) * 2);
1099 
1100  return gbcm_write_flush(socket);
1101 }
1102 
1103 static GBCM_ServerResult gbcms_talking_key_alloc(int socket, long */*hsin*/, void */*sin*/, GBDATA * gbd) {
1104  // command: GBCM_COMMAND_KEY_ALLOC
1105  // (old maybe wrong comment: "do a query in the server")
1106 
1107  char *key;
1108  long index;
1109 
1111  key = gbcm_read_string(socket);
1112  gbcm_read_flush();
1113 
1114  if (key)
1115  index = gb_create_key(GB_MAIN(gbd), key, false);
1116  else
1117  index = 0;
1118 
1119  if (key)
1120  free(key);
1121 
1122  if (gbcm_write_two(socket, GBCM_COMMAND_KEY_ALLOC_RES, index)) {
1123  return GBCM_SERVER_FAULT;
1124  }
1125  return gbcm_write_flush(socket);
1126 }
1127 
1128 static GBCM_ServerResult gbcms_talking_disable_wait_for_new_request(int /*socket*/, long *hsin, void */*sin*/, GBDATA */*gbd*/) {
1129  gb_server_data *hs = (gb_server_data *) hsin;
1130  hs->wait_for_new_request--;
1131  return GBCM_SERVER_OK_WAIT;
1132 }
1133 
1134 static GBCM_ServerResult gbcms_talking_obsolete(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
1135  fputs("Obsolete server function called\n", stderr);
1136  return GBCM_SERVER_FAULT;
1137 }
1138 
1139 // -----------------------
1140 // server talking
1141 
1142 typedef GBCM_ServerResult (*TalkingFunction)(int socket, long *hsin, void *sin, GBDATA *gbd);
1143 
1145  gbcms_talking_unfold, // GBCM_COMMAND_UNFOLD
1146  gbcms_talking_get_update, // GBCM_COMMAND_GET_UPDATA
1147  gbcms_talking_put_update, // GBCM_COMMAND_PUT_UPDATE
1148  gbcms_talking_updated, // GBCM_COMMAND_UPDATED
1149  gbcms_talking_begin_transaction, // GBCM_COMMAND_BEGIN_TRANSACTION
1150  gbcms_talking_commit_transaction, // GBCM_COMMAND_COMMIT_TRANSACTION
1151  gbcms_talking_abort_transaction, // GBCM_COMMAND_ABORT_TRANSACTION
1152  gbcms_talking_init_transaction, // GBCM_COMMAND_INIT_TRANSACTION
1153  gbcms_talking_find, // GBCM_COMMAND_FIND
1154  gbcms_talking_close, // GBCM_COMMAND_CLOSE
1156  gbcms_talking_key_alloc, // GBCM_COMMAND_KEY_ALLOC
1157  gbcms_talking_undo, // GBCM_COMMAND_UNDO
1158  gbcms_talking_disable_wait_for_new_request // GBCM_COMMAND_DONT_WAIT
1159 };
1160 
1161 static GBCM_ServerResult gbcms_talking(int con, long *hs, void *sin) {
1162  gbcm_read_flush();
1163 
1164  next_command :
1165 
1166  long buf[3];
1167  long len = gbcm_read(con, (char *)buf, sizeof(long) * 3);
1168  if (len == sizeof(long) * 3) {
1169  long magic_number = buf[0];
1170  if ((magic_number & GBTUM_MAGIC_NUMBER_FILTER) != GBTUM_MAGIC_NUMBER) {
1171  gbcm_read_flush();
1172  fprintf(stderr, "Illegal Access\n");
1173  return GBCM_SERVER_FAULT;
1174  }
1175  magic_number &= ~GBTUM_MAGIC_NUMBER_FILTER;
1176  GBCM_ServerResult error = (aisc_talking_functions[magic_number])(con, hs, sin, (GBDATA *)buf[2]);
1177  if (error == GBCM_SERVER_OK_WAIT) {
1178  goto next_command;
1179  }
1180  gbcm_read_flush();
1181  return error ? error : GBCM_SERVER_OK;
1182  }
1183  else {
1184  return GBCM_SERVER_FAULT;
1185  }
1186 }
1187 
1188 bool GBCMS_accept_calls(GBDATA *gbd, bool wait_extra_time) {
1189  // returns true if served
1190 
1191  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1192  if (!Main->server_data) return false;
1193  if (Main->get_transaction_level()) return false;
1194 
1195  gb_server_data *hs = Main->server_data;
1196  timeval timeout;
1197 
1198  if (wait_extra_time) {
1199  timeout.tv_sec = 0;
1200  timeout.tv_usec = 100000; // 100 ms
1201  }
1202  else {
1203  timeout.tv_sec = (int)(hs->timeout / 1000);
1204  timeout.tv_usec = (hs->timeout % 1000) * 1000;
1205  }
1206  if (wait_extra_time) {
1207  hs->wait_for_new_request = 1;
1208  }
1209  else {
1210  hs->wait_for_new_request = 0;
1211  }
1212 
1213  {
1214  fd_set set;
1215  fd_set setex;
1216 
1217  FD_ZERO(&set);
1218  FD_ZERO(&setex);
1219  FD_SET(hs->hso, &set);
1220  FD_SET(hs->hso, &setex);
1221 
1222  for (Socinf *si=hs->soci; si; si=si->next) {
1223  FD_SET(si->socket, &set);
1224  FD_SET(si->socket, &setex);
1225  }
1226 
1227  {
1228  long anz;
1229  if (hs->timeout>=0) {
1230  anz = select(FD_SETSIZE, FD_SET_TYPE & set, NULp, FD_SET_TYPE & setex, &timeout);
1231  }
1232  else {
1233  anz = select(FD_SETSIZE, FD_SET_TYPE & set, NULp, FD_SET_TYPE & setex, NULp);
1234  }
1235 
1236  if (anz==-1) return false;
1237  if (!anz) return false; // timed out
1238  }
1239 
1240 
1241  if (FD_ISSET(hs->hso, &set)) {
1242  int con = accept(hs->hso, NULp, NULp);
1243  if (con>0) {
1244  long optval[1];
1245  Socinf *sptr = ARB_calloc<Socinf>(1);
1246  sptr->next = hs->soci;
1247  sptr->socket = con;
1248  hs->soci=sptr;
1249  hs->nsoc++;
1250  optval[0] = 1;
1251  setsockopt(con, IPPROTO_TCP, TCP_NODELAY, (char *)optval, 4);
1252  }
1253  }
1254  else {
1255  Socinf *si_last = NULp;
1256  Socinf *si_next;
1257 
1258  for (Socinf *si=hs->soci; si; si_last=si, si=si_next) {
1259  si_next = si->next;
1260 
1262  if (FD_ISSET(si->socket, &set)) {
1263  error = gbcms_talking(si->socket, (long *)hs, (void *)si);
1264  if (GBCM_SERVER_OK == error) {
1265  hs->wait_for_new_request ++;
1266  continue;
1267  }
1268  } else if (!FD_ISSET(si->socket, &setex)) continue;
1269 
1270  // kill socket
1271 
1272  if (close(si->socket)) {
1273  printf("aisc_accept_calls: ");
1274  printf("couldn't close socket errno = %i!\n", errno);
1275  }
1276 
1277  hs->nsoc--;
1278  if (si==hs->soci) { // first one
1279  hs->soci = si->next;
1280  }
1281  else {
1282  si_last->next = si->next;
1283  }
1284  if (si->username) {
1285  gbcm_logout(Main, si->username);
1286  }
1288  si = NULp;
1289 
1290  if (error != GBCM_SERVER_ABORTED) {
1291  fprintf(stdout, "ARB_DB_SERVER: a client died abnormally\n");
1292  }
1293  break;
1294  }
1295  }
1296 
1297  }
1298  if (hs->wait_for_new_request>0) {
1299  return true;
1300  }
1301  return false;
1302 }
1303 
1304 
1305 GB_ERROR gbcm_unfold_client(GBCONTAINER *gbc, long deep, long index_pos) {
1306  // goes to header: __ATTR__USERESULT
1307 
1308  /* read data from a server
1309  * deep = -1 read whole data
1310  * deep = 0...n read to deep
1311  * index_pos == -1 read all clients
1312  * index_pos == -2 read all clients + header array
1313  */
1314 
1315  GB_ERROR error = NULp;
1316  int socket = GBCONTAINER_MAIN(gbc)->c_link->socket;
1317  gbcm_read_flush();
1318 
1319  if (gbcm_write_two (socket, GBCM_COMMAND_UNFOLD, gbc->server_id)) error = CLIENT_SEND_ERROR();
1320  else if (gbcm_write_two (socket, GBCM_COMMAND_SETDEEP, deep)) error = CLIENT_SEND_ERROR();
1321  else if (gbcm_write_two (socket, GBCM_COMMAND_SETINDEX, index_pos)) error = CLIENT_SEND_ERROR();
1322  else if (gbcm_write_flush(socket)) error = CLIENT_SEND_ERROR();
1323  else {
1324  long buffer[256];
1325  long irror = 0;
1326  if (index_pos == -2) {
1327  irror = gbcm_read_bin(socket, NULp, buffer, 0, gbc, NULp);
1328  }
1329  else {
1330  long nitems;
1331  if (gbcm_read_two(socket, GBCM_COMMAND_SEND_COUNT, NULp, &nitems)) irror = 1;
1332  else {
1333  for (long item = 0; !irror && item<nitems; item++) {
1334  irror = gbcm_read_bin(socket, gbc, buffer, 0, NULp, NULp);
1335  }
1336  }
1337  }
1338 
1339  if (irror) {
1340  error = CLIENT_ERROR(GBS_global_string("receive error while unfolding '%s'", GB_read_key_pntr(gbc)));
1341  }
1342  else {
1343  gbcm_read_flush();
1344  if (index_pos < 0) {
1345  gbc->flags2.folded_container = 0;
1346  }
1347  }
1348  }
1349 
1350  return error;
1351 }
1352 
1353 // -------------------------
1354 // Client functions
1355 
1357  // goes to header: __ATTR__USERESULT
1358 
1359  if (gbcm_write_two(GB_MAIN(gbd)->c_link->socket, GBCM_COMMAND_PUT_UPDATE, gbd->server_id)) {
1360  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1361  }
1362  return NULp;
1363 }
1364 
1366  // goes to header: __ATTR__USERESULT
1367 
1368  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1369  int socket = Main->c_link->socket;
1371  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1372  }
1373 
1374  gbcm_write_flush(socket);
1375  while (1) {
1376  long buffer[2];
1377  if (gbcm_read(socket, (char *)&(buffer[0]), sizeof(long)*2) != sizeof(long)*2) {
1378  return CLIENT_RECEIVE_ERROR();
1379  }
1380  gbd = (GBDATA *)buffer[0];
1381  if (!gbd) break;
1382  gbd->server_id = buffer[1];
1383  GBS_write_numhash(Main->remote_hash, gbd->server_id, (long)gbd);
1384  }
1385  gbcm_read_flush();
1386  return NULp;
1387 }
1388 
1390  // goes to header: __ATTR__USERESULT
1391 
1392  GBCONTAINER *father = GB_FATHER(gbd);
1393  if (!father) {
1394  return CLIENT_ERROR(GBS_global_string("entry '%s' has no father", GB_KEY(gbd)));
1395  }
1396 
1397  int socket = GB_MAIN(father)->c_link->socket;
1399  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1400  }
1401 
1402  long *buffer = (long *)GB_give_buffer(1014);
1403  return gbcm_write_bin(socket, gbd, buffer, -1, 1);
1404 }
1405 
1407  // goes to header: __ATTR__USERESULT
1408 
1409  if (gbcm_write_two(GB_MAIN(gbd)->c_link->socket, GBCM_COMMAND_PUT_UPDATE_DELETE, gbd->server_id)) {
1410  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1411  }
1412  return NULp;
1413 }
1414 
1415 GB_ERROR gbcmc_sendupdate_update(GBDATA *gbd, int send_headera) { // @@@ DRY vs gbcmc_sendupdate_create
1416  // goes to header: __ATTR__USERESULT
1417 
1418  GBCONTAINER *father = GB_FATHER(gbd);
1419  if (!father) {
1420  return CLIENT_ERROR(GBS_global_string("entry '%s' has no father", GB_KEY(gbd)));
1421  }
1422 
1423  int socket = GB_MAIN(father)->c_link->socket;
1425  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1426  }
1427 
1428  long *buffer = (long *)GB_give_buffer(1016);
1429  return gbcm_write_bin(socket, gbd, buffer, 0, send_headera);
1430 }
1431 
1432 static __ATTR__USERESULT GB_ERROR gbcmc_read_keys(int socket, GBDATA *gbd) { // @@@ move into GB_MAIN_TYPE?
1433  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1434  long buffer[2];
1435 
1436  if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1437  return CLIENT_RECEIVE_ERROR();
1438  }
1439 
1440  long size = buffer[0];
1441  Main->first_free_key = buffer[1];
1442  gb_create_key_array(Main, (int)size);
1443 
1444  for (int i=1; i<size; i++) {
1445  if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1446  return CLIENT_RECEIVE_ERROR();
1447  }
1448 
1449  gb_Key &KEY = Main->keys[i];
1450 
1451  KEY.nref = buffer[0]; // to control malloc_index
1452  KEY.next_free_key = buffer[1]; // to control malloc_index
1453 
1454  char *key = gbcm_read_string(socket);
1455  if (key) {
1456  if (!key[0]) { // empty key
1457  free(key);
1458  return CLIENT_ERROR("invalid empty key received");
1459  }
1460 
1461  GBS_write_hash(Main->key_2_index_hash, key, i);
1462  freeset(KEY.key, key);
1463  }
1464  }
1465  Main->keycnt = (int)size;
1466  return NULp;
1467 }
1468 
1470  // goes to header: __ATTR__USERESULT
1471 
1472  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1473  int socket = Main->c_link->socket;
1474  long *buffer = (long *)GB_give_buffer(1026);
1475 
1476  if (gbcm_write_two(socket, GBCM_COMMAND_BEGIN_TRANSACTION, Main->clock)) {
1477  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1478  }
1479 
1480  if (gbcm_write_flush(socket)) {
1481  return CLIENT_SEND_ERROR();
1482  }
1483 
1484  {
1485  long server_clock;
1486  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, &server_clock)) {
1487  return CLIENT_RECEIVE_ERROR();
1488  }
1489  Main->clock = server_clock;
1490  }
1491 
1492  while (1) {
1493  if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1494  return CLIENT_RECEIVE_ERROR();
1495  }
1496 
1497  long d = buffer[1];
1498  GBDATA *gb2 = (GBDATA *)GBS_read_numhash(Main->remote_hash, d);
1499  long mode;
1500  if (gb2) {
1501  mode = gb2->flags2.folded_container
1502  ? -1 // read container
1503  : 0; // read all
1504  }
1505  else {
1506  mode = -2; // read nothing
1507  }
1508 
1509  switch (buffer[0]) {
1511  if (gbcm_read_bin(socket, NULp, buffer, mode, gb2, NULp)) {
1512  return CLIENT_RECEIVE_ERROR();
1513  }
1514  if (gb2) {
1515  gb2->create_extended();
1516  gb2->touch_update(Main->clock);
1517  }
1518  break;
1520  if (gbcm_read_bin(socket, GBDATA::as_container(gb2), buffer, mode, NULp, NULp)) {
1521  return CLIENT_RECEIVE_ERROR();
1522  }
1523  if (gb2) {
1524  gb2->create_extended();
1525  gb2->touch_creation_and_update(Main->clock);
1526  }
1527  break;
1529  if (gb2) gb_delete_entry(gb2);
1530  break;
1532  GB_ERROR error = gbcmc_read_keys(socket, gbd);
1533  if (error) return error;
1534  break;
1535  }
1537  goto endof_gbcmc_begin_transaction;
1538 
1539  default:
1540  return CLIENT_RECEIVE_ERROR();
1541  }
1542  }
1543 
1544  endof_gbcmc_begin_transaction :
1545  gbcm_read_flush();
1546  return NULp;
1547 }
1548 
1550  // goes to header: __ATTR__USERESULT
1551 
1552  GB_ERROR error = NULp;
1553  GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gbc);
1554  int socket = Main->c_link->socket;
1555 
1556  if (gbcm_write_two(socket, GBCM_COMMAND_INIT_TRANSACTION, Main->clock)) {
1557  return CLIENT_SEND_ERROR_AT_ITEM(gbc);
1558  }
1559  gbcm_write_string(socket, Main->this_user->username);
1560  if (gbcm_write_flush(socket)) {
1561  return CLIENT_SEND_ERROR();
1562  }
1563 
1564  {
1565  long server_clock;
1566  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, &server_clock)) {
1567  return CLIENT_RECEIVE_ERROR();
1568  }
1569  Main->clock = server_clock;
1570  }
1571 
1572  long buffer[4];
1573  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, buffer)) {
1574  return CLIENT_RECEIVE_ERROR();
1575  }
1576  gbc->server_id = buffer[0];
1577 
1578  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, buffer)) {
1579  return CLIENT_RECEIVE_ERROR();
1580  }
1581  Main->this_user->userid = (int)buffer[0];
1582  Main->this_user->userbit = 1<<((int)buffer[0]);
1583 
1584  GBS_write_numhash(Main->remote_hash, gbc->server_id, (long)gbc);
1585 
1586  if (gbcm_read(socket, (char *)buffer, 2 * sizeof(long)) != 2 * sizeof(long)) {
1587  return CLIENT_RECEIVE_ERROR();
1588  }
1589  error = gbcmc_read_keys(socket, gbc);
1590  if (error) return error;
1591 
1592  gbcm_read_flush();
1593  return NULp;
1594 }
1595 
1597  // goes to header: __ATTR__USERESULT
1598 
1599  int socket = GB_MAIN(gbd)->c_link->socket;
1601  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1602  }
1603 
1604  if (gbcm_write_flush(socket)) {
1605  return CLIENT_SEND_ERROR();
1606  }
1607 
1608  long dummy;
1609  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, &dummy)) {
1610  return CLIENT_RECEIVE_ERROR();
1611  }
1612  gbcm_read_flush();
1613  return NULp;
1614 }
1615 GB_ERROR gbcmc_abort_transaction(GBDATA *gbd) { // @@@ DRY vs gbcmc_commit_transaction
1616  // goes to header: __ATTR__USERESULT
1617 
1618  int socket = GB_MAIN(gbd)->c_link->socket;
1620  return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1621  }
1622 
1623  if (gbcm_write_flush(socket)) {
1624  return CLIENT_SEND_ERROR();
1625  }
1626 
1627  long dummy;
1628  if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, NULp, &dummy)) {
1629  return CLIENT_RECEIVE_ERROR();
1630  }
1631  gbcm_read_flush();
1632  return NULp;
1633 }
1634 
1636  gb_server_data *hs = GB_MAIN(gbd)->server_data;
1637 
1638  if (hs && hs->soci) {
1640 
1641  dl->creation_date = gbd->creation_date();
1642  dl->update_date = gbd->update_date();
1643  dl->gbd = gbd;
1644 
1645  if (!hs->del_first) {
1646  hs->del_first = hs->del_last = dl;
1647  }
1648  else {
1649  hs->del_last->next = dl;
1650  hs->del_last = dl;
1651  }
1652  }
1653  return NULp;
1654 }
1655 
1656 void GB_set_remote_action(GBDATA *gbd, bool in_action) {
1657  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1658 
1659  if (Main->is_server()) { // GB_set_remote_action has no effect in clients
1660  gb_server_data *hs = Main->server_data;
1661  gb_assert(hs); // have no server data (program logic error)
1662  if (hs) {
1663  gb_assert(hs->inside_remote_action != in_action);
1664  hs->inside_remote_action = in_action;
1665  }
1666  }
1667 }
1669  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1670  bool inside = false;
1671 
1672  gb_assert(Main->is_server()); // GB_inside_remote_action not allowed from clients
1673  if (Main->is_server()) {
1674  gb_server_data *hs = Main->server_data;
1675  if (hs) {
1676  inside = hs->inside_remote_action;
1677  }
1678  }
1679  return inside;
1680 }
1681 
1683  // returns number of clients or
1684  // -1 if not called from server
1685 
1686  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1687  long clients = -1;
1688 
1689  if (Main->is_server()) {
1690  gb_server_data *hs = Main->server_data;
1691  clients = hs ? hs->nsoc : 0;
1692  }
1693 
1694  return clients;
1695 }
1696 
1697 bool GB_is_server(GBDATA *gbd) {
1698  return GB_MAIN(gbd)->is_server();
1699 }
1700 
1702  GB_ERROR error = NULp;
1703 
1704  long readvar[2];
1705  if (!gbcm_read(socket, (char *) readvar, sizeof(long) * 2)) {
1706  error = CLIENT_RECEIVE_ERROR();
1707  }
1708  else {
1709  GBCONTAINER *gb_client = (GBCONTAINER*)readvar[1];
1710  if (gb_client) {
1711  error = gbcmc_unfold_list(socket, gbd);
1712  if (!error) {
1713  gb_client = (GBCONTAINER *)GBS_read_numhash(GB_MAIN(gbd)->remote_hash, (long) gb_client);
1714  gb_unfold(gb_client, 0, (int)readvar[0]);
1715  }
1716  }
1717  }
1718  return error;
1719 }
1720 
1721 static void invalid_use_in_server(const char *function) {
1722  GB_internal_errorf("ARBDB fatal error: function '%s' may not be called in server", function);
1723 }
1724 
1725 GBDATA *GBCMC_find(GBDATA *gbd, const char *key, GB_TYPES type, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs) {
1726  // perform search in DB server (from DB client)
1727  // returns NULp if not found OR error occurred (use GB_have_error to test)
1728 
1729  union {
1730  GBDATA *gbd;
1731  long l;
1732  } result;
1733  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1734 
1735  int socket;
1736  if (Main->is_server()) {
1737  invalid_use_in_server("GBCMC_find");
1738  }
1739 
1740  socket = Main->c_link->socket;
1741 
1742  if (gbcm_write_two(socket, GBCM_COMMAND_FIND, gbd->server_id)) {
1744  return NULp;
1745  }
1746 
1747  gbcm_write_string(socket, key);
1748  gbcm_write_long(socket, type);
1749  switch (type) {
1750  case GB_NONE:
1751  break;
1752  case GB_STRING:
1753  gbcm_write_string(socket, str);
1754  gbcm_write_long(socket, case_sens);
1755  break;
1756  case GB_INT:
1757  gbcm_write_long(socket, *(long*)str);
1758  break;
1759  default:
1760  gb_assert(0);
1761  GB_export_errorf("GBCMC_find: Illegal data type (%i)", type);
1762  return NULp;
1763  }
1764 
1765  gbcm_write_long(socket, gbs);
1766 
1767  if (gbcm_write_flush(socket)) {
1769  return NULp;
1770  }
1771  if (gbcm_read_two(socket, GBCM_COMMAND_FIND_ERG, NULp, &result.l)) {
1773  return NULp;
1774  }
1775  if (result.gbd) {
1776  GB_ERROR error = gbcmc_unfold_list(socket, gbd);
1777  if (error) {
1778  GB_export_error(error);
1779  return NULp;
1780  }
1781  result.l = GBS_read_numhash(Main->remote_hash, result.l);
1782  }
1783  gbcm_read_flush();
1784  return result.gbd;
1785 }
1786 
1787 
1788 long gbcmc_key_alloc(GBDATA *gbd, const char *key) {
1792  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1793  if (Main->is_server()) {
1794  invalid_use_in_server("gbcmc_key_alloc");
1795  }
1796 
1797  int socket = Main->c_link->socket;
1798  GB_ERROR error = NULp;
1799  long result = 0;
1800  if (gbcm_write_two(socket, GBCM_COMMAND_KEY_ALLOC, gbd->server_id)) {
1801  error = CLIENT_SEND_ERROR();
1802  }
1803  else {
1804  gbcm_write_string(socket, key);
1805 
1806  if (gbcm_write_flush(socket)) {
1807  error = CLIENT_SEND_ERROR();
1808  }
1809  else {
1810  if (gbcm_read_two(socket, GBCM_COMMAND_KEY_ALLOC_RES, NULp, &result)) {
1811  error = CLIENT_RECEIVE_ERROR();
1812  result = 0;
1813  }
1814  gbcm_read_flush();
1815  }
1816  }
1817  if (error) {
1818  gb_assert(result == 0); // indicates error
1819  GB_export_error(error);
1820  }
1821  return result;
1822 }
1823 
1824 GB_ERROR gbcmc_send_undo_commands(GBDATA *gbd, enum gb_undo_commands command) { // goes to header: __ATTR__USERESULT
1825  // send an undo command
1826 
1827  GB_ERROR error = NULp;
1828  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1829 
1830  if (Main->is_server()) {
1831  invalid_use_in_server("gbcmc_send_undo_commands");
1832  }
1833  else {
1834  int socket = Main->c_link->socket;
1835 
1836  if (gbcm_write_two (socket, GBCM_COMMAND_UNDO, gbd->server_id)) error = CLIENT_SEND_ERROR();
1837  else if (gbcm_write_two (socket, GBCM_COMMAND_UNDO_CMD, command)) error = CLIENT_SEND_ERROR();
1838  else if (gbcm_write_flush(socket)) error = CLIENT_SEND_ERROR();
1839  else {
1840  error = gbcm_read_string(socket);
1841  gbcm_read_flush();
1842  }
1843  }
1844  return error;
1845 }
1846 
1848  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1849  if (Main->is_server()) {
1850  invalid_use_in_server("gbcmc_send_undo_info_commands");
1851  }
1852 
1853  int socket = Main->c_link->socket;
1854  if (gbcm_write_two(socket, GBCM_COMMAND_UNDO, gbd->server_id) ||
1855  gbcm_write_two(socket, GBCM_COMMAND_UNDO_CMD, command) ||
1856  gbcm_write_flush(socket))
1857  {
1859  return NULp;
1860  }
1861 
1862  char *result = gbcm_read_string(socket);
1863  gbcm_read_flush();
1864  return result;
1865 }
1866 
1868  GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1869  if (Main->is_server()) return NULp;
1870 
1871  int socket = Main->c_link->socket;
1872  if (gbcm_write_two(socket, GBCM_COMMAND_DONT_WAIT, gbd->server_id)) {
1873  return CLIENT_SEND_ERROR();
1874  }
1875 
1876  return NULp;
1877 }
1878 
1879 // ---------------------
1880 // Login/Logout
1881 
1882 
1883 GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *loginname) {
1884  // goes to header: __ATTR__USERESULT
1885 
1886  // look for any free user and set this_user
1887  int i;
1888  GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gb_main);
1889 
1890  for (i = 0; i<GB_MAX_USERS; i++) {
1891  gb_user *user = Main->users[i];
1892  if (user && strcmp(loginname, user->username) == 0) {
1893  Main->this_user = user;
1894  user->nusers++;
1895  return NULp;
1896  }
1897  }
1898  for (i = 0; i<GB_MAX_USERS; i++) {
1899  gb_user*& user = Main->users[i];
1900  if (!user) {
1901  ARB_calloc(user, 1);
1902 
1903  user->username = ARB_strdup(loginname);
1904  user->userid = i;
1905  user->userbit = 1<<i;
1906  user->nusers = 1;
1907 
1908  Main->this_user = user;
1909 
1910  return NULp;
1911  }
1912  }
1913  return GBS_global_string("Too many users in this database (user='%s')", loginname);
1914 }
1915 
1917  if (link->socket) {
1918  if (gbcm_write_two(link->socket, GBCM_COMMAND_CLOSE, 0)) {
1920  return GBCM_SERVER_FAULT;
1921  }
1922  if (gbcm_write_flush(link->socket)) {
1924  return GBCM_SERVER_FAULT;
1925  }
1926  close(link->socket);
1927  link->socket = 0;
1928  }
1929  free(link->unix_name);
1930  free(link);
1931  return GBCM_SERVER_OK;
1932 }
1933 
1934 GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname) {
1935  // if 'loginname' is NULp, the first logged-in user will be logged out
1936 
1937  if (!loginname) {
1938  loginname = Main->users[0]->username;
1939  gb_assert(loginname);
1940  }
1941 
1942  for (long i = 0; i<GB_MAX_USERS; i++) {
1943  gb_user*& user = Main->users[i];
1944  if (user && strcmp(loginname, user->username) == 0) {
1945  user->nusers--;
1946  if (user->nusers<=0) { // kill user and his projects
1947  if (i) fprintf(stdout, "User '%s' has logged out\n", loginname);
1948  free(user->username);
1949  freenull(user);
1950  }
1951  return NULp;
1952  }
1953  }
1954  return GB_export_errorf("User '%s' not logged in", loginname);
1955 }
1956 
1958  /* tell the arb_clean script what programs are running.
1959  * mode == 1 -> install
1960  * mode == 0 -> never install
1961  */
1962 
1963  static long lastpid = -1;
1964  GB_ERROR error = NULp;
1965 
1966  if (mode == 0) {
1967  gb_assert(lastpid == -1); // you have to call GB_install_pid(0) before opening any database!
1968  lastpid = -25; // mark as "never install"
1969  }
1970 
1971  if (lastpid != -25) {
1972  long pid = getpid();
1973 
1974  if (pid != lastpid) { // don't install pid multiple times
1975  char *pidfile_name;
1976  {
1977  const char *user = GB_getenvUSER();
1978  const char *arb_pid = GB_getenv("ARB_PID"); // normally the pid of the 'arb' shell script
1979 
1980  gb_assert(user);
1981  if (!arb_pid) arb_pid = "";
1982 
1983  pidfile_name = GBS_global_string_copy("arb_pids_%s_%s", user, arb_pid);
1984  }
1985 
1986  char *pid_fullname;
1987  FILE *pidfile = GB_fopen_tempfile(pidfile_name, "at", &pid_fullname);
1988 
1989  if (!pidfile) {
1990  error = GBS_global_string("GB_install_pid: %s", GB_await_error());
1991  }
1992  else {
1993  fprintf(pidfile, "%li ", pid);
1994  lastpid = pid; // remember installed pid
1995  fclose(pidfile);
1996  }
1997 
1998  // ensure pid file is private, otherwise someone could inject PIDs which will be killed later
1999  gb_assert(GB_is_privatefile(pid_fullname, false));
2000 
2001  free(pid_fullname);
2002  free(pidfile_name);
2003  }
2004  }
2005 
2006  return error;
2007 }
2008 
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2528
static GBCM_ServerResult gbcms_write_keys(int socket, GBDATA *gbd)
Definition: adcomm.cxx:676
#define GBCM_COMMAND_PUT_UPDATE_UPDATE
Definition: adcomm.cxx:60
char * unix_name
Definition: adcomm.cxx:121
char * gbcm_read_string(int socket)
Definition: adsocket.cxx:240
static __ATTR__USERESULT GB_ERROR gbcm_write_bin(int socket, GBDATA *gbd, long *buffer, long deep, int send_headera)
Definition: adcomm.cxx:278
NOT4PERL GBDATA * GB_find_int(GBDATA *gbd, const char *key, long val, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:311
static GBCONTAINER * gbcms_gb_main
Definition: adcomm.cxx:145
const char * GB_ERROR
Definition: arb_core.h:25
GB_ERROR clientserver_error(const char *clientserver, const char *what_failed, int sourceLine)
Definition: adcomm.cxx:70
string result
static GBCM_ServerResult gbcms_talking_undo(int socket, long *, void *, GBDATA *gbd)
Definition: adcomm.cxx:988
GB_TYPES type
long update_date() const
Definition: gb_data.h:193
#define GBCM_COMMAND_FIND
Definition: adcomm.cxx:47
GBCM_ServerResult gbcm_write_flush(int socket)
Definition: adsocket.cxx:91
int socket
Definition: server.c:57
GB_ERROR GB_commit_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2551
char * GB_read_fp(FILE *in)
Definition: adsocket.cxx:271
#define GBCM_COMMAND_PUT_UPDATE_DELETE
Definition: adcomm.cxx:59
const char * id
Definition: AliAdmin.cxx:17
static TalkingFunction aisc_talking_functions[]
Definition: adcomm.cxx:1144
static GBCM_ServerResult gbcms_write_updated(int socket, GBDATA *gbd, long hsin, long client_clock, long *buffer)
Definition: adcomm.cxx:623
#define RETURN_SERVER_FAULT_ON_BAD_ADDRESS(ptr)
Definition: adcomm.cxx:361
static GBCM_ServerResult gbcms_talking_commit_transaction(int socket, long *, void *, GBDATA *gbd)
Definition: adcomm.cxx:973
void gbcm_read_flush()
Definition: adsocket.cxx:50
gb_undo_commands
Definition: gb_local.h:61
int userid
Definition: gb_comm.h:23
static void gbcms_shift_delete_list(void *hsi, void *soi)
Definition: adcomm.cxx:579
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:454
GB_ERROR gbcmc_send_undo_commands(GBDATA *gbd, enum gb_undo_commands command)
Definition: adcomm.cxx:1824
Definition: arbdb.h:69
void gb_touch_header(GBCONTAINER *gbc)
Definition: ad_core.cxx:108
#define GBCM_COMMAND_BEGIN_TRANSACTION
Definition: adcomm.cxx:43
#define GBCM_COMMAND_KEY_ALLOC
Definition: adcomm.cxx:49
gb_flag_types2 flags2
Definition: gb_data.h:135
#define INSTALL_SIGHANDLER(sig, handler, context)
Definition: SigHandler.h:87
gb_data_base_type_union info
Definition: gb_data.h:204
bool inside_remote_action
Definition: adcomm.cxx:127
GBDATA * GB_find(GBDATA *gbd, const char *key, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:295
GB_MAIN_TYPE * GB_MAIN(GBDATA *gbd)
Definition: gb_data.h:291
static GBCM_ServerResult gbcms_talking_unfold(int socket, long *, void *, GBDATA *gb_in)
Definition: adcomm.cxx:697
#define GBTUM_MAGIC_NUMBER_FILTER
Definition: gb_local.h:26
GBCONTAINER * expect_container() const
Definition: gb_data.h:169
long nref
Definition: gb_key.h:31
gb_user * users[GB_MAX_USERS]
Definition: gb_main.h:156
unsigned int folded_container
Definition: gb_data.h:82
long server_id
Definition: gb_data.h:130
long
Definition: AW_awar.cxx:152
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
unsigned int type
Definition: gb_data.h:66
gb_user * this_user
Definition: gb_main.h:157
GB_ERROR gbcmc_end_sendupdate(GBDATA *gbd)
Definition: adcomm.cxx:1365
long key_clock
Definition: gb_main.h:136
long GBS_write_numhash(GB_NUMHASH *hs, long key, long val)
Definition: adhash.cxx:687
#define CLIENT_SEND_ERROR_AT_ITEM(gb_item)
Definition: adcomm.cxx:87
#define ASSERT_RESULT(Type, Expected, Expr)
Definition: arb_assert.h:336
GBDATA * GBCMC_find(GBDATA *gbd, const char *key, GB_TYPES type, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adcomm.cxx:1725
gbcmc_comm * c_link
Definition: gb_main.h:117
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
const char * GB_get_arb_revision_tag(void)
Definition: adfile.cxx:304
void GB_internal_errorf(const char *templat,...)
Definition: arb_msg.cxx:504
Socinf * soci
Definition: adcomm.cxx:122
void touch_update(long udate)
Definition: gb_data.h:189
GB_ERROR gbcmc_commit_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1596
CONSTEXPR_INLINE GBCONTAINER * GB_GRANDPA(GBDATA *gbd)
Definition: gb_data.h:272
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
void gb_write_index_key(GBCONTAINER *father, long index, GBQUARK new_index)
Definition: ad_core.cxx:660
CONSTEXPR_INLINE gb_header_list * GB_DATA_LIST_HEADER(gb_data_list &dl)
Definition: gb_data.h:105
char * get_data()
Definition: gb_data.h:32
GBCM_ServerResult gbcm_write(int socket, const char *ptr, long size)
Definition: adsocket.cxx:128
gbcms_delete_list * dl
Definition: adcomm.cxx:109
#define CLIENT_RECEIVE_ERROR()
Definition: adcomm.cxx:79
static void gbcms_sighup(int)
Definition: adcomm.cxx:147
#define GBCM_COMMAND_PUT_UPDATE_END
Definition: adcomm.cxx:61
GBCM_ServerResult gbcm_write_long(int socket, long data)
Definition: adsocket.cxx:260
GB_TYPES type() const
Definition: gb_data.h:139
#define COMM_SEND_ERROR()
Definition: adcomm.cxx:85
GB_MAIN_TYPE * GBCONTAINER_MAIN(GBCONTAINER *gbc)
Definition: gb_data.h:289
char * unix_name
Definition: gb_comm.h:16
#define GBCM_COMMAND_FIND_ERG
Definition: adcomm.cxx:63
static void gb_delete_entry(GBCONTAINER *&gbc)
Definition: ad_core.cxx:473
long creation_date() const
Definition: gb_data.h:192
GB_ERROR gbcmc_sendupdate_update(GBDATA *gbd, int send_headera)
Definition: adcomm.cxx:1415
Definition: gb_key.h:28
long clock
Definition: gb_main.h:151
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
#define GBCM_COMMAND_DONT_WAIT
Definition: adcomm.cxx:51
GB_ERROR save_as(const char *as_path, const char *savetype)
gbcms_create * next
Definition: adcomm.cxx:136
#define GB_MAX_USERS
Definition: gb_local.h:23
static HelixNrInfo * start
POS_TREE1 * father
Definition: probe_tree.h:39
#define GBCM_COMMAND_PUT_UPDATE
Definition: adcomm.cxx:41
GB_ERROR GB_export_error(const char *error)
Definition: arb_msg.cxx:257
uchar flags
Definition: probe_tree.h:38
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
static GBCM_ServerResult gbcm_read_bin(int socket, GBCONTAINER *gbc, long *buffer, long mode, GBDATA *gb_source, void *cs_main)
Definition: adcomm.cxx:370
GBCM_ServerResult(* TalkingFunction)(int socket, long *hsin, void *sin, GBDATA *gbd)
Definition: adcomm.cxx:1142
GB_ERROR gb_unfold(GBCONTAINER *gbc, long deep, int index_pos)
Definition: arbdb.cxx:586
gb_flag_types flags
Definition: gb_data.h:134
static GBCM_ServerResult commit_or_abort_transaction(int socket, GBDATA *gbd, ARB_TRANS_TYPE commit_or_abort)
Definition: adcomm.cxx:964
Definition: arbdb.h:78
fflush(stdout)
GBCM_ServerResult gbcm_read_two(int socket, long a, long *b, long *c)
Definition: adsocket.cxx:196
GBCM_ServerResult
Definition: gb_local.h:93
static GBCM_ServerResult gbcms_talking_put_update(int socket, long *, void *, GBDATA *)
Definition: adcomm.cxx:761
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1656
GB_ERROR GB_set_undo_mem(GBDATA *gbd, long memsize)
Definition: adindex.cxx:833
GB_ERROR gbcmc_init_transaction(GBCONTAINER *gbc)
Definition: adcomm.cxx:1549
#define CLIENT_SEND_ERROR()
Definition: adcomm.cxx:83
long header_update_date
Definition: gb_data.h:253
GB_HASH * key_2_index_hash
Definition: gb_main.h:135
static GBCM_ServerResult gbcms_talking_disable_wait_for_new_request(int, long *hsin, void *, GBDATA *)
Definition: adcomm.cxx:1128
GB_ERROR gbcm_unfold_client(GBCONTAINER *gbc, long deep, long index_pos)
Definition: adcomm.cxx:1305
bool is_server() const
Definition: gb_main.h:203
long gbcm_read(int socket, char *ptr, long size)
Definition: adsocket.cxx:79
GB_BUFFER GB_give_buffer(size_t size)
Definition: arbdb.cxx:311
static GBCM_ServerResult gbcms_talking_init_transaction(int socket, long *hsin, void *sin, GBDATA *)
Definition: adcomm.cxx:821
static __ATTR__USERESULT GB_ERROR gbcmc_read_keys(int socket, GBDATA *gbd)
Definition: adcomm.cxx:1432
int nusers
Definition: gb_comm.h:25
long GBS_read_numhash(GB_NUMHASH *hs, long key)
Definition: adhash.cxx:679
GB_ERROR gbcmc_sendupdate_create(GBDATA *gbd)
Definition: adcomm.cxx:1389
static GBCM_ServerResult gbcms_talking_updated(int, long *, void *, GBDATA *)
Definition: adcomm.cxx:817
unsigned int key_quark
Definition: gb_header.h:21
GB_ERROR gbcm_open_socket(const char *path, bool do_connect, int *psocket, char **unix_name)
Definition: adsocket.cxx:144
static GBCM_ServerResult gbcms_talking(int con, long *hs, void *sin)
Definition: adcomm.cxx:1161
bool is_container() const
Definition: gb_data.h:147
GB_ERROR GBCMS_open(const char *path, long timeout, GBDATA *gb_main)
Definition: adcomm.cxx:198
static GBCM_ServerResult gbcms_talking_key_alloc(int socket, long *, void *, GBDATA *gbd)
Definition: adcomm.cxx:1103
long gbcm_read_long(int socket)
Definition: adsocket.cxx:265
static void error(const char *msg)
Definition: mkptypes.cxx:96
GB_ERROR GB_abort_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2539
FILE * GB_fopen_tempfile(const char *filename, const char *fmode, char **res_fullname)
Definition: adsocket.cxx:1176
GB_ERROR gb_delete_force(GBDATA *source)
Definition: arbdb.cxx:1945
fputc('\n', stderr)
gb_flag_types3 flags3
Definition: gb_data.h:245
void index_check_out()
Definition: adindex.cxx:65
GB_ERROR gbcms_add_to_delete_list(GBDATA *gbd)
Definition: adcomm.cxx:1635
#define FD_SET_TYPE
Definition: adcomm.cxx:32
char * GB_undo_info(GBDATA *gb_main, GB_UNDO_TYPE type)
Definition: adindex.cxx:806
GBCONTAINER * as_container() const
Definition: gb_data.h:155
GB_write_int const char GB_write_autoconv_string WRITE_SKELETON(write_pointer, GBDATA *,"%p", GB_write_pointer) char *AW_awa if)(!gb_var) return strdup("")
Definition: AW_awar.cxx:163
#define MAX_QUEUE_LEN
Definition: adcomm.cxx:37
void * gbm_get_mem(size_t size, long index)
Definition: gb_memory.h:130
static GBCM_ServerResult gbcms_talking_get_update(int, long *, void *, GBDATA *)
Definition: adcomm.cxx:757
void gb_create_header_array(GBCONTAINER *gbc, int size)
Definition: ad_core.cxx:176
#define GBCM_COMMAND_SETDEEP
Definition: adcomm.cxx:55
GBCM_ServerResult gbcm_write_string(int socket, const char *key)
Definition: adsocket.cxx:228
long first_free_key
Definition: gb_main.h:133
#define debug_printf(a, b)
Definition: adcomm.cxx:34
CONSTEXPR_INLINE GBCONTAINER * GB_FATHER(GBDATA *gbd)
Definition: gb_data.h:271
int socket
Definition: gb_comm.h:15
GBDATA * gbd
Definition: adcomm.cxx:103
gbcms_delete_list * next
Definition: adcomm.cxx:100
GB_SEARCH_TYPE
Definition: arbdb.h:99
long gbcm_write_two(int socket, long a, long c)
Definition: adsocket.cxx:186
static GBCM_ServerResult gbcms_talking_abort_transaction(int socket, long *, void *, GBDATA *gbd)
Definition: adcomm.cxx:978
char * key
Definition: gb_key.h:29
#define GBCM_COMMAND_PUT_UPDATE_CREATE
Definition: adcomm.cxx:58
Definition: arbdb.h:86
#define GBCM_COMMAND_INIT_TRANSACTION
Definition: adcomm.cxx:46
gbcms_delete_list * del_last
Definition: adcomm.cxx:130
Definition: server.c:55
GB_CASE
Definition: arb_core.h:30
GB_ERROR gbcmc_begin_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1469
GB_ERROR gbcmc_sendupdate_delete(GBDATA *gbd)
Definition: adcomm.cxx:1406
gb_extern_data ex
Definition: gb_data.h:51
ARB_TRANS_TYPE running_client_transaction
Definition: gb_localdata.h:64
#define GBCM_COMMAND_UNDO_CMD
Definition: adcomm.cxx:65
static GBCM_ServerResult gbcms_talking_find(int socket, long *, void *, GBDATA *gbd)
Definition: adcomm.cxx:1029
#define GBCM_COMMAND_UNFOLD
Definition: adcomm.cxx:39
GB_ERROR GB_print_error()
Definition: arb_msg.cxx:324
int get_transaction_level() const
Definition: gb_main.h:177
char * username
Definition: adcomm.cxx:110
char * gbcmc_send_undo_info_commands(GBDATA *gbd, enum gb_undo_commands command)
Definition: adcomm.cxx:1847
GBENTRY * gb_make_entry(GBCONTAINER *father, const char *key, long index_pos, GBQUARK keyq, GB_TYPES type)
Definition: ad_core.cxx:353
GB_CSTR GB_getenv(const char *env)
Definition: adsocket.cxx:709
gbcms_delete_list * del_first
Definition: adcomm.cxx:129
char * data()
Definition: gb_data.h:219
GB_ERROR GB_undo(GBDATA *gb_main, GB_UNDO_TYPE type) __ATTR__USERESULT
Definition: adindex.cxx:755
gb_server_data * server_data
Definition: gb_main.h:118
fputs(TRACE_PREFIX, stderr)
Definition: arbdb.h:63
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:262
void GB_internal_error(const char *message)
Definition: arb_msg.cxx:481
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
GB_ERROR GB_tell_server_dont_wait(GBDATA *gbd)
Definition: adcomm.cxx:1867
GBCONTAINER * gb_make_container(GBCONTAINER *father, const char *key, long index_pos, GBQUARK keyq)
Definition: ad_core.cxx:414
#define GBTUM_MAGIC_NUMBER
Definition: gb_local.h:25
#define gb_assert(cond)
Definition: arbdbt.h:11
GBDATA * gb_main
Definition: adcomm.cxx:125
#define GBCM_COMMAND_COMMIT_TRANSACTION
Definition: adcomm.cxx:44
int userbit
Definition: gb_comm.h:24
bool stored_external() const
Definition: gb_data.h:211
#define assert_or_exit(cond)
Definition: arb_assert.h:263
#define GBCM_COMMAND_SETINDEX
Definition: adcomm.cxx:56
GB_CSTR GB_getenvUSER(void)
Definition: adsocket.cxx:545
static GBCM_ServerResult gbcms_write_deleted(int socket, long hsin, long client_clock, long *buffer)
Definition: adcomm.cxx:590
aisc_com * link
void gb_save_extern_data_in_ts(GBENTRY *gbe)
Definition: ad_core.cxx:639
#define GBCM_COMMAND_ABORT_TRANSACTION
Definition: adcomm.cxx:45
long index
Definition: gb_data.h:133
#define GBCM_COMMAND_SEND
Definition: adcomm.cxx:53
long GB_read_clients(GBDATA *gbd)
Definition: adcomm.cxx:1682
#define __ATTR__USERESULT
Definition: attributes.h:58
void touch_creation_and_update(long date)
Definition: gb_data.h:190
GB_ERROR panic_save(const char *db_panic)
Definition: adcomm.cxx:187
static GBCM_ServerResult gbcms_talking_begin_transaction(int socket, long *hsin, void *sin, GBDATA *long_client_clock)
Definition: adcomm.cxx:893
#define GBCM_COMMAND_TRANSACTION_RETURN
Definition: adcomm.cxx:62
static void g_bcms_delete_Socinf(Socinf *THIS)
Definition: adcomm.cxx:113
GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname)
Definition: adcomm.cxx:1934
GB_BUFFER GB_give_buffer2(long size)
Definition: arbdb.cxx:334
#define GBCMS_TRANSACTION_TIMEOUT
Definition: adcomm.cxx:36
void create_extended()
Definition: gb_data.h:176
#define GBCM_COMMAND_CLOSE
Definition: adcomm.cxx:48
static GBCM_ServerResult gbcms_talking_close(int, long *, void *, GBDATA *)
Definition: adcomm.cxx:983
bool GB_is_server(GBDATA *gbd)
Definition: adcomm.cxx:1697
static void invalid_use_in_server(const char *function)
Definition: adcomm.cxx:1721
#define GBCM_COMMAND_SEND_COUNT
Definition: adcomm.cxx:54
GBDATA * GB_find_string(GBDATA *gbd, const char *key, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:302
gb_Key * keys
Definition: gb_main.h:134
static GBCM_ServerResult gbcms_talking_obsolete(int, long *, void *, GBDATA *)
Definition: adcomm.cxx:1134
GBENTRY * as_entry() const
Definition: gb_data.h:150
GBDATA * GBCONTAINER_ELEM(GBCONTAINER *gbc, int idx)
Definition: gb_header.h:57
#define NULp
Definition: cxxforward.h:116
gb_data_list d
Definition: gb_data.h:246
size_t size() const
Definition: gb_data.h:214
ARB_TRANS_TYPE
Definition: gb_localdata.h:31
long gbcmc_key_alloc(GBDATA *gbd, const char *key)
Definition: adcomm.cxx:1788
static void dumpError(GB_ERROR error)
Definition: adcomm.cxx:89
char * username
Definition: gb_comm.h:22
int keycnt
Definition: gb_main.h:131
gb_header_flags flags
Definition: gb_header.h:35
gbcmc_comm * gbcmc_open(const char *path)
Definition: adsocket.cxx:170
void GB_set_remote_action(GBDATA *gbd, bool in_action)
Definition: adcomm.cxx:1656
static char * command
Definition: arb_a2ps.c:319
bool GB_inside_remote_action(GBDATA *gbd)
Definition: adcomm.cxx:1668
#define GBCM_COMMAND_KEY_ALLOC_RES
Definition: adcomm.cxx:64
void GBCMS_shutdown(GBDATA *gbd)
Definition: adcomm.cxx:247
GB_TYPES
Definition: arbdb.h:62
Definition: trnsprob.h:20
GB_ERROR GB_request_undo_type(GBDATA *gb_main, GB_UNDO_TYPE type) __ATTR__USERESULT_TODO
Definition: adindex.cxx:721
GBDATA * server_id
Definition: adcomm.cxx:137
#define GBCM_COMMAND_PUT_UPDATE_KEYS
Definition: adcomm.cxx:57
GBDATA * gb_main
Definition: adname.cxx:32
void gbm_free_mem(void *block, size_t size, long index)
Definition: gb_memory.h:131
const char * GB_KEY(GBDATA *gbd)
Definition: gb_key.h:49
GB_ERROR gbcmc_abort_transaction(GBDATA *gbd)
Definition: adcomm.cxx:1615
static __ATTR__USERESULT GB_ERROR gbcmc_unfold_list(int socket, GBDATA *gbd)
Definition: adcomm.cxx:1701
Socinf * next
Definition: server.c:56
GB_NUMHASH * remote_hash
Definition: gb_main.h:152
int nheader
Definition: gb_data.h:102
void gb_touch_entry(GBDATA *gbd, GB_CHANGE val)
Definition: ad_core.cxx:83
GBCM_ServerResult gbcmc_close(gbcmc_comm *link)
Definition: adcomm.cxx:1916
void gb_create_key_array(GB_MAIN_TYPE *Main, int index)
Definition: ad_core.cxx:697
int wait_for_new_request
Definition: adcomm.cxx:126
#define STATIC_ASSERT(const_expression)
Definition: static_assert.h:37
void write_into_comm_buffer(long &buffer, T &t)
Definition: adcomm.cxx:271
int GBQUARK
Definition: arbdb_base.h:30
gb_local_data * gb_local
Definition: arbdb.cxx:33
void set_change(GB_CHANGE val)
Definition: gb_header.h:25
GB_ERROR gbcmc_begin_sendupdate(GBDATA *gbd)
Definition: adcomm.cxx:1356
GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *loginname)
Definition: adcomm.cxx:1883
#define CLIENT_ERROR(reason)
Definition: adcomm.cxx:75
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
bool GBCMS_accept_calls(GBDATA *gbd, bool wait_extra_time)
Definition: adcomm.cxx:1188
long next_free_key
Definition: gb_key.h:32
#define GBCM_COMMAND_UNDO
Definition: adcomm.cxx:50
bool GB_is_privatefile(const char *path, bool read_private)
Definition: arb_file.cxx:124
GBDATA * client_id
Definition: adcomm.cxx:138
Definition: arbdb.h:66
GB_ERROR GB_install_pid(int mode)
Definition: adcomm.cxx:1957
unsigned int flags
Definition: gb_header.h:20
void(* SigHandler)(int)
Definition: SigHandler.h:23