1
// ============================================================= //
6
// Institute of Microbiology (Technical University Munich) //
7
// http://www.arb-home.de/ //
9
// ============================================================= //
7
11
#include <names_server.h>
8
12
#include <names_client.h>
17
#include <arb_sleep.h>
11
19
#include <names_prototypes.h>
12
20
#include <server.h>
13
21
#include <client.h>
14
22
#include <servercntrl.h>
15
23
#include <struct_man.h>
30
#define na_assert(cond) arb_assert(cond)
32
#define FULLNAME_LEN_MAX 64
33
#define NAME_LEN_MIN 2
20
35
using namespace std;
22
37
// --------------------------------------------------------------------------------
33
48
// #define DUMP_NAME_CREATION
36
#define UPPERCASE(c) do{ (c) = toupper(c); }while(0)
51
#define UPPERCASE(c) do { (c) = toupper(c); } while (0)
38
53
// --------------------------------------------------------------------------------
40
struct AN_gl_struct AN_global;
41
AN_main *aisc_main; /* muss so heissen */
57
Hs_struct *server_communication;
63
static struct AN_gl_struct AN_global;
64
AN_main *aisc_main; // muss so heissen
43
66
const int SERVER_VERSION = 5;
114
137
AN_shorts *sin = aisc_main->shorts1;
115
138
size_t elems = an_shorts_elems(sin);
116
139
if (elems<100) elems = 100;
118
GB_HASH *hash = GBS_create_hash(2*elems, GB_IGNORE_CASE);
141
GB_HASH *hash = GBS_create_hash(elems, GB_IGNORE_CASE);
121
144
GBS_write_hash_no_strdup(hash, GB_strndup(sin->shrt, PREFIXLEN), (long)sin);
144
167
// ----------------------------------------
146
static void an_add_short(AN_local *locs, const char *new_name,
169
static void an_add_short(const AN_local */*locs*/, const char *new_name,
147
170
const char *parsed_name, const char *parsed_sym,
148
171
const char *shrt, const char *acc, const char *add_id)
150
173
AN_shorts *an_shorts;
151
174
AN_revers *an_revers;
155
if (strlen(parsed_sym)){
177
if (strlen(parsed_sym)) {
156
178
full_name = (char *)calloc(sizeof(char), strlen(parsed_name) + strlen(" sym")+1);
157
sprintf(full_name,"%s sym",parsed_name);
179
sprintf(full_name, "%s sym", parsed_name);
160
182
full_name = strdup(parsed_name);
190
212
normally removing names does make problems - so use it very rarely */
192
214
GBS_write_hash(an_get_prefix_hash(), an_make_prefix(an_shorts->shrt), 0); // delete an_shorts from hash
194
216
AN_revers *an_revers = lookup_an_revers(aisc_main, an_shorts->shrt);
197
aisc_unlink((struct_dllheader_ext*)an_revers);
219
aisc_unlink((dllheader_ext*)an_revers);
199
221
free(an_revers->mh.ident);
200
222
free(an_revers->full_name);
214
static char *nas_string_2_key(const char *str)
215
// converts any string to a valid key
236
static char *nas_string_2_name(const char *str) {
237
// converts a string to a valid name
217
238
#if defined(DUMP_NAME_CREATION)
218
239
const char *org_str = str;
219
240
#endif // DUMP_NAME_CREATION
221
char buf[GB_KEY_LEN_MAX+1];
242
char buf[FULLNAME_LEN_MAX+1];
224
for (i=0;i<GB_KEY_LEN_MAX;) {
245
for (i=0; i<FULLNAME_LEN_MAX;) {
227
248
if (isalpha(c)) buf[i++] = c;
228
// name should not contain _'s (not compatible with FastDNAml)
229
//else if (c==' ' || c=='_') buf[i++] = '_';
231
for (;i<GB_KEY_LEN_MIN;i++) buf[i] = '0';
250
for (; i<NAME_LEN_MIN; i++) buf[i] = '0';
233
252
#if defined(DUMP_NAME_CREATION)
234
printf("nas_string_2_key('%s') = '%s'\n", org_str, buf);
253
printf("nas_string_2_name('%s') = '%s'\n", org_str, buf);
235
254
#endif // DUMP_NAME_CREATION
236
255
return strdup(buf);
240
259
#if defined(DUMP_NAME_CREATION)
241
260
const char *org_str = str;
242
261
#endif // DUMP_NAME_CREATION
243
char buf[GB_KEY_LEN_MAX+1];
262
char buf[FULLNAME_LEN_MAX+1];
247
for (i=0; i<GB_KEY_LEN_MAX; ) {
266
for (i=0; i<FULLNAME_LEN_MAX;) {
250
269
if (strchr("aeiouy", c)==0) {
254
for (; i<GB_KEY_LEN_MIN; i++) buf[i] = '0';
273
for (; i<NAME_LEN_MIN; i++) buf[i] = '0';
256
275
#if defined(DUMP_NAME_CREATION)
257
276
printf("nas_remove_small_vocals('%s') = '%s'\n", org_str, buf);
320
static char *an_get_short(AN_shorts *IF_DEBUG(shorts), dll_public *parent, const char *full){
339
static char *an_get_short(AN_shorts *IF_ASSERTION_USED(shorts), dll_public *parent, const char *full) {
324
gb_assert(shorts == aisc_main->shorts1); // otherwise prefix_hash does not work!
327
return strdup("Xxx");
343
na_assert(shorts == aisc_main->shorts1); // otherwise prefix_hash does not work!
345
if (full[0]==0) return strdup("ZZZ");
347
const char *result = 0;
331
348
char *full1 = strdup(full);
332
349
an_autocaps(full1);
334
char *full2 = nas_string_2_key(full1);
351
char *full2 = nas_string_2_name(full1);
336
look = (AN_shorts *)aisc_find_lib((struct_dllpublic_ext*)parent, full2);
337
if (look) { /* name is already known */
353
look = (AN_shorts *)aisc_find_lib((dllpublic_ext*)parent, full2);
354
if (look) { // name is already known
340
357
return strdup(look->shrt);
419
// generate names containing 1 random character + 2 digits:
421
for (p1='A'; p1<='Z'; p1++) {
423
for (p2=0; p2<=99; p2++) {
424
shrt[1] = '0'+(p2/10);
425
shrt[2] = '0'+(p2%10);
426
look = an_find_shrt_prefix(shrt);
428
an_complete_shrt(shrt, full2);
434
// generate names containing 2 random characters + 1 digit:
436
for (p1='A'; p1<='Z'; p1++) {
438
for (p2='a'; p2<='z'; p2++) {
440
for (p3=0; p3<=9; p3++) {
442
look = an_find_shrt_prefix(shrt);
444
an_complete_shrt(shrt, full2);
451
// generate names containing 3 random characters:
453
for (p1='A'; p1<='Z'; p1++) {
455
for (p2='a'; p2<='z'; p2++) {
457
for (p3='a'; p3<='z'; p3++) {
459
look = an_find_shrt_prefix(shrt);
461
an_complete_shrt(shrt, full2);
436
// failed to produce sth with given name, generate something random now
439
// use digits first, then use upper-case alpha (methods above use lower-case alpha)
440
const char *allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
443
for (p1='A'; p1<='Z'; p1++) { // first character has to be alpha
445
for (p2 = 0; p2<len; p2++) {
446
shrt[1] = allowed[p2];
447
for (p3 = 0; p3<len; p3++) {
448
shrt[2] = allowed[p3];
449
look = an_find_shrt_prefix(shrt);
451
an_complete_shrt(shrt, full2);
459
shrt[0] = 0; // erase result
464
if (result && result[0]) {
473
465
#if defined(DUMP_NAME_CREATION)
474
466
if (isdigit(result[0]) || isdigit(result[1])) {
475
467
printf("generated new short-name '%s' for full-name '%s' full2='%s' full3='%s'\n", shrt, full, full2, full3);
479
471
look = create_AN_shorts();
480
472
look->mh.ident = strdup(full2);
481
473
look->shrt = strdup(result);
482
aisc_link((struct_dllpublic_ext*)parent,(struct_dllheader_ext*)look);
474
aisc_link((dllpublic_ext*)parent, (dllheader_ext*)look);
484
476
aisc_main->touched = 1;
487
479
printf("ARB_name_server: Failed to make a short-name for '%s'\n", full);
520
513
const char *get_first_name() const { return first_name; }
521
514
const char *get_rest_of_name() const { return rest_of_name; }
523
void add_short(AN_local *locs, const char *shrt) const {
524
if (strlen(parsed_name)>3) {
525
an_add_short(locs, id, parsed_name, parsed_sym, shrt, parsed_acc, parsed_add_id);
516
void add_short(const AN_local *locs, const char *shrt) const {
517
an_add_short(locs, id, parsed_name, parsed_sym, shrt, parsed_acc, parsed_add_id);
566
557
#if defined(DEBUG)
567
#define assert_alnum(s) gb_assert(stralnum(s))
558
#define assert_alnum(s) na_assert(stralnum(s))
569
560
#define assert_alnum(s)
572
NameInformation::NameInformation(AN_local *locs) {
563
NameInformation::NameInformation(const AN_local *locs) {
573
564
full_name = locs->full_name;
574
565
if (!full_name || !full_name[0]) full_name = default_full_name;
576
567
parsed_name = GBS_string_eval(full_name,
577
568
"\t= :\"= :'= :" // replace TABs and quotes by space
578
"sp.=species:spec.=species:SP.=SPECIES:SPEC.=SPECIES:" // replace common abbreviations of 'species'
569
"sp.=species:spec.=species:SP.=SPECIES:SPEC.=SPECIES:" // replace common abbreviations of 'species'
579
570
".= :" // replace dots by spaces
580
571
" = :" // multiple spaces -> 1 space
581
"* * *=*1 *2" // skip all beyond 2nd word
575
int leading_spaces = strspn(parsed_name, " ");
576
int len = strlen(parsed_name)-leading_spaces;
577
memmove(parsed_name, parsed_name+leading_spaces, len);
579
char *first_space = strchr(parsed_name, ' ');
581
char *second_space = strchr(first_space+1, ' ');
583
second_space[0] = 0; // skip all beyond 2nd word
583
588
an_autocaps(parsed_name);
585
parsed_sym = GBS_string_eval(full_name, "\t= :* * *sym*=S",0);
590
parsed_sym = GBS_string_eval(full_name, "\t= :* * *sym*=S", 0);
586
591
if (strlen(parsed_sym)>1) freedup(parsed_sym, "");
588
593
const char *add_id = locs->add_id[0] ? locs->add_id : aisc_main->add_field_default;
590
595
parsed_acc = make_alnum(locs->acc);
591
596
parsed_add_id = make_alnum(add_id);
592
first_name = GBS_string_eval(parsed_name,"* *=*1",0);
597
first_name = GBS_string_eval(parsed_name, "* *=*1", 0);
593
598
rest_of_name = make_alnum(parsed_name+strlen(first_name));
595
600
freeset(first_name, make_alnum(first_name));
622
627
// --------------------------------------------------------------------------------
623
628
// AISC functions
625
extern "C" int del_short(AN_local *locs)
626
/* forget about a short name */
630
int del_short(const AN_local *locs) {
631
// forget about a short name
628
632
NameInformation info(locs);
630
634
AN_shorts *an_shorts = lookup_an_shorts(aisc_main, info.get_id());
640
644
static GB_HASH *nameModHash = 0; // key = default name; value = max. counter tested
642
extern "C" aisc_string get_short(AN_local *locs)
643
/* get the short name from the previously set names */
646
aisc_string get_short(const AN_local *locs) {
647
// get the short name from the previously set names
645
648
static char *shrt = 0;
649
652
NameInformation info(locs);
650
653
AN_shorts *an_shorts = lookup_an_shorts(aisc_main, info.get_id());
668
671
shrt = strdup(an_shorts->shrt);
671
if (!shrt) { /* now there is no short name (or an illegal one) */
672
char *first_advice=0,*second_advice=0;
674
if (!shrt) { // now there is no short name (or an illegal one)
675
char *first_advice=0, *second_advice=0;
674
if (locs->advice[0] && !stralnum(locs->advice)) { // bad advice
677
if (locs->advice[0] && !stralnum(locs->advice)) { // bad advice
675
678
locs->advice[0] = 0; // delete it
696
699
? an_get_short(aisc_main->shorts1, &(aisc_main->pshorts1), first_name)
697
700
: strdup(first_advice);
699
gb_assert(first_short);
702
na_assert(first_short);
700
703
if (first_short[0] == 0) { // empty?
701
freedup(first_short, "Xxx");
704
freedup(first_short, "ZZZ");
703
706
first_len = strlen(first_short);
751
754
char test_short[9];
752
sprintf(test_short,"%s%s", first_short, second_short);
754
gb_assert(size_t(both_len) == strlen(test_short));
755
gb_assert(second_len>=5 && second_len <= 8);
755
sprintf(test_short, "%s%s", first_short, second_short);
757
na_assert(size_t(both_len) == strlen(test_short));
758
na_assert(second_len>=5 && second_len <= 8);
757
760
if (lookup_an_revers(aisc_main, test_short)) {
758
761
if (!nameModHash) nameModHash = GBS_create_hash(100, GB_IGNORE_CASE);
772
775
int limit = digLimit[digits];
774
777
if (printOffset>maxOffset) printOffset = maxOffset;
776
779
char *printAt = test_short+printOffset;
778
781
for (; !foundUnused && count <= limit; ++count) {
779
IF_DEBUG(int printed =) sprintf(printAt, "%li", count);
780
gb_assert((printed+printOffset) <= 8);
782
IF_ASSERTION_USED(int printed =) sprintf(printAt, "%li", count);
783
na_assert((printed+printOffset) <= 8);
781
784
if (!lookup_an_revers(aisc_main, test_short)) foundUnused = true; // name does not exist
838
extern "C" int server_save(AN_main *main, int dummy)
841
int server_save(AN_main *main, int) {
844
842
if (main->touched) {
845
843
int server_date = GB_time_of_file(main->server_file);
846
844
if (server_date>main->server_filedate) {
847
845
printf("Another nameserver changed '%s' - your changes are lost.\n", main->server_file);
850
sec_name = (char *)calloc(sizeof(char), strlen(main->server_file)+2);
851
sprintf(sec_name,"%s%%", main->server_file);
848
char *sec_name = (char *)calloc(sizeof(char), strlen(main->server_file)+2);
849
sprintf(sec_name, "%s%%", main->server_file);
852
850
printf("Saving '%s'..\n", main->server_file);
853
file = fopen(sec_name,"w");
852
FILE *file = fopen(sec_name, "w");
855
fprintf(stderr,"ERROR cannot save file '%s'\n",sec_name);
854
fprintf(stderr, "ERROR cannot save file '%s'\n", sec_name);
858
error = save_AN_main(main,file);
861
if (GB_rename_file(sec_name, main->server_file)) {
857
save_AN_main(main, file);
858
if (fclose(file) == 0) {
859
GB_ERROR mv_error = GB_rename_file(sec_name, main->server_file);
860
if (mv_error) GB_warning(mv_error);
861
else main->touched = 0;
864
GB_ERROR save_error = GB_IO_error("saving", sec_name);
865
fprintf(stderr, "Error: %s\n", save_error);
870
870
main->server_filedate = GB_time_of_file(main->server_file);
874
874
printf("No changes to ARB_name_server data.\n");
935
935
AN_shorts *self_find = lookup_an_shorts(main, shrt->mh.ident);
936
936
if (!self_find) { // stored with wrong key (not lowercase)
937
aisc_unlink((struct_dllheader_ext*)shrt);
937
aisc_unlink((dllheader_ext*)shrt);
938
938
an_strlwr(shrt->mh.ident);
939
939
aisc_link(&main->pnames, shrt);
940
940
main->touched = 1;
978
978
list<string>::const_iterator end = idents_to_recreate.end();
979
979
for (list<string>::const_iterator i = idents_to_recreate.begin(); i != end; ++i) {
980
980
const char *ident = i->c_str();
981
an_get_short(main->shorts1, &(main->pshorts1), ident);
981
free(an_get_short(main->shorts1, &(main->pshorts1), ident));
982
982
regen_name_parts++;
986
986
// now capitalize all short names
987
for (AN_shorts *shrt = main->names; shrt; ) {
987
for (AN_shorts *shrt = main->names; shrt;) {
988
988
AN_shorts *next = shrt->next;
989
989
char *cap_name = strdup(shrt->shrt);
990
990
an_autocaps(cap_name);
992
992
if (strcmp(cap_name, shrt->shrt) != 0) {
993
// fprintf(stderr, "Deleting entry '%s'\n", shrt->shrt);
994
993
an_remove_short(shrt);
1010
1009
int illegal_names = 0;
1012
1011
// first check name parts
1013
for (AN_shorts *shrt = main->shorts1; shrt; ) {
1012
for (AN_shorts *shrt = main->shorts1; shrt;) {
1014
1013
AN_shorts *next = shrt->next;
1015
1014
if (!stralnum(shrt->shrt)) {
1016
1015
fprintf(stderr, "- Fixing illegal chars in '%s'\n", shrt->shrt);
1022
1021
// then check full short-names
1023
for (AN_shorts *shrt = main->names; shrt; ) {
1022
for (AN_shorts *shrt = main->names; shrt;) {
1024
1023
AN_shorts *next = shrt->next;
1025
1024
if (!stralnum(shrt->shrt)) {
1026
1025
fprintf(stderr, "- Fixing illegal chars in '%s'\n", shrt->shrt);
1044
1043
// (empty default was old behavior)
1046
1045
long count = 0;
1047
for (AN_shorts *shrt = main->names; shrt; ) {
1046
for (AN_shorts *shrt = main->names; shrt;) {
1048
1047
AN_shorts *next = shrt->next;
1049
1048
if (!shrt->add_id[0]) {
1050
aisc_unlink((struct_dllheader_ext*)shrt);
1049
aisc_unlink((dllheader_ext*)shrt);
1052
1051
freedup(shrt->add_id, main->add_field_default);
1053
gb_assert(strchr(shrt->mh.ident, 0)[-1] == '*');
1052
na_assert(strchr(shrt->mh.ident, 0)[-1] == '*');
1054
1053
freeset(shrt->mh.ident, GBS_global_string_copy("%s%s", shrt->mh.ident, main->add_field_default));
1056
1055
aisc_link(&main->pnames, shrt);
1076
1075
fprintf(stderr, "Starting ARB_name_server..\n");
1078
file = fopen(main->server_file,"r");
1077
file = fopen(main->server_file, "r");
1080
1079
error = GBS_global_string("No such file '%s'", main->server_file);
1083
1082
fprintf(stderr, "* Loading %s\n", main->server_file);
1084
int err_code = load_AN_main(main,file);
1083
int err_code = load_AN_main(main, file);
1085
1084
if (err_code) {
1086
1085
error = GBS_global_string("Error #%i while loading '%s'", err_code, main->server_file);
1134
void names_server_shutdown(int exitcode) __ATTR__NORETURN;
1135
void names_server_shutdown(int exitcode) {
1133
__ATTR__NORETURN static void names_server_shutdown(int exitcode) {
1136
1134
aisc_server_shutdown_and_exit(AN_global.server_communication, exitcode); // never returns
1139
int names_server_save(void) {
1137
int names_server_save() {
1140
1138
server_save(aisc_main, 0);
1144
extern "C" int server_shutdown(AN_main *pm, aisc_string passwd){
1146
if( strcmp(passwd, "ldfiojkherjkh") ) return 1;
1142
int server_shutdown(AN_main */*pm*/, aisc_string passwd) {
1144
if (strcmp(passwd, "ldfiojkherjkh")) return 1;
1147
1145
printf("\narb_name_server: I got the shutdown message.\n");
1149
/** shoot clients **/
1150
1148
aisc_broadcast(AN_global.server_communication, 0,
1151
1149
"SERVER SHUTDOWN BY ADMINISTRATOR!\n");
1154
1152
printf("ARB_name_server: server shutdown by administrator\n");
1155
1153
names_server_shutdown(0); // never returns!
1167
1164
, SERVER_VERSION, exeName);
1168
1165
arb_print_server_params();
1169
1166
if (err) printf("Error: %s\n", err);
1173
int main(int argc,char **argv)
1177
struct Hs_struct *so;
1178
struct arb_params *params;
1170
int ARB_main(int argc, char *argv[]) {
1180
params = arb_trace_argv(&argc,argv);
1176
params = arb_trace_argv(&argc, (const char **)argv);
1181
1177
const char *executable = argv[0];
1183
1179
if (!params->default_file) usage(executable, "Missing default file");
1191
1187
if (argc!=2) usage(executable, "Too many parameters");
1193
1189
aisc_main = create_AN_main();
1194
/***** try to open com with any other pb server ******/
1191
// try to open com with running name server
1195
1192
if (params->tcp) {
1196
1193
name = params->tcp;
1199
const char *cname = GBS_read_arb_tcp("ARB_NAME_SERVER");
1196
const char *cname = GBS_read_arb_tcp(GBS_nameserver_tag(NULL));
1202
1199
GB_print_error();
1205
1202
name = strdup(cname);
1208
AN_global.cl_link = (aisc_com *)aisc_open(name, (long *)&AN_global.cl_main,AISC_MAGIC_NUMBER);
1205
GB_ERROR error = NULL;
1206
AN_global.cl_link = aisc_open(name, AN_global.cl_main, AISC_MAGIC_NUMBER, &error);
1210
1208
if (AN_global.cl_link) {
1211
if( !strcmp(argv[1],"-look")) {
1209
if (!strcmp(argv[1], "-look")) {
1212
1210
printf("ARB_name_server: No client - terminating.\n");
1213
aisc_close(AN_global.cl_link);AN_global.cl_link = 0;
1211
aisc_close(AN_global.cl_link, AN_global.cl_main); AN_global.cl_link = 0;
1217
1215
printf("There is another active nameserver. I try to kill it..\n");
1218
1216
aisc_nput(AN_global.cl_link, AN_MAIN, AN_global.cl_main,
1219
1217
MAIN_SHUTDOWN, "ldfiojkherjkh",
1221
aisc_close(AN_global.cl_link);AN_global.cl_link=0;
1224
if( ((strcmp(argv[1],"-kill")==0)) ||
1225
((argc==3) && (strcmp(argv[2],"-kill")==0))){
1219
aisc_close(AN_global.cl_link, AN_global.cl_main); AN_global.cl_link=0;
1224
printf("ARB_name_server: %s\n", error);
1228
if (((strcmp(argv[1], "-kill") == 0)) ||
1229
((argc==3) && (strcmp(argv[2], "-kill")==0))) {
1226
1230
printf("ARB_name_server: Now I kill myself!\n");
1229
for (i=0, so=0; (i<MAX_TRY) && (!so); i++){
1230
so = open_aisc_server(name, NAME_SERVER_SLEEP*1000L ,0);
1231
if (!so) sleep(RETRY_SLEEP);
1233
for (i=0, so=0; (i<MAX_TRY) && (!so); i++) {
1234
so = open_aisc_server(name, NAME_SERVER_SLEEP*1000L, 0);
1235
if (!so) GB_sleep(RETRY_SLEEP, SEC);
1234
1238
printf("AN_SERVER: Gave up on opening the communication socket!\n");
1237
1241
AN_global.server_communication = so;
1239
1243
aisc_main->server_file = strdup(params->default_file);
1240
1244
aisc_main->server_filedate = GB_time_of_file(aisc_main->server_file);
1242
GB_ERROR error = server_load(aisc_main);
1246
error = server_load(aisc_main);
1245
1249
const char *field = params->field;