source: tags/ms_r16q2/ARBDB/adcomm.cxx

Last change on this file was 14556, checked in by westram, 8 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.1 KB
Line 
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
29static 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
70inline 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
89static 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
99struct gbcms_delete_list {                          // Store all deleted items in a list
100    gbcms_delete_list *next;
101    long               creation_date;
102    long               update_date;
103    GBDATA            *gbd;
104};
105
106struct 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
113static void g_bcms_delete_Socinf(Socinf *THIS) {
114    freenull(THIS->username);
115    THIS->next = 0;
116    free(THIS);
117}
118
119struct gb_server_data {
120    int     hso;
121    char   *unix_name;
122    Socinf *soci;
123    long    nsoc;
124    long    timeout;
125    GBDATA *gb_main;
126    int     wait_for_new_request;
127    bool    inside_remote_action;
128
129    gbcms_delete_list *del_first; // All deleted items, that are yet unknown to at least one client
130    gbcms_delete_list *del_last;
131};
132
133
134
135struct gbcms_create {
136    gbcms_create *next;
137    GBDATA       *server_id;
138    GBDATA       *client_id;
139};
140
141
142// --------------------
143//      Panic save
144
145static GBCONTAINER *gbcms_gb_main;
146
147static void gbcms_sighup(int) {
148    char *panic_file = 0;                      // hang-up trigger file
149    char *db_panic   = 0;                      // 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
187GB_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
198GB_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 = 0;
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 = NULL;
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 = (gb_server_data *)GB_calloc(sizeof(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
247void 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
270template<typename T>
271inline 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
278static __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);
312            gb_header_flags *buf2 = (gb_header_flags *)GB_give_buffer2(gbc->d.nheader * sizeof(gb_header_flags));
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 0;
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
370static 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
417                RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gb2);
418            }
419            if (stype != GB_DB) {
420                gb_save_extern_data_in_ts(gb2->as_entry());
421            }
422            gb_touch_entry(gb2, GB_NORMAL_CHANGE);
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, 0, 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, 0, 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
433                gb_touch_entry(gb2, GB_CREATED);
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;
441                cs = (gbcms_create *) GB_calloc(sizeof(gbcms_create), 1);
442                cs->next = *((gbcms_create **) cs_main);
443                *((gbcms_create **) cs_main) = cs;
444                cs->server_id = gb2;
445                cs->client_id = (GBDATA *)id;
446            }
447        }
448        gb2->flags = flags;
449        if (type == GB_DB) {
450            gb2->as_container()->flags3 = *((gb_flag_types3 *)&(buffer[i++]));
451        }
452    }
453    else {
454      dont_create_in_a_folded_container :
455        if (type == GB_DB) {
456            // gb_flag_types3 flags3 = *((gb_flag_types3 *)&(buffer[i++]));
457            ++i;
458        }
459        gb2 = 0;
460    }
461
462    if (type == GB_DB) {
463        long nheader = buffer[i++];
464        long nitems  = buffer[i++];
465
466        if (nheader > 0) {
467            long             realsize = nheader* sizeof(gb_header_flags);
468            gb_header_flags *buffer2  = (gb_header_flags *)GB_give_buffer2(realsize);
469
470            size = gbcm_read(socket, (char *)buffer2, realsize);
471            if (size != realsize) {
472                GB_internal_error("receive failed data\n");
473                return GBCM_SERVER_FAULT;
474            }
475            if (gb2 && mode >= -1) {
476                GBCONTAINER  *gbc2 = gb2->as_container();
477                GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gbc2);
478
479                gb_create_header_array(gbc2, (int)nheader);
480                if (nheader < gbc2->d.nheader) {
481                    GB_internal_error("Inconsistency Client-Server Cache");
482                }
483                gbc2->d.nheader = (int)nheader;
484                gb_header_list *hdl = GB_DATA_LIST_HEADER(gbc2->d);
485                for (long item = 0; item < nheader; item++) {
486                    GBQUARK old_index = hdl->flags.key_quark;
487                    GBQUARK new_index = buffer2->key_quark;
488                    if (new_index && !old_index) {  // a rename ...
489                        gb_write_index_key(gbc2, item, new_index);
490                    }
491                    if (mode>0) {   // server read data
492
493
494                    }
495                    else {
496                        if (buffer2->changed >= GB_DELETED) {
497                            hdl->flags.set_change(GB_DELETED);
498                        }
499                    }
500                    hdl->flags.flags = buffer2->flags;
501                    hdl++; buffer2++;
502                }
503                if (mode>0) {   // transaction only in server
504                    gb_touch_header(gbc2);
505                }
506                else {
507                    gbc2->header_update_date = Main->clock;
508                }
509            }
510        }
511
512        if (nitems >= 0) {
513            long newmod = mode;
514            if (mode>=0) {
515                if (mode==0 && nitems<=1) {         // only a partial send
516                    gb2->flags2.folded_container = 1;
517                }
518            }
519            else {
520                newmod = -2;
521            }
522            debug_printf("Client %i \n", nheader);
523            for (long item = 0; item < nitems; item++) {
524                debug_printf("  Client reading %i\n", item);
525                long irror = gbcm_read_bin(socket, gb2->as_container(), buffer, newmod, 0, cs_main);
526                if (irror) {
527                    return GBCM_SERVER_FAULT;
528                }
529            }
530            debug_printf("Client done\n", 0);
531        }
532        else {
533            if ((mode==0) && !gb_source) {      // created GBDATA at client
534                gb2->flags2.folded_container = 1;
535            }
536        }
537    }
538    else {
539        if (mode >= 0) {
540            GBENTRY *ge2 = gb2->as_entry();
541            if (type < GB_BITS) {
542                ge2->info.i = buffer[i++];
543            }
544            else {
545                long  realsize = buffer[i++];
546                long  memsize  = buffer[i++];
547
548                ge2->index_check_out();
549                assert_or_exit(!(ge2->stored_external() && ge2->info.ex.get_data()));
550
551                GBENTRY_memory storage(ge2, realsize, memsize);
552                size = gbcm_read(socket, storage, memsize);
553                if (size != memsize) {
554                    fprintf(stderr, "receive failed data\n");
555                    return GBCM_SERVER_FAULT;
556                }
557            }
558        }
559        else {
560            if (type >= GB_BITS) { // dummy read (e.g. updata in server && not cached in client
561                long memsize;
562                char *buffer2;
563                i++;
564                memsize = buffer[i++];
565                buffer2 = GB_give_buffer2(memsize);
566
567                size = gbcm_read(socket, buffer2, memsize);
568                if (size != memsize) {
569                    GB_internal_error("receive failed data\n");
570                    return GBCM_SERVER_FAULT;
571                }
572            }
573        }
574    }
575
576    return GBCM_SERVER_OK;
577}
578
579
580static void gbcms_shift_delete_list(void *hsi, void *soi) {
581    gb_server_data *hs     = (gb_server_data *)hsi;
582    Socinf         *socinf = (Socinf *)soi;
583
584    if (!hs->del_first) return;
585    while ((!socinf->dl) || (socinf->dl->next)) {
586        if (!socinf->dl) socinf->dl = hs->del_first;
587        else    socinf->dl = socinf->dl->next;
588    }
589}
590
591static GBCM_ServerResult gbcms_write_deleted(int socket, long hsin, long client_clock, long *buffer) {
592    Socinf            *socinf;
593    gb_server_data    *hs;
594    gbcms_delete_list *dl;
595
596    hs = (gb_server_data *)hsin;
597    for (socinf = hs->soci; socinf; socinf=socinf->next) {
598        if (socinf->socket == socket) break;
599    }
600    if (!socinf) return GBCM_SERVER_OK;
601    if (!hs->del_first) return GBCM_SERVER_OK;
602    while (!socinf->dl || (socinf->dl->next)) {
603        if (!socinf->dl) socinf->dl = hs->del_first;
604        else    socinf->dl = socinf->dl->next;
605        if (socinf->dl->creation_date>client_clock) continue;
606        // created and deleted object
607        buffer[0] = GBCM_COMMAND_PUT_UPDATE_DELETE;
608        buffer[1] = (long)socinf->dl->gbd;
609        if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
610    }
611    for (socinf = hs->soci; socinf; socinf=socinf->next) {
612        if (!socinf->dl) return GBCM_SERVER_OK;
613    }
614    while ((dl = hs->del_first)) {
615        for (socinf = hs->soci; socinf; socinf=socinf->next) {
616            if (socinf->dl == dl) return GBCM_SERVER_OK;
617        }
618        hs->del_first = dl->next;
619        gbm_free_mem(dl, sizeof(gbcms_delete_list), GBM_CB_INDEX);
620    }
621    return GBCM_SERVER_OK;
622}
623
624static GBCM_ServerResult gbcms_write_updated(int socket, GBDATA *gbd, long hsin, long client_clock, long *buffer) {
625    if (gbd->update_date()<=client_clock) return GBCM_SERVER_OK;
626    if (gbd->creation_date() > client_clock) {
627        buffer[0] = GBCM_COMMAND_PUT_UPDATE_CREATE;
628        buffer[1] = (long)GB_FATHER(gbd);
629        if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
630
631        GB_ERROR error = gbcm_write_bin(socket, gbd, buffer, 0, 1);
632        if (error) {
633            dumpError(error);
634            return GBCM_SERVER_FAULT;
635        }
636    }
637    else { // send clients first
638        if (gbd->is_container()) {
639            GBCONTAINER *gbc         = gbd->as_container();
640            int          end         = (int)gbc->d.nheader;
641            int          send_header = (gbc->header_update_date > client_clock) ? 1 : 0;
642
643            buffer[0] = GBCM_COMMAND_PUT_UPDATE_UPDATE;
644            buffer[1] = (long)gbd;
645            if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
646
647            GB_ERROR error = gbcm_write_bin(socket, gbd, buffer, 0, send_header);
648            if (error) {
649                dumpError(error);
650                return GBCM_SERVER_FAULT;
651            }
652
653            for (int index = 0; index < end; index++) {
654                GBDATA *gb2 = GBCONTAINER_ELEM(gbc, index);
655                if (gb2 && gbcms_write_updated(socket, gb2, hsin, client_clock, buffer)) {
656                    return GBCM_SERVER_FAULT;
657                }
658            }
659        }
660        else {
661            buffer[0]             = GBCM_COMMAND_PUT_UPDATE_UPDATE;
662            buffer[1]             = (long)gbd;
663            if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
664
665            const int SEND_HEADER = 0;
666            GB_ERROR  error       = gbcm_write_bin(socket, gbd, buffer, 0, SEND_HEADER);
667            if (error) {
668                dumpError(error);
669                return GBCM_SERVER_FAULT;
670            }
671        }
672    }
673
674    return GBCM_SERVER_OK;
675}
676
677static GBCM_ServerResult gbcms_write_keys(int socket, GBDATA *gbd) { // @@@ move into GB_MAIN_TYPE?
678    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
679
680    long buffer[4];
681    buffer[0] = GBCM_COMMAND_PUT_UPDATE_KEYS;
682    buffer[1] = (long)gbd;
683    buffer[2] = Main->keycnt;
684    buffer[3] = Main->first_free_key;
685
686    if (gbcm_write(socket, (const char *)buffer, 4*sizeof(long))) return GBCM_SERVER_FAULT;
687
688    for (int i=1; i<Main->keycnt; i++) {
689        gb_Key &key = Main->keys[i];
690        buffer[0] = key.nref;
691        buffer[1] = key.next_free_key;
692        if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
693        if (gbcm_write_string(socket, key.key)) return GBCM_SERVER_FAULT;
694    }
695    return GBCM_SERVER_OK;
696}
697
698static GBCM_ServerResult gbcms_talking_unfold(int socket, long */*hsin*/, void */*sin*/, GBDATA *gb_in) {
699    // command: GBCM_COMMAND_UNFOLD
700
701    GBCONTAINER *gbc = gb_in->expect_container();
702    GBDATA      *gb2;
703    char        *buffer;
704    long         deep[1];
705    long         index_pos[1];
706    int          index, start, end;
707
708    RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gbc);
709    if (gbc->type() != GB_DB) return GBCM_SERVER_FAULT;
710    if (gbcm_read_two(socket, GBCM_COMMAND_SETDEEP, 0, deep)) {
711        return GBCM_SERVER_FAULT;
712    }
713    if (gbcm_read_two(socket, GBCM_COMMAND_SETINDEX, 0, index_pos)) {
714        return GBCM_SERVER_FAULT;
715    }
716
717    gbcm_read_flush();
718    buffer = GB_give_buffer(1014);
719
720    if (index_pos[0]==-2) {
721        GB_ERROR error = gbcm_write_bin(socket, gbc, (long *)buffer, deep[0]+1, 1);
722        if (error) {
723            dumpError(error);
724            return GBCM_SERVER_FAULT;
725        }
726        gbcm_write_flush(socket);
727        return GBCM_SERVER_OK;
728    }
729
730    if (index_pos[0] >= 0) {
731        start  = (int)index_pos[0];
732        end = start + 1;
733        if (gbcm_write_two(socket, GBCM_COMMAND_SEND_COUNT, 1)) {
734            return GBCM_SERVER_FAULT;
735        }
736    }
737    else {
738        start = 0;
739        end = gbc->d.nheader;
740        if (gbcm_write_two(socket, GBCM_COMMAND_SEND_COUNT, gbc->d.size)) {
741            return GBCM_SERVER_FAULT;
742        }
743    }
744    for (index = start; index < end; index++) {
745        if ((gb2 = GBCONTAINER_ELEM(gbc, index))) {
746            GB_ERROR error = gbcm_write_bin(socket, gb2, (long *)buffer, deep[0], 1);
747            if (error) {
748                dumpError(error);
749                return GBCM_SERVER_FAULT;
750            }
751        }
752    }
753
754    gbcm_write_flush(socket);
755    return GBCM_SERVER_OK;
756}
757
758static GBCM_ServerResult gbcms_talking_get_update(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
759    return GBCM_SERVER_OK;
760}
761
762static GBCM_ServerResult gbcms_talking_put_update(int socket, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
763    /* Reads
764     * - the date
765     * - and all changed data
766     * from client.
767     *
768     * command: GBCM_COMMAND_PUT_UPDATE
769     */
770    long          irror;
771    GBDATA       *gbd;
772    gbcms_create *cs[1], *cs_main[1];
773    long         *buffer;
774    bool          end;
775
776    cs_main[0] = 0;
777    buffer     = (long *) GB_give_buffer(1024);
778    end        = false;
779    while (!end) {
780        if (gbcm_read(socket, (char *) buffer, sizeof(long) * 3) != sizeof(long) * 3) {
781            return GBCM_SERVER_FAULT;
782        }
783        gbd = (GBDATA *) buffer[2];
784        RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gbd);
785        switch (buffer[0]) {
786            case GBCM_COMMAND_PUT_UPDATE_CREATE:
787                irror = gbcm_read_bin(socket, gbd->as_container(), buffer, 1, 0, (void *)cs_main);
788                if (irror) return GBCM_SERVER_FAULT;
789                break;
790            case GBCM_COMMAND_PUT_UPDATE_DELETE:
791                gb_delete_force(gbd);
792                break;
793            case GBCM_COMMAND_PUT_UPDATE_UPDATE:
794                irror = gbcm_read_bin(socket, 0, buffer, 1, gbd, 0);
795                if (irror) return GBCM_SERVER_FAULT;
796                break;
797            case GBCM_COMMAND_PUT_UPDATE_END:
798                end = true;
799                break;
800            default:
801                return GBCM_SERVER_FAULT;
802        }
803    }
804    gbcm_read_flush();                        // send all id's of newly created objects
805    for (cs[0] = cs_main[0]; cs[0]; cs[0]=cs_main[0]) {
806        cs_main[0] = cs[0]->next;
807        buffer[0] = (long)cs[0]->client_id;
808        buffer[1] = (long)cs[0]->server_id;
809        if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
810        free(cs[0]);
811    }
812    buffer[0] = 0;
813    if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
814    gbcm_write_flush(socket);
815    return GBCM_SERVER_OK;
816}
817
818static GBCM_ServerResult gbcms_talking_updated(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
819    return GBCM_SERVER_OK;
820}
821
822static GBCM_ServerResult gbcms_talking_init_transaction(int socket, long *hsin, void *sin, GBDATA */*gbd*/) {
823    /* begin client transaction
824     * sends clock
825     *
826     * command: GBCM_COMMAND_INIT_TRANSACTION
827     */
828
829    gb_server_data *hs = (gb_server_data *)hsin;
830    Socinf         *si = (Socinf *)sin;
831
832    GBDATA       *gb_main = hs->gb_main;
833    GB_MAIN_TYPE *Main    = GB_MAIN(gb_main);
834    GBDATA       *gbd     = gb_main;
835    char         *user    = gbcm_read_string(socket);
836
837    gbcm_read_flush();
838    if (gbcm_login(gbd->as_container(), user)) {
839        return GBCM_SERVER_FAULT;
840    }
841    si->username = user;
842
843    gb_local->running_client_transaction = ARB_TRANS;
844
845    if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, Main->clock)) {
846        return GBCM_SERVER_FAULT;
847    }
848    if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, (long)gbd)) {
849        return GBCM_SERVER_FAULT;
850    }
851    if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, (long)Main->this_user->userid)) {
852        return GBCM_SERVER_FAULT;
853    }
854    gbcms_write_keys(socket, gbd);
855
856    gbcm_write_flush(socket);
857    // send modified data to client
858
859    GB_begin_transaction(gbd);
860    while (gb_local->running_client_transaction == ARB_TRANS) {
861        fd_set set;
862        FD_ZERO(&set);
863        FD_SET(socket, &set);
864
865        struct timeval timeout;
866        timeout.tv_sec  = GBCMS_TRANSACTION_TIMEOUT;
867        timeout.tv_usec = 100000;
868
869        long anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, NULL, &timeout);
870
871        if (anz<0) continue;
872        if (anz==0) {
873            GB_export_errorf("ARB_DB ERROR CLIENT TRANSACTION TIMEOUT, CLIENT DISCONNECTED (I waited %lu seconds)", timeout.tv_sec);
874            GB_print_error();
875            gb_local->running_client_transaction = ARB_ABORT;
876            GB_abort_transaction(gbd);
877            return GBCM_SERVER_FAULT;
878        }
879        if (GBCM_SERVER_OK == gbcms_talking(socket, hsin, sin)) continue;
880        gb_local->running_client_transaction = ARB_ABORT;
881        GB_abort_transaction(gbd);
882        return GBCM_SERVER_FAULT;
883    }
884    if (gb_local->running_client_transaction == ARB_COMMIT) {
885        GB_commit_transaction(gbd);
886        gbcms_shift_delete_list(hsin, sin);
887    }
888    else {
889        GB_abort_transaction(gbd);
890    }
891    return GBCM_SERVER_OK;
892}
893
894static GBCM_ServerResult gbcms_talking_begin_transaction(int socket, long *hsin, void *sin, GBDATA *long_client_clock) {
895    /* begin client transaction
896     * sends clock
897     * deleted
898     * created+updated
899     *
900     * command: GBCM_COMMAND_BEGIN_TRANSACTION
901     */
902    long            client_clock = (long)long_client_clock;
903    GBDATA         *gb_main;
904    GBDATA         *gbd;
905    gb_server_data *hs           = (gb_server_data *)hsin;
906    long            anz;
907    long           *buffer;
908    fd_set          set;
909    timeval         timeout;
910
911    gb_main = hs->gb_main;
912    gbd = gb_main;
913    gbcm_read_flush();
914    gb_local->running_client_transaction = ARB_TRANS;
915
916    if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, GB_MAIN(gbd)->clock)) {
917        return GBCM_SERVER_FAULT;
918    }
919
920    // send modified data to client
921    buffer = (long *)GB_give_buffer(1024);
922    if (GB_MAIN(gb_main)->key_clock > client_clock) {
923        if (gbcms_write_keys(socket, gbd)) return GBCM_SERVER_FAULT;
924    }
925    if (gbcms_write_deleted(socket,      (long)hs, client_clock, buffer)) return GBCM_SERVER_FAULT;
926    if (gbcms_write_updated(socket, gbd, (long)hs, client_clock, buffer)) return GBCM_SERVER_FAULT;
927    buffer[0] = GBCM_COMMAND_PUT_UPDATE_END;
928    buffer[1] = 0;
929    if (gbcm_write(socket, (const char *)buffer, sizeof(long)*2)) return GBCM_SERVER_FAULT;
930    if (gbcm_write_flush(socket))       return GBCM_SERVER_FAULT;
931
932    GB_begin_transaction(gbd);
933    while (gb_local->running_client_transaction == ARB_TRANS) {
934        FD_ZERO(&set);
935        FD_SET(socket, &set);
936
937        timeout.tv_sec  = GBCMS_TRANSACTION_TIMEOUT;
938        timeout.tv_usec = 0;
939
940        anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, NULL, &timeout);
941
942        if (anz<0) continue;
943        if (anz==0) {
944            GB_export_errorf("ARB_DB ERROR CLIENT TRANSACTION TIMEOUT, CLIENT DISCONNECTED (I waited %lu seconds)", timeout.tv_sec);
945            GB_print_error();
946            gb_local->running_client_transaction = ARB_ABORT;
947            GB_abort_transaction(gbd);
948            return GBCM_SERVER_FAULT;
949        }
950        if (GBCM_SERVER_OK == gbcms_talking(socket, hsin, sin)) continue;
951        gb_local->running_client_transaction = ARB_ABORT;
952        GB_abort_transaction(gbd);
953        return GBCM_SERVER_FAULT;
954    }
955    if (gb_local->running_client_transaction == ARB_COMMIT) {
956        GB_commit_transaction(gbd);
957        gbcms_shift_delete_list(hsin, sin);
958    }
959    else {
960        GB_abort_transaction(gbd);
961    }
962    return GBCM_SERVER_OK;
963}
964
965static GBCM_ServerResult commit_or_abort_transaction(int socket, GBDATA *gbd, ARB_TRANS_TYPE commit_or_abort) {
966    RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gbd);
967   
968    gb_local->running_client_transaction = commit_or_abort;
969    gbcm_read_flush();
970
971    if (gbcm_write_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0)) return GBCM_SERVER_FAULT;
972    return gbcm_write_flush(socket);
973}
974static GBCM_ServerResult gbcms_talking_commit_transaction(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
975    // command: GBCM_COMMAND_COMMIT_TRANSACTION
976    return commit_or_abort_transaction(socket, gbd, ARB_COMMIT);
977}
978
979static GBCM_ServerResult gbcms_talking_abort_transaction(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
980    // command: GBCM_COMMAND_ABORT_TRANSACTION
981    return commit_or_abort_transaction(socket, gbd, ARB_ABORT);
982}
983
984static GBCM_ServerResult gbcms_talking_close(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
985    // command: GBCM_COMMAND_CLOSE
986    return GBCM_SERVER_ABORTED;
987}
988
989static GBCM_ServerResult gbcms_talking_undo(int socket, long */*hsin*/, void */*sin*/, GBDATA *gbd) {
990    // command: GBCM_COMMAND_UNDO
991    long cmd;
992    GB_ERROR result = 0;
993    char *to_free = 0;
994    if (gbcm_read_two(socket, GBCM_COMMAND_UNDO_CMD, 0, &cmd)) {
995        return GBCM_SERVER_FAULT;
996    }
997    gbcm_read_flush();
998    switch (cmd) {
999        case _GBCMC_UNDOCOM_REQUEST_NOUNDO:
1000            result = GB_request_undo_type(gbd, GB_UNDO_NONE);
1001            break;
1002        case _GBCMC_UNDOCOM_REQUEST_NOUNDO_KILL:
1003            result = GB_request_undo_type(gbd, GB_UNDO_KILL);
1004            break;
1005        case _GBCMC_UNDOCOM_REQUEST_UNDO:
1006            result = GB_request_undo_type(gbd, GB_UNDO_UNDO);
1007            break;
1008        case _GBCMC_UNDOCOM_INFO_UNDO:
1009            result = to_free = GB_undo_info(gbd, GB_UNDO_UNDO);
1010            break;
1011        case _GBCMC_UNDOCOM_INFO_REDO:
1012            result = to_free = GB_undo_info(gbd, GB_UNDO_REDO);
1013            break;
1014        case _GBCMC_UNDOCOM_UNDO:
1015            result = GB_undo(gbd, GB_UNDO_UNDO);
1016            break;
1017        case _GBCMC_UNDOCOM_REDO:
1018            result = GB_undo(gbd, GB_UNDO_REDO);
1019            break;
1020        default:    result = GB_set_undo_mem(gbd, cmd);
1021    }
1022    if (gbcm_write_string(socket, result)) {
1023        if (to_free) free(to_free);
1024        return GBCM_SERVER_FAULT;
1025    }
1026    if (to_free) free(to_free);
1027    return gbcm_write_flush(socket);
1028}
1029
1030static GBCM_ServerResult gbcms_talking_find(int socket, long */*hsin*/, void */*sin*/, GBDATA * gbd) {
1031    // command: GBCM_COMMAND_FIND
1032   
1033    char     *key;
1034    char     *val1      = 0;
1035    GB_CASE   case_sens = GB_CASE_UNDEFINED;
1036    long      val2      = 0;
1037    GB_TYPES  type;
1038    void     *buffer[2];
1039
1040    RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gbd);
1041
1042    key  = gbcm_read_string(socket);
1043    type = GB_TYPES(gbcm_read_long(socket));
1044
1045    switch (type) {
1046        case GB_NONE:
1047            break;
1048
1049        case GB_STRING:
1050            val1      = gbcm_read_string(socket);
1051            case_sens = GB_CASE(gbcm_read_long(socket));
1052            break;
1053
1054        case GB_INT:
1055            val2 = gbcm_read_long(socket);
1056            break;
1057
1058        default:
1059            gb_assert(0);
1060            GB_export_errorf("gbcms_talking_find: illegal data type (%i)", type);
1061            GB_print_error();
1062            return GBCM_SERVER_FAULT;
1063    }
1064
1065    {
1066        GB_SEARCH_TYPE gbs = GB_SEARCH_TYPE(gbcm_read_long(socket));
1067        gbcm_read_flush();
1068
1069        if (type == GB_FIND) {
1070            gbd = GB_find(gbd, key, gbs);
1071        }
1072        else if (type == GB_STRING) {
1073            gbd = GB_find_string(gbd, key, val1, case_sens, gbs);
1074            free(val1);
1075        }
1076        else if (type == GB_INT) {
1077            gbd = GB_find_int(gbd, key, val2, gbs);
1078        }
1079        else {
1080            GB_internal_errorf("Searching DBtype %i not implemented", type);
1081        }
1082    }
1083
1084    free(key);
1085
1086    if (gbcm_write_two(socket, GBCM_COMMAND_FIND_ERG, (long) gbd)) {
1087        return GBCM_SERVER_FAULT;
1088    }
1089    if (gbd) {
1090        while (GB_GRANDPA(gbd)) {
1091            buffer[0] = (void *)gbd->index;
1092            buffer[1] = (void *)GB_FATHER(gbd);
1093            gbcm_write(socket, (const char *) buffer, sizeof(long) * 2);
1094            gbd = GB_FATHER(gbd);
1095        }
1096    }
1097    buffer[0] = NULL;
1098    buffer[1] = NULL;
1099    gbcm_write(socket, (const char *) buffer, sizeof(long) * 2);
1100
1101    return gbcm_write_flush(socket);
1102}
1103
1104static GBCM_ServerResult gbcms_talking_key_alloc(int socket, long */*hsin*/, void */*sin*/, GBDATA * gbd) {
1105    // command: GBCM_COMMAND_KEY_ALLOC
1106    // (old maybe wrong comment: "do a query in the server")
1107
1108    char *key;
1109    long  index;
1110
1111    RETURN_SERVER_FAULT_ON_BAD_ADDRESS(gbd);
1112    key = gbcm_read_string(socket);
1113    gbcm_read_flush();
1114
1115    if (key)
1116        index = gb_create_key(GB_MAIN(gbd), key, false);
1117    else
1118        index = 0;
1119
1120    if (key)
1121        free(key);
1122
1123    if (gbcm_write_two(socket, GBCM_COMMAND_KEY_ALLOC_RES, index)) {
1124        return GBCM_SERVER_FAULT;
1125    }
1126    return gbcm_write_flush(socket);
1127}
1128
1129static GBCM_ServerResult gbcms_talking_disable_wait_for_new_request(int /*socket*/, long *hsin, void */*sin*/, GBDATA */*gbd*/) {
1130    gb_server_data *hs = (gb_server_data *) hsin;
1131    hs->wait_for_new_request--;
1132    return GBCM_SERVER_OK_WAIT;
1133}
1134
1135static GBCM_ServerResult gbcms_talking_obsolete(int /*socket*/, long */*hsin*/, void */*sin*/, GBDATA */*gbd*/) {
1136    fputs("Obsolete server function called\n", stderr);
1137    return GBCM_SERVER_FAULT;
1138}
1139
1140// -----------------------
1141//      server talking
1142
1143typedef GBCM_ServerResult (*TalkingFunction)(int socket, long *hsin, void *sin, GBDATA *gbd);
1144
1145static TalkingFunction aisc_talking_functions[] = {
1146    gbcms_talking_unfold,                           // GBCM_COMMAND_UNFOLD
1147    gbcms_talking_get_update,                       // GBCM_COMMAND_GET_UPDATA
1148    gbcms_talking_put_update,                       // GBCM_COMMAND_PUT_UPDATE
1149    gbcms_talking_updated,                          // GBCM_COMMAND_UPDATED
1150    gbcms_talking_begin_transaction,                // GBCM_COMMAND_BEGIN_TRANSACTION
1151    gbcms_talking_commit_transaction,               // GBCM_COMMAND_COMMIT_TRANSACTION
1152    gbcms_talking_abort_transaction,                // GBCM_COMMAND_ABORT_TRANSACTION
1153    gbcms_talking_init_transaction,                 // GBCM_COMMAND_INIT_TRANSACTION
1154    gbcms_talking_find,                             // GBCM_COMMAND_FIND
1155    gbcms_talking_close,                            // GBCM_COMMAND_CLOSE
1156    gbcms_talking_obsolete,
1157    gbcms_talking_key_alloc,                        // GBCM_COMMAND_KEY_ALLOC
1158    gbcms_talking_undo,                             // GBCM_COMMAND_UNDO
1159    gbcms_talking_disable_wait_for_new_request      // GBCM_COMMAND_DONT_WAIT
1160};
1161
1162static GBCM_ServerResult gbcms_talking(int con, long *hs, void *sin) {
1163    gbcm_read_flush();
1164
1165  next_command :
1166
1167    long buf[3];
1168    long len = gbcm_read(con, (char *)buf, sizeof(long) * 3);
1169    if (len == sizeof(long) * 3) {
1170        long magic_number = buf[0];
1171        if ((magic_number & GBTUM_MAGIC_NUMBER_FILTER) != GBTUM_MAGIC_NUMBER) {
1172            gbcm_read_flush();
1173            fprintf(stderr, "Illegal Access\n");
1174            return GBCM_SERVER_FAULT;
1175        }
1176        magic_number &= ~GBTUM_MAGIC_NUMBER_FILTER;
1177        GBCM_ServerResult error = (aisc_talking_functions[magic_number])(con, hs, sin, (GBDATA *)buf[2]);
1178        if (error == GBCM_SERVER_OK_WAIT) {
1179            goto next_command;
1180        }
1181        gbcm_read_flush();
1182        return error ? error : GBCM_SERVER_OK;
1183    }
1184    else {
1185        return GBCM_SERVER_FAULT;
1186    }
1187}
1188
1189bool GBCMS_accept_calls(GBDATA *gbd, bool wait_extra_time) {
1190    // returns true if served
1191
1192    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1193    if (!Main->server_data) return false;
1194    if (Main->get_transaction_level()) return false;
1195
1196    gb_server_data *hs = Main->server_data;
1197    timeval         timeout;
1198
1199    if (wait_extra_time) {
1200        timeout.tv_sec = 0;
1201        timeout.tv_usec = 100000; // 100 ms
1202    }
1203    else {
1204        timeout.tv_sec = (int)(hs->timeout / 1000);
1205        timeout.tv_usec = (hs->timeout % 1000) * 1000;
1206    }
1207    if (wait_extra_time) {
1208        hs->wait_for_new_request = 1;
1209    }
1210    else {
1211        hs->wait_for_new_request = 0;
1212    }
1213
1214    {
1215        fd_set set;
1216        fd_set setex;
1217
1218        FD_ZERO(&set);
1219        FD_ZERO(&setex);
1220        FD_SET(hs->hso, &set);
1221        FD_SET(hs->hso, &setex);
1222
1223        for (Socinf *si=hs->soci; si; si=si->next) {
1224            FD_SET(si->socket, &set);
1225            FD_SET(si->socket, &setex);
1226        }
1227
1228        {
1229            long anz;
1230            if (hs->timeout>=0) {
1231                anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, &timeout);
1232            }
1233            else {
1234                anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, 0);
1235            }
1236
1237            if (anz==-1) return false;
1238            if (!anz) return false; // timed out
1239        }
1240
1241
1242        if (FD_ISSET(hs->hso, &set)) {
1243            int con = accept(hs->hso, NULL, 0);
1244            if (con>0) {
1245                long optval[1];
1246                Socinf *sptr = (Socinf *)GB_calloc(sizeof(Socinf), 1);
1247                if (!sptr) return 0;
1248                sptr->next = hs->soci;
1249                sptr->socket = con;
1250                hs->soci=sptr;
1251                hs->nsoc++;
1252                optval[0] = 1;
1253                setsockopt(con, IPPROTO_TCP, TCP_NODELAY, (char *)optval, 4);
1254            }
1255        }
1256        else {
1257            Socinf *si_last = 0;
1258            Socinf *si_next;
1259
1260            for (Socinf *si=hs->soci; si; si_last=si, si=si_next) {
1261                si_next = si->next;
1262
1263                GBCM_ServerResult error = GBCM_SERVER_OK;
1264                if (FD_ISSET(si->socket, &set)) {
1265                    error = gbcms_talking(si->socket, (long *)hs, (void *)si);
1266                    if (GBCM_SERVER_OK == error) {
1267                        hs->wait_for_new_request ++;
1268                        continue;
1269                    }
1270                } else if (!FD_ISSET(si->socket, &setex)) continue;
1271
1272                // kill socket
1273
1274                if (close(si->socket)) {
1275                    printf("aisc_accept_calls: ");
1276                    printf("couldn't close socket errno = %i!\n", errno);
1277                }
1278
1279                hs->nsoc--;
1280                if (si==hs->soci) { // first one
1281                    hs->soci = si->next;
1282                }
1283                else {
1284                    si_last->next = si->next;
1285                }
1286                if (si->username) {
1287                    gbcm_logout(Main, si->username);
1288                }
1289                g_bcms_delete_Socinf(si);
1290                si = 0;
1291
1292                if (error != GBCM_SERVER_ABORTED) {
1293                    fprintf(stdout, "ARB_DB_SERVER: a client died abnormally\n");
1294                }
1295                break;
1296            }
1297        }
1298
1299    }
1300    if (hs->wait_for_new_request>0) {
1301        return true;
1302    }
1303    return false;
1304}
1305
1306
1307GB_ERROR gbcm_unfold_client(GBCONTAINER *gbc, long deep, long index_pos) {
1308    // goes to header: __ATTR__USERESULT
1309
1310    /* read data from a server
1311     * deep       = -1   read whole data
1312     * deep       = 0...n    read to deep
1313     * index_pos == -1 read all clients
1314     * index_pos == -2 read all clients + header array
1315     */
1316
1317    GB_ERROR error  = NULL;
1318    int      socket = GBCONTAINER_MAIN(gbc)->c_link->socket;
1319    gbcm_read_flush();
1320
1321    if      (gbcm_write_two  (socket, GBCM_COMMAND_UNFOLD, gbc->server_id)) error = CLIENT_SEND_ERROR();
1322    else if (gbcm_write_two  (socket, GBCM_COMMAND_SETDEEP, deep))          error = CLIENT_SEND_ERROR();
1323    else if (gbcm_write_two  (socket, GBCM_COMMAND_SETINDEX, index_pos))    error = CLIENT_SEND_ERROR();
1324    else if (gbcm_write_flush(socket))                                      error = CLIENT_SEND_ERROR();
1325    else {
1326        long buffer[256];
1327        long irror = 0;
1328        if (index_pos == -2) {
1329            irror = gbcm_read_bin(socket, 0, buffer, 0, gbc, 0);
1330        }
1331        else {
1332            long nitems;
1333            if (gbcm_read_two(socket, GBCM_COMMAND_SEND_COUNT, 0, &nitems)) irror = 1;
1334            else {
1335                for (long item = 0; !irror && item<nitems; item++) {
1336                    irror = gbcm_read_bin(socket, gbc, buffer, 0, 0, 0);
1337                }
1338            }
1339        }
1340
1341        if (irror) {
1342            error = CLIENT_ERROR(GBS_global_string("receive error while unfolding '%s'", GB_read_key_pntr(gbc)));
1343        }
1344        else {
1345            gbcm_read_flush();
1346            if (index_pos < 0) {
1347                gbc->flags2.folded_container = 0;
1348            }
1349        }
1350    }
1351
1352    return error;
1353}
1354
1355// -------------------------
1356//      Client functions
1357
1358GB_ERROR gbcmc_begin_sendupdate(GBDATA *gbd) {
1359    // goes to header: __ATTR__USERESULT
1360
1361    if (gbcm_write_two(GB_MAIN(gbd)->c_link->socket, GBCM_COMMAND_PUT_UPDATE, gbd->server_id)) {
1362        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1363    }
1364    return 0;
1365}
1366
1367GB_ERROR gbcmc_end_sendupdate(GBDATA *gbd) {
1368    // goes to header: __ATTR__USERESULT
1369
1370    GB_MAIN_TYPE *Main   = GB_MAIN(gbd);
1371    int           socket = Main->c_link->socket;
1372    if (gbcm_write_two(socket, GBCM_COMMAND_PUT_UPDATE_END, gbd->server_id)) {
1373        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1374    }
1375
1376    gbcm_write_flush(socket);
1377    while (1) {
1378        long buffer[2];
1379        if (gbcm_read(socket, (char *)&(buffer[0]), sizeof(long)*2) != sizeof(long)*2) {
1380            return CLIENT_RECEIVE_ERROR();
1381        }
1382        gbd = (GBDATA *)buffer[0];
1383        if (!gbd) break;
1384        gbd->server_id = buffer[1];
1385        GBS_write_numhash(Main->remote_hash, gbd->server_id, (long)gbd);
1386    }
1387    gbcm_read_flush();
1388    return 0;
1389}
1390
1391GB_ERROR gbcmc_sendupdate_create(GBDATA *gbd) {
1392    // goes to header: __ATTR__USERESULT
1393
1394    GBCONTAINER *father = GB_FATHER(gbd);
1395    if (!father) {
1396        return CLIENT_ERROR(GBS_global_string("entry '%s' has no father", GB_KEY(gbd)));
1397    }
1398
1399    int socket = GB_MAIN(father)->c_link->socket;
1400    if (gbcm_write_two(socket, GBCM_COMMAND_PUT_UPDATE_CREATE, father->server_id)) {
1401        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1402    }
1403
1404    long *buffer = (long *)GB_give_buffer(1014);
1405    return gbcm_write_bin(socket, gbd, buffer, -1, 1);
1406}
1407
1408GB_ERROR gbcmc_sendupdate_delete(GBDATA *gbd) {
1409    // goes to header: __ATTR__USERESULT
1410
1411    if (gbcm_write_two(GB_MAIN(gbd)->c_link->socket, GBCM_COMMAND_PUT_UPDATE_DELETE, gbd->server_id)) {
1412        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1413    }
1414    return 0;
1415}
1416
1417GB_ERROR gbcmc_sendupdate_update(GBDATA *gbd, int send_headera) { // @@@ DRY vs gbcmc_sendupdate_create
1418    // goes to header: __ATTR__USERESULT
1419
1420    GBCONTAINER *father = GB_FATHER(gbd);
1421    if (!father) {
1422        return CLIENT_ERROR(GBS_global_string("entry '%s' has no father", GB_KEY(gbd)));
1423    }
1424
1425    int socket = GB_MAIN(father)->c_link->socket;
1426    if (gbcm_write_two(socket, GBCM_COMMAND_PUT_UPDATE_UPDATE, gbd->server_id)) {
1427        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1428    }
1429
1430    long *buffer = (long *)GB_give_buffer(1016);
1431    return gbcm_write_bin(socket, gbd, buffer, 0, send_headera);
1432}
1433
1434static __ATTR__USERESULT GB_ERROR gbcmc_read_keys(int socket, GBDATA *gbd) { // @@@ move into GB_MAIN_TYPE?
1435    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1436    long          buffer[2];
1437
1438    if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1439        return CLIENT_RECEIVE_ERROR();
1440    }
1441
1442    long size            = buffer[0];
1443    Main->first_free_key = buffer[1];
1444    gb_create_key_array(Main, (int)size);
1445
1446    for (int i=1; i<size; i++) {
1447        if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1448            return CLIENT_RECEIVE_ERROR();
1449        }
1450
1451        gb_Key &KEY = Main->keys[i];
1452
1453        KEY.nref          = buffer[0];    // to control malloc_index
1454        KEY.next_free_key = buffer[1];    // to control malloc_index
1455
1456        char *key = gbcm_read_string(socket);
1457        if (key) {
1458            if (!key[0]) { // empty key
1459                free(key);
1460                return CLIENT_ERROR("invalid empty key received");
1461            }
1462
1463            GBS_write_hash(Main->key_2_index_hash, key, i);
1464            freeset(KEY.key, key);
1465        }
1466    }
1467    Main->keycnt = (int)size;
1468    return 0;
1469}
1470
1471GB_ERROR gbcmc_begin_transaction(GBDATA *gbd) {
1472    // goes to header: __ATTR__USERESULT
1473
1474    GB_MAIN_TYPE *Main   = GB_MAIN(gbd);
1475    int           socket = Main->c_link->socket;
1476    long         *buffer = (long *)GB_give_buffer(1026);
1477
1478    if (gbcm_write_two(socket, GBCM_COMMAND_BEGIN_TRANSACTION, Main->clock)) {
1479        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1480    }
1481
1482    if (gbcm_write_flush(socket)) {
1483        return CLIENT_SEND_ERROR();
1484    }
1485
1486    {
1487        long server_clock;
1488        if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, &server_clock)) {
1489            return CLIENT_RECEIVE_ERROR();
1490        }
1491        Main->clock = server_clock;
1492    }
1493
1494    while (1) {
1495        if (gbcm_read(socket, (char *)buffer, sizeof(long)*2) != sizeof(long)*2) {
1496            return CLIENT_RECEIVE_ERROR();
1497        }
1498
1499        long    d   = buffer[1];
1500        GBDATA *gb2 = (GBDATA *)GBS_read_numhash(Main->remote_hash, d);
1501        long    mode;
1502        if (gb2) {
1503            mode = gb2->flags2.folded_container
1504                ? -1                                // read container
1505                : 0;                                // read all
1506        }
1507        else {
1508            mode = -2;                              // read nothing
1509        }
1510
1511        switch (buffer[0]) {
1512            case GBCM_COMMAND_PUT_UPDATE_UPDATE:
1513                if (gbcm_read_bin(socket, 0, buffer, mode, gb2, 0)) {
1514                    return CLIENT_RECEIVE_ERROR();
1515                }
1516                if (gb2) {
1517                    gb2->create_extended();
1518                    gb2->touch_update(Main->clock);
1519                }
1520                break;
1521            case GBCM_COMMAND_PUT_UPDATE_CREATE:
1522                if (gbcm_read_bin(socket, GBDATA::as_container(gb2), buffer, mode, 0, 0)) {
1523                    return CLIENT_RECEIVE_ERROR();
1524                }
1525                if (gb2) {
1526                    gb2->create_extended();
1527                    gb2->touch_creation_and_update(Main->clock);
1528                }
1529                break;
1530            case GBCM_COMMAND_PUT_UPDATE_DELETE:
1531                if (gb2) gb_delete_entry(gb2);
1532                break;
1533            case GBCM_COMMAND_PUT_UPDATE_KEYS: {
1534                GB_ERROR error = gbcmc_read_keys(socket, gbd);
1535                if (error) return error;
1536                break;
1537            }
1538            case GBCM_COMMAND_PUT_UPDATE_END:
1539                goto endof_gbcmc_begin_transaction;
1540
1541            default:
1542                return CLIENT_RECEIVE_ERROR();
1543        }
1544    }
1545
1546  endof_gbcmc_begin_transaction :
1547    gbcm_read_flush();
1548    return 0;
1549}
1550
1551GB_ERROR gbcmc_init_transaction(GBCONTAINER *gbc) {
1552    // goes to header: __ATTR__USERESULT
1553
1554    GB_ERROR      error  = 0;
1555    GB_MAIN_TYPE *Main   = GBCONTAINER_MAIN(gbc);
1556    int           socket = Main->c_link->socket;
1557
1558    if (gbcm_write_two(socket, GBCM_COMMAND_INIT_TRANSACTION, Main->clock)) {
1559        return CLIENT_SEND_ERROR_AT_ITEM(gbc);
1560    }
1561    gbcm_write_string(socket, Main->this_user->username);
1562    if (gbcm_write_flush(socket)) {
1563        return CLIENT_SEND_ERROR();
1564    }
1565
1566    {
1567        long server_clock;
1568        if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, &server_clock)) {
1569            return CLIENT_RECEIVE_ERROR();
1570        }
1571        Main->clock = server_clock;
1572    }
1573
1574    long buffer[4];
1575    if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, buffer)) {
1576        return CLIENT_RECEIVE_ERROR();
1577    }
1578    gbc->server_id = buffer[0];
1579
1580    if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, buffer)) {
1581        return CLIENT_RECEIVE_ERROR();
1582    }
1583    Main->this_user->userid = (int)buffer[0];
1584    Main->this_user->userbit = 1<<((int)buffer[0]);
1585
1586    GBS_write_numhash(Main->remote_hash, gbc->server_id, (long)gbc);
1587
1588    if (gbcm_read(socket, (char *)buffer, 2 * sizeof(long)) != 2 * sizeof(long)) {
1589        return CLIENT_RECEIVE_ERROR();
1590    }
1591    error = gbcmc_read_keys(socket, gbc);
1592    if (error) return error;
1593
1594    gbcm_read_flush();
1595    return 0;
1596}
1597
1598GB_ERROR gbcmc_commit_transaction(GBDATA *gbd) {
1599    // goes to header: __ATTR__USERESULT
1600
1601    int socket = GB_MAIN(gbd)->c_link->socket;
1602    if (gbcm_write_two(socket, GBCM_COMMAND_COMMIT_TRANSACTION, gbd->server_id)) {
1603        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1604    }
1605
1606    if (gbcm_write_flush(socket)) {
1607        return CLIENT_SEND_ERROR();
1608    }
1609
1610    long dummy;
1611    if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, &dummy)) {
1612        return CLIENT_RECEIVE_ERROR();
1613    }
1614    gbcm_read_flush();
1615    return NULL;
1616}
1617GB_ERROR gbcmc_abort_transaction(GBDATA *gbd) { // @@@ DRY vs gbcmc_commit_transaction
1618    // goes to header: __ATTR__USERESULT
1619
1620    int socket = GB_MAIN(gbd)->c_link->socket;
1621    if (gbcm_write_two(socket, GBCM_COMMAND_ABORT_TRANSACTION, gbd->server_id)) {
1622        return CLIENT_SEND_ERROR_AT_ITEM(gbd);
1623    }
1624
1625    if (gbcm_write_flush(socket)) {
1626        return CLIENT_SEND_ERROR();
1627    }
1628
1629    long dummy;
1630    if (gbcm_read_two(socket, GBCM_COMMAND_TRANSACTION_RETURN, 0, &dummy)) {
1631        return CLIENT_RECEIVE_ERROR();
1632    }
1633    gbcm_read_flush();
1634    return 0;
1635}
1636
1637GB_ERROR gbcms_add_to_delete_list(GBDATA *gbd) {
1638    gb_server_data *hs = GB_MAIN(gbd)->server_data;
1639
1640    if (hs && hs->soci) {
1641        gbcms_delete_list *dl = (gbcms_delete_list *)gbm_get_mem(sizeof(gbcms_delete_list), GBM_CB_INDEX);
1642
1643        dl->creation_date = gbd->creation_date();
1644        dl->update_date   = gbd->update_date();
1645        dl->gbd           = gbd;
1646
1647        if (!hs->del_first) {
1648            hs->del_first = hs->del_last = dl;
1649        }
1650        else {
1651            hs->del_last->next = dl;
1652            hs->del_last = dl;
1653        }
1654    }
1655    return 0;
1656}
1657
1658void GB_set_remote_action(GBDATA *gbd, bool in_action) {
1659    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1660
1661    if (Main->is_server()) { // GB_set_remote_action has no effect in clients
1662        gb_server_data *hs = Main->server_data;
1663        gb_assert(hs); // have no server data (program logic error)
1664        if (hs) {
1665            gb_assert(hs->inside_remote_action != in_action);
1666            hs->inside_remote_action = in_action;
1667        }
1668    }
1669}
1670bool GB_inside_remote_action(GBDATA *gbd) {
1671    GB_MAIN_TYPE *Main   = GB_MAIN(gbd);
1672    bool          inside = false;
1673
1674    gb_assert(Main->is_server()); // GB_inside_remote_action not allowed from clients
1675    if (Main->is_server()) {
1676        gb_server_data *hs = Main->server_data;
1677        if (hs) {
1678            inside = hs->inside_remote_action;
1679        }
1680    }
1681    return inside;
1682}
1683
1684long GB_read_clients(GBDATA *gbd) {
1685    // returns number of clients or
1686    // -1 if not called from server
1687
1688    GB_MAIN_TYPE *Main    = GB_MAIN(gbd);
1689    long          clients = -1;
1690
1691    if (Main->is_server()) {
1692        gb_server_data *hs = Main->server_data;
1693        clients = hs ? hs->nsoc : 0;
1694    }
1695
1696    return clients;
1697}
1698
1699bool GB_is_server(GBDATA *gbd) {
1700    return GB_MAIN(gbd)->is_server();
1701}
1702
1703static __ATTR__USERESULT GB_ERROR gbcmc_unfold_list(int socket, GBDATA * gbd) {
1704    GB_ERROR error = NULL;
1705
1706    long readvar[2];
1707    if (!gbcm_read(socket, (char *) readvar, sizeof(long) * 2)) {
1708        error = CLIENT_RECEIVE_ERROR();
1709    }
1710    else {
1711        GBCONTAINER *gb_client = (GBCONTAINER*)readvar[1];
1712        if (gb_client) {
1713            error = gbcmc_unfold_list(socket, gbd);
1714            if (!error) {
1715                gb_client = (GBCONTAINER *)GBS_read_numhash(GB_MAIN(gbd)->remote_hash, (long) gb_client);
1716                gb_unfold(gb_client, 0, (int)readvar[0]);
1717            }
1718        }
1719    }
1720    return error;
1721}
1722
1723static void invalid_use_in_server(const char *function) {
1724    GB_internal_errorf("ARBDB fatal error: function '%s' may not be called in server", function);
1725}
1726
1727GBDATA *GBCMC_find(GBDATA *gbd, const char *key, GB_TYPES type, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs) {
1728    // perform search in DB server (from DB client)
1729    // returns NULL if not found OR error occurred (use GB_have_error to test)
1730
1731    union {
1732        GBDATA *gbd;
1733        long    l;
1734    } result;
1735    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1736
1737    int socket;
1738    if (Main->is_server()) {
1739        invalid_use_in_server("GBCMC_find");
1740    }
1741
1742    socket = Main->c_link->socket;
1743
1744    if (gbcm_write_two(socket, GBCM_COMMAND_FIND, gbd->server_id)) {
1745        GB_export_error(CLIENT_SEND_ERROR());
1746        return 0;
1747    }
1748
1749    gbcm_write_string(socket, key);
1750    gbcm_write_long(socket, type);
1751    switch (type) {
1752        case GB_NONE:
1753            break;
1754        case GB_STRING:
1755            gbcm_write_string(socket, str);
1756            gbcm_write_long(socket, case_sens);
1757            break;
1758        case GB_INT:
1759            gbcm_write_long(socket, *(long*)str);
1760            break;
1761        default:
1762            gb_assert(0);
1763            GB_export_errorf("GBCMC_find: Illegal data type (%i)", type);
1764            return 0;
1765    }
1766
1767    gbcm_write_long(socket, gbs);
1768
1769    if (gbcm_write_flush(socket)) {
1770        GB_export_error(CLIENT_SEND_ERROR());
1771        return 0;
1772    }
1773    if (gbcm_read_two(socket, GBCM_COMMAND_FIND_ERG, 0, &result.l)) {
1774        GB_export_error(CLIENT_RECEIVE_ERROR());
1775        return 0;
1776    }
1777    if (result.gbd) {
1778        GB_ERROR error = gbcmc_unfold_list(socket, gbd);
1779        if (error) {
1780            GB_export_error(error);
1781            return 0;
1782        }
1783        result.l = GBS_read_numhash(Main->remote_hash, result.l);
1784    }
1785    gbcm_read_flush();
1786    return result.gbd;
1787}
1788
1789
1790long gbcmc_key_alloc(GBDATA *gbd, const char *key) {
1791    /*! allocate a new key quark from client
1792     * returns new key quark for 'key' or 0 (error is exported in that case)
1793     */
1794    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1795    if (Main->is_server()) {
1796        invalid_use_in_server("gbcmc_key_alloc");
1797    }
1798
1799    int      socket = Main->c_link->socket;
1800    GB_ERROR error  = NULL;
1801    long     result = 0;
1802    if (gbcm_write_two(socket, GBCM_COMMAND_KEY_ALLOC, gbd->server_id)) {
1803        error = CLIENT_SEND_ERROR();
1804    }
1805    else {
1806        gbcm_write_string(socket, key);
1807
1808        if (gbcm_write_flush(socket)) {
1809            error = CLIENT_SEND_ERROR();
1810        }
1811        else {
1812            if (gbcm_read_two(socket, GBCM_COMMAND_KEY_ALLOC_RES, 0, &result)) {
1813                error  = CLIENT_RECEIVE_ERROR();
1814                result = 0;
1815            }
1816            gbcm_read_flush();
1817        }
1818    }
1819    if (error) {
1820        gb_assert(result == 0); // indicates error
1821        GB_export_error(error);
1822    }
1823    return result;
1824}
1825
1826GB_ERROR gbcmc_send_undo_commands(GBDATA *gbd, enum gb_undo_commands command) { // goes to header: __ATTR__USERESULT
1827    // send an undo command
1828
1829    GB_ERROR      error = NULL;
1830    GB_MAIN_TYPE *Main  = GB_MAIN(gbd);
1831
1832    if (Main->is_server()) {
1833        invalid_use_in_server("gbcmc_send_undo_commands");
1834    }
1835    else {
1836        int socket = Main->c_link->socket;
1837
1838        if      (gbcm_write_two  (socket, GBCM_COMMAND_UNDO, gbd->server_id)) error = CLIENT_SEND_ERROR();
1839        else if (gbcm_write_two  (socket, GBCM_COMMAND_UNDO_CMD, command))    error = CLIENT_SEND_ERROR();
1840        else if (gbcm_write_flush(socket))                                    error = CLIENT_SEND_ERROR();
1841        else {
1842            error = gbcm_read_string(socket);
1843            gbcm_read_flush();
1844        }
1845    }
1846    return error;
1847}
1848
1849char *gbcmc_send_undo_info_commands(GBDATA *gbd, enum gb_undo_commands command) {
1850    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1851    if (Main->is_server()) {
1852        invalid_use_in_server("gbcmc_send_undo_info_commands");
1853    }
1854
1855    int socket = Main->c_link->socket;
1856    if (gbcm_write_two(socket, GBCM_COMMAND_UNDO, gbd->server_id) ||
1857        gbcm_write_two(socket, GBCM_COMMAND_UNDO_CMD, command) ||
1858        gbcm_write_flush(socket))
1859    {
1860        GB_export_error(CLIENT_SEND_ERROR());
1861        return 0;
1862    }
1863
1864    char *result = gbcm_read_string(socket);
1865    gbcm_read_flush();
1866    return result;
1867}
1868
1869GB_ERROR GB_tell_server_dont_wait(GBDATA *gbd) {
1870    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
1871    if (Main->is_server()) return 0;
1872
1873    int socket = Main->c_link->socket;
1874    if (gbcm_write_two(socket, GBCM_COMMAND_DONT_WAIT, gbd->server_id)) {
1875        return CLIENT_SEND_ERROR();
1876    }
1877
1878    return 0;
1879}
1880
1881// ---------------------
1882//      Login/Logout
1883
1884
1885GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *loginname) {
1886    // goes to header: __ATTR__USERESULT
1887
1888     // look for any free user and set this_user
1889    int i;
1890    GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gb_main);
1891
1892    for (i = 0; i<GB_MAX_USERS; i++) {
1893        gb_user *user = Main->users[i];
1894        if (user && strcmp(loginname, user->username) == 0) {
1895            Main->this_user = user;
1896            user->nusers++;
1897            return 0;
1898        }
1899    }
1900    for (i = 0; i<GB_MAX_USERS; i++) {
1901        gb_user*& user = Main->users[i];
1902        if (!user) {
1903            user = (gb_user *) GB_calloc(sizeof(gb_user), 1);
1904           
1905            user->username = strdup(loginname);
1906            user->userid   = i;
1907            user->userbit  = 1<<i;
1908            user->nusers   = 1;
1909
1910            Main->this_user = user;
1911
1912            return 0;
1913        }
1914    }
1915    return GBS_global_string("Too many users in this database (user='%s')", loginname);
1916}
1917
1918GBCM_ServerResult gbcmc_close(gbcmc_comm * link) {
1919    if (link->socket) {
1920        if (gbcm_write_two(link->socket, GBCM_COMMAND_CLOSE, 0)) {
1921            GB_export_error(CLIENT_SEND_ERROR());
1922            return GBCM_SERVER_FAULT;
1923        }
1924        if (gbcm_write_flush(link->socket)) {
1925            GB_export_error(CLIENT_SEND_ERROR());
1926            return GBCM_SERVER_FAULT;
1927        }
1928        close(link->socket);
1929        link->socket = 0;
1930    }
1931    free(link->unix_name);
1932    free(link);
1933    return GBCM_SERVER_OK;
1934}
1935
1936GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname) {
1937    // if 'loginname' is NULL, the first logged-in user will be logged out
1938
1939    if (!loginname) {
1940        loginname = Main->users[0]->username;
1941        gb_assert(loginname);
1942    }
1943
1944    for (long i = 0; i<GB_MAX_USERS; i++) {
1945        gb_user*& user = Main->users[i];
1946        if (user && strcmp(loginname, user->username) == 0) {
1947            user->nusers--;
1948            if (user->nusers<=0) { // kill user and his projects
1949                if (i) fprintf(stdout, "User '%s' has logged out\n", loginname);
1950                free(user->username);
1951                freenull(user);
1952            }
1953            return 0;
1954        }
1955    }
1956    return GB_export_errorf("User '%s' not logged in", loginname);
1957}
1958
1959GB_ERROR GB_install_pid(int mode) {
1960    /* tell the arb_clean script what programs are running.
1961     * mode == 1 -> install
1962     * mode == 0 -> never install
1963     */
1964
1965    static long lastpid = -1;
1966    GB_ERROR    error   = 0;
1967
1968    if (mode == 0) {
1969        gb_assert(lastpid == -1); // you have to call GB_install_pid(0) before opening any database!
1970        lastpid = -25;            // mark as "never install"
1971    }
1972
1973    if (lastpid != -25) {
1974        long pid = getpid();
1975
1976        if (pid != lastpid) {   // don't install pid multiple times
1977            char *pidfile_name;
1978            {
1979                const char *user    = GB_getenvUSER();
1980                const char *arb_pid = GB_getenv("ARB_PID"); // normally the pid of the 'arb' shell script
1981
1982                gb_assert(user);
1983                if (!arb_pid) arb_pid = "";
1984
1985                pidfile_name = GBS_global_string_copy("arb_pids_%s_%s", user, arb_pid);
1986            }
1987
1988            char *pid_fullname;
1989            FILE *pidfile = GB_fopen_tempfile(pidfile_name, "at", &pid_fullname);
1990
1991            if (!pidfile) {
1992                error = GBS_global_string("GB_install_pid: %s", GB_await_error());
1993            }
1994            else {
1995                fprintf(pidfile, "%li ", pid);
1996                lastpid = pid; // remember installed pid
1997                fclose(pidfile);
1998            }
1999
2000            // ensure pid file is private, otherwise someone could inject PIDs which will be killed later
2001            gb_assert(GB_is_privatefile(pid_fullname, false));
2002
2003            free(pid_fullname);
2004            free(pidfile_name);
2005        }
2006    }
2007
2008    return error;
2009}
2010
Note: See TracBrowser for help on using the repository browser.