source: tags/arb-6.0.6/ARBDB/adcomm.cxx

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