root/trunk/ARBDB/adcomm.cxx

Revision 8607, 63.3 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8135] [8136] [8137] [8138] [8139] [8140] [8141] [8142] [8143] [8144] [8222]
this revives the reverted patches [8129] [8130] [8131] [8132]

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