source: tags/svn.1.5.4/SERVERCNTRL/servercntrl.cxx

Last change on this file was 8309, checked in by westram, 14 years ago
  • moved much code into static scope

(partly reverted by [8310])

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