source: tags/arb_5.2/SERVERCNTRL/servercntrl.c

Last change on this file was 6100, checked in by westram, 15 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_export_error → GB_export_error/GB_export_errorf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5#include <ctype.h>
6/* #include <malloc.h> */
7#include <client_privat.h>
8#include <client.h>
9#include <arbdb.h>
10#include <servercntrl.h>
11
12/*
13 * The following lines go to servercntrl.h
14 * edit here, not there!!
15 * call 'make proto' to update
16 */
17
18/* AISC_MKPT_PROMOTE:struct arb_params {*/
19/* AISC_MKPT_PROMOTE:    char *species_name;*/
20/* AISC_MKPT_PROMOTE:    char *extended_name;*/
21/* AISC_MKPT_PROMOTE:    char *alignment;*/
22/* AISC_MKPT_PROMOTE:    char *default_file;*/
23/* AISC_MKPT_PROMOTE:    char *field;*/
24/* AISC_MKPT_PROMOTE:    const char *field_default;*/
25/* AISC_MKPT_PROMOTE:*/
26/* AISC_MKPT_PROMOTE:    int  read_only;*/
27/* AISC_MKPT_PROMOTE:*/
28/* AISC_MKPT_PROMOTE:    char *job_server;*/
29/* AISC_MKPT_PROMOTE:    char *db_server;*/
30/* AISC_MKPT_PROMOTE:    char *mgr_server;*/
31/* AISC_MKPT_PROMOTE:    char *pt_server;*/
32/* AISC_MKPT_PROMOTE:*/
33/* AISC_MKPT_PROMOTE:    char *tcp;*/
34/* AISC_MKPT_PROMOTE:};*/
35
36#define TRIES 1
37
38struct gl_struct {
39    aisc_com *link;
40    long      locs;
41    long      com;
42} glservercntrl;
43
44
45char *prefixSSH(const char *host, const char *command, int async) {
46    /* 'host' is a hostname or 'hostname:port' (where hostname may be an IP)
47       'command' is the command to be executed
48       if 'async' is 1 -> append '&'
49
50       returns a SSH system call for foreign host or
51       a direct system call for the local machine
52    */
53
54    char *result    = 0;
55    char  asyncChar = " &"[!!async];
56
57    if (host && host[0]) {
58        const char *hostPort = strchr(host, ':');
59        char       *hostOnly = GB_strpartdup(host, hostPort ? hostPort-1 : 0);
60
61        if (!GB_host_is_local(hostOnly)) {
62            result = GBS_global_string_copy("ssh %s -n '%s' %c", hostOnly, command, asyncChar);
63        }
64        free(hostOnly);
65    }
66
67    if (!result) {
68        result = GBS_global_string_copy("(%s) %c", command, asyncChar);
69    }
70
71    return result;
72}
73
74GB_ERROR arb_start_server(const char *arb_tcp_env, GBDATA *gbmain, int do_sleep)
75{
76    const char *tcp_id;
77    GB_ERROR error = 0;
78
79    if (!(tcp_id = GBS_read_arb_tcp(arb_tcp_env))) {
80        error = GB_export_errorf("Entry '%s' in $(ARBHOME)/lib/arb_tcp.dat not found", arb_tcp_env);
81    }
82    else {
83        const char *server       = strchr(tcp_id, 0) + 1;
84        char       *serverparams = 0;
85
86        /* concatenate all params behind server
87           Note :  changed behavior on 2007/Mar/09 -- ralf
88           serverparams now is one space if nothing defined in arb_tcp.dat
89           (previously was same as 'server' - most likely a bug)
90        */
91        {
92            const char *param  = strchr(server, 0)+1;
93            size_t      plen   = strlen(param);
94            size_t      alllen = 0;
95
96            while (plen) {
97                param  += plen+1;
98                alllen += plen+1;
99                plen    = strlen(param);
100            }
101
102            serverparams = (char*)malloc(alllen+1);
103            {
104                char *sp = serverparams;
105
106                param = strchr(server, 0)+1;
107                plen  = strlen(param);
108                if (!plen) sp++;
109                else do {
110                    memcpy(sp, param, plen);
111                    sp[plen]  = ' ';
112                    sp       += plen+1;
113                    param    += plen+1;
114                    plen      = strlen(param);
115                } while (plen);
116                sp[-1] = 0;
117            }
118        }
119
120        {
121            char *command = 0;
122            int   delay   = 5;
123
124            if (*tcp_id == ':') { /* local mode */
125                command = GBS_global_string_copy("%s %s -T%s &",server, serverparams, tcp_id);
126            }
127            else {
128                const char *port = strchr(tcp_id, ':');
129
130                if (!port) {
131                    error = GB_export_errorf("Error: Missing ':' in line '%s' file $(ARBHOME)/lib/arb_tcp.dat", arb_tcp_env);
132                }
133                else {
134                    char *remoteCommand = GBS_global_string_copy("$ARBHOME/bin/%s %s -T%s", server, serverparams, port);
135
136                    command = prefixSSH(tcp_id, remoteCommand, 1);
137                    free(remoteCommand);
138                }
139            }
140
141            if (!error) {
142#if defined(DEBUG)
143                printf("Starting server (cmd='%s')\n", command);
144#endif /* DEBUG */
145                if (!gbmain || GBCMC_system(gbmain,command)) system(command);
146                if (do_sleep) sleep(delay);
147            }
148            free(command);
149        }
150        free(serverparams);
151    }
152    return error;
153}
154
155static GB_ERROR arb_wait_for_server(const char *arb_tcp_env, GBDATA *gbmain, const char *tcp_id, int magic_number, struct gl_struct *serverctrl, int wait) {
156    serverctrl->link = aisc_open(tcp_id, &(serverctrl->com), magic_number);
157    if (!serverctrl->link) { // no server running -> start one
158        GB_ERROR error = arb_start_server(arb_tcp_env, gbmain, 0);
159        if (error) return error;
160
161        while (!serverctrl->link && wait) {
162            sleep(1);
163            wait--;
164            if ((wait%10) == 0 && wait>0) {
165                printf("Waiting for server '%s' to come up (%i seconds left)\n", arb_tcp_env, wait);
166            }
167            serverctrl->link  = aisc_open(tcp_id, &(serverctrl->com), magic_number);
168        }
169    }
170
171    return 0;
172}
173
174GB_ERROR arb_look_and_start_server(long magic_number, const char *arb_tcp_env, GBDATA *gbmain) {
175    GB_ERROR    error       = 0;
176    const char *tcp_id      = GBS_read_arb_tcp(arb_tcp_env);
177    const char *arb_tcp_dat = "$(ARBHOME)/lib/arb_tcp.dat";
178
179    if (!tcp_id) {
180        error = GBS_global_string("Entry '%s' not found in %s", arb_tcp_env, arb_tcp_dat);
181    }
182    else {
183        const char *file = GBS_scan_arb_tcp_param(tcp_id, "-d"); // find parameter behind '-d'
184
185        if (!file) {
186            error = GBS_global_string("Parameter -d missing for entry '%s' in %s", arb_tcp_env, arb_tcp_dat);
187        }
188        else {
189            if (strcmp(file, "!ASSUME_RUNNING") == 0) {
190                // assume pt-server is running on a host,  w/o access to common network drive
191                // i.e. we cannot check for the existance of the database file
192            }
193            else if (GB_size_of_file(file) <= 0) {
194                if (strncmp(arb_tcp_env, "ARB_NAME_SERVER", 15) == 0) {
195                    char *dir       = strdup(file);
196                    char *lastSlash = strrchr(dir, '/');
197
198                    if (lastSlash) {
199                        lastSlash[0]         = 0; // cut off file
200                        {
201                            const char *copy_cmd = GBS_global_string("cp %s/names.dat.template %s", dir, file);
202                            system(copy_cmd);
203                        }
204                        if (GB_size_of_file(file) <= 0) {
205                            error = GBS_global_string("Cannot copy nameserver template (%s/names.dat.template missing?)", dir);
206                        }
207                    }
208                    else {
209                        error = GBS_global_string("Can't determine directory from '%s'", dir);
210                    }
211                    free(dir);
212                }
213                else if (strncmp(arb_tcp_env, "ARB_PT_SERVER", 13) == 0) {
214                    const char *nameOnly    = strrchr(file, '/');
215                    if (!nameOnly) nameOnly = file;
216
217                    error = GBS_global_string("PT_server '%s' has not been created yet.\n"
218                                              " To create it follow these steps:\n"
219                                              " 1. Start ARB on the whole database you want to use for probe match/design\n"
220                                              " 2. Go to ARB_NTREE/Probes/PT_SERVER Admin\n"
221                                              " 3. Select '%s' and press BUILD SERVER\n"
222                                              " 4. Wait (up to hours, depending on your DB size)\n"
223                                              " 5. Meanwhile read the help file: PT_SERVER: What Why and How",
224                                              file, nameOnly);
225                }
226                else {
227                    error = GBS_global_string("The file '%s' is missing. \nUnable to start %s", file, arb_tcp_env);
228                }
229            }
230        }
231
232        if (!error) {
233            error = arb_wait_for_server(arb_tcp_env, gbmain, tcp_id, magic_number, &glservercntrl, 20);
234
235            if (!error) {
236                if (!glservercntrl.link) { // couldn't start server
237                    error =
238                        "I got some problems to start your server:\n"
239                        "   Possible Reasons may be one or more of the following list:\n"
240                        "   - there is no database in $ARBHOME/lib/pts/*\n"
241                        "     update server <ARB_NTREE/Probes/PT_SERVER Admin/BUILD SERVER>\n"
242                        "   - you are not allowed to run 'ssh host pt_server ....&'\n"
243                        "     check file '/etc/hosts.equiv' (read man pages for help)\n"
244                        "   - the permissions of $ARBHOME/lib/pts/* do not allow read access\n"
245                        "   - the PT_SERVER host is not up\n"
246                        "   - the tcp_id is already used by another program\n"
247                        "     check $ARBHOME/lib/arb_tcp.dat and /etc/services\n";
248                }
249                else {
250                    aisc_close(glservercntrl.link);
251                    glservercntrl.link = 0;
252                }
253            }
254        }
255    }
256
257    return error;
258}
259
260GB_ERROR arb_look_and_kill_server(int magic_number, const char *arb_tcp_env)
261{
262    const char *tcp_id;
263    GB_ERROR    error = 0;
264
265    if (!(tcp_id = GBS_read_arb_tcp(arb_tcp_env))) {
266        error = GB_export_errorf("Missing line '%s' in $(ARBHOME)/lib/arb_tcp.dat:",arb_tcp_env);
267    }
268    else {
269        const char *server = strchr(tcp_id, 0)+1;
270
271        glservercntrl.link = (aisc_com *) aisc_open(tcp_id, &glservercntrl.com, magic_number);
272        if (glservercntrl.link) {
273            const char *command = GBS_global_string("%s -kill -T%s &", server, tcp_id);
274            /* sprintf(command, "%s -kill -T%s &", server, tcp_id); */
275            if (system(command)) {
276                error = GB_export_errorf("Cannot execute '%s'",command);
277            }
278            aisc_close(glservercntrl.link);
279            glservercntrl.link = 0;
280        }
281        else {
282            error= GB_export_error("I cannot kill your server because I cannot find it");
283        }
284    }
285    return error;
286}
287
288void arb_print_server_params() {
289    printf("General server parameters (some maybe unused by this server):\n"
290           "    -s<name>        sets species name to '<name>'\n"
291           "    -e<name>        sets extended name to '<name>'\n"
292           "    -a<ali>         sets alignment to '<ali>'\n"
293           "    -d<file>        sets default file to '<file>'\n"
294           "    -f<field>=<def> sets DB field to '<field>' (using <def> as default)\n"
295           "    -r              read-only mode\n"
296           "    -D<server>      sets DB-server to '<server>'  [default = ':']\n"
297           "    -J<server>      sets job-server to '<server>' [default = 'ARB_JOB_SERVER']\n"
298           "    -M<server>      sets MGR-server to '<server>' [default = 'ARB_MGR_SERVER']\n"
299           "    -P<server>      sets PT-server to '<server>'  [default = 'ARB_PT_SERVER']\n"
300           "    -T<[host]:port>   sets TCP connection to '<[host]:port>'\n"
301           );
302}
303
304struct arb_params *arb_trace_argv(int *argc, char **argv)
305{
306    struct arb_params *erg;
307    int s,d;
308
309    erg             = (struct arb_params *)calloc(sizeof(struct arb_params),1);
310    erg->db_server  = strdup(":");
311    erg->job_server = strdup("ARB_JOB_SERVER");
312    erg->mgr_server = strdup("ARB_MGR_SERVER");
313    erg->pt_server  = strdup("ARB_PT_SERVER");
314
315    for (s=d=0; s<*argc; s++) {
316        if (argv[s][0] == '-') {
317            switch (argv[s][1]) {
318                case 's': erg->species_name  = strdup(argv[s]+2);break;
319                case 'e': erg->extended_name = strdup(argv[s]+2);break;
320                case 'a': erg->alignment     = strdup(argv[s]+2);break;
321                case 'd': erg->default_file  = strdup(argv[s]+2);break;
322                case 'f': {
323                    char *eq;
324                    erg->field = strdup(argv[s]+2);
325
326                    eq = strchr(erg->field, '=');
327                    if (eq) {
328                        erg->field_default = eq+1;
329                        eq[0]              = 0;
330                    }
331                    else {
332                        erg->field_default = 0; // this is illegal - error handling done in caller
333                    }
334                    break;
335                }
336                case 'r': erg->read_only     = 1;break;
337                case 'J': erg->job_server    = strdup(argv[s]+2);break;
338                case 'D': erg->db_server     = strdup(argv[s]+2);break;
339                case 'M': erg->mgr_server    = strdup(argv[s]+2);break;
340                case 'P': erg->pt_server     = strdup(argv[s]+2);break;
341                case 'T': {
342                    char *ipport = argv[s]+2;
343                    if (ipport[0] == ':' &&
344                        ipport[1] >= '0' && ipport[1] <= '9') { /* port only -> assume localhost */
345                        erg->tcp = GBS_global_string_copy("localhost%s", ipport);
346                    }
347                    else {
348                        erg->tcp = strdup(ipport);
349                    }
350                    break;
351                }
352                default:
353                    argv[d++] = argv[s];
354                    break;
355            }
356        }
357        else {
358            argv[d++] = argv[s];
359        }
360    }
361    *argc = d;
362    return erg;
363}
Note: See TracBrowser for help on using the repository browser.