00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "midas.h"
00013 #include "msystem.h"
00014 #include "strlcpy.h"
00015 #include <assert.h>
00016 #include <signal.h>
00017
00018
00019
00020
00021
00022 char *svn_revision = "$Rev: 4825 $";
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00051
00052
00053
00054 INT tid_size[] = {
00055 0,
00056 1,
00057 1,
00058 1,
00059 2,
00060 2,
00061 4,
00062 4,
00063 4,
00064 4,
00065 8,
00066 1,
00067 0,
00068 0,
00069 0,
00070 0,
00071 0
00072 };
00073
00074
00075 char *tid_name[] = {
00076 "NULL",
00077 "BYTE",
00078 "SBYTE",
00079 "CHAR",
00080 "WORD",
00081 "SHORT",
00082 "DWORD",
00083 "INT",
00084 "BOOL",
00085 "FLOAT",
00086 "DOUBLE",
00087 "BITFIELD",
00088 "STRING",
00089 "ARRAY",
00090 "STRUCT",
00091 "KEY",
00092 "LINK"
00093 };
00094
00095 struct {
00096 int transition;
00097 char name[32];
00098 } trans_name[] = {
00099 {
00100 TR_START, "START",}, {
00101 TR_STOP, "STOP",}, {
00102 TR_PAUSE, "PAUSE",}, {
00103 TR_RESUME, "RESUME",}, {
00104 TR_STARTABORT, "STARTABORT",}, {
00105 TR_DEFERRED, "DEFERRED",}, {
00106 0, "",},};
00107
00108
00109 #ifdef OS_MSDOS
00110 extern unsigned _stklen = 60000U;
00111 #endif
00112
00113 extern DATABASE *_database;
00114 extern INT _database_entries;
00115
00116 static BUFFER *_buffer;
00117 static INT _buffer_entries = 0;
00118
00119 static INT _msg_buffer = 0;
00120 static void (*_msg_dispatch) (HNDLE, HNDLE, EVENT_HEADER *, void *);
00121
00122 static REQUEST_LIST *_request_list;
00123 static INT _request_list_entries = 0;
00124
00125 static EVENT_HEADER *_event_buffer;
00126 static INT _event_buffer_size = 0;
00127
00128 static char *_net_recv_buffer;
00129 static INT _net_recv_buffer_size = 0;
00130 static INT _net_recv_buffer_size_odb = 0;
00131
00132 static char *_net_send_buffer;
00133 static INT _net_send_buffer_size = 0;
00134
00135 static char *_tcp_buffer = NULL;
00136 static INT _tcp_wp = 0;
00137 static INT _tcp_rp = 0;
00138 static INT _rpc_sock = 0;
00139 static MUTEX_T *_mutex_rpc = NULL;
00140
00141 static void (*_debug_print) (char *) = NULL;
00142 static INT _debug_mode = 0;
00143
00144 static INT _watchdog_last_called = 0;
00145
00146 int _rpc_connect_timeout = 10000;
00147
00148
00149
00150 typedef struct {
00151 INT transition;
00152 INT sequence_number;
00153 INT(*func) (INT, char *);
00154 } TRANS_TABLE;
00155
00156 #define MAX_TRANSITIONS 20
00157
00158 TRANS_TABLE _trans_table[MAX_TRANSITIONS];
00159
00160 TRANS_TABLE _deferred_trans_table[] = {
00161 {TR_START, 0, NULL},
00162 {TR_STOP, 0, NULL},
00163 {TR_PAUSE, 0, NULL},
00164 {TR_RESUME, 0, NULL},
00165 {0, 0, NULL}
00166 };
00167
00168 static BOOL _server_registered = FALSE;
00169
00170 static INT rpc_transition_dispatch(INT idx, void *prpc_param[]);
00171
00172 void cm_ctrlc_handler(int sig);
00173
00174 typedef struct {
00175 INT code;
00176 char *string;
00177 } ERROR_TABLE;
00178
00179 ERROR_TABLE _error_table[] = {
00180 {CM_WRONG_PASSWORD, "Wrong password"},
00181 {CM_UNDEF_EXP, "Experiment not defined"},
00182 {CM_UNDEF_ENVIRON,
00183 "\"exptab\" file not found and MIDAS_DIR environment variable not defined"},
00184 {RPC_NET_ERROR, "Cannot connect to remote host"},
00185 {0, NULL}
00186 };
00187
00188
00189 typedef struct {
00190 void *adr;
00191 int size;
00192 char file[80];
00193 int line;
00194 } DBG_MEM_LOC;
00195
00196 DBG_MEM_LOC *_mem_loc = NULL;
00197 INT _n_mem = 0;
00198
00199 void *dbg_malloc(unsigned int size, char *file, int line)
00200 {
00201 FILE *f;
00202 void *adr;
00203 int i;
00204
00205 adr = malloc(size);
00206
00207
00208 for (i = 0; i < _n_mem; i++)
00209 if (_mem_loc[i].adr == NULL)
00210 break;
00211
00212 if (i == _n_mem) {
00213 _n_mem++;
00214 if (!_mem_loc)
00215 _mem_loc = (DBG_MEM_LOC *) malloc(sizeof(DBG_MEM_LOC));
00216 else
00217 _mem_loc = (DBG_MEM_LOC *) realloc(_mem_loc, sizeof(DBG_MEM_LOC) * _n_mem);
00218 }
00219
00220 _mem_loc[i].adr = adr;
00221 _mem_loc[i].size = size;
00222 strcpy(_mem_loc[i].file, file);
00223 _mem_loc[i].line = line;
00224
00225 f = fopen("mem.txt", "w");
00226 for (i = 0; i < _n_mem; i++)
00227 if (_mem_loc[i].adr)
00228 fprintf(f, "%s:%d size=%d adr=%p\n", _mem_loc[i].file, _mem_loc[i].line, _mem_loc[i].size,
00229 _mem_loc[i].adr);
00230 fclose(f);
00231
00232 return adr;
00233 }
00234
00235 void *dbg_calloc(unsigned int size, unsigned int count, char *file, int line)
00236 {
00237 void *adr;
00238
00239 adr = dbg_malloc(size * count, file, line);
00240 if (adr)
00241 memset(adr, 0, size * count);
00242
00243 return adr;
00244 }
00245
00246 void dbg_free(void *adr, char *file, int line)
00247 {
00248 FILE *f;
00249 int i;
00250
00251 free(adr);
00252
00253 for (i = 0; i < _n_mem; i++)
00254 if (_mem_loc[i].adr == adr)
00255 break;
00256
00257 if (i < _n_mem)
00258 _mem_loc[i].adr = NULL;
00259
00260 f = fopen("mem.txt", "w");
00261 for (i = 0; i < _n_mem; i++)
00262 if (_mem_loc[i].adr)
00263 fprintf(f, "%s:%d %s:%d size=%d adr=%p\n", _mem_loc[i].file, _mem_loc[i].line,
00264 file, line, _mem_loc[i].size, _mem_loc[i].adr);
00265 fclose(f);
00266 }
00267
00268
00269 static int resize_net_send_buffer(const char* from, int new_size)
00270
00271 {
00272 if (new_size <= _net_send_buffer_size)
00273 return SUCCESS;
00274
00275 _net_send_buffer = (char *) realloc(_net_send_buffer, new_size);
00276 if (_net_send_buffer == NULL) {
00277 cm_msg(MERROR, from, "Cannot allocate %d bytes for network buffer", new_size);
00278 return RPC_EXCEED_BUFFER;
00279 }
00280
00281
00282 _net_send_buffer_size = new_size;
00283 return SUCCESS;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 static int (*_message_print) (const char *) = puts;
00293 static INT _message_mask_system = MT_ALL;
00294 static INT _message_mask_user = MT_ALL;
00295
00296
00297
00298 #endif
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 INT cm_get_error(INT code, char *string)
00314 {
00315 INT i;
00316
00317 for (i = 0; _error_table[i].code; i++)
00318 if (_error_table[i].code == code) {
00319 strcpy(string, _error_table[i].string);
00320 return CM_SUCCESS;
00321 }
00322
00323 sprintf(string, "Unexpected error #%d", code);
00324 return CM_SUCCESS;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 INT cm_set_msg_print(INT system_mask, INT user_mask, int (*func) (const char *))
00359 {
00360 _message_mask_system = system_mask;
00361 _message_mask_user = user_mask;
00362 _message_print = func;
00363
00364 return BM_SUCCESS;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 INT cm_msg_log(INT message_type, const char *message)
00376 {
00377 char dir[256];
00378 char filename[256];
00379 char path[256];
00380 char str[256];
00381 INT status, size, fh, semaphore;
00382 HNDLE hDB, hKey;
00383
00384 if (rpc_is_remote())
00385 return rpc_call(RPC_CM_MSG_LOG, message_type, message);
00386
00387 if (message_type != MT_DEBUG) {
00388 cm_get_experiment_database(&hDB, NULL);
00389
00390 if (hDB) {
00391
00392 strcpy(filename, "midas.log");
00393 size = sizeof(filename);
00394 db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
00395
00396 if (strchr(filename, '%')) {
00397
00398 time_t now;
00399 struct tm *tms;
00400
00401 tzset();
00402 time(&now);
00403 tms = localtime(&now);
00404
00405 strftime(str, sizeof(str), filename, tms);
00406 strlcpy(filename, str, sizeof(filename));
00407 }
00408
00409 if (strchr(filename, DIR_SEPARATOR) == NULL) {
00410 status = db_find_key(hDB, 0, "/Logger/Data dir", &hKey);
00411 if (status == DB_SUCCESS) {
00412 size = sizeof(dir);
00413 memset(dir, 0, size);
00414 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
00415 if (dir[0] != 0)
00416 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00417 strcat(dir, DIR_SEPARATOR_STR);
00418
00419 strcpy(path, dir);
00420 strcat(path, filename);
00421 } else {
00422 cm_get_path(dir);
00423 if (dir[0] != 0)
00424 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00425 strcat(dir, DIR_SEPARATOR_STR);
00426
00427 strcpy(path, dir);
00428 strcat(path, "midas.log");
00429 }
00430 } else {
00431 strcpy(path, filename);
00432 }
00433 } else
00434 strcpy(path, "midas.log");
00435
00436 fh = open(path, O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE, 0644);
00437 if (fh < 0) {
00438 printf("Cannot open message log file %s\n", path);
00439 } else {
00440
00441 cm_get_experiment_semaphore(NULL, NULL, NULL, &semaphore);
00442 status = ss_semaphore_wait_for(semaphore, 5 * 1000);
00443
00444 strcpy(str, ss_asctime());
00445 write(fh, str, strlen(str));
00446 write(fh, " ", 1);
00447 write(fh, message, strlen(message));
00448 write(fh, "\n", 1);
00449 close(fh);
00450
00451 ss_semaphore_release(semaphore);
00452 }
00453 }
00454
00455 return CM_SUCCESS;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 INT cm_msg_log1(INT message_type, const char *message, const char *facility)
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 {
00488 char dir[256];
00489 char filename[256];
00490 char path[256];
00491 char str[256];
00492 FILE *f;
00493 INT status, size;
00494 HNDLE hDB, hKey;
00495
00496
00497 if (rpc_is_remote())
00498 return rpc_call(RPC_CM_MSG_LOG1, message_type, message, facility);
00499
00500 if (message_type != MT_DEBUG) {
00501 cm_get_experiment_database(&hDB, NULL);
00502
00503 if (hDB) {
00504 strcpy(filename, "midas.log");
00505 size = sizeof(filename);
00506 db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
00507
00508 if (strchr(filename, '%')) {
00509
00510 time_t now;
00511 struct tm *tms;
00512
00513 tzset();
00514 time(&now);
00515 tms = localtime(&now);
00516
00517 strftime(str, sizeof(str), filename, tms);
00518 strlcpy(filename, str, sizeof(filename));
00519 }
00520
00521 if (strchr(filename, DIR_SEPARATOR) == NULL) {
00522
00523 status = db_find_key(hDB, 0, "/Logger/Data dir", &hKey);
00524 if (status == DB_SUCCESS) {
00525 size = sizeof(dir);
00526 memset(dir, 0, size);
00527 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
00528 if (dir[0] != 0)
00529 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00530 strcat(dir, DIR_SEPARATOR_STR);
00531
00532 if (facility[0]) {
00533 strcpy(filename, facility);
00534 strcat(filename, ".log");
00535 } else {
00536 strcpy(filename, "midas.log");
00537 size = sizeof(filename);
00538 db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
00539
00540 if (strchr(filename, '%')) {
00541
00542 time_t now;
00543 struct tm *tms;
00544
00545 tzset();
00546 time(&now);
00547 tms = localtime(&now);
00548
00549 strftime(str, sizeof(str), filename, tms);
00550 strlcpy(filename, str, sizeof(filename));
00551 }
00552 }
00553
00554 strcpy(path, dir);
00555 strcat(path, filename);
00556 } else {
00557 cm_get_path(dir);
00558 if (dir[0] != 0)
00559 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00560 strcat(dir, DIR_SEPARATOR_STR);
00561
00562 strcpy(path, dir);
00563 if (facility[0]) {
00564 strcat(path, facility);
00565 strcat(path, ".log");
00566 } else
00567 strcat(path, "midas.log");
00568 }
00569 } else {
00570 strcpy(path, filename);
00571 *(strrchr(path, DIR_SEPARATOR) + 1) = 0;
00572 if (facility[0]) {
00573 strcat(path, facility);
00574 strcat(path, ".log");
00575 } else
00576 strcat(path, "midas.log");
00577 }
00578 } else {
00579 if (facility[0]) {
00580 strcpy(path, facility);
00581 strcat(path, ".log");
00582 } else
00583 strcpy(path, "midas.log");
00584 }
00585
00586 f = fopen(path, "a");
00587 if (f == NULL) {
00588 printf("Cannot open message log file %s\n", path);
00589 } else {
00590 strcpy(str, ss_asctime());
00591 fprintf(f, "%s", str);
00592 fprintf(f, " %s\n", message);
00593 fclose(f);
00594 }
00595 }
00596
00597 return CM_SUCCESS;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format, ...)
00623 {
00624 va_list argptr;
00625 char event[1000], type_str[256], str[1000], format_cpy[900], local_message[1000], send_message[1000];
00626 const char *pc;
00627 EVENT_HEADER *pevent;
00628 INT status;
00629 static BOOL in_routine = FALSE;
00630
00631
00632 if (in_routine)
00633 return 0;
00634
00635 in_routine = TRUE;
00636
00637
00638 pc = filename + strlen(filename);
00639 while (*pc != '\\' && *pc != '/' && pc != filename)
00640 pc--;
00641 if (pc != filename)
00642 pc++;
00643
00644
00645 type_str[0] = 0;
00646 if (message_type & MT_ERROR)
00647 strlcat(type_str, MT_ERROR_STR, sizeof(type_str));
00648 if (message_type & MT_INFO)
00649 strlcat(type_str, MT_INFO_STR, sizeof(type_str));
00650 if (message_type & MT_DEBUG)
00651 strlcat(type_str, MT_DEBUG_STR, sizeof(type_str));
00652 if (message_type & MT_USER)
00653 strlcat(type_str, MT_USER_STR, sizeof(type_str));
00654 if (message_type & MT_LOG)
00655 strlcat(type_str, MT_LOG_STR, sizeof(type_str));
00656 if (message_type & MT_TALK)
00657 strlcat(type_str, MT_TALK_STR, sizeof(type_str));
00658
00659
00660 if (message_type == MT_USER)
00661 sprintf(send_message, "[%s] ", routine);
00662 else {
00663 rpc_get_name(str);
00664 if (str[0])
00665 sprintf(send_message, "[%s,%s] ", str, type_str);
00666 else
00667 send_message[0] = 0;
00668 }
00669
00670 local_message[0] = 0;
00671
00672
00673 if (message_type == MT_ERROR) {
00674 sprintf(str, "[%s:%d:%s,%s] ", pc, line, routine, type_str);
00675 strlcat(send_message, str, sizeof(send_message));
00676 strlcat(local_message, str, sizeof(send_message));
00677 } else if (message_type == MT_USER)
00678 sprintf(local_message, "[%s,%s] ", routine, type_str);
00679
00680
00681 strlcpy(format_cpy, format, sizeof(format_cpy));
00682
00683
00684 va_start(argptr, format);
00685 vsprintf(str, (char *) format, argptr);
00686 va_end(argptr);
00687 strcat(send_message, str);
00688 strcat(local_message, str);
00689
00690
00691 if (_message_print != NULL && (message_type & _message_mask_user) != 0)
00692 _message_print(local_message);
00693
00694
00695 if ((message_type & _message_mask_system) == 0) {
00696 in_routine = FALSE;
00697 return CM_SUCCESS;
00698 }
00699
00700
00701 pevent = (EVENT_HEADER *) event;
00702 strlcpy(event + sizeof(EVENT_HEADER), send_message, sizeof(event) - sizeof(EVENT_HEADER));
00703
00704
00705 if (message_type != MT_LOG) {
00706
00707 if (_msg_buffer == 0) {
00708 status = bm_open_buffer(MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE, &_msg_buffer);
00709 if (status != BM_SUCCESS && status != BM_CREATED) {
00710 in_routine = FALSE;
00711 return status;
00712 }
00713 }
00714
00715
00716 bm_compose_event(pevent, EVENTID_MESSAGE, (WORD) message_type, strlen(event + sizeof(EVENT_HEADER)) + 1,
00717 0);
00718 bm_send_event(_msg_buffer, event, pevent->data_size + sizeof(EVENT_HEADER), SYNC);
00719 }
00720
00721
00722 cm_msg_log(message_type, send_message);
00723
00724 in_routine = FALSE;
00725
00726 return CM_SUCCESS;
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 INT cm_msg1(INT message_type, const char *filename, INT line,
00755 const char *facility, const char *routine, const char *format, ...)
00756 {
00757 va_list argptr;
00758 char event[1000], str[256], local_message[256], send_message[256];
00759 const char *pc;
00760 EVENT_HEADER *pevent;
00761 INT status;
00762 static BOOL in_routine = FALSE;
00763
00764
00765 if (in_routine)
00766 return 0;
00767
00768 in_routine = TRUE;
00769
00770
00771 pc = filename + strlen(filename);
00772 while (*pc != '\\' && *pc != '/' && pc != filename)
00773 pc--;
00774 if (pc != filename)
00775 pc++;
00776
00777
00778 if (message_type == MT_USER)
00779 sprintf(send_message, "[%s] ", routine);
00780 else {
00781 rpc_get_name(str);
00782 if (str[0])
00783 sprintf(send_message, "[%s] ", str);
00784 else
00785 send_message[0] = 0;
00786 }
00787
00788 local_message[0] = 0;
00789
00790
00791 if (message_type == MT_ERROR) {
00792 sprintf(str, "[%s:%d:%s] ", pc, line, routine);
00793 strcat(send_message, str);
00794 strcat(local_message, str);
00795 }
00796
00797
00798 va_start(argptr, format);
00799 vsprintf(str, (char *) format, argptr);
00800 va_end(argptr);
00801
00802 if (facility)
00803 sprintf(local_message + strlen(local_message), "{%s} ", facility);
00804
00805 strcat(send_message, str);
00806 strcat(local_message, str);
00807
00808
00809 if (_message_print != NULL && (message_type & _message_mask_user) != 0)
00810 _message_print(local_message);
00811
00812
00813 if ((message_type & _message_mask_system) == 0) {
00814 in_routine = FALSE;
00815 return CM_SUCCESS;
00816 }
00817
00818
00819 pevent = (EVENT_HEADER *) event;
00820 strcpy(event + sizeof(EVENT_HEADER), send_message);
00821
00822
00823 if (message_type != MT_LOG) {
00824
00825 if (_msg_buffer == 0) {
00826 status = bm_open_buffer(MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE, &_msg_buffer);
00827 if (status != BM_SUCCESS && status != BM_CREATED) {
00828 in_routine = FALSE;
00829 return status;
00830 }
00831 }
00832
00833
00834 bm_compose_event(pevent, EVENTID_MESSAGE, (WORD) message_type, strlen(event + sizeof(EVENT_HEADER)) + 1,
00835 0);
00836 bm_send_event(_msg_buffer, event, pevent->data_size + sizeof(EVENT_HEADER), SYNC);
00837 }
00838
00839
00840 cm_msg_log1(message_type, send_message, facility);
00841
00842 in_routine = FALSE;
00843
00844 return CM_SUCCESS;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 INT cm_msg_register(void (*func) (HNDLE, HNDLE, EVENT_HEADER *, void *))
00887 {
00888 INT status, id;
00889
00890
00891 if (_msg_buffer == 0) {
00892 status = bm_open_buffer(MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE, &_msg_buffer);
00893 if (status != BM_SUCCESS && status != BM_CREATED)
00894 return status;
00895 }
00896
00897 _msg_dispatch = func;
00898
00899 status = bm_request_event(_msg_buffer, EVENTID_ALL, TRIGGER_ALL, GET_NONBLOCKING, &id, func);
00900
00901 return status;
00902 }
00903
00904
00905 INT cm_msg_retrieve1(char *filename, INT n_message, char *message, INT buf_size)
00906 {
00907 FILE *f;
00908 INT offset, i, j;
00909 char *p;
00910
00911 f = fopen(filename, "rb");
00912 if (f == NULL) {
00913 sprintf(message, "Cannot open message log file %s\n", filename);
00914 return -1;
00915 }
00916
00917
00918 fseek(f, -(buf_size - 1), SEEK_END);
00919 offset = ftell(f);
00920 if (offset != 0) {
00921
00922 fgets(message, buf_size - 1, f);
00923 offset = ftell(f) - offset;
00924 buf_size -= offset;
00925 }
00926
00927 memset(message, 0, buf_size);
00928 fread(message, 1, buf_size - 1, f);
00929 message[buf_size - 1] = 0;
00930 fclose(f);
00931
00932 p = message + (buf_size - 2);
00933
00934
00935 while (p != message && *p == 0)
00936 p--;
00937
00938
00939 j = 0;
00940 while (p != message && (*p == '\n' || *p == '\r')) {
00941 *(p--) = 0;
00942 j = 1;
00943 }
00944
00945
00946
00947 for (i = 0; i < n_message; i++) {
00948 while (p != message && *p != '\n')
00949 p--;
00950
00951 while (p != message && (*p == '\n' || *p == '\r'))
00952 p--;
00953
00954 if (p == message)
00955 break;
00956
00957 j++;
00958 }
00959 if (p != message) {
00960 p++;
00961 while (*p == '\n' || *p == '\r')
00962 p++;
00963 }
00964
00965 buf_size = (buf_size - 1) - (p - message);
00966
00967 memmove(message, p, buf_size);
00968 message[buf_size] = 0;
00969
00970 return j;
00971 }
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 INT cm_msg_retrieve(INT n_message, char *message, INT buf_size)
00986 {
00987 char dir[256], str[256];
00988 char filename[256], filename2[256];
00989 char path[256], *message2;
00990 INT status, size, n, i;
00991 HNDLE hDB, hKey;
00992 time_t now;
00993 struct tm *tms;
00994
00995 if (rpc_is_remote())
00996 return rpc_call(RPC_CM_MSG_RETRIEVE, n_message, message, buf_size);
00997
00998 cm_get_experiment_database(&hDB, NULL);
00999 status = 0;
01000
01001 if (hDB) {
01002 strcpy(filename, "midas.log");
01003 size = sizeof(filename);
01004 db_get_value(hDB, 0, "/Logger/Message file", filename, &size, TID_STRING, TRUE);
01005
01006 strlcpy(filename2, filename, sizeof(filename2));
01007
01008 if (strchr(filename, '%')) {
01009
01010 tzset();
01011 time(&now);
01012 tms = localtime(&now);
01013
01014 strftime(filename2, sizeof(str), filename, tms);
01015 }
01016
01017 if (strchr(filename2, DIR_SEPARATOR) == NULL) {
01018 status = db_find_key(hDB, 0, "/Logger/Data dir", &hKey);
01019 if (status == DB_SUCCESS) {
01020 size = sizeof(dir);
01021 memset(dir, 0, size);
01022 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
01023 if (dir[0] != 0)
01024 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
01025 strcat(dir, DIR_SEPARATOR_STR);
01026
01027 strcpy(path, dir);
01028 strcat(path, filename2);
01029 } else {
01030 cm_get_path(dir);
01031 if (dir[0] != 0)
01032 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
01033 strcat(dir, DIR_SEPARATOR_STR);
01034
01035 strcpy(path, dir);
01036 strcat(path, filename2);
01037 }
01038 } else {
01039 strcpy(path, filename2);
01040 }
01041 } else
01042 strcpy(path, "midas.log");
01043
01044 n = cm_msg_retrieve1(path, n_message, message, buf_size);
01045
01046 while (n < n_message && strchr(filename, '%')) {
01047 now -= 3600 * 24;
01048 tms = localtime(&now);
01049
01050 strftime(filename2, sizeof(str), filename, tms);
01051
01052 if (strchr(filename2, DIR_SEPARATOR) == NULL) {
01053 status = db_find_key(hDB, 0, "/Logger/Data dir", &hKey);
01054 if (status == DB_SUCCESS) {
01055 size = sizeof(dir);
01056 memset(dir, 0, size);
01057 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
01058 if (dir[0] != 0)
01059 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
01060 strcat(dir, DIR_SEPARATOR_STR);
01061
01062 strcpy(path, dir);
01063 strcat(path, filename2);
01064 } else {
01065 cm_get_path(dir);
01066 if (dir[0] != 0)
01067 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
01068 strcat(dir, DIR_SEPARATOR_STR);
01069
01070 strcpy(path, dir);
01071 strcat(path, filename2);
01072 }
01073 } else {
01074 strcpy(path, filename2);
01075 }
01076
01077 message2 = (char *) malloc(buf_size);
01078
01079 i = cm_msg_retrieve1(path, n_message - n, message2, buf_size - strlen(message) - 1);
01080 if (i < 0)
01081 break;
01082 strlcat(message2, "\r\n", buf_size);
01083
01084 memmove(message + strlen(message2), message, strlen(message) + 1);
01085 memcpy(message, message2, strlen(message2));
01086 free(message2);
01087 n += i;
01088 }
01089
01090 return status;
01091 }
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 INT cm_synchronize(DWORD * seconds)
01108 {
01109 INT sec, status;
01110
01111
01112 if (rpc_is_remote()) {
01113 status = rpc_call(RPC_CM_SYNCHRONIZE, &sec);
01114
01115
01116 if (status == CM_SUCCESS)
01117 ss_settime(sec);
01118 }
01119
01120
01121 if (seconds != NULL) {
01122 *seconds = ss_time();
01123 }
01124
01125 return CM_SUCCESS;
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135 INT cm_asctime(char *str, INT buf_size)
01136 {
01137
01138 if (rpc_is_remote())
01139 return rpc_call(RPC_CM_ASCTIME, str, buf_size);
01140
01141
01142 strcpy(str, ss_asctime());
01143
01144 return CM_SUCCESS;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153 INT cm_time(DWORD * t)
01154 {
01155
01156 if (rpc_is_remote())
01157 return rpc_call(RPC_CM_TIME, t);
01158
01159
01160 *t = ss_time();
01161
01162 return CM_SUCCESS;
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 static HNDLE _hKeyClient = 0;
01177 static HNDLE _hDB = 0;
01178 static char _client_name[NAME_LENGTH];
01179 static char _path_name[MAX_STRING_LENGTH];
01180 static INT _call_watchdog = TRUE;
01181 static INT _watchdog_timeout = DEFAULT_WATCHDOG_TIMEOUT;
01182 INT _semaphore_alarm, _semaphore_elog, _semaphore_history, _semaphore_msg;
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 char *cm_get_version()
01194 {
01195 return MIDAS_VERSION;
01196 }
01197
01198
01199
01200
01201
01202 int cm_get_revision()
01203 {
01204 return atoi(svn_revision + 6);
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 INT cm_set_path(char *path)
01217 {
01218 strcpy(_path_name, path);
01219
01220
01221 if (strlen(_path_name) > 0 && _path_name[strlen(_path_name) - 1] != DIR_SEPARATOR)
01222 strcat(_path_name, DIR_SEPARATOR_STR);
01223
01224 return CM_SUCCESS;
01225 }
01226
01227
01228
01229
01230
01231
01232
01233 INT cm_get_path(char *path)
01234 {
01235 strcpy(path, _path_name);
01236
01237 return CM_SUCCESS;
01238 }
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01250
01251 typedef struct {
01252 char name[NAME_LENGTH];
01253 char directory[MAX_STRING_LENGTH];
01254 char user[NAME_LENGTH];
01255 } experiment_table;
01256
01257 static experiment_table exptab[MAX_EXPERIMENT];
01258
01259
01260 #endif
01261
01262
01263
01264
01265
01266
01267
01268
01269 INT cm_scan_experiments(void)
01270 {
01271 INT i;
01272 FILE *f;
01273 char str[MAX_STRING_LENGTH], alt_str[MAX_STRING_LENGTH], *pdir;
01274
01275 for (i = 0; i < MAX_EXPERIMENT; i++)
01276 exptab[i].name[0] = 0;
01277
01278
01279 if (getenv("MIDAS_DIR")) {
01280 strlcpy(str, getenv("MIDAS_DIR"), sizeof(str));
01281
01282 strcpy(exptab[0].name, "Default");
01283 strlcpy(exptab[0].directory, getenv("MIDAS_DIR"), sizeof(exptab[0].directory));
01284 exptab[0].user[0] = 0;
01285
01286 return CM_SUCCESS;
01287 }
01288
01289
01290 #if defined (OS_WINNT)
01291 if (getenv("SystemRoot"))
01292 strlcpy(str, getenv("SystemRoot"), sizeof(str));
01293 else if (getenv("windir"))
01294 strlcpy(str, getenv("windir"), sizeof(str));
01295 else
01296 strcpy(str, "");
01297
01298 strcpy(alt_str, str);
01299 strcat(str, "\\system32\\exptab");
01300 strcat(alt_str, "\\system\\exptab");
01301 #elif defined (OS_UNIX)
01302 strcpy(str, "/etc/exptab");
01303 strcpy(alt_str, "/exptab");
01304 #else
01305 strcpy(str, "exptab");
01306 strcpy(alt_str, "exptab");
01307 #endif
01308
01309
01310 if (getenv("MIDAS_EXPTAB")) {
01311 strlcpy(str, getenv("MIDAS_EXPTAB"), sizeof(str));
01312 strlcpy(alt_str, getenv("MIDAS_EXPTAB"), sizeof(alt_str));
01313 }
01314
01315
01316 f = fopen(str, "r");
01317 if (f == NULL) {
01318 f = fopen(alt_str, "r");
01319 if (f == NULL)
01320 return CM_UNDEF_ENVIRON;
01321 }
01322
01323 i = 0;
01324 if (f != NULL) {
01325 do {
01326 str[0] = 0;
01327 if (fgets(str, 100, f) == NULL)
01328 break;
01329 if (str[0] && str[0] != '#' && str[0] != ' ' && str[0] != '\t'
01330 && (strchr(str, ' ') || strchr(str, '\t'))) {
01331 sscanf(str, "%s %s %s", exptab[i].name, exptab[i].directory, exptab[i].user);
01332
01333
01334 pdir = exptab[i].directory;
01335 if (pdir[strlen(pdir) - 1] != DIR_SEPARATOR)
01336 strcat(pdir, DIR_SEPARATOR_STR);
01337
01338 i++;
01339 }
01340 } while (!feof(f));
01341 fclose(f);
01342 }
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 return CM_SUCCESS;
01353 }
01354
01355
01356
01357
01358
01359
01360
01361
01362 INT cm_delete_client_info(HNDLE hDB, INT pid)
01363 {
01364 #ifdef LOCAL_ROUTINES
01365
01366
01367 if (!rpc_is_remote()) {
01368 INT status;
01369 HNDLE hKey;
01370 char str[256];
01371
01372 if (!pid)
01373 pid = ss_getpid();
01374
01375
01376 if (_database_entries == 0)
01377 return CM_SUCCESS;
01378
01379
01380 db_lock_database(hDB);
01381
01382 sprintf(str, "System/Clients/%0d", pid);
01383 status = db_find_key1(hDB, 0, str, &hKey);
01384 if (status != DB_SUCCESS) {
01385 db_unlock_database(hDB);
01386 return status;
01387 }
01388
01389
01390 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE | MODE_DELETE, 2);
01391 db_delete_key1(hDB, hKey, 1, TRUE);
01392
01393 db_unlock_database(hDB);
01394
01395
01396 status = 0;
01397 db_set_value(hDB, 0, "/System/Client Notify", &status, sizeof(status), 1, TID_INT);
01398 }
01399 #endif
01400
01401 return CM_SUCCESS;
01402 }
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 INT cm_check_client(HNDLE hDB, HNDLE hKeyClient)
01414 {
01415 if (rpc_is_remote())
01416 return rpc_call(RPC_CM_CHECK_CLIENT, hDB, hKeyClient);
01417
01418 #ifdef LOCAL_ROUTINES
01419 {
01420 KEY key;
01421 DATABASE_HEADER *pheader;
01422 DATABASE_CLIENT *pclient;
01423 INT i, client_pid, status, dead = 0, found = 0;
01424 char name[NAME_LENGTH];
01425
01426 db_get_key(hDB, hKeyClient, &key);
01427 client_pid = atoi(key.name);
01428
01429 i = sizeof(name);
01430 db_get_value(hDB, hKeyClient, "Name", name, &i, TID_STRING, TRUE);
01431
01432 db_lock_database(hDB);
01433 if (_database[hDB - 1].attached) {
01434 pheader = _database[hDB - 1].database_header;
01435 pclient = pheader->client;
01436
01437
01438 for (i = 0; i < pheader->max_client_index; i++, pclient++)
01439 if (pclient->pid == client_pid) {
01440 found = 1;
01441 break;
01442 }
01443 #ifdef OS_UNIX
01444 #ifdef ESRCH
01445 if (found) {
01446
01447 errno = 0;
01448 kill(client_pid, 0);
01449 if (errno == ESRCH) {
01450 cm_msg(MERROR, "cm_check_client",
01451 "Removing client \'%s\', pid %d, index %d because this pid no longer exists",
01452 pclient->name, client_pid, i);
01453 dead = 1;
01454 }
01455 }
01456 #endif
01457 #endif
01458
01459 if (!found || dead) {
01460
01461 db_unlock_database(hDB);
01462
01463 status = cm_delete_client_info(hDB, client_pid);
01464 if (status != CM_SUCCESS)
01465 cm_msg(MERROR, "cm_check_client",
01466 "Cannot delete client info for client \'%s\', pid %d, status %d", name, client_pid,
01467 status);
01468 else
01469 cm_msg(MINFO, "cm_check_client",
01470 "Deleted entry \'/System/Clients/%d\' for client \'%s\'", client_pid, name);
01471
01472 return CM_NO_CLIENT;
01473 }
01474 }
01475
01476 db_unlock_database(hDB);
01477 }
01478 #endif
01479
01480 return CM_SUCCESS;
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 INT cm_set_client_info(HNDLE hDB, HNDLE * hKeyClient, char *host_name,
01498 char *client_name, INT hw_type, char *password, DWORD watchdog_timeout)
01499 {
01500 if (rpc_is_remote())
01501 return rpc_call(RPC_CM_SET_CLIENT_INFO, hDB, hKeyClient,
01502 host_name, client_name, hw_type, password, watchdog_timeout);
01503
01504 #ifdef LOCAL_ROUTINES
01505 {
01506 INT status, pid, data, i, idx, size;
01507 HNDLE hKey, hSubkey;
01508 char str[256], name[NAME_LENGTH], orig_name[NAME_LENGTH], pwd[NAME_LENGTH];
01509 BOOL call_watchdog, allow;
01510 PROGRAM_INFO_STR(program_info_str);
01511
01512
01513 status = db_find_key(hDB, 0, "/Experiment/Security/Password", &hKey);
01514 if (hKey) {
01515
01516 size = sizeof(pwd);
01517 db_get_data(hDB, hKey, pwd, &size, TID_STRING);
01518
01519
01520 allow = FALSE;
01521 db_find_key(hDB, 0, "/Experiment/Security/Allowed hosts", &hKey);
01522 if (hKey && db_find_key(hDB, hKey, host_name, &hKey) == DB_SUCCESS)
01523 allow = TRUE;
01524
01525
01526 db_find_key(hDB, 0, "/Experiment/Security/Allowed programs", &hKey);
01527 if (hKey && db_find_key(hDB, hKey, client_name, &hKey) == DB_SUCCESS)
01528 allow = TRUE;
01529
01530
01531 if (!allow && strcmp(password, pwd) != 0) {
01532 if (password[0])
01533 cm_msg(MINFO, "cm_set_client_info", "Wrong password for host %s", host_name);
01534 db_close_all_databases();
01535 bm_close_all_buffers();
01536 _msg_buffer = 0;
01537 return CM_WRONG_PASSWORD;
01538 }
01539 }
01540
01541
01542 db_lock_database(hDB);
01543
01544
01545 pid = ss_getpid();
01546
01547 sprintf(str, "System/Clients/%0d", pid);
01548 status = db_find_key(hDB, 0, str, &hKey);
01549 if (status == DB_SUCCESS) {
01550 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE | MODE_DELETE, TRUE);
01551 db_delete_key(hDB, hKey, TRUE);
01552 }
01553
01554 if (strlen(client_name) >= NAME_LENGTH)
01555 client_name[NAME_LENGTH] = 0;
01556
01557 strcpy(name, client_name);
01558 strcpy(orig_name, client_name);
01559
01560
01561 status = db_find_key(hDB, 0, "System/Clients", &hKey);
01562
01563 for (idx = 1; status != DB_NO_MORE_SUBKEYS; idx++) {
01564 for (i = 0;; i++) {
01565 status = db_enum_key(hDB, hKey, i, &hSubkey);
01566 if (status == DB_NO_MORE_SUBKEYS)
01567 break;
01568
01569 if (status == DB_SUCCESS) {
01570 size = sizeof(str);
01571 status = db_get_value(hDB, hSubkey, "Name", str, &size, TID_STRING, TRUE);
01572 }
01573
01574
01575 if (cm_check_client(hDB, hSubkey) == CM_NO_CLIENT)
01576 continue;
01577
01578 if (equal_ustring(str, name)) {
01579 sprintf(name, "%s%d", client_name, idx);
01580 break;
01581 }
01582 }
01583 }
01584
01585
01586 sprintf(str, "System/Clients/%0d/Name", pid);
01587 status = db_set_value(hDB, 0, str, name, NAME_LENGTH, 1, TID_STRING);
01588 if (status != DB_SUCCESS) {
01589 db_unlock_database(hDB);
01590 cm_msg(MERROR, "cm_set_client_info", "cannot set client name");
01591 return status;
01592 }
01593
01594
01595 strcpy(client_name, name);
01596 db_set_client_name(hDB, client_name);
01597
01598
01599 rpc_set_name(client_name);
01600
01601
01602 sprintf(str, "System/Clients/%0d", pid);
01603 db_find_key(hDB, 0, str, &hKey);
01604
01605
01606 status = db_set_value(hDB, hKey, "Host", host_name, HOST_NAME_LENGTH, 1, TID_STRING);
01607 if (status != DB_SUCCESS) {
01608 db_unlock_database(hDB);
01609 return status;
01610 }
01611
01612
01613 status = db_set_value(hDB, hKey, "Hardware type", &hw_type, sizeof(hw_type), 1, TID_INT);
01614 if (status != DB_SUCCESS) {
01615 db_unlock_database(hDB);
01616 return status;
01617 }
01618
01619
01620 data = 0;
01621 status = db_set_value(hDB, hKey, "Server Port", &data, sizeof(INT), 1, TID_INT);
01622 if (status != DB_SUCCESS) {
01623 db_unlock_database(hDB);
01624 return status;
01625 }
01626
01627
01628 db_set_mode(hDB, hKey, MODE_READ, TRUE);
01629
01630
01631 size = sizeof(watchdog_timeout);
01632 sprintf(str, "/Programs/%s/Watchdog Timeout", orig_name);
01633 db_get_value(hDB, 0, str, &watchdog_timeout, &size, TID_INT, TRUE);
01634
01635
01636 sprintf(str, "/Programs/%s", orig_name);
01637 db_create_record(hDB, 0, str, strcomb(program_info_str));
01638
01639
01640 rpc_set_server_option(RPC_ODB_HANDLE, hDB);
01641 rpc_set_server_option(RPC_CLIENT_HANDLE, hKey);
01642
01643
01644 cm_get_watchdog_params(&call_watchdog, NULL);
01645 cm_set_watchdog_params(call_watchdog, watchdog_timeout);
01646 if (call_watchdog)
01647 ss_alarm(WATCHDOG_INTERVAL, cm_watchdog);
01648
01649
01650 db_unlock_database(hDB);
01651
01652
01653 data = 0;
01654 db_set_value(hDB, 0, "/System/Client Notify", &data, sizeof(data), 1, TID_INT);
01655
01656 *hKeyClient = hKey;
01657 }
01658 #endif
01659
01660 return CM_SUCCESS;
01661 }
01662
01663
01664
01665
01666
01667
01668
01669 INT cm_get_client_info(char *client_name)
01670 {
01671 INT status, length;
01672 HNDLE hDB, hKey;
01673
01674
01675 cm_get_experiment_database(&hDB, &hKey);
01676 if (!hDB) {
01677 client_name[0] = 0;
01678 return CM_UNDEF_EXP;
01679 }
01680
01681 status = db_find_key(hDB, hKey, "Name", &hKey);
01682 if (status != DB_SUCCESS)
01683 return status;
01684
01685 length = NAME_LENGTH;
01686 status = db_get_data(hDB, hKey, client_name, &length, TID_STRING);
01687 if (status != DB_SUCCESS)
01688 return status;
01689
01690 return CM_SUCCESS;
01691 }
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
01746 {
01747 host_name[0] = exp_name[0] = 0;
01748
01749 if (getenv("MIDAS_SERVER_HOST"))
01750 strlcpy(host_name, getenv("MIDAS_SERVER_HOST"), host_name_size);
01751
01752 if (getenv("MIDAS_EXPT_NAME"))
01753 strlcpy(exp_name, getenv("MIDAS_EXPT_NAME"), exp_name_size);
01754
01755 return CM_SUCCESS;
01756 }
01757
01758
01759
01760 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01761
01762
01763 void cm_check_connect(void)
01764 {
01765 if (_hKeyClient)
01766 cm_msg(MERROR, "", "cm_disconnect_experiment not called at end of program");
01767 }
01768
01769
01770 #endif
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842 INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void (*func) (char *))
01843 {
01844 INT status;
01845 char str[256];
01846
01847 status =
01848 cm_connect_experiment1(host_name, exp_name, client_name, func, DEFAULT_ODB_SIZE,
01849 DEFAULT_WATCHDOG_TIMEOUT);
01850 if (status != CM_SUCCESS) {
01851 cm_get_error(status, str);
01852 puts(str);
01853 }
01854
01855 return status;
01856 }
01857
01858
01859
01860
01861
01862
01863
01864 INT cm_connect_experiment1(const char *host_name, const char *exp_name,
01865 const char *client_name, void (*func) (char *), INT odb_size, DWORD watchdog_timeout)
01866 {
01867 INT status, i, semaphore_elog, semaphore_alarm, semaphore_history, semaphore_msg, size;
01868 char local_host_name[HOST_NAME_LENGTH];
01869 char client_name1[NAME_LENGTH];
01870 char password[NAME_LENGTH], str[256], exp_name1[NAME_LENGTH];
01871 HNDLE hDB, hKeyClient;
01872 BOOL call_watchdog;
01873 RUNINFO_STR(runinfo_str);
01874
01875 if (_hKeyClient)
01876 cm_disconnect_experiment();
01877
01878 rpc_set_name(client_name);
01879
01880
01881 if (equal_ustring(host_name, "local"))
01882 host_name = NULL;
01883
01884 #ifdef OS_WINNT
01885 {
01886 WSADATA WSAData;
01887
01888
01889 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
01890 return RPC_NET_ERROR;
01891 }
01892 #endif
01893
01894
01895 if (exp_name == NULL)
01896 exp_name = "";
01897
01898 strcpy(exp_name1, exp_name);
01899 if (exp_name1[0] == 0) {
01900 status = cm_select_experiment(host_name, exp_name1);
01901 if (status != CM_SUCCESS)
01902 return status;
01903 }
01904
01905
01906 if (host_name && host_name[0]) {
01907 status = rpc_server_connect(host_name, exp_name1);
01908 if (status != RPC_SUCCESS)
01909 return status;
01910
01911
01912 status = rpc_register_functions(rpc_get_internal_list(1), NULL);
01913 if (status != RPC_SUCCESS)
01914 return status;
01915 } else {
01916
01917 status = cm_scan_experiments();
01918 if (status != CM_SUCCESS)
01919 return status;
01920
01921 for (i = 0; i < MAX_EXPERIMENT && exptab[i].name[0]; i++)
01922 if (equal_ustring(exp_name1, exptab[i].name))
01923 break;
01924
01925
01926 if (i == MAX_EXPERIMENT || exptab[i].name[0] == 0) {
01927
01928
01929
01930
01931 return CM_UNDEF_EXP;
01932 }
01933
01934 cm_set_path(exptab[i].directory);
01935
01936
01937 status = ss_semaphore_create("ALARM", &semaphore_alarm);
01938 if (status != SS_CREATED && status != SS_SUCCESS) {
01939 cm_msg(MERROR, "cm_connect_experiment", "Cannot create alarm semaphore");
01940 return status;
01941 }
01942 status = ss_semaphore_create("ELOG", &semaphore_elog);
01943 if (status != SS_CREATED && status != SS_SUCCESS) {
01944 cm_msg(MERROR, "cm_connect_experiment", "Cannot create elog semaphore");
01945 return status;
01946 }
01947 status = ss_semaphore_create("HISTORY", &semaphore_history);
01948 if (status != SS_CREATED && status != SS_SUCCESS) {
01949 cm_msg(MERROR, "cm_connect_experiment", "Cannot create history semaphore");
01950 return status;
01951 }
01952 status = ss_semaphore_create("MSG", &semaphore_msg);
01953 if (status != SS_CREATED && status != SS_SUCCESS) {
01954 cm_msg(MERROR, "cm_connect_experiment", "Cannot create message semaphore");
01955 return status;
01956 }
01957
01958 cm_set_experiment_semaphore(semaphore_alarm, semaphore_elog, semaphore_history, semaphore_msg);
01959 }
01960
01961
01962 if (odb_size == 0)
01963 odb_size = DEFAULT_ODB_SIZE;
01964
01965 status = db_open_database("ODB", odb_size, &hDB, client_name);
01966 if (status != DB_SUCCESS && status != DB_CREATED) {
01967 cm_msg(MERROR, "cm_connect_experiment1", "cannot open database");
01968 return status;
01969 }
01970
01971
01972 gethostname(local_host_name, sizeof(local_host_name));
01973
01974
01975 if (watchdog_timeout == 0)
01976 watchdog_timeout = DEFAULT_WATCHDOG_TIMEOUT;
01977
01978 strcpy(client_name1, client_name);
01979 password[0] = 0;
01980 status = cm_set_client_info(hDB, &hKeyClient, local_host_name,
01981 client_name1, rpc_get_option(0, RPC_OHW_TYPE), password, watchdog_timeout);
01982
01983 if (status == CM_WRONG_PASSWORD) {
01984 if (func == NULL)
01985 strcpy(str, ss_getpass("Password: "));
01986 else
01987 func(str);
01988
01989
01990 status = db_open_database("ODB", odb_size, &hDB, client_name);
01991 if (status != DB_SUCCESS && status != DB_CREATED) {
01992 cm_msg(MERROR, "cm_connect_experiment1", "cannot open database");
01993 return status;
01994 }
01995
01996 strcpy(password, ss_crypt(str, "mi"));
01997 status = cm_set_client_info(hDB, &hKeyClient, local_host_name,
01998 client_name1, rpc_get_option(0, RPC_OHW_TYPE), password, watchdog_timeout);
01999 if (status != CM_SUCCESS) {
02000
02001 if (rpc_is_remote())
02002 rpc_server_disconnect();
02003
02004 return status;
02005 }
02006 }
02007
02008 cm_set_experiment_database(hDB, hKeyClient);
02009
02010
02011 db_set_value(hDB, 0, "/Experiment/Name", exp_name1, NAME_LENGTH, 1, TID_STRING);
02012
02013
02014 cm_get_path(str);
02015 size = sizeof(str);
02016 db_get_value(hDB, 0, "/Logger/Data dir", str, &size, TID_STRING, TRUE);
02017
02018
02019 status = db_check_record(hDB, 0, "/Runinfo", strcomb(runinfo_str), TRUE);
02020 if (status == DB_STRUCT_MISMATCH) {
02021 cm_msg(MERROR, "cm_connect_experiment1", "Aborting on mismatching /Runinfo structure");
02022 cm_disconnect_experiment();
02023 abort();
02024 }
02025
02026
02027 status = cm_register_server();
02028 if (status != CM_SUCCESS)
02029 return status;
02030
02031
02032 cm_get_watchdog_params(&call_watchdog, &watchdog_timeout);
02033 size = sizeof(watchdog_timeout);
02034 sprintf(str, "/Programs/%s/Watchdog Timeout", client_name);
02035 db_get_value(hDB, 0, str, &watchdog_timeout, &size, TID_INT, TRUE);
02036 cm_set_watchdog_params(call_watchdog, watchdog_timeout);
02037
02038
02039 if (strchr(local_host_name, '.'))
02040 *strchr(local_host_name, '.') = 0;
02041
02042
02043 _message_print = NULL;
02044
02045 cm_msg(MINFO, "cm_connect_experiment", "Program %s on host %s started", client_name, local_host_name);
02046
02047
02048 cm_set_msg_print(MT_ALL, MT_ALL, puts);
02049
02050
02051 atexit((void (*)(void)) cm_check_connect);
02052
02053
02054 ss_ctrlc_handler(cm_ctrlc_handler);
02055
02056 return CM_SUCCESS;
02057 }
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067 INT cm_list_experiments(const char *host_name, char exp_name[MAX_EXPERIMENT][NAME_LENGTH])
02068 {
02069 INT i, status;
02070 struct sockaddr_in bind_addr;
02071 INT sock;
02072 char str[MAX_EXPERIMENT * NAME_LENGTH];
02073 struct hostent *phe;
02074 int port = MIDAS_TCP_PORT;
02075 char hname[256];
02076 char *s;
02077
02078 if (host_name == NULL || host_name[0] == 0 || equal_ustring(host_name, "local")) {
02079 status = cm_scan_experiments();
02080 if (status != CM_SUCCESS)
02081 return status;
02082
02083 for (i = 0; i < MAX_EXPERIMENT; i++)
02084 strcpy(exp_name[i], exptab[i].name);
02085
02086 return CM_SUCCESS;
02087 }
02088 #ifdef OS_WINNT
02089 {
02090 WSADATA WSAData;
02091
02092
02093 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
02094 return RPC_NET_ERROR;
02095 }
02096 #endif
02097
02098
02099 sock = socket(AF_INET, SOCK_STREAM, 0);
02100 if (sock == -1) {
02101 cm_msg(MERROR, "cm_list_experiments", "cannot create socket");
02102 return RPC_NET_ERROR;
02103 }
02104
02105
02106 strlcpy(hname, host_name, sizeof(hname));
02107 s = strchr(hname, ':');
02108 if (s) {
02109 *s = 0;
02110 port = strtoul(s + 1, NULL, 0);
02111 }
02112
02113
02114 memset(&bind_addr, 0, sizeof(bind_addr));
02115 bind_addr.sin_family = AF_INET;
02116 bind_addr.sin_addr.s_addr = 0;
02117 bind_addr.sin_port = htons(port);
02118
02119 #ifdef OS_VXWORKS
02120 {
02121 INT host_addr;
02122
02123 host_addr = hostGetByName(hname);
02124 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
02125 }
02126 #else
02127 phe = gethostbyname(hname);
02128 if (phe == NULL) {
02129 cm_msg(MERROR, "cm_list_experiments", "cannot resolve host name \'%s\'", hname);
02130 return RPC_NET_ERROR;
02131 }
02132 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
02133 #endif
02134
02135 #ifdef OS_UNIX
02136 do {
02137 status = connect(sock, (void *) &bind_addr, sizeof(bind_addr));
02138
02139
02140 } while (status == -1 && errno == EINTR);
02141 #else
02142 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
02143 #endif
02144
02145 if (status != 0) {
02146
02147 return RPC_NET_ERROR;
02148 }
02149
02150
02151 send(sock, "I", 2, 0);
02152
02153 for (i = 0; i < MAX_EXPERIMENT; i++) {
02154 exp_name[i][0] = 0;
02155 status = recv_string(sock, str, sizeof(str), _rpc_connect_timeout);
02156
02157 if (status < 0)
02158 return RPC_NET_ERROR;
02159
02160 if (status == 0)
02161 break;
02162
02163 strcpy(exp_name[i], str);
02164 }
02165
02166 exp_name[i][0] = 0;
02167 closesocket(sock);
02168
02169 return CM_SUCCESS;
02170 }
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181 INT cm_select_experiment(const char *host_name, char *exp_name)
02182 {
02183 INT status, i;
02184 char expts[MAX_EXPERIMENT][NAME_LENGTH];
02185 char str[32];
02186
02187
02188 status = cm_list_experiments(host_name, expts);
02189 if (status != CM_SUCCESS)
02190 return status;
02191
02192 if (expts[1][0]) {
02193 if (host_name[0])
02194 printf("Available experiments on server %s:\n", host_name);
02195 else
02196 printf("Available experiments on local computer:\n");
02197
02198 for (i = 0; expts[i][0]; i++)
02199 printf("%d : %s\n", i, expts[i]);
02200 printf("Select number: ");
02201 ss_gets(str, 32);
02202 i = atoi(str);
02203 strcpy(exp_name, expts[i]);
02204 } else
02205 strcpy(exp_name, expts[0]);
02206
02207 return CM_SUCCESS;
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220 INT cm_connect_client(char *client_name, HNDLE * hConn)
02221 {
02222 HNDLE hDB, hKeyRoot, hSubkey, hKey;
02223 INT status, i, length, port;
02224 char name[NAME_LENGTH], host_name[HOST_NAME_LENGTH];
02225
02226
02227 cm_get_experiment_database(&hDB, &hKey);
02228
02229 status = db_find_key(hDB, 0, "System/Clients", &hKeyRoot);
02230 if (status != DB_SUCCESS)
02231 return status;
02232
02233 i = 0;
02234 do {
02235
02236 status = db_enum_key(hDB, hKeyRoot, i++, &hSubkey);
02237 if (status == DB_NO_MORE_SUBKEYS)
02238 return CM_NO_CLIENT;
02239
02240 status = db_find_key(hDB, hSubkey, "Name", &hKey);
02241 if (status != DB_SUCCESS)
02242 return status;
02243
02244 length = NAME_LENGTH;
02245 status = db_get_data(hDB, hKey, name, &length, TID_STRING);
02246 if (status != DB_SUCCESS)
02247 return status;
02248
02249 if (equal_ustring(name, client_name)) {
02250 status = db_find_key(hDB, hSubkey, "Server Port", &hKey);
02251 if (status != DB_SUCCESS)
02252 return status;
02253
02254 length = sizeof(INT);
02255 status = db_get_data(hDB, hKey, &port, &length, TID_INT);
02256 if (status != DB_SUCCESS)
02257 return status;
02258
02259 status = db_find_key(hDB, hSubkey, "Host", &hKey);
02260 if (status != DB_SUCCESS)
02261 return status;
02262
02263 length = sizeof(host_name);
02264 status = db_get_data(hDB, hKey, host_name, &length, TID_STRING);
02265 if (status != DB_SUCCESS)
02266 return status;
02267
02268
02269 return rpc_client_connect(host_name, port, client_name, hConn);
02270 }
02271
02272
02273 } while (TRUE);
02274 }
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286 INT cm_disconnect_client(HNDLE hConn, BOOL bShutdown)
02287 {
02288 return rpc_client_disconnect(hConn, bShutdown);
02289 }
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300 INT cm_disconnect_experiment(void)
02301 {
02302 HNDLE hDB, hKey;
02303 char local_host_name[HOST_NAME_LENGTH], client_name[80];
02304
02305
02306 rpc_get_name(client_name);
02307 gethostname(local_host_name, sizeof(local_host_name));
02308 if (strchr(local_host_name, '.'))
02309 *strchr(local_host_name, '.') = 0;
02310
02311
02312 _message_print = NULL;
02313
02314 cm_msg(MINFO, "cm_disconnect_experiment", "Program %s on host %s stopped", client_name, local_host_name);
02315
02316 if (rpc_is_remote()) {
02317
02318 db_close_all_records();
02319
02320 rpc_client_disconnect(-1, FALSE);
02321 rpc_server_disconnect();
02322 } else {
02323 rpc_client_disconnect(-1, FALSE);
02324
02325 #ifdef LOCAL_ROUTINES
02326 ss_alarm(0, cm_watchdog);
02327 _watchdog_last_called = 0;
02328 #endif
02329
02330
02331 cm_get_experiment_database(&hDB, &hKey);
02332
02333 if (hDB)
02334 cm_delete_client_info(hDB, 0);
02335
02336 bm_close_all_buffers();
02337 db_close_all_databases();
02338 }
02339
02340 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_REMOTE)
02341 rpc_server_shutdown();
02342
02343
02344 rpc_deregister_functions();
02345
02346 cm_set_experiment_database(0, 0);
02347
02348 _msg_buffer = 0;
02349
02350
02351 if (_event_buffer_size > 0) {
02352 M_FREE(_event_buffer);
02353 _event_buffer_size = 0;
02354 }
02355
02356 if (_net_recv_buffer_size > 0) {
02357 M_FREE(_net_recv_buffer);
02358 _net_recv_buffer_size = 0;
02359 _net_recv_buffer_size_odb = 0;
02360 }
02361
02362 if (_net_send_buffer_size > 0) {
02363 M_FREE(_net_send_buffer);
02364 _net_send_buffer_size = 0;
02365 }
02366
02367 if (_tcp_buffer != NULL) {
02368 M_FREE(_tcp_buffer);
02369 _tcp_buffer = NULL;
02370 }
02371
02372 return CM_SUCCESS;
02373 }
02374
02375
02376
02377
02378
02379
02380
02381
02382 INT cm_set_experiment_database(HNDLE hDB, HNDLE hKeyClient)
02383 {
02384 _hDB = hDB;
02385 _hKeyClient = hKeyClient;
02386
02387 return CM_SUCCESS;
02388 }
02389
02390
02391
02392
02393 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02394
02395
02396 INT cm_set_experiment_semaphore(INT semaphore_alarm, INT semaphore_elog, INT semaphore_history, INT semaphore_msg)
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416 {
02417 _semaphore_alarm = semaphore_alarm;
02418 _semaphore_elog = semaphore_elog;
02419 _semaphore_history = semaphore_history;
02420 _semaphore_msg = semaphore_msg;
02421
02422 return CM_SUCCESS;
02423 }
02424
02425
02426 #endif
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449 INT cm_get_experiment_database(HNDLE * hDB, HNDLE * hKeyClient)
02450 {
02451 if (_hDB) {
02452 if (hDB != NULL)
02453 *hDB = _hDB;
02454 if (hKeyClient != NULL)
02455 *hKeyClient = _hKeyClient;
02456 } else {
02457 if (hDB != NULL)
02458 *hDB = rpc_get_server_option(RPC_ODB_HANDLE);
02459 if (hKeyClient != NULL)
02460 *hKeyClient = rpc_get_server_option(RPC_CLIENT_HANDLE);
02461 }
02462
02463 return CM_SUCCESS;
02464 }
02465
02466
02467 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02468
02469
02470 INT cm_get_experiment_semaphore(INT * semaphore_alarm, INT * semaphore_elog, INT * semaphore_history, INT * semaphore_msg)
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490 {
02491 if (semaphore_alarm)
02492 *semaphore_alarm = _semaphore_alarm;
02493 if (semaphore_elog)
02494 *semaphore_elog = _semaphore_elog;
02495 if (semaphore_history)
02496 *semaphore_history = _semaphore_history;
02497 if (semaphore_msg)
02498 *semaphore_msg = _semaphore_msg;
02499
02500 return CM_SUCCESS;
02501 }
02502
02503
02504 #endif
02505
02506 static int bm_validate_client_index(const BUFFER * buf)
02507 {
02508 int badindex = 0;
02509 BUFFER_CLIENT *bcl = buf->buffer_header->client;
02510
02511 if (buf->client_index < 0)
02512 badindex = 1;
02513 else if (buf->client_index > buf->buffer_header->max_client_index)
02514 badindex = 1;
02515 else {
02516 bcl = &(buf->buffer_header->client[buf->client_index]);
02517 if (bcl->name[0] == 0)
02518 badindex = 1;
02519 else if (bcl->pid != ss_getpid())
02520 badindex = 1;
02521 }
02522
02523 #if 0
02524 printf
02525 ("bm_validate_client_index: badindex=%d, buf=%p, client_index=%d, max_client_index=%d, client_name=\'%s\', client_pid=%d, pid=%d\n",
02526 badindex, buf, buf->client_index, buf->buffer_header->max_client_index,
02527 buf->buffer_header->client[buf->client_index].name, buf->buffer_header->client[buf->client_index].pid,
02528 ss_getpid());
02529 #endif
02530
02531 if (badindex) {
02532 static int prevent_recursion = 1;
02533 if (prevent_recursion) {
02534 prevent_recursion = 0;
02535 cm_msg(MERROR, "bm_validate_client_index",
02536 "Invalid client index %d in buffer \'%s\'. Client name \'%s\', pid %d should be %d",
02537 buf->client_index, buf->buffer_header->name, bcl->name, bcl->pid, ss_getpid());
02538 cm_msg(MERROR, "bm_validate_client_index",
02539 "Maybe this client was removed by a timeout. Cannot continue, exiting.");
02540 }
02541 exit(1);
02542 }
02543
02544 return buf->client_index;
02545 }
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583 INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
02584 {
02585 INT i;
02586
02587
02588 _watchdog_timeout = timeout;
02589
02590 if (rpc_is_remote())
02591 return rpc_call(RPC_CM_SET_WATCHDOG_PARAMS, call_watchdog, timeout);
02592
02593 #ifdef LOCAL_ROUTINES
02594
02595 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE) {
02596 HNDLE hDB, hKey;
02597
02598 rpc_set_server_option(RPC_WATCHDOG_TIMEOUT, timeout);
02599
02600
02601 cm_get_experiment_database(&hDB, &hKey);
02602
02603 if (hDB) {
02604 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE, TRUE);
02605 db_set_value(hDB, hKey, "Link timeout", &timeout, sizeof(timeout), 1, TID_INT);
02606 db_set_mode(hDB, hKey, MODE_READ, TRUE);
02607 }
02608 } else {
02609 _call_watchdog = call_watchdog;
02610 _watchdog_timeout = timeout;
02611
02612
02613 for (i = _buffer_entries; i > 0; i--) {
02614 BUFFER_CLIENT *pclient;
02615 BUFFER_HEADER *pheader;
02616 INT idx;
02617
02618 idx = bm_validate_client_index(&_buffer[i - 1]);
02619 pheader = _buffer[i - 1].buffer_header;
02620 pclient = &pheader->client[idx];
02621
02622 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE
02623 && _buffer[i - 1].index != rpc_get_server_acception())
02624 continue;
02625
02626 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE && _buffer[i - 1].index != ss_gettid())
02627 continue;
02628
02629 if (!_buffer[i - 1].attached)
02630 continue;
02631
02632
02633 pclient->watchdog_timeout = timeout;
02634
02635
02636 pclient->last_activity = ss_millitime();
02637 }
02638
02639
02640 for (i = _database_entries; i > 0; i--) {
02641 DATABASE_HEADER *pheader;
02642 DATABASE_CLIENT *pclient;
02643 INT idx;
02644
02645 db_lock_database(i);
02646 idx = _database[i - 1].client_index;
02647 pheader = _database[i - 1].database_header;
02648 pclient = &pheader->client[idx];
02649
02650 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
02651 _database[i - 1].index != rpc_get_server_acception()) {
02652 db_unlock_database(i);
02653 continue;
02654 }
02655
02656 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE && _database[i - 1].index != ss_gettid()) {
02657 db_unlock_database(i);
02658 continue;
02659 }
02660
02661 if (!_database[i - 1].attached) {
02662 db_unlock_database(i);
02663 continue;
02664 }
02665
02666
02667 pclient->watchdog_timeout = timeout;
02668
02669
02670 pclient->last_activity = ss_millitime();
02671
02672 db_unlock_database(i);
02673 }
02674
02675 if (call_watchdog)
02676
02677 ss_alarm(WATCHDOG_INTERVAL, cm_watchdog);
02678 else
02679
02680 ss_alarm(0, cm_watchdog);
02681 }
02682
02683 #endif
02684
02685 return CM_SUCCESS;
02686 }
02687
02688
02689
02690
02691
02692
02693
02694
02695 INT cm_get_watchdog_params(BOOL * call_watchdog, DWORD * timeout)
02696 {
02697 if (call_watchdog)
02698 *call_watchdog = _call_watchdog;
02699 if (timeout)
02700 *timeout = _watchdog_timeout;
02701
02702 return CM_SUCCESS;
02703 }
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715 INT cm_get_watchdog_info(HNDLE hDB, char *client_name, DWORD * timeout, DWORD * last)
02716 {
02717 if (rpc_is_remote())
02718 return rpc_call(RPC_CM_GET_WATCHDOG_INFO, hDB, client_name, timeout, last);
02719
02720 #ifdef LOCAL_ROUTINES
02721 {
02722 DATABASE_HEADER *pheader;
02723 DATABASE_CLIENT *pclient;
02724 INT i;
02725
02726 if (hDB > _database_entries || hDB <= 0) {
02727 cm_msg(MERROR, "cm_get_watchdog_info", "invalid database handle");
02728 return DB_INVALID_HANDLE;
02729 }
02730
02731 if (!_database[hDB - 1].attached) {
02732 cm_msg(MERROR, "cm_get_watchdog_info", "invalid database handle");
02733 return DB_INVALID_HANDLE;
02734 }
02735
02736
02737 db_lock_database(hDB);
02738
02739 pheader = _database[hDB - 1].database_header;
02740 pclient = pheader->client;
02741
02742
02743 for (i = 0; i < pheader->max_client_index; i++, pclient++)
02744 if (pclient->pid && equal_ustring(pclient->name, client_name)) {
02745 *timeout = pclient->watchdog_timeout;
02746 *last = ss_millitime() - pclient->last_activity;
02747 db_unlock_database(hDB);
02748 return CM_SUCCESS;
02749 }
02750
02751 *timeout = *last = 0;
02752
02753 db_unlock_database(hDB);
02754
02755 return CM_NO_CLIENT;
02756 }
02757 #else
02758 return CM_SUCCESS;
02759 #endif
02760 }
02761
02762
02763
02764 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02765
02766
02767 INT cm_register_server(void)
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785 {
02786 INT status, port;
02787 HNDLE hDB, hKey;
02788
02789 if (!_server_registered) {
02790 port = 0;
02791 status = rpc_register_server(ST_REMOTE, NULL, &port, NULL);
02792 if (status != RPC_SUCCESS)
02793 return status;
02794 _server_registered = TRUE;
02795
02796
02797 rpc_register_functions(rpc_get_internal_list(1), NULL);
02798
02799
02800 cm_get_experiment_database(&hDB, &hKey);
02801
02802 status = db_find_key(hDB, hKey, "Server Port", &hKey);
02803 if (status != DB_SUCCESS)
02804 return status;
02805
02806
02807 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE, TRUE);
02808
02809
02810 status = db_set_data(hDB, hKey, &port, sizeof(INT), 1, TID_INT);
02811 if (status != DB_SUCCESS)
02812 return status;
02813
02814
02815 db_set_mode(hDB, hKey, MODE_READ, TRUE);
02816 }
02817
02818 return CM_SUCCESS;
02819 }
02820
02821
02822 #endif
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874 INT cm_register_transition(INT transition, INT(*func) (INT, char *), INT sequence_number)
02875 {
02876 INT status, i;
02877 HNDLE hDB, hKey, hKeyTrans;
02878 KEY key;
02879 char str[256];
02880
02881
02882 if (transition != TR_START && transition != TR_STOP && transition != TR_PAUSE && transition != TR_RESUME
02883 && transition != TR_STARTABORT) {
02884 cm_msg(MERROR, "cm_register_transition", "Invalid transition request \"%d\"", transition);
02885 return CM_INVALID_TRANSITION;
02886 }
02887
02888 cm_get_experiment_database(&hDB, &hKey);
02889
02890 rpc_register_function(RPC_RC_TRANSITION, rpc_transition_dispatch);
02891
02892
02893
02894
02895 for (i = 0; i < MAX_TRANSITIONS; i++)
02896 if (!_trans_table[i].transition)
02897 break;
02898
02899 if (i == MAX_TRANSITIONS) {
02900 cm_msg(MERROR, "cm_register_transition",
02901 "To many transition registrations. Please increase MAX_TRANSITIONS and recompile");
02902 return CM_TOO_MANY_REQUESTS;
02903 }
02904
02905 _trans_table[i].transition = transition;
02906 _trans_table[i].func = func;
02907 _trans_table[i].sequence_number = sequence_number;
02908
02909 for (i = 0;; i++)
02910 if (trans_name[i].name[0] == 0 || trans_name[i].transition == transition)
02911 break;
02912
02913 sprintf(str, "Transition %s", trans_name[i].name);
02914
02915
02916 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE | MODE_DELETE, TRUE);
02917
02918
02919 status = db_find_key(hDB, hKey, str, &hKeyTrans);
02920 if (!hKeyTrans) {
02921 status = db_set_value(hDB, hKey, str, &sequence_number, sizeof(INT), 1, TID_INT);
02922 if (status != DB_SUCCESS)
02923 return status;
02924 } else {
02925 status = db_get_key(hDB, hKeyTrans, &key);
02926 if (status != DB_SUCCESS)
02927 return status;
02928 status = db_set_data_index(hDB, hKeyTrans, &sequence_number, sizeof(INT), key.num_values, TID_INT);
02929 if (status != DB_SUCCESS)
02930 return status;
02931 }
02932
02933
02934 db_set_mode(hDB, hKey, MODE_READ, TRUE);
02935
02936 return CM_SUCCESS;
02937 }
02938
02939 INT cm_deregister_transition(INT transition)
02940 {
02941 INT status, i;
02942 HNDLE hDB, hKey, hKeyTrans;
02943 char str[256];
02944
02945
02946 if (transition != TR_START && transition != TR_STOP && transition != TR_PAUSE && transition != TR_RESUME) {
02947 cm_msg(MERROR, "cm_deregister_transition", "Invalid transition request \"%d\"", transition);
02948 return CM_INVALID_TRANSITION;
02949 }
02950
02951 cm_get_experiment_database(&hDB, &hKey);
02952
02953
02954 for (i = 0; i < MAX_TRANSITIONS; i++)
02955 if (_trans_table[i].transition == transition)
02956 break;
02957
02958 if (i == MAX_TRANSITIONS) {
02959 cm_msg(MERROR, "cm_register_transition",
02960 "Cannot de-register transition registration, request not found");
02961 return CM_INVALID_TRANSITION;
02962 }
02963
02964 _trans_table[i].transition = 0;
02965 _trans_table[i].func = NULL;
02966 _trans_table[i].sequence_number = 0;
02967
02968 for (i = 0;; i++)
02969 if (trans_name[i].name[0] == 0 || trans_name[i].transition == transition)
02970 break;
02971
02972 sprintf(str, "Transition %s", trans_name[i].name);
02973
02974
02975 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE | MODE_DELETE, TRUE);
02976
02977
02978 status = db_find_key(hDB, hKey, str, &hKeyTrans);
02979 if (hKeyTrans) {
02980 status = db_delete_key(hDB, hKeyTrans, FALSE);
02981 if (status != DB_SUCCESS)
02982 return status;
02983 }
02984
02985
02986 db_set_mode(hDB, hKey, MODE_READ, TRUE);
02987
02988 return CM_SUCCESS;
02989 }
02990
02991
02992
02993
02994
02995
02996
02997
02998 INT cm_set_transition_sequence(INT transition, INT sequence_number)
02999 {
03000 INT status, i;
03001 HNDLE hDB, hKey;
03002 char str[256];
03003
03004
03005 if (transition != TR_START && transition != TR_STOP && transition != TR_PAUSE && transition != TR_RESUME) {
03006 cm_msg(MERROR, "cm_set_transition_sequence", "Invalid transition request \"%d\"", transition);
03007 return CM_INVALID_TRANSITION;
03008 }
03009
03010 cm_get_experiment_database(&hDB, &hKey);
03011
03012
03013 for (i = 0;; i++)
03014 if (trans_name[i].name[0] == 0 || trans_name[i].transition == transition)
03015 break;
03016 sprintf(str, "Transition %s", trans_name[i].name);
03017
03018
03019 for (i = 0; i < MAX_TRANSITIONS; i++)
03020 if (_trans_table[i].transition == transition) {
03021 _trans_table[i].sequence_number = sequence_number;
03022 break;
03023 }
03024
03025
03026 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE, TRUE);
03027
03028
03029 status = db_set_value(hDB, hKey, str, &sequence_number, sizeof(INT), 1, TID_INT);
03030 if (status != DB_SUCCESS)
03031 return status;
03032
03033
03034 db_set_mode(hDB, hKey, MODE_READ, TRUE);
03035
03036 return CM_SUCCESS;
03037
03038 }
03039
03040
03041 #ifndef DOXYGEN_SHOULD_SKIP_THIS
03042
03043 static INT _requested_transition;
03044 static DWORD _deferred_transition_mask;
03045
03046
03047 #endif
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062 INT cm_register_deferred_transition(INT transition, BOOL(*func) (INT, BOOL))
03063 {
03064 INT status, i, size;
03065 char tr_key_name[256];
03066 HNDLE hDB, hKey;
03067
03068 cm_get_experiment_database(&hDB, &hKey);
03069
03070 for (i = 0; _deferred_trans_table[i].transition; i++)
03071 if (_deferred_trans_table[i].transition == transition)
03072 _deferred_trans_table[i].func = (int (*)(int, char *)) func;
03073
03074
03075 _deferred_transition_mask |= transition;
03076
03077 for (i = 0;; i++)
03078 if (trans_name[i].name[0] == 0 || trans_name[i].transition == transition)
03079 break;
03080
03081 sprintf(tr_key_name, "Transition %s DEFERRED", trans_name[i].name);
03082
03083
03084 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE, TRUE);
03085
03086
03087 i = 0;
03088 status = db_set_value(hDB, hKey, tr_key_name, &i, sizeof(INT), 1, TID_INT);
03089 if (status != DB_SUCCESS)
03090 return status;
03091
03092
03093 db_set_mode(hDB, hKey, MODE_READ, TRUE);
03094
03095
03096 size = sizeof(_requested_transition);
03097 db_get_value(hDB, 0, "/Runinfo/Requested Transition", &_requested_transition, &size, TID_INT, TRUE);
03098 db_find_key(hDB, 0, "/Runinfo/Requested Transition", &hKey);
03099 status = db_open_record(hDB, hKey, &_requested_transition, sizeof(INT), MODE_READ, NULL, NULL);
03100 if (status != DB_SUCCESS) {
03101 cm_msg(MERROR, "cm_register_deferred_transition", "Cannot hotlink /Runinfo/Requested Transition");
03102 return status;
03103 }
03104
03105 return CM_SUCCESS;
03106 }
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119 INT cm_check_deferred_transition()
03120 {
03121 INT i, status;
03122 char str[256];
03123 static BOOL first;
03124
03125 if (_requested_transition == 0)
03126 first = TRUE;
03127
03128 if (_requested_transition & _deferred_transition_mask) {
03129 for (i = 0; _deferred_trans_table[i].transition; i++)
03130 if (_deferred_trans_table[i].transition == _requested_transition)
03131 break;
03132
03133 if (_deferred_trans_table[i].transition == _requested_transition) {
03134 if (((BOOL(*)(INT, BOOL)) _deferred_trans_table[i].func) (_requested_transition, first)) {
03135 status = cm_transition(_requested_transition | TR_DEFERRED, 0, str, sizeof(str), SYNC, FALSE);
03136 if (status != CM_SUCCESS)
03137 cm_msg(MERROR, "cm_check_deferred_transition", "Cannot perform deferred transition: %s", str);
03138
03139
03140 _requested_transition = 0;
03141
03142 return status;
03143 }
03144 first = FALSE;
03145 }
03146 }
03147
03148 return SUCCESS;
03149 }
03150
03151
03152
03153 #ifndef DOXYGEN_SHOULD_SKIP_THIS
03154
03155
03156
03157
03158 #endif
03159
03160 typedef struct {
03161 int sequence_number;
03162 char host_name[HOST_NAME_LENGTH];
03163 char client_name[NAME_LENGTH];
03164 int port;
03165 } TR_CLIENT;
03166
03167 int tr_compare(const void *arg1, const void *arg2)
03168 {
03169 return ((TR_CLIENT *) arg1)->sequence_number - ((TR_CLIENT *) arg2)->sequence_number;
03170 }
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212 INT cm_transition1(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag,
03213 INT debug_flag)
03214 {
03215 INT i, j, status, idx, size, sequence_number, port, state, old_timeout, n_tr_clients;
03216 HNDLE hDB, hRootKey, hSubkey, hKey, hKeylocal, hConn, hKeyTrans;
03217 DWORD seconds;
03218 char host_name[HOST_NAME_LENGTH], client_name[NAME_LENGTH], str[256], error[256], tr_key_name[256];
03219 char *trname = "unknown";
03220 KEY key;
03221 BOOL deferred;
03222 PROGRAM_INFO program_info;
03223 TR_CLIENT *tr_client;
03224 int connect_timeout = 10000;
03225 int timeout = 120000;
03226 int t0, t1;
03227
03228 deferred = (transition & TR_DEFERRED) > 0;
03229 transition &= ~TR_DEFERRED;
03230
03231
03232 if (transition != TR_START && transition != TR_STOP && transition != TR_PAUSE && transition != TR_RESUME
03233 && transition != TR_STARTABORT) {
03234 cm_msg(MERROR, "cm_transition", "Invalid transition request \"%d\"", transition);
03235 if (errstr != NULL)
03236 strlcpy(errstr, "Invalid transition request", errstr_size);
03237 return CM_INVALID_TRANSITION;
03238 }
03239
03240
03241 cm_get_experiment_database(&hDB, &hKeylocal);
03242
03243 if (errstr != NULL)
03244 strlcpy(errstr, "Unknown error", errstr_size);
03245
03246 if (debug_flag == 0) {
03247 size = sizeof(i);
03248 db_get_value(hDB, 0, "/Experiment/Transition debug flag", &debug_flag, &size, TID_INT, TRUE);
03249 }
03250
03251
03252 if (async_flag == DETACH) {
03253 char *args[100];
03254 int iarg = 0;
03255 char debug_arg[256];
03256 char start_arg[256];
03257 char expt_name[256];
03258 extern RPC_SERVER_CONNECTION _server_connection;
03259
03260 args[iarg++] = "mtransition";
03261
03262 if (_server_connection.send_sock) {
03263
03264 args[iarg++] = "-h";
03265 args[iarg++] = _server_connection.host_name;
03266 args[iarg++] = "-e";
03267 args[iarg++] = _server_connection.exp_name;
03268 } else {
03269
03270 size = sizeof(expt_name);
03271 db_get_value(hDB, 0, "/Experiment/Name", expt_name, &size, TID_STRING, FALSE);
03272
03273 args[iarg++] = "-e";
03274 args[iarg++] = expt_name;
03275 }
03276
03277 if (debug_flag) {
03278 args[iarg++] = "-d";
03279
03280 sprintf(debug_arg, "%d", debug_flag);
03281 args[iarg++] = debug_arg;
03282 }
03283
03284 if (transition == TR_STOP)
03285 args[iarg++] = "STOP";
03286 else if (transition == TR_PAUSE)
03287 args[iarg++] = "PAUSE";
03288 else if (transition == TR_RESUME)
03289 args[iarg++] = "RESUME";
03290 else if (transition == TR_START) {
03291 args[iarg++] = "START";
03292
03293 sprintf(start_arg, "%d", run_number);
03294 args[iarg++] = start_arg;
03295 }
03296
03297 args[iarg++] = NULL;
03298
03299 if (0)
03300 for (iarg = 0; args[iarg] != NULL; iarg++)
03301 printf("arg[%d] [%s]\n", iarg, args[iarg]);
03302
03303 status = ss_spawnv(P_DETACH, args[0], args);
03304
03305 if (status != SUCCESS) {
03306 if (errstr != NULL)
03307 sprintf(errstr, "Cannot execute mtransition, ss_spawnvp() returned %d", status);
03308 return CM_SET_ERROR;
03309 }
03310
03311 return CM_SUCCESS;
03312 }
03313
03314
03315 if (run_number == 0) {
03316 size = sizeof(run_number);
03317 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
03318 assert(status == SUCCESS);
03319 }
03320
03321 if (run_number <= 0) {
03322 cm_msg(MERROR, "cm_transition", "aborting on attempt to use invalid run number %d", run_number);
03323 abort();
03324 }
03325
03326
03327 if (!deferred) {
03328 i = 0;
03329 size = sizeof(i);
03330 db_get_value(hDB, 0, "/Runinfo/Transition in progress", &i, &size, TID_INT, TRUE);
03331 if (i == 1) {
03332 sprintf(errstr, "Start/Stop transition %d already in progress, please try again later\n", i);
03333 strlcat(errstr, "or set \"/Runinfo/Transition in progress\" manually to zero.\n", errstr_size);
03334 return CM_TRANSITION_IN_PROGRESS;
03335 }
03336 }
03337
03338
03339 size = sizeof(timeout);
03340 db_get_value(hDB, 0, "/Experiment/Transition connect timeout", &connect_timeout, &size, TID_INT, TRUE);
03341
03342 if (connect_timeout < 1000)
03343 connect_timeout = 1000;
03344
03345
03346 size = sizeof(timeout);
03347 db_get_value(hDB, 0, "/Experiment/Transition timeout", &timeout, &size, TID_INT, TRUE);
03348
03349 if (timeout < 1000)
03350 timeout = 1000;
03351
03352
03353 i = transition;
03354 db_set_value(hDB, 0, "/Runinfo/Transition in progress", &i, sizeof(INT), 1, TID_INT);
03355
03356
03357 i = 0;
03358 db_set_value(hDB, 0, "/Runinfo/Start abort", &i, sizeof(INT), 1, TID_INT);
03359
03360
03361 if (transition == TR_START) {
03362 if (debug_flag == 1)
03363 printf("Setting run number %d in ODB\n", run_number);
03364 if (debug_flag == 2)
03365 cm_msg(MINFO, "cm_transition", "cm_transition: Setting run number %d in ODB", run_number);
03366
03367 status = db_set_value(hDB, 0, "Runinfo/Run number", &run_number, sizeof(run_number), 1, TID_INT);
03368 assert(status == SUCCESS);
03369 if (status != DB_SUCCESS)
03370 cm_msg(MERROR, "cm_transition", "cannot set Runinfo/Run number in database");
03371 }
03372
03373 if (deferred) {
03374
03375 i = 0;
03376 db_set_value(hDB, 0, "/Runinfo/Requested transition", &i, sizeof(int), 1, TID_INT);
03377 } else {
03378 status = db_find_key(hDB, 0, "System/Clients", &hRootKey);
03379 if (status != DB_SUCCESS) {
03380 cm_msg(MERROR, "cm_transition", "cannot find System/Clients entry in database");
03381 if (errstr != NULL)
03382 strlcpy(errstr, "Cannot find /System/Clients in ODB", errstr_size);
03383 return status;
03384 }
03385
03386
03387 size = sizeof(i);
03388 db_get_value(hDB, 0, "/Runinfo/Requested transition", &i, &size, TID_INT, TRUE);
03389 if (i) {
03390 if (errstr != NULL)
03391 strlcpy(errstr, "Deferred transition already in progress", errstr_size);
03392 return CM_TRANSITION_IN_PROGRESS;
03393 }
03394
03395 for (i = 0; trans_name[i].name[0] != 0; i++)
03396 if (trans_name[i].transition == transition) {
03397 trname = trans_name[i].name;
03398 break;
03399 }
03400
03401 sprintf(tr_key_name, "Transition %s DEFERRED", trname);
03402
03403
03404 for (i = 0, status = 0;; i++) {
03405 status = db_enum_key(hDB, hRootKey, i, &hSubkey);
03406 if (status == DB_NO_MORE_SUBKEYS)
03407 break;
03408
03409 if (status == DB_SUCCESS) {
03410 size = sizeof(sequence_number);
03411 status = db_get_value(hDB, hSubkey, tr_key_name, &sequence_number, &size, TID_INT, FALSE);
03412
03413
03414 if (status == DB_SUCCESS) {
03415 size = NAME_LENGTH;
03416 db_get_value(hDB, hSubkey, "Name", str, &size, TID_STRING, TRUE);
03417 db_set_value(hDB, 0, "/Runinfo/Requested transition", &transition, sizeof(int), 1, TID_INT);
03418
03419 if (debug_flag == 1)
03420 printf("---- Transition %s deferred by client \"%s\" ----\n", trname, str);
03421 if (debug_flag == 2)
03422 cm_msg(MINFO, "cm_transition",
03423 "cm_transition: ---- Transition %s deferred by client \"%s\" ----", trname, str);
03424
03425 if (errstr)
03426 sprintf(errstr, "Transition %s deferred by client \"%s\"", trname, str);
03427
03428 return CM_DEFERRED_TRANSITION;
03429 }
03430 }
03431 }
03432 }
03433
03434
03435 if (transition == TR_START) {
03436 str[0] = 0;
03437 size = sizeof(str);
03438 db_get_value(hDB, 0, "/Programs/Execute on start run", str, &size, TID_STRING, TRUE);
03439 if (str[0])
03440 ss_system(str);
03441
03442 db_find_key(hDB, 0, "/Programs", &hRootKey);
03443 if (hRootKey) {
03444 for (i = 0;; i++) {
03445 status = db_enum_key(hDB, hRootKey, i, &hKey);
03446 if (status == DB_NO_MORE_SUBKEYS)
03447 break;
03448
03449 db_get_key(hDB, hKey, &key);
03450
03451
03452 if (key.type != TID_KEY)
03453 continue;
03454
03455 size = sizeof(program_info);
03456 status = db_get_record(hDB, hKey, &program_info, &size, 0);
03457 if (status != DB_SUCCESS) {
03458 cm_msg(MERROR, "cm_transition", "Cannot get program info record");
03459 continue;
03460 }
03461
03462 if (program_info.auto_start && program_info.start_command[0])
03463 ss_system(program_info.start_command);
03464 }
03465 }
03466 }
03467
03468
03469 if (transition == TR_START) {
03470
03471 cm_asctime(str, sizeof(str));
03472 db_set_value(hDB, 0, "Runinfo/Start Time", str, 32, 1, TID_STRING);
03473
03474
03475 seconds = 0;
03476 db_set_value(hDB, 0, "Runinfo/Stop Time binary", &seconds, sizeof(seconds), 1, TID_DWORD);
03477
03478
03479 cm_time(&seconds);
03480 db_set_value(hDB, 0, "Runinfo/Start Time binary", &seconds, sizeof(seconds), 1, TID_DWORD);
03481 }
03482
03483
03484 if (transition == TR_STOP) {
03485 size = sizeof(state);
03486 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT, TRUE);
03487 if (status != DB_SUCCESS)
03488 cm_msg(MERROR, "cm_transition", "cannot get Runinfo/State in database");
03489
03490 if (state != STATE_STOPPED) {
03491
03492 cm_time(&seconds);
03493 status = db_set_value(hDB, 0, "Runinfo/Stop Time binary", &seconds, sizeof(seconds), 1, TID_DWORD);
03494 if (status != DB_SUCCESS)
03495 cm_msg(MERROR, "cm_transition", "cannot set \"Runinfo/Stop Time binary\" in database");
03496
03497
03498 cm_asctime(str, sizeof(str));
03499 status = db_set_value(hDB, 0, "Runinfo/Stop Time", str, 32, 1, TID_STRING);
03500 if (status != DB_SUCCESS)
03501 cm_msg(MERROR, "cm_transition", "cannot set \"Runinfo/Stop Time\" in database");
03502 }
03503 }
03504
03505 status = db_find_key(hDB, 0, "System/Clients", &hRootKey);
03506 if (status != DB_SUCCESS) {
03507 cm_msg(MERROR, "cm_transition", "cannot find System/Clients entry in database");
03508 if (errstr)
03509 strlcpy(errstr, "Cannot find /System/Clients in ODB", errstr_size);
03510 return status;
03511 }
03512
03513 for (i = 0; trans_name[i].name[0] != 0; i++)
03514 if (trans_name[i].transition == transition) {
03515 trname = trans_name[i].name;
03516 break;
03517 }
03518
03519
03520 for (i = 0;;) {
03521 status = db_enum_key(hDB, hRootKey, i, &hSubkey);
03522 if (status != DB_SUCCESS)
03523 break;
03524
03525 status = cm_check_client(hDB, hSubkey);
03526
03527 if (status == DB_SUCCESS) {
03528
03529 i++;
03530 continue;
03531 }
03532
03533 assert(status == CM_NO_CLIENT);
03534
03535
03536
03537 i = 0;
03538 }
03539
03540 if (debug_flag == 1)
03541 printf("---- Transition %s started ----\n", trname);
03542 if (debug_flag == 2)
03543 cm_msg(MINFO, "cm_transition", "cm_transition: ---- Transition %s started ----", trname);
03544
03545 sprintf(tr_key_name, "Transition %s", trname);
03546
03547
03548 n_tr_clients = 0;
03549 tr_client = NULL;
03550
03551 for (i = 0, status = 0;; i++) {
03552 status = db_enum_key(hDB, hRootKey, i, &hSubkey);
03553 if (status == DB_NO_MORE_SUBKEYS)
03554 break;
03555
03556 if (status == DB_SUCCESS) {
03557 status = db_find_key(hDB, hSubkey, tr_key_name, &hKeyTrans);
03558
03559 if (status == DB_SUCCESS) {
03560
03561 db_get_key(hDB, hKeyTrans, &key);
03562
03563 for (j = 0; j < key.num_values; j++) {
03564 size = sizeof(sequence_number);
03565 status = db_get_data_index(hDB, hKeyTrans, &sequence_number, &size, j, TID_INT);
03566 assert(status == DB_SUCCESS);
03567
03568 if (tr_client == NULL)
03569 tr_client = (TR_CLIENT *) malloc(sizeof(TR_CLIENT));
03570 else
03571 tr_client = (TR_CLIENT *) realloc(tr_client, sizeof(TR_CLIENT) * (n_tr_clients + 1));
03572 assert(tr_client);
03573
03574 tr_client[n_tr_clients].sequence_number = sequence_number;
03575
03576 if (hSubkey == hKeylocal) {
03577
03578 tr_client[n_tr_clients].port = 0;
03579 } else {
03580
03581 size = sizeof(client_name);
03582 db_get_value(hDB, hSubkey, "Name", client_name, &size, TID_STRING, TRUE);
03583 strcpy(tr_client[n_tr_clients].client_name, client_name);
03584
03585 size = sizeof(port);
03586 db_get_value(hDB, hSubkey, "Server Port", &port, &size, TID_INT, TRUE);
03587 tr_client[n_tr_clients].port = port;
03588
03589 size = sizeof(host_name);
03590 db_get_value(hDB, hSubkey, "Host", host_name, &size, TID_STRING, TRUE);
03591 strcpy(tr_client[n_tr_clients].host_name, host_name);
03592 }
03593
03594 n_tr_clients++;
03595 }
03596 }
03597 }
03598 }
03599
03600
03601 if (n_tr_clients > 1)
03602 qsort(tr_client, n_tr_clients, sizeof(TR_CLIENT), tr_compare);
03603
03604
03605 for (idx = 0; idx < n_tr_clients; idx++) {
03606
03607 error[0] = 0;
03608
03609 if (debug_flag == 1)
03610 printf("\n==== Found client \"%s\" with sequence number %d\n",
03611 tr_client[idx].client_name, tr_client[idx].sequence_number);
03612 if (debug_flag == 2)
03613 cm_msg(MINFO, "cm_transition",
03614 "cm_transition: ==== Found client \"%s\" with sequence number %d",
03615 tr_client[idx].client_name, tr_client[idx].sequence_number);
03616
03617
03618 if (tr_client[idx].port == 0) {
03619 for (i = 0; _trans_table[i].transition; i++)
03620 if (_trans_table[i].transition == transition)
03621 break;
03622
03623
03624 if (_trans_table[i].transition == transition && _trans_table[i].func) {
03625 if (debug_flag == 1)
03626 printf("Calling local transition callback\n");
03627 if (debug_flag == 2)
03628 cm_msg(MINFO, "cm_transition", "cm_transition: Calling local transition callback");
03629
03630 status = _trans_table[i].func(run_number, error);
03631
03632 if (debug_flag == 1)
03633 printf("Local transition callback finished\n");
03634 if (debug_flag == 2)
03635 cm_msg(MINFO, "cm_transition", "cm_transition: Local transition callback finished");
03636 } else
03637 status = CM_SUCCESS;
03638
03639 if (errstr != NULL)
03640 memcpy(errstr, error,
03641 (INT) strlen(error) + 1 < errstr_size ? (INT) strlen(error) + 1 : errstr_size);
03642
03643 if (status != CM_SUCCESS) {
03644
03645 i = 1;
03646 db_set_value(hDB, 0, "/Runinfo/Start abort", &i, sizeof(INT), 1, TID_INT);
03647 i = 0;
03648 db_set_value(hDB, 0, "/Runinfo/Transition in progress", &i, sizeof(INT), 1, TID_INT);
03649
03650 free(tr_client);
03651 return status;
03652 }
03653
03654 } else {
03655
03656
03657 if (debug_flag == 1)
03658 printf("Connecting to client \"%s\" on host %s...\n", tr_client[idx].client_name,
03659 tr_client[idx].host_name);
03660 if (debug_flag == 2)
03661 cm_msg(MINFO, "cm_transition",
03662 "cm_transition: Connecting to client \"%s\" on host %s...",
03663 tr_client[idx].client_name, tr_client[idx].host_name);
03664
03665
03666 old_timeout = rpc_get_option(-2, RPC_OTIMEOUT);
03667 rpc_set_option(-2, RPC_OTIMEOUT, connect_timeout);
03668
03669
03670 status =
03671 rpc_client_connect(tr_client[idx].host_name, tr_client[idx].port, tr_client[idx].client_name,
03672 &hConn);
03673
03674 rpc_set_option(-2, RPC_OTIMEOUT, old_timeout);
03675
03676 if (status != RPC_SUCCESS) {
03677 cm_msg(MERROR, "cm_transition",
03678 "cannot connect to client \"%s\" on host %s, port %d, status %d",
03679 tr_client[idx].client_name, tr_client[idx].host_name, tr_client[idx].port, status);
03680 if (errstr != NULL) {
03681 strlcpy(errstr, "Cannot connect to client \'", errstr_size);
03682 strlcat(errstr, tr_client[idx].client_name, errstr_size);
03683 strlcat(errstr, "\'", errstr_size);
03684 }
03685
03686
03687 cm_shutdown(tr_client[idx].client_name, TRUE);
03688 cm_cleanup(tr_client[idx].client_name, TRUE);
03689
03690
03691 i = 1;
03692 db_set_value(hDB, 0, "/Runinfo/Start abort", &i, sizeof(INT), 1, TID_INT);
03693 i = 0;
03694 db_set_value(hDB, 0, "/Runinfo/Transition in progress", &i, sizeof(INT), 1, TID_INT);
03695
03696 return status;
03697 }
03698
03699 if (debug_flag == 1)
03700 printf("Connection established to client \"%s\" on host %s\n",
03701 tr_client[idx].client_name, tr_client[idx].host_name);
03702 if (debug_flag == 2)
03703 cm_msg(MINFO, "cm_transition",
03704 "cm_transition: Connection established to client \"%s\" on host %s",
03705 tr_client[idx].client_name, tr_client[idx].host_name);
03706
03707
03708 old_timeout = rpc_get_option(hConn, RPC_OTIMEOUT);
03709 rpc_set_option(hConn, RPC_OTIMEOUT, timeout);
03710
03711
03712 if (async_flag == ASYNC)
03713 rpc_set_option(hConn, RPC_OTRANSPORT, RPC_FTCP);
03714
03715 if (debug_flag == 1)
03716 printf("Executing RPC transition client \"%s\" on host %s...\n",
03717 tr_client[idx].client_name, tr_client[idx].host_name);
03718 if (debug_flag == 2)
03719 cm_msg(MINFO, "cm_transition",
03720 "cm_transition: Executing RPC transition client \"%s\" on host %s...",
03721 tr_client[idx].client_name, tr_client[idx].host_name);
03722
03723 t0 = ss_millitime();
03724
03725 status = rpc_client_call(hConn, RPC_RC_TRANSITION, transition,
03726 run_number, error, errstr_size, tr_client[idx].sequence_number);
03727
03728 t1 = ss_millitime();
03729
03730
03731 rpc_set_option(hConn, RPC_OTIMEOUT, old_timeout);
03732
03733
03734 if (async_flag == ASYNC)
03735 rpc_set_option(hConn, RPC_OTRANSPORT, RPC_TCP);
03736
03737 if (debug_flag == 1)
03738 printf("RPC transition finished client \"%s\" on host %s in %d ms with status %d\n",
03739 tr_client[idx].client_name, tr_client[idx].host_name, t1 - t0, status);
03740 if (debug_flag == 2)
03741 cm_msg(MINFO, "cm_transition",
03742 "cm_transition: RPC transition finished client \"%s\" on host %s in %d ms with status %d",
03743 tr_client[idx].client_name, tr_client[idx].host_name, t1 - t0, status);
03744
03745 if (errstr != NULL) {
03746 if (strlen(error) < 2)
03747 sprintf(errstr, "Unknown error %d from client \'%s\' on host %s", status,
03748 tr_client[idx].client_name, tr_client[idx].host_name);
03749 else
03750 memcpy(errstr, error,
03751 (INT) strlen(error) + 1 < (INT) errstr_size ? (INT) strlen(error) + 1 : errstr_size);
03752 }
03753
03754 if (status != CM_SUCCESS) {
03755
03756 i = 1;
03757 db_set_value(hDB, 0, "/Runinfo/Start abort", &i, sizeof(INT), 1, TID_INT);
03758 i = 0;
03759 db_set_value(hDB, 0, "/Runinfo/Transition in progress", &i, sizeof(INT), 1, TID_INT);
03760
03761 free(tr_client);
03762 return status;
03763 }
03764 }
03765 }
03766
03767 if (tr_client)
03768 free(tr_client);
03769
03770 if (debug_flag == 1)
03771 printf("\n---- Transition %s finished ----\n", trname);
03772 if (debug_flag == 2)
03773 cm_msg(MINFO, "cm_transition", "cm_transition: ---- Transition %s finished ----", trname);
03774
03775
03776 if (transition == TR_START || transition == TR_RESUME)
03777 state = STATE_RUNNING;
03778
03779 if (transition == TR_PAUSE)
03780 state = STATE_PAUSED;
03781
03782 if (transition == TR_STOP)
03783 state = STATE_STOPPED;
03784
03785 if (transition == TR_STARTABORT)
03786 state = STATE_STOPPED;
03787
03788 size = sizeof(state);
03789 status = db_set_value(hDB, 0, "Runinfo/State", &state, size, 1, TID_INT);
03790 if (status != DB_SUCCESS)
03791 cm_msg(MERROR, "cm_transition", "cannot set Runinfo/State in database");
03792
03793
03794 str[0] = 0;
03795 if (transition == TR_START)
03796 sprintf(str, "Run #%d started", run_number);
03797 if (transition == TR_STOP)
03798 sprintf(str, "Run #%d stopped", run_number);
03799 if (transition == TR_PAUSE)
03800 sprintf(str, "Run #%d paused", run_number);
03801 if (transition == TR_RESUME)
03802 sprintf(str, "Run #%d resumed", run_number);
03803 if (transition == TR_STARTABORT)
03804 sprintf(str, "Run #%d start aborted", run_number);
03805
03806 if (str[0])
03807 cm_msg(MINFO, "cm_transition", str);
03808
03809
03810 db_find_key(hDB, 0, "/Experiment/Lock when running", &hKey);
03811 if (hKey) {
03812 if (state == STATE_STOPPED)
03813 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE | MODE_DELETE, TRUE);
03814 else
03815 db_set_mode(hDB, hKey, MODE_READ, TRUE);
03816 }
03817
03818
03819 if (transition == TR_STOP)
03820 db_flush_database(hDB);
03821
03822
03823 if (transition == TR_STOP) {
03824 str[0] = 0;
03825 size = sizeof(str);
03826 db_get_value(hDB, 0, "/Programs/Execute on stop run", str, &size, TID_STRING, TRUE);
03827 if (str[0])
03828 ss_system(str);
03829
03830 db_find_key(hDB, 0, "/Programs", &hRootKey);
03831 if (hRootKey) {
03832 for (i = 0;; i++) {
03833 status = db_enum_key(hDB, hRootKey, i, &hKey);
03834 if (status == DB_NO_MORE_SUBKEYS)
03835 break;
03836
03837 db_get_key(hDB, hKey, &key);
03838
03839
03840 if (key.type != TID_KEY)
03841 continue;
03842
03843 size = sizeof(program_info);
03844 status = db_get_record(hDB, hKey, &program_info, &size, 0);
03845 if (status != DB_SUCCESS) {
03846 cm_msg(MERROR, "cm_transition", "Cannot get program info record");
03847 continue;
03848 }
03849
03850 if (program_info.auto_stop)
03851 cm_shutdown(key.name, FALSE);
03852 }
03853 }
03854 }
03855
03856
03857
03858 i = 0;
03859 db_set_value(hDB, 0, "/Runinfo/Transition in progress", &i, sizeof(INT), 1, TID_INT);
03860
03861 if (errstr != NULL)
03862 strlcpy(errstr, "Success", errstr_size);
03863
03864 return CM_SUCCESS;
03865 }
03866
03867 INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag,
03868 INT debug_flag)
03869 {
03870 int status;
03871
03872 status = cm_transition1(transition, run_number, errstr, errstr_size, async_flag, debug_flag);
03873
03874 if (transition == TR_START && status != CM_SUCCESS) {
03875 cm_msg(MERROR, "cm_transition", "Could not start a run: cm_transition() status %d, message \'%s\'",
03876 status, errstr);
03877 cm_transition1(TR_STARTABORT, run_number, NULL, 0, async_flag, debug_flag);
03878 }
03879
03880 return status;
03881 }
03882
03883
03884
03885
03886 #ifndef DOXYGEN_SHOULD_SKIP_THIS
03887
03888
03889 INT cm_dispatch_ipc(char *message, int s)
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908 {
03909 if (message[0] == 'O') {
03910 HNDLE hDB, hKey;
03911 sscanf(message + 2, "%d %d", &hDB, &hKey);
03912 return db_update_record(hDB, hKey, s);
03913 }
03914
03915
03916 if (message[0] == 'B' && message[2] != ' ') {
03917 char str[80];
03918
03919 strcpy(str, message + 2);
03920 if (strchr(str, ' '))
03921 *strchr(str, ' ') = 0;
03922
03923 if (s)
03924 return bm_notify_client(str, s);
03925 else
03926 return bm_push_event(str);
03927 }
03928
03929 return CM_SUCCESS;
03930 }
03931
03932
03933 static BOOL _ctrlc_pressed = FALSE;
03934
03935 void cm_ctrlc_handler(int sig)
03936 {
03937 int i;
03938
03939 i = sig;
03940
03941 if (_ctrlc_pressed) {
03942 printf("Received 2nd break. Hard abort.\n");
03943 exit(0);
03944 }
03945 printf("Received break. Aborting...\n");
03946 _ctrlc_pressed = TRUE;
03947
03948 ss_ctrlc_handler(cm_ctrlc_handler);
03949 }
03950
03951 BOOL cm_is_ctrlc_pressed()
03952 {
03953 return _ctrlc_pressed;
03954 }
03955
03956 void cm_ack_ctrlc_pressed()
03957 {
03958 _ctrlc_pressed = FALSE;
03959 }
03960
03961
03962
03963 #endif
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979 INT cm_yield(INT millisec)
03980 {
03981 INT status;
03982 BOOL bMore;
03983 static DWORD last_checked = 0;
03984
03985
03986 if (_ctrlc_pressed)
03987 return RPC_SHUTDOWN;
03988
03989
03990 if (rpc_is_remote()) {
03991 bMore = bm_poll_event(TRUE);
03992 if (bMore)
03993 status = ss_suspend(0, 0);
03994 else
03995 status = ss_suspend(millisec, 0);
03996
03997 return status;
03998 }
03999
04000
04001 if (!rpc_is_remote() && ss_time() - last_checked > 10) {
04002 al_check();
04003 last_checked = ss_time();
04004 }
04005
04006 bMore = bm_check_buffers();
04007
04008 if (bMore) {
04009
04010 status = ss_suspend(0, 0);
04011 } else {
04012
04013 bm_mark_read_waiting(TRUE);
04014
04015 status = ss_suspend(millisec, 0);
04016
04017
04018 bm_mark_read_waiting(FALSE);
04019 }
04020
04021 return status;
04022 }
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032 INT cm_execute(const char *command, char *result, INT bufsize)
04033 {
04034 char str[256];
04035 INT n;
04036 int fh;
04037
04038 if (rpc_is_remote())
04039 return rpc_call(RPC_CM_EXECUTE, command, result, bufsize);
04040
04041 if (bufsize > 0) {
04042 strcpy(str, command);
04043 sprintf(str, "%s > %d.tmp", command, ss_getpid());
04044
04045 system(str);
04046
04047 sprintf(str, "%d.tmp", ss_getpid());
04048 fh = open(str, O_RDONLY, 0644);
04049 result[0] = 0;
04050 if (fh) {
04051 n = read(fh, result, bufsize - 1);
04052 result[MAX(0, n)] = 0;
04053 close(fh);
04054 }
04055 remove(str);
04056 } else
04057 system(command);
04058
04059 return CM_SUCCESS;
04060 }
04061
04062
04063
04064
04065 #ifndef DOXYGEN_SHOULD_SKIP_THIS
04066
04067
04068 INT cm_register_function(INT id, INT(*func) (INT, void **))
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088 {
04089 HNDLE hDB, hKey;
04090 INT status;
04091 char str[80];
04092
04093 status = rpc_register_function(id, func);
04094 if (status != RPC_SUCCESS)
04095 return status;
04096
04097 cm_get_experiment_database(&hDB, &hKey);
04098
04099
04100 status = 1;
04101 sprintf(str, "RPC/%d", id);
04102
04103 db_set_mode(hDB, hKey, MODE_READ | MODE_WRITE, TRUE);
04104 status = db_set_value(hDB, hKey, str, &status, sizeof(BOOL), 1, TID_BOOL);
04105 db_set_mode(hDB, hKey, MODE_READ, TRUE);
04106
04107 if (status != DB_SUCCESS)
04108 return status;
04109
04110 return CM_SUCCESS;
04111 }
04112
04113
04114
04115 #endif
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140 INT bm_match_event(short int event_id, short int trigger_mask, EVENT_HEADER * pevent)
04141 {
04142 if ((pevent->event_id & 0xF000) == EVENTID_FRAG1 || (pevent->event_id & 0xF000) == EVENTID_FRAG)
04143
04144 return ((event_id == EVENTID_ALL ||
04145 event_id == (pevent->event_id & 0x0FFF)) &&
04146 (trigger_mask == TRIGGER_ALL || (trigger_mask & pevent->trigger_mask)));
04147
04148 return ((event_id == EVENTID_ALL ||
04149 event_id == pevent->event_id) && (trigger_mask == TRIGGER_ALL
04150 || (trigger_mask & pevent->trigger_mask)));
04151 }
04152
04153
04154
04155
04156
04157 void bm_remove_client_locked(BUFFER_HEADER * pheader, int j)
04158 {
04159 int k, nc;
04160 BUFFER_CLIENT *pbctmp;
04161
04162
04163 memset(&(pheader->client[j]), 0, sizeof(BUFFER_CLIENT));
04164
04165
04166 for (k = MAX_CLIENTS - 1; k >= 0; k--)
04167 if (pheader->client[k].pid != 0)
04168 break;
04169 pheader->max_client_index = k + 1;
04170
04171
04172 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
04173 if (pheader->client[k].pid != 0)
04174 nc++;
04175 pheader->num_clients = nc;
04176
04177
04178 pbctmp = pheader->client;
04179
04180 for (k = 0; k < pheader->max_client_index; k++, pbctmp++)
04181 if (pbctmp->pid && (pbctmp->write_wait || pbctmp->read_wait))
04182 ss_resume(pbctmp->port, "B ");
04183 }
04184
04185
04186
04187
04188
04189 static void bm_cleanup(const char *who, DWORD actual_time, BOOL wrong_interval)
04190 {
04191 BUFFER_HEADER *pheader;
04192 BUFFER_CLIENT *pbclient;
04193 int i, j;
04194 char str[256];
04195
04196
04197 for (i = 0; i < _buffer_entries; i++)
04198 if (_buffer[i].attached) {
04199
04200 pheader = _buffer[i].buffer_header;
04201 pbclient = pheader->client;
04202 pbclient[bm_validate_client_index(&_buffer[i])].last_activity = actual_time;
04203
04204
04205 if (wrong_interval)
04206 continue;
04207
04208
04209 for (j = 0; j < pheader->max_client_index; j++, pbclient++) {
04210
04211 #ifdef OS_UNIX
04212 #ifdef ESRCH
04213 if (pbclient->pid) {
04214 errno = 0;
04215 kill(pbclient->pid, 0);
04216 if (errno == ESRCH) {
04217 cm_msg(MINFO, "bm_cleanup",
04218 "Client \'%s\' on buffer \'%s\' removed by %s because client pid %d does not exist",
04219 pbclient->name, pheader->name, who, pbclient->pid);
04220
04221 bm_lock_buffer(i + 1);
04222 bm_remove_client_locked(pheader, j);
04223 bm_unlock_buffer(i + 1);
04224 continue;
04225 }
04226 }
04227 #endif
04228 #endif
04229
04230
04231 if (pbclient->pid && pbclient->watchdog_timeout > 0 &&
04232 actual_time > pbclient->last_activity &&
04233 actual_time - pbclient->last_activity > pbclient->watchdog_timeout) {
04234 bm_lock_buffer(i + 1);
04235 str[0] = 0;
04236
04237
04238 actual_time = ss_millitime();
04239 if (pbclient->pid && pbclient->watchdog_timeout > 0 &&
04240 actual_time > pbclient->last_activity &&
04241 actual_time - pbclient->last_activity > pbclient->watchdog_timeout) {
04242 sprintf(str,
04243 "Client \'%s\' on buffer \'%s\' removed by %s (idle %1.1lfs,TO %1.0lfs)",
04244 pbclient->name, pheader->name, who,
04245 (actual_time - pbclient->last_activity) / 1000.0,
04246 pbclient->watchdog_timeout / 1000.0);
04247
04248 bm_remove_client_locked(pheader, j);
04249 }
04250
04251 bm_unlock_buffer(i + 1);
04252
04253
04254 if (str[0])
04255 cm_msg(MINFO, "bm_cleanup", str);
04256 }
04257 }
04258 }
04259 }
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309 INT bm_open_buffer(char *buffer_name, INT buffer_size, INT * buffer_handle)
04310 {
04311 INT status;
04312
04313 if (rpc_is_remote()) {
04314 status = rpc_call(RPC_BM_OPEN_BUFFER, buffer_name, buffer_size, buffer_handle);
04315 bm_mark_read_waiting(TRUE);
04316 return status;
04317 }
04318 #ifdef LOCAL_ROUTINES
04319 {
04320 INT i, handle, size;
04321 BUFFER_CLIENT *pclient;
04322 BOOL shm_created;
04323 HNDLE shm_handle;
04324 BUFFER_HEADER *pheader;
04325 HNDLE hDB, odb_key;
04326 char odb_path[256];
04327 void *p;
04328
04329 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
04330
04331
04332 strlcpy(odb_path, "/Experiment/Buffer sizes/", sizeof(odb_path));
04333 strlcat(odb_path, buffer_name, sizeof(odb_path));
04334
04335 status = cm_get_experiment_database(&hDB, &odb_key);
04336 assert(status == SUCCESS);
04337 size = sizeof(INT);
04338 status = db_get_value(hDB, 0, odb_path, &buffer_size, &size, TID_DWORD, TRUE);
04339
04340 if (buffer_size <= 0 || buffer_size > 1 * 1024 * 1024 * 1024) {
04341 cm_msg(MERROR, "bm_open_buffer", "invalid buffer size %d", buffer_size);
04342 return BM_INVALID_PARAM;
04343 }
04344
04345 if (!buffer_name[0]) {
04346 cm_msg(MERROR, "bm_open_buffer", "cannot open buffer with zero name");
04347 return BM_INVALID_PARAM;
04348 }
04349
04350
04351 if (_buffer_entries == 0) {
04352 _buffer = (BUFFER *) M_MALLOC(sizeof(BUFFER));
04353 memset(_buffer, 0, sizeof(BUFFER));
04354 if (_buffer == NULL) {
04355 *buffer_handle = 0;
04356 return BM_NO_MEMORY;
04357 }
04358
04359 _buffer_entries = 1;
04360 i = 0;
04361 } else {
04362
04363 for (i = 0; i < _buffer_entries; i++)
04364 if (_buffer[i].attached && equal_ustring(_buffer[i].buffer_header->name, buffer_name)) {
04365 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
04366 _buffer[i].index != rpc_get_server_acception())
04367 continue;
04368
04369 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE && _buffer[i].index != ss_gettid())
04370 continue;
04371
04372 *buffer_handle = i + 1;
04373 return BM_SUCCESS;
04374 }
04375
04376
04377 for (i = 0; i < _buffer_entries; i++)
04378 if (!_buffer[i].attached)
04379 break;
04380
04381
04382 if (i == _buffer_entries) {
04383 _buffer = (BUFFER *) realloc(_buffer, sizeof(BUFFER) * (_buffer_entries + 1));
04384 memset(&_buffer[_buffer_entries], 0, sizeof(BUFFER));
04385
04386 _buffer_entries++;
04387 if (_buffer == NULL) {
04388 _buffer_entries--;
04389 *buffer_handle = 0;
04390 return BM_NO_MEMORY;
04391 }
04392 }
04393 }
04394
04395 handle = i;
04396
04397 if (strlen(buffer_name) >= NAME_LENGTH)
04398 buffer_name[NAME_LENGTH] = 0;
04399
04400
04401 #ifdef MAX_SHM_SIZE
04402 if (buffer_size + sizeof(BUFFER_HEADER) > MAX_SHM_SIZE)
04403 buffer_size = MAX_SHM_SIZE - sizeof(BUFFER_HEADER);
04404 #endif
04405
04406
04407
04408
04409 status = ss_shm_open(buffer_name, sizeof(BUFFER_HEADER) + buffer_size, &p, &shm_handle, FALSE);
04410 _buffer[handle].buffer_header = (BUFFER_HEADER *) p;
04411
04412 if (status != SS_SUCCESS && status != SS_CREATED) {
04413 *buffer_handle = 0;
04414 _buffer_entries--;
04415 return BM_NO_SHM;
04416 }
04417
04418 pheader = _buffer[handle].buffer_header;
04419
04420 shm_created = (status == SS_CREATED);
04421
04422 if (shm_created) {
04423
04424 memset(pheader, 0, sizeof(BUFFER_HEADER) + buffer_size);
04425
04426 strcpy(pheader->name, buffer_name);
04427 pheader->size = buffer_size;
04428 } else {
04429
04430 if (pheader->size != buffer_size) {
04431 cm_msg(MERROR, "bm_open_buffer", "Requested buffer size (%d) differs from existing size (%d)",
04432 buffer_size, pheader->size);
04433 *buffer_handle = 0;
04434 _buffer_entries--;
04435 return BM_MEMSIZE_MISMATCH;
04436 }
04437 }
04438
04439
04440 status = ss_semaphore_create(buffer_name, &(_buffer[handle].semaphore));
04441 if (status != SS_CREATED && status != SS_SUCCESS) {
04442 *buffer_handle = 0;
04443 _buffer_entries--;
04444 return BM_NO_SEMAPHORE;
04445 }
04446
04447
04448 bm_lock_buffer(handle + 1);
04449
04450
04451
04452
04453
04454
04455
04456 for (i = 0; i < MAX_CLIENTS; i++)
04457 if (pheader->client[i].pid == 0)
04458 break;
04459
04460 if (i == MAX_CLIENTS) {
04461 bm_unlock_buffer(handle + 1);
04462 *buffer_handle = 0;
04463 cm_msg(MERROR, "bm_open_buffer", "maximum number of clients exceeded");
04464 return BM_NO_SLOT;
04465 }
04466
04467
04468 _buffer[handle].client_index = i;
04469
04470
04471
04472
04473
04474 pheader->num_clients++;
04475 if (i + 1 > pheader->max_client_index)
04476 pheader->max_client_index = i + 1;
04477
04478
04479 pclient = &pheader->client[i];
04480
04481 memset(pclient, 0, sizeof(BUFFER_CLIENT));
04482
04483 cm_get_client_info(pclient->name);
04484 if (pclient->name[0] == 0)
04485 strcpy(pclient->name, "unknown");
04486 pclient->pid = ss_getpid();
04487
04488 ss_suspend_get_port(&pclient->port);
04489
04490 pclient->read_pointer = pheader->write_pointer;
04491 pclient->last_activity = ss_millitime();
04492
04493 cm_get_watchdog_params(NULL, &pclient->watchdog_timeout);
04494
04495 bm_unlock_buffer(handle + 1);
04496
04497
04498 _buffer[handle].buffer_data = _buffer[handle].buffer_header + 1;
04499 _buffer[handle].attached = TRUE;
04500 _buffer[handle].shm_handle = shm_handle;
04501 _buffer[handle].callback = FALSE;
04502
04503
04504 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE)
04505 _buffer[handle].index = rpc_get_server_acception();
04506 else
04507 _buffer[handle].index = ss_gettid();
04508
04509 *buffer_handle = (handle + 1);
04510
04511
04512 bm_init_buffer_counters(handle + 1);
04513
04514
04515 ss_suspend_set_dispatch(CH_IPC, 0, (int (*)(void)) cm_dispatch_ipc);
04516
04517 bm_cleanup("bm_open_buffer", ss_millitime(), FALSE);
04518
04519 if (shm_created)
04520 return BM_CREATED;
04521 }
04522 #endif
04523
04524 return BM_SUCCESS;
04525 }
04526
04527
04528
04529
04530
04531
04532
04533 INT bm_close_buffer(INT buffer_handle)
04534 {
04535 if (rpc_is_remote())
04536 return rpc_call(RPC_BM_CLOSE_BUFFER, buffer_handle);
04537
04538 #ifdef LOCAL_ROUTINES
04539 {
04540 BUFFER_CLIENT *pclient;
04541 BUFFER_HEADER *pheader;
04542 INT i, j, idx, destroy_flag;
04543
04544 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
04545 cm_msg(MERROR, "bm_close_buffer", "invalid buffer handle %d", buffer_handle);
04546 return BM_INVALID_HANDLE;
04547 }
04548
04549
04550 if (!_buffer[buffer_handle - 1].attached) {
04551 return BM_SUCCESS;
04552 }
04553
04554
04555
04556
04557
04558
04559
04560 idx = bm_validate_client_index(&_buffer[buffer_handle - 1]);
04561 pheader = _buffer[buffer_handle - 1].buffer_header;
04562
04563 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
04564 _buffer[buffer_handle - 1].index != rpc_get_server_acception())
04565 return BM_INVALID_HANDLE;
04566
04567 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE
04568 && _buffer[buffer_handle - 1].index != ss_gettid())
04569 return BM_INVALID_HANDLE;
04570
04571 if (!_buffer[buffer_handle - 1].attached) {
04572
04573
04574 return BM_SUCCESS;
04575 }
04576
04577
04578 for (i = 0; i < _request_list_entries; i++)
04579 if (_request_list[i].buffer_handle == buffer_handle)
04580 bm_delete_request(i);
04581
04582
04583 bm_lock_buffer(buffer_handle);
04584
04585
04586 _buffer[buffer_handle - 1].attached = FALSE;
04587
04588
04589 memset(&(pheader->client[idx]), 0, sizeof(BUFFER_CLIENT));
04590
04591
04592 for (i = MAX_CLIENTS - 1; i >= 0; i--)
04593 if (pheader->client[i].pid != 0)
04594 break;
04595 pheader->max_client_index = i + 1;
04596
04597
04598 for (i = MAX_CLIENTS - 1, j = 0; i >= 0; i--)
04599 if (pheader->client[i].pid != 0)
04600 j++;
04601 pheader->num_clients = j;
04602
04603 destroy_flag = (pheader->num_clients == 0);
04604
04605
04606 if (_buffer[buffer_handle - 1].read_cache_size > 0)
04607 M_FREE(_buffer[buffer_handle - 1].read_cache);
04608 if (_buffer[buffer_handle - 1].write_cache_size > 0)
04609 M_FREE(_buffer[buffer_handle - 1].write_cache);
04610
04611
04612 pclient = pheader->client;
04613
04614 for (i = 0; i < pheader->max_client_index; i++, pclient++)
04615 if (pclient->pid && (pclient->write_wait || pclient->read_wait))
04616 ss_resume(pclient->port, "B ");
04617
04618
04619 ss_shm_close(pheader->name, _buffer[buffer_handle - 1].buffer_header,
04620 _buffer[buffer_handle - 1].shm_handle, destroy_flag);
04621
04622
04623 bm_unlock_buffer(buffer_handle);
04624
04625
04626 ss_semaphore_delete(_buffer[buffer_handle - 1].semaphore, destroy_flag);
04627
04628
04629 if (buffer_handle == _buffer_entries)
04630 _buffer_entries--;
04631
04632 if (_buffer_entries > 0)
04633 _buffer = (BUFFER *) realloc(_buffer, sizeof(BUFFER) * (_buffer_entries));
04634 else {
04635 M_FREE(_buffer);
04636 _buffer = NULL;
04637 }
04638 }
04639 #endif
04640
04641 return BM_SUCCESS;
04642 }
04643
04644
04645
04646
04647
04648
04649 INT bm_close_all_buffers(void)
04650 {
04651 if (rpc_is_remote())
04652 return rpc_call(RPC_BM_CLOSE_ALL_BUFFERS);
04653
04654 #ifdef LOCAL_ROUTINES
04655 {
04656 INT i;
04657
04658 for (i = _buffer_entries; i > 0; i--)
04659 bm_close_buffer(i);
04660 }
04661 #endif
04662
04663 return BM_SUCCESS;
04664 }
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675 #ifdef LOCAL_ROUTINES
04676
04677
04678
04679
04680
04681
04682
04683 void cm_watchdog(int dummy)
04684 {
04685 DATABASE_HEADER *pdbheader;
04686 DATABASE_CLIENT *pdbclient;
04687 KEY *pkey;
04688 DWORD actual_time, interval;
04689 INT client_pid;
04690 INT i, j, k, nc, status;
04691 BOOL bDeleted, time_changed, wrong_interval;
04692 char str[256];
04693
04694 i = dummy;
04695
04696
04697 if (!_call_watchdog)
04698 return;
04699
04700
04701 ss_set_async_flag(TRUE);
04702
04703
04704
04705 actual_time = ss_millitime();
04706 if (_watchdog_last_called == 0)
04707 _watchdog_last_called = actual_time - WATCHDOG_INTERVAL;
04708 interval = actual_time - _watchdog_last_called;
04709
04710
04711 time_changed = interval > 600000;
04712 wrong_interval = interval < 0.8 * WATCHDOG_INTERVAL || interval > 1.2 * WATCHDOG_INTERVAL;
04713
04714 if (time_changed)
04715 cm_msg(MINFO, "cm_watchdog",
04716 "System time has been changed! last:%dms now:%dms delta:%dms",
04717 _watchdog_last_called, actual_time, interval);
04718
04719 bm_cleanup("cm_watchdog", actual_time, wrong_interval);
04720
04721
04722 for (i = 0; i < _database_entries; i++)
04723 if (_database[i].attached) {
04724
04725 pdbheader = _database[i].database_header;
04726 pdbclient = pdbheader->client;
04727 pdbclient[_database[i].client_index].last_activity = actual_time;
04728
04729
04730 if (wrong_interval)
04731 continue;
04732
04733
04734 for (j = 0; j < pdbheader->max_client_index; j++, pdbclient++)
04735
04736 if (pdbclient->pid && pdbclient->watchdog_timeout > 0 &&
04737 actual_time - pdbclient->last_activity > pdbclient->watchdog_timeout) {
04738 client_pid = pdbclient->pid;
04739 bDeleted = FALSE;
04740 db_lock_database(i + 1);
04741 str[0] = 0;
04742
04743
04744 actual_time = ss_millitime();
04745 if (pdbclient->pid && pdbclient->watchdog_timeout &&
04746 actual_time > pdbclient->last_activity &&
04747 actual_time - pdbclient->last_activity > pdbclient->watchdog_timeout) {
04748 sprintf(str,
04749 "Client \'%s\' (PID %d) on buffer \'%s\' removed by cm_watchdog (idle %1.1lfs,TO %1.0lfs)",
04750 pdbclient->name, client_pid, pdbheader->name,
04751 (actual_time - pdbclient->last_activity) / 1000.0,
04752 pdbclient->watchdog_timeout / 1000.0);
04753
04754
04755 for (k = 0; k < pdbclient->max_index; k++)
04756 if (pdbclient->open_record[k].handle) {
04757 pkey = (KEY *) ((char *) pdbheader + pdbclient->open_record[k].handle);
04758 if (pkey->notify_count > 0)
04759 pkey->notify_count--;
04760
04761 if (pdbclient->open_record[k].access_mode & MODE_WRITE)
04762 db_set_mode(i + 1, pdbclient->open_record[k].handle,
04763 (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2);
04764 }
04765
04766
04767 memset(&(pdbheader->client[j]), 0, sizeof(DATABASE_CLIENT));
04768
04769
04770 for (k = MAX_CLIENTS - 1; k >= 0; k--)
04771 if (pdbheader->client[k].pid != 0)
04772 break;
04773 pdbheader->max_client_index = k + 1;
04774
04775
04776 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
04777 if (pdbheader->client[k].pid != 0)
04778 nc++;
04779 pdbheader->num_clients = nc;
04780 bDeleted = TRUE;
04781 }
04782
04783
04784 if (bDeleted) {
04785 status = cm_delete_client_info(i + 1, client_pid);
04786 if (status != CM_SUCCESS)
04787 cm_msg(MERROR, "cm_watchdog",
04788 "cannot delete client info for client \'%s\', pid %d from buffer \'%s\', status %d",
04789 pdbclient->name, client_pid, pdbheader->name, status);
04790 }
04791
04792 db_unlock_database(i + 1);
04793
04794
04795 if (str[0])
04796 cm_msg(MINFO, "cm_watchdog", str);
04797 }
04798 }
04799
04800 _watchdog_last_called = actual_time;
04801
04802 ss_set_async_flag(FALSE);
04803
04804
04805 if (_call_watchdog)
04806 ss_alarm(WATCHDOG_INTERVAL, cm_watchdog);
04807 }
04808
04809
04810
04811
04812
04813
04814
04815
04816 INT cm_enable_watchdog(BOOL flag)
04817 {
04818 static INT timeout = DEFAULT_WATCHDOG_TIMEOUT;
04819 static BOOL call_flag = FALSE;
04820
04821 if (flag) {
04822 if (call_flag)
04823 cm_set_watchdog_params(TRUE, timeout);
04824 } else {
04825 call_flag = _call_watchdog;
04826 timeout = _watchdog_timeout;
04827 if (call_flag)
04828 cm_set_watchdog_params(FALSE, 0);
04829 }
04830
04831 return CM_SUCCESS;
04832 }
04833
04834 #endif
04835
04836
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846 INT cm_shutdown(const char *name, BOOL bUnique)
04847 {
04848 INT status, return_status, i, size;
04849 HNDLE hDB, hKeyClient, hKey, hSubkey, hKeyTmp, hConn;
04850 KEY key;
04851 char client_name[NAME_LENGTH], remote_host[HOST_NAME_LENGTH];
04852 INT port;
04853 DWORD start_time;
04854
04855 cm_get_experiment_database(&hDB, &hKeyClient);
04856
04857 status = db_find_key(hDB, 0, "System/Clients", &hKey);
04858 if (status != DB_SUCCESS)
04859 return DB_NO_KEY;
04860
04861 return_status = CM_NO_CLIENT;
04862
04863
04864 for (i = 0;; i++) {
04865 status = db_enum_key(hDB, hKey, i, &hSubkey);
04866 if (status == DB_NO_MORE_SUBKEYS)
04867 break;
04868
04869
04870 if (hSubkey == hKeyClient)
04871 continue;
04872
04873 if (status == DB_SUCCESS) {
04874 db_get_key(hDB, hSubkey, &key);
04875
04876
04877 size = sizeof(client_name);
04878 db_get_value(hDB, hSubkey, "Name", client_name, &size, TID_STRING, TRUE);
04879
04880 if (!bUnique)
04881 client_name[strlen(name)] = 0;
04882
04883
04884 if (!equal_ustring("all", name) && !equal_ustring(client_name, name))
04885 continue;
04886
04887 size = sizeof(port);
04888 db_get_value(hDB, hSubkey, "Server Port", &port, &size, TID_INT, TRUE);
04889
04890 size = sizeof(remote_host);
04891 db_get_value(hDB, hSubkey, "Host", remote_host, &size, TID_STRING, TRUE);
04892
04893
04894 status = rpc_client_connect(remote_host, port, client_name, &hConn);
04895 if (status != RPC_SUCCESS) {
04896 int client_pid = atoi(key.name);
04897 return_status = CM_NO_CLIENT;
04898 cm_msg(MERROR, "cm_shutdown", "Cannot connect to client \'%s\' on host \'%s\', port %d",
04899 client_name, remote_host, port);
04900 #ifdef SIGKILL
04901 cm_msg(MERROR, "cm_shutdown", "Killing and Deleting client \'%s\' pid %d", client_name,
04902 client_pid);
04903 kill(client_pid, SIGKILL);
04904 status = cm_delete_client_info(hDB, client_pid);
04905 if (status != CM_SUCCESS)
04906 cm_msg(MERROR, "cm_shutdown", "Cannot delete client info for client \'%s\', pid %d, status %d",
04907 name, client_pid, status);
04908 #endif
04909 } else {
04910
04911 rpc_client_disconnect(hConn, TRUE);
04912
04913
04914 start_time = ss_millitime();
04915 do {
04916 ss_sleep(100);
04917 status = db_find_key(hDB, hKey, key.name, &hKeyTmp);
04918 } while (status == DB_SUCCESS && (ss_millitime() - start_time < 5000));
04919
04920 if (status == DB_SUCCESS) {
04921 int client_pid = atoi(key.name);
04922 return_status = CM_NO_CLIENT;
04923 cm_msg(MERROR, "cm_shutdown", "Client \'%s\' not responding to shutdown command", client_name);
04924 #ifdef SIGKILL
04925 cm_msg(MERROR, "cm_shutdown", "Killing and Deleting client \'%s\' pid %d", client_name,
04926 client_pid);
04927 kill(client_pid, SIGKILL);
04928 status = cm_delete_client_info(hDB, client_pid);
04929 if (status != CM_SUCCESS)
04930 cm_msg(MERROR, "cm_shutdown",
04931 "Cannot delete client info for client \'%s\', pid %d, status %d", name, client_pid,
04932 status);
04933 #endif
04934 return_status = CM_NO_CLIENT;
04935 } else {
04936 return_status = CM_SUCCESS;
04937 i--;
04938 }
04939 }
04940 }
04941 }
04942
04943 return return_status;
04944 }
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955 INT cm_exist(const char *name, BOOL bUnique)
04956 {
04957 INT status, i, size;
04958 HNDLE hDB, hKeyClient, hKey, hSubkey;
04959 char client_name[NAME_LENGTH];
04960
04961 if (rpc_is_remote())
04962 return rpc_call(RPC_CM_EXIST, name, bUnique);
04963
04964 cm_get_experiment_database(&hDB, &hKeyClient);
04965
04966 status = db_find_key(hDB, 0, "System/Clients", &hKey);
04967 if (status != DB_SUCCESS)
04968 return DB_NO_KEY;
04969
04970
04971 for (i = 0;; i++) {
04972 status = db_enum_key(hDB, hKey, i, &hSubkey);
04973 if (status == DB_NO_MORE_SUBKEYS)
04974 break;
04975
04976 if (hSubkey == hKeyClient)
04977 continue;
04978
04979 if (status == DB_SUCCESS) {
04980
04981 size = sizeof(client_name);
04982 db_get_value(hDB, hSubkey, "Name", client_name, &size, TID_STRING, TRUE);
04983
04984 if (equal_ustring(client_name, name))
04985 return CM_SUCCESS;
04986
04987 if (!bUnique) {
04988 client_name[strlen(name)] = 0;
04989 if (equal_ustring(client_name, name))
04990 return CM_SUCCESS;
04991 }
04992 }
04993 }
04994
04995 return CM_NO_CLIENT;
04996 }
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033 INT cm_cleanup(const char *client_name, BOOL ignore_timeout)
05034 {
05035 if (rpc_is_remote())
05036 return rpc_call(RPC_CM_CLEANUP, client_name);
05037
05038 #ifdef LOCAL_ROUTINES
05039 {
05040 BUFFER_HEADER *pheader = NULL;
05041 BUFFER_CLIENT *pbclient;
05042 DATABASE_HEADER *pdbheader;
05043 DATABASE_CLIENT *pdbclient;
05044 KEY *pkey;
05045 INT client_pid;
05046 INT i, j, k, status, nc;
05047 BOOL bDeleted;
05048 char str[256];
05049 DWORD interval;
05050 DWORD now = ss_millitime();
05051
05052
05053 for (i = 0; i < _buffer_entries; i++)
05054 if (_buffer[i].attached) {
05055
05056 pheader = _buffer[i].buffer_header;
05057 pbclient = pheader->client;
05058 pbclient[bm_validate_client_index(&_buffer[i])].last_activity = ss_millitime();
05059
05060
05061 for (j = 0; j < pheader->max_client_index; j++, pbclient++)
05062 if (j != _buffer[i].client_index && pbclient->pid &&
05063 (client_name == NULL || client_name[0] == 0
05064 || strncmp(pbclient->name, client_name, strlen(client_name)) == 0)) {
05065 if (ignore_timeout)
05066 interval = 2 * WATCHDOG_INTERVAL;
05067 else
05068 interval = pbclient->watchdog_timeout;
05069
05070
05071 if (interval > 0
05072 && now > pbclient->last_activity && now - pbclient->last_activity > interval) {
05073 bm_lock_buffer(i + 1);
05074 str[0] = 0;
05075
05076
05077 if (interval > 0
05078 && now > pbclient->last_activity && now - pbclient->last_activity > interval) {
05079 sprintf(str,
05080 "Client \'%s\' on \'%s\' removed by cm_cleanup (idle %1.1lfs,TO %1.0lfs)",
05081 pbclient->name, pheader->name,
05082 (ss_millitime() - pbclient->last_activity) / 1000.0, interval / 1000.0);
05083
05084 bm_remove_client_locked(pheader, j);
05085 }
05086
05087 bm_unlock_buffer(i + 1);
05088
05089
05090 if (str[0])
05091 cm_msg(MINFO, "cm_cleanup", str);
05092
05093
05094 j = 0;
05095 }
05096 }
05097 }
05098
05099
05100 for (i = 0; i < _database_entries; i++)
05101 if (_database[i].attached) {
05102
05103 db_lock_database(i + 1);
05104
05105 pdbheader = _database[i].database_header;
05106 pdbclient = pdbheader->client;
05107 pdbclient[_database[i].client_index].last_activity = ss_millitime();
05108
05109
05110 for (j = 0; j < pdbheader->max_client_index; j++, pdbclient++)
05111 if (j != _database[i].client_index && pdbclient->pid &&
05112 (client_name == NULL || client_name[0] == 0
05113 || strncmp(pdbclient->name, client_name, strlen(client_name)) == 0)) {
05114 client_pid = pdbclient->pid;
05115 if (ignore_timeout)
05116 interval = 2 * WATCHDOG_INTERVAL;
05117 else
05118 interval = pdbclient->watchdog_timeout;
05119
05120
05121
05122 if (interval > 0 && ss_millitime() - pdbclient->last_activity > interval) {
05123 bDeleted = FALSE;
05124 str[0] = 0;
05125
05126
05127 if (interval > 0 && ss_millitime() - pdbclient->last_activity > interval) {
05128 sprintf(str,
05129 "Client \'%s\' on \'%s\' removed by cm_cleanup (idle %1.1lfs,TO %1.0lfs)",
05130 pdbclient->name, pdbheader->name,
05131 (ss_millitime() - pdbclient->last_activity) / 1000.0, interval / 1000.0);
05132
05133
05134 for (k = 0; k < pdbclient->max_index; k++)
05135 if (pdbclient->open_record[k].handle) {
05136 pkey = (KEY *) ((char *) pdbheader + pdbclient->open_record[k].handle);
05137 if (pkey->notify_count > 0)
05138 pkey->notify_count--;
05139
05140 if (pdbclient->open_record[k].access_mode & MODE_WRITE)
05141 db_set_mode(i + 1, pdbclient->open_record[k].handle,
05142 (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2);
05143 }
05144
05145
05146 memset(&(pdbheader->client[j]), 0, sizeof(DATABASE_CLIENT));
05147
05148
05149 for (k = MAX_CLIENTS - 1; k >= 0; k--)
05150 if (pdbheader->client[k].pid != 0)
05151 break;
05152 pdbheader->max_client_index = k + 1;
05153
05154
05155 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
05156 if (pheader->client[k].pid != 0)
05157 nc++;
05158 pdbheader->num_clients = nc;
05159
05160 bDeleted = TRUE;
05161 }
05162
05163
05164
05165 if (bDeleted) {
05166 db_unlock_database(i + 1);
05167
05168
05169 cm_msg(MINFO, "cm_cleanup", str);
05170
05171 status = cm_delete_client_info(i + 1, client_pid);
05172 if (status != CM_SUCCESS)
05173 cm_msg(MERROR, "cm_cleanup", "cannot delete client info");
05174
05175
05176 db_lock_database(i + 1);
05177 pdbheader = _database[i].database_header;
05178 pdbclient = pdbheader->client;
05179
05180
05181 j = 0;
05182 }
05183 }
05184 }
05185
05186 db_unlock_database(i + 1);
05187 }
05188
05189 }
05190 #endif
05191
05192 return CM_SUCCESS;
05193 }
05194
05195
05196 #ifndef DOXYGEN_SHOULD_SKIP_THIS
05197
05198
05199 INT bm_get_buffer_info(INT buffer_handle, BUFFER_HEADER * buffer_header)
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221 {
05222 if (rpc_is_remote())
05223 return rpc_call(RPC_BM_GET_BUFFER_INFO, buffer_handle, buffer_header);
05224
05225 #ifdef LOCAL_ROUTINES
05226
05227 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05228 cm_msg(MERROR, "bm_get_buffer_info", "invalid buffer handle %d", buffer_handle);
05229 return BM_INVALID_HANDLE;
05230 }
05231
05232 if (!_buffer[buffer_handle - 1].attached) {
05233 cm_msg(MERROR, "bm_get_buffer_info", "invalid buffer handle %d", buffer_handle);
05234 return BM_INVALID_HANDLE;
05235 }
05236
05237 bm_lock_buffer(buffer_handle);
05238
05239 memcpy(buffer_header, _buffer[buffer_handle - 1].buffer_header, sizeof(BUFFER_HEADER));
05240
05241 bm_unlock_buffer(buffer_handle);
05242
05243 #endif
05244
05245 return BM_SUCCESS;
05246 }
05247
05248
05249 INT bm_get_buffer_level(INT buffer_handle, INT * n_bytes)
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268 {
05269 if (rpc_is_remote())
05270 return rpc_call(RPC_BM_GET_BUFFER_LEVEL, buffer_handle, n_bytes);
05271
05272 #ifdef LOCAL_ROUTINES
05273 {
05274 BUFFER *pbuf;
05275 BUFFER_HEADER *pheader;
05276 BUFFER_CLIENT *pclient;
05277
05278 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05279 cm_msg(MERROR, "bm_get_buffer_level", "invalid buffer handle %d", buffer_handle);
05280 return BM_INVALID_HANDLE;
05281 }
05282
05283 pbuf = &_buffer[buffer_handle - 1];
05284 pheader = pbuf->buffer_header;
05285
05286 if (!pbuf->attached) {
05287 cm_msg(MERROR, "bm_get_buffer_level", "invalid buffer handle %d", buffer_handle);
05288 return BM_INVALID_HANDLE;
05289 }
05290
05291 bm_lock_buffer(buffer_handle);
05292
05293 pclient = &(pheader->client[bm_validate_client_index(pbuf)]);
05294
05295 *n_bytes = pheader->write_pointer - pclient->read_pointer;
05296 if (*n_bytes < 0)
05297 *n_bytes += pheader->size;
05298
05299 bm_unlock_buffer(buffer_handle);
05300
05301
05302 if (pbuf->read_cache_wp > pbuf->read_cache_rp)
05303 *n_bytes += pbuf->read_cache_wp - pbuf->read_cache_rp;
05304 }
05305 #endif
05306
05307 return BM_SUCCESS;
05308 }
05309
05310
05311
05312 #ifdef LOCAL_ROUTINES
05313
05314
05315 INT bm_lock_buffer(INT buffer_handle)
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332 {
05333 int status;
05334
05335 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05336 cm_msg(MERROR, "bm_lock_buffer", "invalid buffer handle %d", buffer_handle);
05337 return BM_INVALID_HANDLE;
05338 }
05339
05340 status = ss_semaphore_wait_for(_buffer[buffer_handle - 1].semaphore, 5 * 60 * 1000);
05341
05342 if (status != SS_SUCCESS) {
05343 cm_msg(MERROR, "bm_lock_buffer",
05344 "Cannot lock buffer handle %d, ss_semaphore_wait_for() status %d", buffer_handle, status);
05345 abort();
05346 return BM_INVALID_HANDLE;
05347 }
05348
05349 return BM_SUCCESS;
05350 }
05351
05352
05353 INT bm_unlock_buffer(INT buffer_handle)
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370 {
05371 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05372 cm_msg(MERROR, "bm_unlock_buffer", "invalid buffer handle %d", buffer_handle);
05373 return BM_INVALID_HANDLE;
05374 }
05375
05376 ss_semaphore_release(_buffer[buffer_handle - 1].semaphore);
05377 return BM_SUCCESS;
05378 }
05379
05380 #endif
05381
05382
05383 INT bm_init_buffer_counters(INT buffer_handle)
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402 {
05403 if (rpc_is_remote())
05404 return rpc_call(RPC_BM_INIT_BUFFER_COUNTERS, buffer_handle);
05405
05406 #ifdef LOCAL_ROUTINES
05407
05408 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05409 cm_msg(MERROR, "bm_init_buffer_counters", "invalid buffer handle %d", buffer_handle);
05410 return BM_INVALID_HANDLE;
05411 }
05412
05413 if (!_buffer[buffer_handle - 1].attached) {
05414 cm_msg(MERROR, "bm_init_buffer_counters", "invalid buffer handle %d", buffer_handle);
05415 return BM_INVALID_HANDLE;
05416 }
05417
05418 _buffer[buffer_handle - 1].buffer_header->num_in_events = 0;
05419 _buffer[buffer_handle - 1].buffer_header->num_out_events = 0;
05420
05421 #endif
05422
05423 return BM_SUCCESS;
05424 }
05425
05426
05427 #endif
05428
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461 INT bm_set_cache_size(INT buffer_handle, INT read_size, INT write_size)
05462
05463 {
05464 if (rpc_is_remote())
05465 return rpc_call(RPC_BM_SET_CACHE_SIZE, buffer_handle, read_size, write_size);
05466
05467 #ifdef LOCAL_ROUTINES
05468 {
05469 BUFFER *pbuf;
05470
05471 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05472 cm_msg(MERROR, "bm_set_cache_size", "invalid buffer handle %d", buffer_handle);
05473 return BM_INVALID_HANDLE;
05474 }
05475
05476 if (!_buffer[buffer_handle - 1].attached) {
05477 cm_msg(MERROR, "bm_set_cache_size", "invalid buffer handle %d", buffer_handle);
05478 return BM_INVALID_HANDLE;
05479 }
05480
05481 if (read_size < 0 || read_size > 1E6) {
05482 cm_msg(MERROR, "bm_set_cache_size", "invalid read chache size");
05483 return BM_INVALID_PARAM;
05484 }
05485
05486 if (write_size < 0 || write_size > 1E6) {
05487 cm_msg(MERROR, "bm_set_cache_size", "invalid write chache size");
05488 return BM_INVALID_PARAM;
05489 }
05490
05491
05492 pbuf = &_buffer[buffer_handle - 1];
05493
05494 if (pbuf->read_cache_size > 0)
05495 M_FREE(pbuf->read_cache);
05496
05497 if (read_size > 0) {
05498 pbuf->read_cache = (char *) M_MALLOC(read_size);
05499 if (pbuf->read_cache == NULL) {
05500 cm_msg(MERROR, "bm_set_cache_size", "not enough memory to allocate cache buffer");
05501 return BM_NO_MEMORY;
05502 }
05503 }
05504
05505 pbuf->read_cache_size = read_size;
05506 pbuf->read_cache_rp = pbuf->read_cache_wp = 0;
05507
05508
05509 if (pbuf->write_cache_size > 0)
05510 M_FREE(pbuf->write_cache);
05511
05512 if (write_size > 0) {
05513 pbuf->write_cache = (char *) M_MALLOC(write_size);
05514 if (pbuf->write_cache == NULL) {
05515 cm_msg(MERROR, "bm_set_cache_size", "not enough memory to allocate cache buffer");
05516 return BM_NO_MEMORY;
05517 }
05518 }
05519
05520 pbuf->write_cache_size = write_size;
05521 pbuf->write_cache_rp = pbuf->write_cache_wp = 0;
05522
05523 }
05524 #endif
05525
05526 return BM_SUCCESS;
05527 }
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556 INT bm_compose_event(EVENT_HEADER * event_header, short int event_id, short int trigger_mask, DWORD size,
05557 DWORD serial)
05558 {
05559 event_header->event_id = event_id;
05560 event_header->trigger_mask = trigger_mask;
05561 event_header->data_size = size;
05562 event_header->time_stamp = ss_time();
05563 event_header->serial_number = serial;
05564
05565 return BM_SUCCESS;
05566 }
05567
05568
05569
05570 #ifndef DOXYGEN_SHOULD_SKIP_THIS
05571
05572
05573 INT bm_add_event_request(INT buffer_handle, short int event_id,
05574 short int trigger_mask,
05575 INT sampling_type, void (*func) (HNDLE, HNDLE, EVENT_HEADER *, void *),
05576 INT request_id)
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616 {
05617 if (rpc_is_remote())
05618 return rpc_call(RPC_BM_ADD_EVENT_REQUEST, buffer_handle, event_id,
05619 trigger_mask, sampling_type, (INT) (POINTER_T) func, request_id);
05620
05621 #ifdef LOCAL_ROUTINES
05622 {
05623 INT i;
05624 BUFFER_CLIENT *pclient;
05625
05626 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05627 cm_msg(MERROR, "bm_add_event_request", "invalid buffer handle %d", buffer_handle);
05628 return BM_INVALID_HANDLE;
05629 }
05630
05631 if (!_buffer[buffer_handle - 1].attached) {
05632 cm_msg(MERROR, "bm_add_event_request", "invalid buffer handle %d", buffer_handle);
05633 return BM_INVALID_HANDLE;
05634 }
05635
05636
05637 if (func == NULL && _buffer[buffer_handle - 1].callback) {
05638 cm_msg(MERROR, "bm_add_event_request", "mixing callback/non callback requests not possible");
05639 return BM_INVALID_MIXING;
05640 }
05641
05642
05643 if (sampling_type == GET_RECENT && _buffer[buffer_handle - 1].read_cache_size > 0)
05644 return BM_INVALID_PARAM;
05645
05646
05647 pclient = &(_buffer[buffer_handle - 1].buffer_header->
05648 client[bm_validate_client_index(&_buffer[buffer_handle - 1])]);
05649
05650
05651 bm_lock_buffer(buffer_handle);
05652
05653
05654 for (i = 0; i < MAX_EVENT_REQUESTS; i++)
05655 if (!pclient->event_request[i].valid)
05656 break;
05657
05658 if (i == MAX_EVENT_REQUESTS) {
05659 bm_unlock_buffer(buffer_handle);
05660 return BM_NO_MEMORY;
05661 }
05662
05663
05664 pclient->event_request[i].id = request_id;
05665 pclient->event_request[i].valid = TRUE;
05666 pclient->event_request[i].event_id = event_id;
05667 pclient->event_request[i].trigger_mask = trigger_mask;
05668 pclient->event_request[i].sampling_type = sampling_type;
05669
05670 pclient->all_flag = pclient->all_flag || (sampling_type & GET_ALL);
05671
05672
05673 if (func != NULL)
05674 _buffer[buffer_handle - 1].callback = TRUE;
05675
05676
05677
05678
05679
05680
05681 if (i + 1 > pclient->max_request_index)
05682 pclient->max_request_index = i + 1;
05683
05684 bm_unlock_buffer(buffer_handle);
05685 }
05686 #endif
05687
05688 return BM_SUCCESS;
05689 }
05690
05691
05692 #endif
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721
05722 INT bm_request_event(HNDLE buffer_handle, short int event_id,
05723 short int trigger_mask,
05724 INT sampling_type, HNDLE * request_id, void (*func) (HNDLE, HNDLE, EVENT_HEADER *,
05725 void *))
05726 {
05727 INT idx, status;
05728
05729
05730 if (_request_list_entries == 0) {
05731 _request_list = (REQUEST_LIST *) M_MALLOC(sizeof(REQUEST_LIST));
05732 memset(_request_list, 0, sizeof(REQUEST_LIST));
05733 if (_request_list == NULL) {
05734 cm_msg(MERROR, "bm_request_event", "not enough memory to allocate request list buffer");
05735 return BM_NO_MEMORY;
05736 }
05737
05738 _request_list_entries = 1;
05739 idx = 0;
05740 } else {
05741
05742 for (idx = 0; idx < _request_list_entries; idx++)
05743 if (!_request_list[idx].buffer_handle)
05744 break;
05745
05746
05747 if (idx == _request_list_entries) {
05748 _request_list =
05749 (REQUEST_LIST *) realloc(_request_list, sizeof(REQUEST_LIST) * (_request_list_entries + 1));
05750 if (_request_list == NULL) {
05751 cm_msg(MERROR, "bm_request_event", "not enough memory to allocate request list buffer");
05752 return BM_NO_MEMORY;
05753 }
05754
05755 memset(&_request_list[_request_list_entries], 0, sizeof(REQUEST_LIST));
05756
05757 _request_list_entries++;
05758 }
05759 }
05760
05761
05762 _request_list[idx].buffer_handle = buffer_handle;
05763 _request_list[idx].event_id = event_id;
05764 _request_list[idx].trigger_mask = trigger_mask;
05765 _request_list[idx].dispatcher = func;
05766
05767 *request_id = idx;
05768
05769
05770 status = bm_add_event_request(buffer_handle, event_id, trigger_mask, sampling_type, func, idx);
05771 if (status != BM_SUCCESS)
05772 return status;
05773
05774 return BM_SUCCESS;
05775 }
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786 INT bm_remove_event_request(INT buffer_handle, INT request_id)
05787 {
05788 if (rpc_is_remote())
05789 return rpc_call(RPC_BM_REMOVE_EVENT_REQUEST, buffer_handle, request_id);
05790
05791 #ifdef LOCAL_ROUTINES
05792 {
05793 INT i, deleted;
05794 BUFFER_CLIENT *pclient;
05795
05796 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
05797 cm_msg(MERROR, "bm_remove_event_request", "invalid buffer handle %d", buffer_handle);
05798 return BM_INVALID_HANDLE;
05799 }
05800
05801 if (!_buffer[buffer_handle - 1].attached) {
05802 cm_msg(MERROR, "bm_remove_event_request", "invalid buffer handle %d", buffer_handle);
05803 return BM_INVALID_HANDLE;
05804 }
05805
05806
05807 pclient = &(_buffer[buffer_handle - 1].buffer_header->
05808 client[bm_validate_client_index(&_buffer[buffer_handle - 1])]);
05809
05810
05811 bm_lock_buffer(buffer_handle);
05812
05813
05814 for (i = 0, deleted = 0; i < pclient->max_request_index; i++)
05815 if (pclient->event_request[i].valid && pclient->event_request[i].id == request_id) {
05816 memset(&pclient->event_request[i], 0, sizeof(EVENT_REQUEST));
05817 deleted++;
05818 }
05819
05820
05821 for (i = MAX_EVENT_REQUESTS - 1; i >= 0; i--)
05822 if (pclient->event_request[i].valid)
05823 break;
05824
05825 pclient->max_request_index = i + 1;
05826
05827
05828 pclient->all_flag = FALSE;
05829
05830 for (i = 0; i < pclient->max_request_index; i++)
05831 if (pclient->event_request[i].valid && (pclient->event_request[i].sampling_type & GET_ALL)) {
05832 pclient->all_flag = TRUE;
05833 break;
05834 }
05835
05836 bm_unlock_buffer(buffer_handle);
05837
05838 if (!deleted)
05839 return BM_NOT_FOUND;
05840 }
05841 #endif
05842
05843 return BM_SUCCESS;
05844 }
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854
05855 INT bm_delete_request(INT request_id)
05856 {
05857 if (request_id < 0 || request_id >= _request_list_entries)
05858 return BM_INVALID_HANDLE;
05859
05860
05861 bm_remove_event_request(_request_list[request_id].buffer_handle, request_id);
05862
05863 memset(&_request_list[request_id], 0, sizeof(REQUEST_LIST));
05864
05865 return BM_SUCCESS;
05866 }
05867
05868 #if 0 // currently not used
05869 static void bm_show_pointers(const BUFFER_HEADER * pheader)
05870 {
05871 int i;
05872 const BUFFER_CLIENT *pclient;
05873
05874 pclient = pheader->client;
05875
05876 printf("buffer \'%s\', rptr: %d, wptr: %d, size: %d\n", pheader->name, pheader->read_pointer,
05877 pheader->write_pointer, pheader->size);
05878 for (i = 0; i < pheader->max_client_index; i++)
05879 if (pclient[i].pid) {
05880 printf("pointers: client %d \'%s\', rptr %d\n", i, pclient[i].name, pclient[i].read_pointer);
05881 }
05882
05883 printf("done\n");
05884 }
05885 #endif
05886
05887 static void bm_validate_client_pointers(BUFFER_HEADER * pheader, BUFFER_CLIENT * pclient)
05888 {
05889 assert(pheader->read_pointer >= 0 && pheader->read_pointer <= pheader->size);
05890 assert(pclient->read_pointer >= 0 && pclient->read_pointer <= pheader->size);
05891
05892 if (pheader->read_pointer <= pheader->write_pointer) {
05893
05894 if (pclient->read_pointer < pheader->read_pointer) {
05895 cm_msg(MINFO, "bm_validate_client_pointers",
05896 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d", pclient->name,
05897 pheader->name, pclient->read_pointer, pheader->read_pointer);
05898
05899 pclient->read_pointer = pheader->read_pointer;
05900 }
05901
05902 if (pclient->read_pointer > pheader->write_pointer) {
05903 cm_msg(MINFO, "bm_validate_client_pointers",
05904 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d", pclient->name,
05905 pheader->name, pclient->read_pointer, pheader->write_pointer);
05906
05907 pclient->read_pointer = pheader->write_pointer;
05908 }
05909
05910 } else {
05911
05912 if (pclient->read_pointer < 0) {
05913 cm_msg(MINFO, "bm_validate_client_pointers",
05914 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d", pclient->name,
05915 pheader->name, pclient->read_pointer, pheader->read_pointer);
05916
05917 pclient->read_pointer = pheader->read_pointer;
05918 }
05919
05920 if (pclient->read_pointer >= pheader->size) {
05921 cm_msg(MINFO, "bm_validate_client_pointers",
05922 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d", pclient->name,
05923 pheader->name, pclient->read_pointer, pheader->read_pointer);
05924
05925 pclient->read_pointer = pheader->read_pointer;
05926 }
05927
05928 if (pclient->read_pointer > pheader->write_pointer && pclient->read_pointer < pheader->read_pointer) {
05929 cm_msg(MINFO, "bm_validate_client_pointers",
05930 "Corrected read pointer for client \'%s\' on buffer \'%s\' from %d to %d", pclient->name,
05931 pheader->name, pclient->read_pointer, pheader->read_pointer);
05932
05933 pclient->read_pointer = pheader->read_pointer;
05934 }
05935 }
05936 }
05937
05938 #if 0 // currently not used
05939 static void bm_validate_pointers(BUFFER_HEADER * pheader)
05940 {
05941 BUFFER_CLIENT *pclient = pheader->client;
05942 int i;
05943
05944 for (i = 0; i < pheader->max_client_index; i++)
05945 if (pclient[i].pid) {
05946 bm_validate_client_pointers(pheader, &pclient[i]);
05947 }
05948 }
05949 #endif
05950
05951 static BOOL bm_update_read_pointer(const char *caller_name, BUFFER_HEADER * pheader)
05952 {
05953 BOOL did_move;
05954 int i;
05955 int min_rp;
05956 BUFFER_CLIENT *pclient;
05957
05958 assert(caller_name);
05959 pclient = pheader->client;
05960
05961
05962 min_rp = pheader->write_pointer;
05963
05964 for (i = 0; i < pheader->max_client_index; i++)
05965 if (pclient[i].pid) {
05966 #ifdef DEBUG_MSG
05967 cm_msg(MDEBUG, caller_name, "bm_update_read_pointer: client %d rp=%d", i, pclient[i].read_pointer);
05968 #endif
05969 bm_validate_client_pointers(pheader, &pclient[i]);
05970
05971 if (pheader->read_pointer <= pheader->write_pointer) {
05972 if (pclient[i].read_pointer < min_rp)
05973 min_rp = pclient[i].read_pointer;
05974 } else {
05975 if (pclient[i].read_pointer <= pheader->write_pointer) {
05976 if (pclient[i].read_pointer < min_rp)
05977 min_rp = pclient[i].read_pointer;
05978 } else {
05979 int xptr = pclient[i].read_pointer - pheader->size;
05980 if (xptr < min_rp)
05981 min_rp = xptr;
05982 }
05983 }
05984 }
05985
05986 if (min_rp < 0)
05987 min_rp += pheader->size;
05988
05989 assert(min_rp >= 0);
05990 assert(min_rp < pheader->size);
05991
05992 #ifdef DEBUG_MSG
05993 if (min_rp == pheader->read_pointer)
05994 cm_msg(MDEBUG, caller_name, "bm_update_read_pointer -> wp=%d", pheader->write_pointer);
05995 else
05996 cm_msg(MDEBUG, caller_name, "bm_update_read_pointer -> wp=%d, rp %d -> %d, size=%d",
05997 pheader->write_pointer, pheader->read_pointer, min_rp, pheader->size);
05998 #endif
05999
06000 did_move = (pheader->read_pointer != min_rp);
06001
06002 pheader->read_pointer = min_rp;
06003
06004 return did_move;
06005 }
06006
06007 static void bm_wakeup_producers(const BUFFER_HEADER * pheader, const BUFFER_CLIENT * pc)
06008 {
06009 int i;
06010 int size;
06011 const BUFFER_CLIENT *pctmp = pheader->client;
06012
06013
06014
06015
06016
06017
06018
06019 size = pc->read_pointer - pheader->write_pointer;
06020 if (size <= 0)
06021 size += pheader->size;
06022
06023 if (size >= pheader->size * 0.5)
06024 for (i = 0; i < pheader->max_client_index; i++, pctmp++)
06025 if (pctmp->pid)
06026 if (pctmp->write_wait < size) {
06027 #ifdef DEBUG_MSG
06028 cm_msg(MDEBUG, "Receive wake: rp=%d, wp=%d, level=%1.1lf",
06029 pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
06030 #endif
06031 ss_resume(pctmp->port, "B ");
06032 }
06033 }
06034
06035 static void bm_dispatch_event(int buffer_handle, EVENT_HEADER * pevent)
06036 {
06037 int i;
06038
06039
06040 for (i = 0; i < _request_list_entries; i++)
06041 if (_request_list[i].buffer_handle == buffer_handle &&
06042 bm_match_event(_request_list[i].event_id, _request_list[i].trigger_mask, pevent)) {
06043
06044 if ((pevent->event_id & 0xF000) == EVENTID_FRAG1 || (pevent->event_id & 0xF000) == EVENTID_FRAG)
06045 bm_defragment_event(buffer_handle, i, pevent, (void *) (pevent + 1), _request_list[i].dispatcher);
06046 else
06047 _request_list[i].dispatcher(buffer_handle, i, pevent, (void *) (pevent + 1));
06048 }
06049 }
06050
06051 static void bm_dispatch_from_cache(BUFFER * pbuf, int buffer_handle)
06052 {
06053 EVENT_HEADER *pevent;
06054 int size;
06055
06056 pevent = (EVENT_HEADER *) (pbuf->read_cache + pbuf->read_cache_rp);
06057 size = pevent->data_size + sizeof(EVENT_HEADER);
06058
06059
06060 size = ALIGN8(size);
06061
06062
06063 pbuf->read_cache_rp += size;
06064
06065 if (pbuf->read_cache_rp == pbuf->read_cache_wp)
06066 pbuf->read_cache_rp = pbuf->read_cache_wp = 0;
06067
06068 bm_dispatch_event(buffer_handle, pevent);
06069 }
06070
06071 static void bm_convert_event_header(EVENT_HEADER * pevent, int convert_flags)
06072 {
06073
06074 if (convert_flags) {
06075 rpc_convert_single(&pevent->event_id, TID_SHORT, RPC_OUTGOING, convert_flags);
06076 rpc_convert_single(&pevent->trigger_mask, TID_SHORT, RPC_OUTGOING, convert_flags);
06077 rpc_convert_single(&pevent->serial_number, TID_DWORD, RPC_OUTGOING, convert_flags);
06078 rpc_convert_single(&pevent->time_stamp, TID_DWORD, RPC_OUTGOING, convert_flags);
06079 rpc_convert_single(&pevent->data_size, TID_DWORD, RPC_OUTGOING, convert_flags);
06080 }
06081 }
06082
06083 static int bm_copy_from_cache(BUFFER * pbuf, void *destination, int max_size, int *buf_size,
06084 int convert_flags)
06085 {
06086 int status;
06087 EVENT_HEADER *pevent;
06088 int size;
06089
06090 pevent = (EVENT_HEADER *) (pbuf->read_cache + pbuf->read_cache_rp);
06091 size = pevent->data_size + sizeof(EVENT_HEADER);
06092
06093 if (size > max_size) {
06094 memcpy(destination, pevent, max_size);
06095 cm_msg(MERROR, "bm_receive_event", "event size %d larger than buffer size %d", size, max_size);
06096 *buf_size = max_size;
06097 status = BM_TRUNCATED;
06098 } else {
06099 memcpy(destination, pevent, size);
06100 *buf_size = size;
06101 status = BM_SUCCESS;
06102 }
06103
06104 bm_convert_event_header((EVENT_HEADER *) destination, convert_flags);
06105
06106
06107 size = ALIGN8(size);
06108
06109 pbuf->read_cache_rp += size;
06110
06111 if (pbuf->read_cache_rp == pbuf->read_cache_wp)
06112 pbuf->read_cache_rp = pbuf->read_cache_wp = 0;
06113
06114 return status;
06115 }
06116
06117 static int bm_read_cache_has_events(const BUFFER * pbuf)
06118 {
06119 if (pbuf->read_cache_size == 0)
06120 return 0;
06121
06122 if (pbuf->read_cache_rp == pbuf->read_cache_wp)
06123 return 0;
06124
06125 return 1;
06126 }
06127
06128 static int bm_wait_for_free_space(int buffer_handle, BUFFER * pbuf, int async_flag, int requested_space)
06129 {
06130 int status;
06131 BUFFER_HEADER *pheader = pbuf->buffer_header;
06132 char *pdata = (char *) (pheader + 1);
06133
06134
06135
06136
06137
06138
06139 requested_space += 100;
06140
06141 if (requested_space >= pheader->size)
06142 return BM_NO_MEMORY;
06143
06144 while (1) {
06145
06146 BUFFER_CLIENT *pc;
06147 int n_blocking;
06148 int i;
06149 int size;
06150
06151
06152
06153 size = pheader->read_pointer - pheader->write_pointer;
06154 if (size <= 0)
06155 size += pheader->size;
06156
06157 #if 0
06158 printf
06159 ("bm_send_event: buffer pointers: read: %d, write: %d, free space: %d, bufsize: %d, event size: %d\n",
06160 pheader->read_pointer, pheader->write_pointer, size, pheader->size, requested_space);
06161 #endif
06162
06163 if (requested_space < size)
06164 return BM_SUCCESS;
06165
06166
06167 n_blocking = 0;
06168
06169 for (i = 0, pc = pheader->client; i < pheader->max_client_index; i++, pc++)
06170 if (pc->pid) {
06171 if (pc->read_pointer == pheader->read_pointer) {
06172
06173
06174
06175
06176 BOOL blocking = FALSE;
06177 int blocking_request_id = 0;
06178 int j;
06179
06180
06181
06182 EVENT_REQUEST *prequest = pc->event_request;
06183 EVENT_HEADER *pevent_test = (EVENT_HEADER *) (pdata + pc->read_pointer);
06184
06185 assert(pc->read_pointer >= 0);
06186 assert(pc->read_pointer <= pheader->size);
06187
06188 for (j = 0; j < pc->max_request_index; j++, prequest++)
06189 if (prequest->valid
06190 && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent_test)) {
06191 if (prequest->sampling_type & GET_ALL) {
06192 blocking = TRUE;
06193 blocking_request_id = prequest->id;
06194 break;
06195 }
06196 }
06197
06198 if (blocking) {
06199 n_blocking++;
06200
06201 if (pc->read_wait) {
06202 char str[80];
06203 #ifdef DEBUG_MSG
06204 cm_msg(MDEBUG, "Send wake: rp=%d, wp=%d", pheader->read_pointer, pheader->write_pointer);
06205 #endif
06206 sprintf(str, "B %s %d", pheader->name, blocking_request_id);
06207 ss_resume(pc->port, str);
06208 }
06209
06210 } else {
06211
06212
06213
06214
06215
06216 int new_read_pointer;
06217 int increment =
06218 sizeof(EVENT_HEADER) + ((EVENT_HEADER *) (pdata + pc->read_pointer))->data_size;
06219
06220
06221 increment = ALIGN8(increment);
06222
06223 assert(increment > 0);
06224 assert(increment <= pheader->size);
06225
06226 new_read_pointer = (pc->read_pointer + increment) % pheader->size;
06227
06228 if (new_read_pointer > pheader->size - (int) sizeof(EVENT_HEADER))
06229 new_read_pointer = 0;
06230
06231 pc->read_pointer = new_read_pointer;
06232 }
06233 }
06234 }
06235
06236 if (n_blocking == 0) {
06237
06238 BOOL moved;
06239
06240
06241
06242
06243
06244 moved = bm_update_read_pointer("bm_send_event", pheader);
06245
06246 if (!moved) {
06247 cm_msg(MERROR, "bm_wait_for_free_space",
06248 "BUG: read pointer did not move while waiting for %d bytes, bytes available: %d, buffer size: %d",
06249 requested_space, size, pheader->size);
06250 return BM_NO_MEMORY;
06251 }
06252
06253 continue;
06254 }
06255
06256
06257
06258 bm_unlock_buffer(buffer_handle);
06259
06260
06261 if (async_flag)
06262 return BM_ASYNC_RETURN;
06263
06264 #ifdef DEBUG_MSG
06265 cm_msg(MDEBUG, "Send sleep: rp=%d, wp=%d, level=%1.1lf",
06266 pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
06267 #endif
06268
06269
06270 pheader->client[bm_validate_client_index(pbuf)].write_wait = requested_space;
06271
06272 bm_cleanup("bm_wait_for_free_space", ss_millitime(), FALSE);
06273
06274 status = ss_suspend(1000, MSG_BM);
06275
06276
06277
06278
06279
06280
06281
06282
06283 if (status != SS_TIMEOUT)
06284 ss_sleep(10);
06285
06286
06287 pheader->client[bm_validate_client_index(pbuf)].write_wait = 0;
06288
06289
06290 if (status == SS_ABORT)
06291 return SS_ABORT;
06292
06293 #ifdef DEBUG_MSG
06294 cm_msg(MDEBUG, "Send woke up: rp=%d, wp=%d, level=%1.1lf",
06295 pheader->read_pointer, pheader->write_pointer, 100 - 100.0 * size / pheader->size);
06296 #endif
06297
06298 bm_lock_buffer(buffer_handle);
06299 }
06300 }
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347
06348
06349
06350
06351
06352
06353 INT bm_send_event(INT buffer_handle, void *source, INT buf_size, INT async_flag)
06354 {
06355 EVENT_HEADER *pevent;
06356
06357
06358 if (buf_size < sizeof(EVENT_HEADER)) {
06359 cm_msg(MERROR, "bm_send_event", "event size (%d) it too small", buf_size);
06360 return BM_INVALID_PARAM;
06361 }
06362
06363
06364 if (ALIGN8(buf_size) != (INT) ALIGN8(((EVENT_HEADER *) source)->data_size + sizeof(EVENT_HEADER))) {
06365 cm_msg(MERROR, "bm_send_event", "event size (%d) mismatch in header (%d)",
06366 ALIGN8(buf_size), (INT) ALIGN8(((EVENT_HEADER *) source)->data_size + sizeof(EVENT_HEADER)));
06367 return BM_INVALID_PARAM;
06368 }
06369
06370 if (rpc_is_remote())
06371 return rpc_call(RPC_BM_SEND_EVENT, buffer_handle, source, buf_size, async_flag);
06372
06373 #ifdef LOCAL_ROUTINES
06374 {
06375 BUFFER *pbuf;
06376 BUFFER_HEADER *pheader;
06377 BUFFER_CLIENT *pclient;
06378 EVENT_REQUEST *prequest;
06379 INT i, j, size, total_size, status;
06380 INT my_client_index;
06381 INT old_write_pointer;
06382 INT num_requests_client;
06383 char *pdata;
06384 INT request_id;
06385
06386 pbuf = &_buffer[buffer_handle - 1];
06387
06388 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
06389 cm_msg(MERROR, "bm_send_event", "invalid buffer handle %d", buffer_handle);
06390 return BM_INVALID_HANDLE;
06391 }
06392
06393 if (!pbuf->attached) {
06394 cm_msg(MERROR, "bm_send_event", "invalid buffer handle %d", buffer_handle);
06395 return BM_INVALID_HANDLE;
06396 }
06397
06398 pevent = (EVENT_HEADER *) source;
06399 total_size = buf_size;
06400
06401
06402 total_size = ALIGN8(total_size);
06403
06404
06405 if (pbuf->write_cache_size) {
06406 status = BM_SUCCESS;
06407
06408 if (pbuf->write_cache_size - pbuf->write_cache_wp < total_size)
06409 status = bm_flush_cache(buffer_handle, async_flag);
06410
06411 if (status != BM_SUCCESS)
06412 return status;
06413
06414 if (total_size < pbuf->write_cache_size) {
06415 memcpy(pbuf->write_cache + pbuf->write_cache_wp, source, total_size);
06416
06417 pbuf->write_cache_wp += total_size;
06418 return BM_SUCCESS;
06419 }
06420 }
06421
06422
06423
06424
06425 pheader = pbuf->buffer_header;
06426 pdata = (char *) (pheader + 1);
06427 my_client_index = bm_validate_client_index(pbuf);
06428 pclient = pheader->client;
06429
06430
06431 if (total_size >= pheader->size) {
06432 cm_msg(MERROR, "bm_send_event",
06433 "total event size (%d) larger than size (%d) of buffer \'%s\'", total_size, pheader->size, pheader->name);
06434 return BM_NO_MEMORY;
06435 }
06436
06437
06438 bm_lock_buffer(buffer_handle);
06439
06440 status = bm_wait_for_free_space(buffer_handle, pbuf, async_flag, total_size);
06441 if (status != BM_SUCCESS) {
06442 bm_unlock_buffer(buffer_handle);
06443 return status;
06444 }
06445
06446
06447 old_write_pointer = pheader->write_pointer;
06448
06449 if (pheader->write_pointer + total_size <= pheader->size) {
06450 memcpy(pdata + pheader->write_pointer, pevent, total_size);
06451 pheader->write_pointer = (pheader->write_pointer + total_size) % pheader->size;
06452 if (pheader->write_pointer > pheader->size - (int) sizeof(EVENT_HEADER))
06453 pheader->write_pointer = 0;
06454 } else {
06455
06456 size = pheader->size - pheader->write_pointer;
06457
06458 memcpy(pdata + pheader->write_pointer, pevent, size);
06459 memcpy(pdata, (char *) pevent + size, total_size - size);
06460
06461 pheader->write_pointer = total_size - size;
06462 }
06463
06464
06465
06466
06467
06468
06469
06470
06471 assert(pheader->write_pointer != pheader->read_pointer);
06472
06473
06474 for (i = 0; i < pheader->max_client_index; i++)
06475 if (pclient[i].pid) {
06476 prequest = pclient[i].event_request;
06477 num_requests_client = 0;
06478 request_id = -1;
06479
06480 for (j = 0; j < pclient[i].max_request_index; j++, prequest++)
06481 if (prequest->valid && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
06482 if (prequest->sampling_type & GET_ALL)
06483 pclient[i].num_waiting_events++;
06484
06485 num_requests_client++;
06486 request_id = prequest->id;
06487 }
06488
06489
06490 if (num_requests_client && pclient[i].read_wait) {
06491 char str[80];
06492 #ifdef DEBUG_MSG
06493 cm_msg(MDEBUG, "Send wake: rp=%d, wp=%d", pheader->read_pointer, pheader->write_pointer);
06494 #endif
06495 sprintf(str, "B %s %d", pheader->name, request_id);
06496 ss_resume(pclient[i].port, str);
06497 }
06498
06499
06500 if (num_requests_client == 0 && pclient[i].read_pointer == old_write_pointer)
06501 pclient[i].read_pointer = pheader->write_pointer;
06502 }
06503
06504
06505 if (pclient[my_client_index].read_pointer == old_write_pointer)
06506 pclient[my_client_index].read_pointer = pheader->write_pointer;
06507
06508
06509
06510 bm_update_read_pointer("bm_send_event", pheader);
06511
06512
06513 pheader->num_in_events++;
06514
06515
06516 bm_unlock_buffer(buffer_handle);
06517 }
06518 #endif
06519
06520 return BM_SUCCESS;
06521 }
06522
06523
06524
06525
06526
06527
06528
06529
06530
06531
06532
06533
06534
06535
06536
06537
06538
06539
06540
06541
06542 INT bm_flush_cache(INT buffer_handle, INT async_flag)
06543 {
06544 if (rpc_is_remote())
06545 return rpc_call(RPC_BM_FLUSH_CACHE, buffer_handle, async_flag);
06546
06547 #ifdef LOCAL_ROUTINES
06548 {
06549 BUFFER *pbuf;
06550 BUFFER_HEADER *pheader;
06551 BUFFER_CLIENT *pclient;
06552 EVENT_HEADER *pevent;
06553 INT i, size, total_size, status;
06554 INT my_client_index;
06555 INT old_write_pointer;
06556 char *pdata;
06557
06558 pbuf = &_buffer[buffer_handle - 1];
06559
06560 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
06561 cm_msg(MERROR, "bm_flush_cache", "invalid buffer handle %d", buffer_handle);
06562 return BM_INVALID_HANDLE;
06563 }
06564
06565 if (!pbuf->attached) {
06566 cm_msg(MERROR, "bm_flush_cache", "invalid buffer handle %d", buffer_handle);
06567 return BM_INVALID_HANDLE;
06568 }
06569
06570 if (pbuf->write_cache_size == 0)
06571 return BM_SUCCESS;
06572
06573
06574 if (pbuf->write_cache_rp == pbuf->write_cache_wp)
06575 return BM_SUCCESS;
06576
06577
06578 pheader = _buffer[buffer_handle - 1].buffer_header;
06579 pdata = (char *) (pheader + 1);
06580 my_client_index = bm_validate_client_index(pbuf);
06581 pclient = pheader->client;
06582 pevent = (EVENT_HEADER *) (pbuf->write_cache + pbuf->write_cache_rp);
06583
06584
06585 bm_lock_buffer(buffer_handle);
06586
06587 #ifdef DEBUG_MSG
06588 cm_msg(MDEBUG, "bm_flush_cache initial: rp=%d, wp=%d", pheader->read_pointer, pheader->write_pointer);
06589 #endif
06590
06591 status = bm_wait_for_free_space(buffer_handle, pbuf, async_flag, pbuf->write_cache_wp);
06592 if (status != BM_SUCCESS) {
06593 bm_unlock_buffer(buffer_handle);
06594 return status;
06595 }
06596
06597
06598 old_write_pointer = pheader->write_pointer;
06599
06600 #ifdef DEBUG_MSG
06601 cm_msg(MDEBUG, "bm_flush_cache: found space rp=%d, wp=%d", pheader->read_pointer,
06602 pheader->write_pointer);
06603 #endif
06604
06605 while (pbuf->write_cache_rp < pbuf->write_cache_wp) {
06606
06607
06608 assert(pbuf->write_cache_rp >= 0);
06609 assert(pbuf->write_cache_rp < pbuf->write_cache_size);
06610
06611 pevent = (EVENT_HEADER *) (pbuf->write_cache + pbuf->write_cache_rp);
06612 total_size = pevent->data_size + sizeof(EVENT_HEADER);
06613
06614 assert(total_size > 0);
06615 assert(total_size <= pheader->size);
06616
06617
06618 total_size = ALIGN8(total_size);
06619
06620 if (pheader->write_pointer + total_size <= pheader->size) {
06621 memcpy(pdata + pheader->write_pointer, pevent, total_size);
06622 pheader->write_pointer = (pheader->write_pointer + total_size) % pheader->size;
06623 if (pheader->write_pointer > pheader->size - (int) sizeof(EVENT_HEADER))
06624 pheader->write_pointer = 0;
06625 } else {
06626
06627 size = pheader->size - pheader->write_pointer;
06628
06629 memcpy(pdata + pheader->write_pointer, pevent, size);
06630 memcpy(pdata, (char *) pevent + size, total_size - size);
06631
06632 pheader->write_pointer = total_size - size;
06633 }
06634
06635
06636
06637 assert(pheader->write_pointer != pheader->read_pointer);
06638
06639
06640
06641
06642
06643 pbuf->write_cache_rp += total_size;
06644 }
06645
06646 pbuf->write_cache_rp = pbuf->write_cache_wp = 0;
06647
06648
06649 for (i = 0; i < pheader->max_client_index; i++)
06650 if (pclient[i].pid && pclient[i].read_wait) {
06651 char str[80];
06652 #ifdef DEBUG_MSG
06653 cm_msg(MDEBUG, "Send wake: rp=%d, wp=%d", pheader->read_pointer, pheader->write_pointer);
06654 #endif
06655 sprintf(str, "B %s %d", pheader->name, -1);
06656 ss_resume(pclient[i].port, str);
06657 }
06658
06659
06660 if (pclient[my_client_index].read_pointer == old_write_pointer)
06661 pclient[my_client_index].read_pointer = pheader->write_pointer;
06662
06663
06664
06665 bm_update_read_pointer("bm_flush_cache", pheader);
06666
06667
06668 pheader->num_in_events++;
06669
06670
06671 bm_unlock_buffer(buffer_handle);
06672 }
06673 #endif
06674
06675 return BM_SUCCESS;
06676 }
06677
06678
06679
06680
06681
06682
06683
06684
06685
06686
06687
06688
06689
06690
06691
06692
06693
06694
06695
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
06722
06723
06724
06725
06726
06727
06728
06729
06730
06731
06732
06733
06734
06735
06736
06737
06738
06739 INT bm_receive_event(INT buffer_handle, void *destination, INT * buf_size, INT async_flag)
06740 {
06741 if (rpc_is_remote()) {
06742 int status, old_timeout = 0;
06743
06744 status = resize_net_send_buffer("bm_receive_event", *buf_size);
06745 if (status != SUCCESS)
06746 return status;
06747
06748 if (!async_flag) {
06749 old_timeout = rpc_get_option(-1, RPC_OTIMEOUT);
06750 rpc_set_option(-1, RPC_OTIMEOUT, 0);
06751 }
06752
06753 status = rpc_call(RPC_BM_RECEIVE_EVENT, buffer_handle, destination, buf_size, async_flag);
06754
06755 if (!async_flag) {
06756 rpc_set_option(-1, RPC_OTIMEOUT, old_timeout);
06757 }
06758
06759 return status;
06760 }
06761 #ifdef LOCAL_ROUTINES
06762 {
06763 BUFFER *pbuf;
06764 BUFFER_HEADER *pheader;
06765 BUFFER_CLIENT *pclient, *pc;
06766 char *pdata;
06767 INT convert_flags;
06768 INT i, size, max_size;
06769 INT status = 0;
06770 INT my_client_index;
06771 BOOL cache_is_full = FALSE;
06772 BOOL use_event_buffer = FALSE;
06773 int cycle = 0;
06774
06775 pbuf = &_buffer[buffer_handle - 1];
06776
06777 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
06778 cm_msg(MERROR, "bm_receive_event", "invalid buffer handle %d", buffer_handle);
06779 return BM_INVALID_HANDLE;
06780 }
06781
06782 if (!pbuf->attached) {
06783 cm_msg(MERROR, "bm_receive_event", "invalid buffer handle %d", buffer_handle);
06784 return BM_INVALID_HANDLE;
06785 }
06786
06787 max_size = *buf_size;
06788 *buf_size = 0;
06789
06790 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
06791 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
06792 else
06793 convert_flags = 0;
06794
06795
06796 if (bm_read_cache_has_events(pbuf))
06797 return bm_copy_from_cache(pbuf, destination, max_size, buf_size, convert_flags);
06798
06799 LOOP:
06800
06801
06802
06803 pheader = pbuf->buffer_header;
06804 pdata = (char *) (pheader + 1);
06805 my_client_index = bm_validate_client_index(pbuf);
06806 pclient = pheader->client;
06807 pc = pheader->client + my_client_index;
06808
06809
06810 if (async_flag == ASYNC && pheader->write_pointer == pc->read_pointer)
06811 return BM_ASYNC_RETURN;
06812
06813
06814 bm_lock_buffer(buffer_handle);
06815
06816 while (pheader->write_pointer == pc->read_pointer) {
06817
06818 bm_unlock_buffer(buffer_handle);
06819
06820
06821 if (async_flag == ASYNC)
06822 return BM_ASYNC_RETURN;
06823
06824 pc->read_wait = TRUE;
06825
06826
06827 if (pheader->write_pointer == pc->read_pointer) {
06828 #ifdef DEBUG_MSG
06829 cm_msg(MDEBUG, "Receive sleep: grp=%d, rp=%d wp=%d",
06830 pheader->read_pointer, pc->read_pointer, pheader->write_pointer);
06831 #endif
06832
06833 status = ss_suspend(1000, MSG_BM);
06834
06835 #ifdef DEBUG_MSG
06836 cm_msg(MDEBUG, "Receive woke up: rp=%d, wp=%d", pheader->read_pointer, pheader->write_pointer);
06837 #endif
06838
06839
06840 if (status == SS_ABORT)
06841 return SS_ABORT;
06842 }
06843
06844 pc->read_wait = FALSE;
06845
06846
06847 bm_validate_client_index(pbuf);
06848
06849 bm_lock_buffer(buffer_handle);
06850 }
06851
06852
06853
06854 do {
06855 int new_read_pointer;
06856 int total_size;
06857 EVENT_REQUEST *prequest;
06858 EVENT_HEADER *pevent = (EVENT_HEADER *) (pdata + pc->read_pointer);
06859
06860 assert(pc->read_pointer >= 0);
06861 assert(pc->read_pointer <= pheader->size);
06862
06863 total_size = pevent->data_size + sizeof(EVENT_HEADER);
06864 total_size = ALIGN8(total_size);
06865
06866 assert(total_size > 0);
06867 assert(total_size <= pheader->size);
06868
06869 prequest = pc->event_request;
06870
06871
06872
06873
06874 for (i = 0; i < pc->max_request_index; i++, prequest++)
06875 if (prequest->valid && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
06876
06877
06878
06879 if (pbuf->read_cache_size > 0 && total_size < pbuf->read_cache_size) {
06880
06881
06882
06883 if (pbuf->read_cache_wp + total_size >= pbuf->read_cache_size) {
06884 cache_is_full = TRUE;
06885 break;
06886 }
06887
06888 if (pc->read_pointer + total_size <= pheader->size) {
06889
06890 memcpy(pbuf->read_cache + pbuf->read_cache_wp, pevent, total_size);
06891 } else {
06892
06893 size = pheader->size - pc->read_pointer;
06894 memcpy(pbuf->read_cache + pbuf->read_cache_wp, pevent, size);
06895 memcpy((char *) pbuf->read_cache + pbuf->read_cache_wp + size, pdata, total_size - size);
06896 }
06897
06898 pbuf->read_cache_wp += total_size;
06899
06900 } else {
06901 int copy_size = total_size;
06902
06903
06904
06905
06906
06907 if (bm_read_cache_has_events(pbuf)) {
06908 cache_is_full = TRUE;
06909 break;
06910 }
06911
06912 use_event_buffer = TRUE;
06913
06914 status = BM_SUCCESS;
06915 if (copy_size > max_size) {
06916 copy_size = max_size;
06917 cm_msg(MERROR, "bm_receive_event",
06918 "event size %d larger than buffer size %d", total_size, max_size);
06919 status = BM_TRUNCATED;
06920 }
06921
06922 if (pc->read_pointer + total_size <= pheader->size) {
06923
06924 memcpy(destination, pevent, copy_size);
06925 } else {
06926
06927 size = pheader->size - pc->read_pointer;
06928
06929 if (size > max_size)
06930 memcpy(destination, pevent, max_size);
06931 else
06932 memcpy(destination, pevent, size);
06933
06934 if (total_size > max_size) {
06935 if (size <= max_size)
06936 memcpy((char *) destination + size, pdata, max_size - size);
06937 } else
06938 memcpy((char *) destination + size, pdata, total_size - size);
06939 }
06940
06941 *buf_size = copy_size;
06942
06943 bm_convert_event_header((EVENT_HEADER *) destination, convert_flags);
06944 }
06945
06946
06947 pheader->num_out_events++;
06948 break;
06949 }
06950
06951 if (cache_is_full)
06952 break;
06953
06954
06955
06956 assert(total_size > 0);
06957 assert(total_size <= pheader->size);
06958
06959 new_read_pointer = pc->read_pointer + total_size;
06960 if (new_read_pointer >= pheader->size) {
06961 new_read_pointer = new_read_pointer % pheader->size;
06962
06963
06964 cycle++;
06965 assert(cycle < 2);
06966 }
06967
06968
06969 if (new_read_pointer > pheader->size - (int) sizeof(EVENT_HEADER))
06970 new_read_pointer = 0;
06971
06972 #ifdef DEBUG_MSG
06973 cm_msg(MDEBUG, "bm_receive_event -> wp=%d, rp %d -> %d (found=%d,size=%d)",
06974 pheader->write_pointer, pc->read_pointer, new_read_pointer, found, total_size);
06975 #endif
06976
06977 pc->read_pointer = new_read_pointer;
06978
06979 if (use_event_buffer)
06980 break;
06981
06982 } while (pheader->write_pointer != pc->read_pointer);
06983
06984
06985
06986 bm_update_read_pointer("bm_receive_event", pheader);
06987
06988
06989
06990
06991
06992
06993
06994 bm_wakeup_producers(pheader, pc);
06995
06996 bm_unlock_buffer(buffer_handle);
06997
06998 if (bm_read_cache_has_events(pbuf)) {
06999 assert(!use_event_buffer);
07000 return bm_copy_from_cache(pbuf, destination, max_size, buf_size, convert_flags);
07001 }
07002
07003 if (use_event_buffer)
07004 return status;
07005
07006 goto LOOP;
07007 }
07008 #else
07009
07010 return SS_SUCCESS;
07011 #endif
07012 }
07013
07014
07015
07016
07017
07018
07019
07020
07021
07022
07023 INT bm_skip_event(INT buffer_handle)
07024 {
07025 if (rpc_is_remote())
07026 return rpc_call(RPC_BM_SKIP_EVENT, buffer_handle);
07027
07028 #ifdef LOCAL_ROUTINES
07029 {
07030 BUFFER *pbuf;
07031 BUFFER_HEADER *pheader;
07032 BUFFER_CLIENT *pclient;
07033
07034 if (buffer_handle > _buffer_entries || buffer_handle <= 0) {
07035 cm_msg(MERROR, "bm_skip_event", "invalid buffer handle %d", buffer_handle);
07036 return BM_INVALID_HANDLE;
07037 }
07038
07039 pbuf = &_buffer[buffer_handle - 1];
07040 pheader = pbuf->buffer_header;
07041
07042 if (!pbuf->attached) {
07043 cm_msg(MERROR, "bm_skip_event", "invalid buffer handle %d", buffer_handle);
07044 return BM_INVALID_HANDLE;
07045 }
07046
07047
07048 if (pbuf->read_cache_wp > pbuf->read_cache_rp)
07049 pbuf->read_cache_rp = pbuf->read_cache_wp = 0;
07050
07051 bm_lock_buffer(buffer_handle);
07052
07053
07054 pclient = pheader->client + bm_validate_client_index(pbuf);
07055 pclient->read_pointer = pheader->write_pointer;
07056
07057 bm_unlock_buffer(buffer_handle);
07058 }
07059 #endif
07060
07061 return BM_SUCCESS;
07062 }
07063
07064
07065
07066
07067
07068
07069
07070
07071 INT bm_push_event(char *buffer_name)
07072 {
07073 #ifdef LOCAL_ROUTINES
07074 {
07075 BUFFER *pbuf;
07076 BUFFER_HEADER *pheader;
07077 BUFFER_CLIENT *pclient, *pc;
07078 char *pdata;
07079 INT i, size, buffer_handle;
07080 INT my_client_index;
07081 BOOL use_event_buffer = 0;
07082 BOOL cache_is_full = 0;
07083 int cycle = 0;
07084
07085 for (i = 0; i < _buffer_entries; i++)
07086 if (strcmp(buffer_name, _buffer[i].buffer_header->name) == 0)
07087 break;
07088 if (i == _buffer_entries)
07089 return BM_INVALID_HANDLE;
07090
07091 buffer_handle = i + 1;
07092 pbuf = &_buffer[buffer_handle - 1];
07093
07094 if (!pbuf->attached)
07095 return BM_INVALID_HANDLE;
07096
07097
07098 if (!pbuf->callback)
07099 return BM_SUCCESS;
07100
07101 if (_event_buffer_size == 0) {
07102 _event_buffer = (EVENT_HEADER *) M_MALLOC(1000);
07103 if (_event_buffer == NULL) {
07104 cm_msg(MERROR, "bm_push_event", "not enough memory to allocate cache buffer");
07105 return BM_NO_MEMORY;
07106 }
07107 _event_buffer_size = 1000;
07108 }
07109
07110
07111 if (bm_read_cache_has_events(pbuf)) {
07112 bm_dispatch_from_cache(pbuf, buffer_handle);
07113 return BM_MORE_EVENTS;
07114 }
07115
07116
07117 pheader = pbuf->buffer_header;
07118 pdata = (char *) (pheader + 1);
07119 my_client_index = bm_validate_client_index(pbuf);
07120 pclient = pheader->client;
07121 pc = pheader->client + my_client_index;
07122
07123
07124 if (pheader->write_pointer == pc->read_pointer)
07125 return BM_SUCCESS;
07126
07127
07128 bm_lock_buffer(buffer_handle);
07129
07130 if (pheader->write_pointer == pc->read_pointer) {
07131
07132 bm_unlock_buffer(buffer_handle);
07133
07134
07135 return BM_SUCCESS;
07136 }
07137
07138
07139
07140 do {
07141 int new_read_pointer;
07142 int total_size;
07143 EVENT_REQUEST *prequest;
07144 EVENT_HEADER *pevent = (EVENT_HEADER *) (pdata + pc->read_pointer);
07145
07146 assert(pc->read_pointer >= 0);
07147 assert(pc->read_pointer <= pheader->size);
07148
07149 total_size = pevent->data_size + sizeof(EVENT_HEADER);
07150 total_size = ALIGN8(total_size);
07151
07152 assert(total_size > 0);
07153 assert(total_size <= pheader->size);
07154
07155 prequest = pc->event_request;
07156
07157
07158
07159
07160 for (i = 0; i < pc->max_request_index; i++, prequest++)
07161 if (prequest->valid && bm_match_event(prequest->event_id, prequest->trigger_mask, pevent)) {
07162
07163
07164 if (prequest->sampling_type == GET_RECENT) {
07165 if (ss_time() - pevent->time_stamp > 1) {
07166
07167 continue;
07168 }
07169
07170 printf("now: %d, event: %d\n", ss_time(), pevent->time_stamp);
07171 }
07172
07173
07174
07175 if (pbuf->read_cache_size > 0 && total_size < pbuf->read_cache_size) {
07176
07177
07178
07179 if (pbuf->read_cache_wp + total_size >= pbuf->read_cache_size) {
07180 cache_is_full = TRUE;
07181 break;
07182 }
07183
07184 if (pc->read_pointer + total_size <= pheader->size) {
07185
07186 memcpy(pbuf->read_cache + pbuf->read_cache_wp, pevent, total_size);
07187 } else {
07188
07189 size = pheader->size - pc->read_pointer;
07190 memcpy(pbuf->read_cache + pbuf->read_cache_wp, pevent, size);
07191 memcpy((char *) pbuf->read_cache + pbuf->read_cache_wp + size, pdata, total_size - size);
07192 }
07193
07194 pbuf->read_cache_wp += total_size;
07195
07196 } else {
07197
07198
07199
07200
07201
07202
07203 if (bm_read_cache_has_events(pbuf)) {
07204 cache_is_full = TRUE;
07205 break;
07206 }
07207
07208 use_event_buffer = TRUE;
07209
07210 if (total_size > _event_buffer_size) {
07211
07212 _event_buffer = (EVENT_HEADER *) realloc(_event_buffer, total_size);
07213 _event_buffer_size = total_size;
07214 }
07215
07216 if (pc->read_pointer + total_size <= pheader->size) {
07217 memcpy(_event_buffer, pevent, total_size);
07218 } else {
07219
07220 size = pheader->size - pc->read_pointer;
07221
07222 memcpy(_event_buffer, pevent, size);
07223 memcpy((char *) _event_buffer + size, pdata, total_size - size);
07224 }
07225 }
07226
07227
07228 pheader->num_out_events++;
07229 break;
07230
07231 }
07232
07233 if (cache_is_full)
07234 break;
07235
07236
07237
07238 assert(total_size > 0);
07239 assert(total_size <= pheader->size);
07240
07241 new_read_pointer = pc->read_pointer + total_size;
07242 if (new_read_pointer >= pheader->size) {
07243 new_read_pointer = new_read_pointer % pheader->size;
07244
07245
07246 cycle++;
07247 assert(cycle < 2);
07248 }
07249
07250
07251 if (new_read_pointer > pheader->size - (int) sizeof(EVENT_HEADER))
07252 new_read_pointer = 0;
07253
07254 #ifdef DEBUG_MSG
07255 cm_msg(MDEBUG, "bm_push_event -> wp=%d, rp %d -> %d (found=%d,size=%d)",
07256 pheader->write_pointer, pc->read_pointer, new_read_pointer, found, total_size);
07257 #endif
07258
07259 pc->read_pointer = new_read_pointer;
07260
07261 if (use_event_buffer)
07262 break;
07263
07264 } while (pheader->write_pointer != pc->read_pointer);
07265
07266
07267
07268 bm_update_read_pointer("bm_push_event", pheader);
07269
07270
07271
07272
07273
07274
07275
07276 bm_wakeup_producers(pheader, pc);
07277
07278 bm_unlock_buffer(buffer_handle);
07279
07280 if (bm_read_cache_has_events(pbuf)) {
07281 assert(!use_event_buffer);
07282 bm_dispatch_from_cache(pbuf, buffer_handle);
07283 return BM_MORE_EVENTS;
07284 }
07285
07286 if (use_event_buffer) {
07287 bm_dispatch_event(buffer_handle, _event_buffer);
07288 return BM_MORE_EVENTS;
07289 }
07290
07291 return BM_SUCCESS;
07292 }
07293 #else
07294
07295 return BM_SUCCESS;
07296 #endif
07297 }
07298
07299
07300
07301
07302
07303
07304
07305 INT bm_check_buffers()
07306 {
07307 #ifdef LOCAL_ROUTINES
07308 {
07309 INT idx, status = 0;
07310 INT server_type, server_conn, tid;
07311 BOOL bMore;
07312 DWORD start_time;
07313
07314 server_type = rpc_get_server_option(RPC_OSERVER_TYPE);
07315 server_conn = rpc_get_server_acception();
07316 tid = ss_gettid();
07317
07318
07319
07320 if (server_type == ST_SUBPROCESS || server_type == ST_MTHREAD)
07321 return FALSE;
07322
07323 bMore = FALSE;
07324 start_time = ss_millitime();
07325
07326
07327 for (idx = 0; idx < _buffer_entries; idx++) {
07328 if (server_type == ST_SINGLE && _buffer[idx].index != server_conn)
07329 continue;
07330
07331 if (server_type != ST_SINGLE && _buffer[idx].index != tid)
07332 continue;
07333
07334 if (!_buffer[idx].attached)
07335 continue;
07336
07337 do {
07338
07339
07340
07341
07342 if (idx < _buffer_entries && _buffer[idx].buffer_header->name != NULL)
07343 status = bm_push_event(_buffer[idx].buffer_header->name);
07344
07345 if (status != BM_MORE_EVENTS)
07346 break;
07347
07348
07349 if (ss_millitime() - start_time > 1000) {
07350 bMore = TRUE;
07351 break;
07352 }
07353
07354 } while (TRUE);
07355 }
07356
07357 return bMore;
07358
07359 }
07360 #else
07361
07362 return FALSE;
07363
07364 #endif
07365 }
07366
07367
07368 #ifndef DOXYGEN_SHOULD_SKIP_THIS
07369
07370
07371 INT bm_mark_read_waiting(BOOL flag)
07372
07373
07374
07375
07376
07377
07378
07379
07380
07381
07382
07383
07384
07385
07386
07387
07388
07389
07390 {
07391 if (rpc_is_remote())
07392 return rpc_call(RPC_BM_MARK_READ_WAITING, flag);
07393
07394 #ifdef LOCAL_ROUTINES
07395 {
07396 INT i;
07397 BUFFER_HEADER *pheader;
07398 BUFFER_CLIENT *pclient;
07399
07400
07401 for (i = 0; i < _buffer_entries; i++) {
07402 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE
07403 && _buffer[i].index != rpc_get_server_acception())
07404 continue;
07405
07406 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE && _buffer[i].index != ss_gettid())
07407 continue;
07408
07409 if (!_buffer[i].attached)
07410 continue;
07411
07412 pheader = _buffer[i].buffer_header;
07413 pclient = pheader->client + bm_validate_client_index(&_buffer[i]);
07414 pclient->read_wait = flag;
07415 }
07416 }
07417 #endif
07418
07419 return BM_SUCCESS;
07420 }
07421
07422
07423 INT bm_notify_client(char *buffer_name, int s)
07424
07425
07426
07427
07428
07429
07430
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441
07442 {
07443 char buffer[32];
07444 NET_COMMAND *nc;
07445 INT i, convert_flags;
07446 static DWORD last_time = 0;
07447
07448 for (i = 0; i < _buffer_entries; i++)
07449 if (strcmp(buffer_name, _buffer[i].buffer_header->name) == 0)
07450 break;
07451 if (i == _buffer_entries)
07452 return BM_INVALID_HANDLE;
07453
07454
07455
07456 if (!_buffer[i].callback)
07457 return DB_SUCCESS;
07458
07459 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
07460
07461
07462 if (ss_millitime() - last_time < 500 && !(convert_flags & CF_ASCII))
07463 return DB_SUCCESS;
07464
07465 last_time = ss_millitime();
07466
07467 if (convert_flags & CF_ASCII) {
07468 sprintf(buffer, "MSG_BM&%s", buffer_name);
07469 send_tcp(s, buffer, strlen(buffer) + 1, 0);
07470 } else {
07471 nc = (NET_COMMAND *) buffer;
07472
07473 nc->header.routine_id = MSG_BM;
07474 nc->header.param_size = 0;
07475
07476 if (convert_flags) {
07477 rpc_convert_single(&nc->header.routine_id, TID_DWORD, RPC_OUTGOING, convert_flags);
07478 rpc_convert_single(&nc->header.param_size, TID_DWORD, RPC_OUTGOING, convert_flags);
07479 }
07480
07481
07482 send_tcp(s, (char *) buffer, sizeof(NET_COMMAND_HEADER), 0);
07483 }
07484
07485 return BM_SUCCESS;
07486 }
07487
07488
07489 INT bm_poll_event(INT flag)
07490
07491
07492
07493
07494
07495
07496
07497
07498
07499
07500
07501
07502
07503
07504
07505
07506
07507
07508
07509 {
07510 INT status, size, i, request_id;
07511 DWORD start_time;
07512 BOOL bMore;
07513 static BOOL bMoreLast = FALSE;
07514
07515 if (_event_buffer_size == 0) {
07516 HNDLE hDB, odb_key;
07517 int max_event_size = MAX_EVENT_SIZE;
07518
07519
07520 status = cm_get_experiment_database(&hDB, &odb_key);
07521 assert(status == SUCCESS);
07522 size = sizeof(INT);
07523 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &max_event_size, &size, TID_DWORD, TRUE);
07524
07525 size = max_event_size + sizeof(EVENT_HEADER);
07526
07527 _event_buffer = (EVENT_HEADER *) M_MALLOC(size);
07528 if (!_event_buffer) {
07529 cm_msg(MERROR, "bm_poll_event", "not enough memory to allocate event buffer of size %d", size);
07530 return SS_ABORT;
07531 }
07532 _event_buffer_size = size;
07533 }
07534
07535 start_time = ss_millitime();
07536
07537
07538 if (!flag)
07539 bm_mark_read_waiting(FALSE);
07540
07541
07542 if (flag) {
07543 if (!bMoreLast)
07544 return FALSE;
07545 }
07546
07547 bMore = FALSE;
07548
07549
07550 for (request_id = 0; request_id < _request_list_entries; request_id++) {
07551
07552 if (_request_list[request_id].dispatcher == NULL)
07553 continue;
07554
07555 do {
07556
07557 size = _event_buffer_size;
07558 status = bm_receive_event(_request_list[request_id].buffer_handle, _event_buffer, &size, ASYNC);
07559
07560
07561
07562 if (status == BM_SUCCESS)
07563
07564 for (i = 0; i < _request_list_entries; i++)
07565 if ((_request_list[i].buffer_handle ==
07566 _request_list[request_id].buffer_handle) &&
07567 bm_match_event(_request_list[i].event_id, _request_list[i].trigger_mask, _event_buffer)) {
07568 if ((_event_buffer->event_id & 0xF000) == EVENTID_FRAG1 ||
07569 (_event_buffer->event_id & 0xF000) == EVENTID_FRAG)
07570 bm_defragment_event(_request_list[i].buffer_handle, i, _event_buffer,
07571 (void *) (((EVENT_HEADER *) _event_buffer) + 1),
07572 _request_list[i].dispatcher);
07573 else
07574 _request_list[i].dispatcher(_request_list[i].buffer_handle, i,
07575 _event_buffer,
07576 (void *) (((EVENT_HEADER *) _event_buffer) + 1));
07577 }
07578
07579
07580 if (status == BM_ASYNC_RETURN)
07581 break;
07582
07583
07584 if (status == RPC_NET_ERROR)
07585 return SS_ABORT;
07586
07587
07588 if (ss_millitime() - start_time > 1000) {
07589 bMore = TRUE;
07590 break;
07591 }
07592
07593 } while (TRUE);
07594 }
07595
07596 if (!bMore)
07597 bm_mark_read_waiting(TRUE);
07598
07599 bMoreLast = bMore;
07600
07601 return bMore;
07602 }
07603
07604
07605 #endif
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616
07617
07618
07619
07620
07621
07622
07623
07624
07625
07626
07627
07628
07629
07630
07631
07632 INT bm_empty_buffers()
07633 {
07634 if (rpc_is_remote())
07635 return rpc_call(RPC_BM_EMPTY_BUFFERS);
07636
07637 #ifdef LOCAL_ROUTINES
07638 {
07639 INT idx, server_type, server_conn, tid;
07640 BUFFER *pbuf;
07641 BUFFER_CLIENT *pclient;
07642
07643 server_type = rpc_get_server_option(RPC_OSERVER_TYPE);
07644 server_conn = rpc_get_server_acception();
07645 tid = ss_gettid();
07646
07647
07648 for (idx = 0; idx < _buffer_entries; idx++) {
07649 if (server_type == ST_SINGLE && _buffer[idx].index != server_conn)
07650 continue;
07651
07652 if (server_type != ST_SINGLE && _buffer[idx].index != tid)
07653 continue;
07654
07655 if (!_buffer[idx].attached)
07656 continue;
07657
07658 pbuf = &_buffer[idx];
07659
07660
07661 pbuf->read_cache_rp = pbuf->read_cache_wp = 0;
07662
07663
07664 pclient = (pbuf->buffer_header)->client + bm_validate_client_index(pbuf);
07665 bm_lock_buffer(idx + 1);
07666 pclient->read_pointer = (pbuf->buffer_header)->write_pointer;
07667 bm_unlock_buffer(idx + 1);
07668 }
07669
07670 }
07671 #endif
07672
07673 return BM_SUCCESS;
07674 }
07675
07676
07677 #ifndef DOXYGEN_SHOULD_SKIP_THIS
07678
07679 #define MAX_DEFRAG_EVENTS 10
07680
07681 typedef struct {
07682 WORD event_id;
07683 DWORD data_size;
07684 DWORD received;
07685 EVENT_HEADER *pevent;
07686 } EVENT_DEFRAG_BUFFER;
07687
07688 EVENT_DEFRAG_BUFFER defrag_buffer[MAX_DEFRAG_EVENTS];
07689
07690
07691 void bm_defragment_event(HNDLE buffer_handle, HNDLE request_id,
07692 EVENT_HEADER * pevent, void *pdata, void (*dispatcher) (HNDLE, HNDLE, EVENT_HEADER *,
07693 void *))
07694
07695
07696
07697
07698
07699
07700
07701
07702
07703
07704
07705
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716
07717 {
07718 INT i;
07719 static int j = -1;
07720
07721 if ((pevent->event_id & 0xF000) == EVENTID_FRAG1) {
07722
07723
07724
07725
07726
07727 for (i = 0; i < MAX_DEFRAG_EVENTS; i++)
07728 if (defrag_buffer[i].event_id == (pevent->event_id & 0x0FFF))
07729 break;
07730
07731 if (i < MAX_DEFRAG_EVENTS) {
07732 free(defrag_buffer[i].pevent);
07733 memset(&defrag_buffer[i].event_id, 0, sizeof(EVENT_DEFRAG_BUFFER));
07734 cm_msg(MERROR, "bm_defragement_event",
07735 "Received new event with ID %d while old fragments were not completed",
07736 (pevent->event_id & 0x0FFF));
07737 }
07738
07739
07740 for (i = 0; i < MAX_DEFRAG_EVENTS; i++)
07741 if (defrag_buffer[i].event_id == 0)
07742 break;
07743
07744 if (i == MAX_DEFRAG_EVENTS) {
07745 cm_msg(MERROR, "bm_defragment_event",
07746 "Not enough defragment buffers, please increase MAX_DEFRAG_EVENTS and recompile");
07747 return;
07748 }
07749
07750
07751 if (pevent->data_size != sizeof(DWORD)) {
07752 cm_msg(MERROR, "bm_defragment_event",
07753 "Received first event fragment with %s bytes instead of %d bytes, event ignored",
07754 pevent->data_size, sizeof(DWORD));
07755 return;
07756 }
07757
07758
07759 defrag_buffer[i].event_id = (pevent->event_id & 0x0FFF);
07760 defrag_buffer[i].data_size = *(DWORD *) pdata;
07761 defrag_buffer[i].received = 0;
07762 defrag_buffer[i].pevent = (EVENT_HEADER *) malloc(sizeof(EVENT_HEADER) + defrag_buffer[i].data_size);
07763
07764 if (defrag_buffer[i].pevent == NULL) {
07765 memset(&defrag_buffer[i].event_id, 0, sizeof(EVENT_DEFRAG_BUFFER));
07766 cm_msg(MERROR, "bm_defragement_event", "Not enough memory to allocate event defragment buffer");
07767 return;
07768 }
07769
07770 memcpy(defrag_buffer[i].pevent, pevent, sizeof(EVENT_HEADER));
07771 defrag_buffer[i].pevent->event_id = defrag_buffer[i].event_id;
07772 defrag_buffer[i].pevent->data_size = defrag_buffer[i].data_size;
07773
07774
07775
07776
07777 j = 0;
07778
07779 return;
07780 }
07781
07782
07783 for (i = 0; i < MAX_DEFRAG_EVENTS; i++)
07784 if (defrag_buffer[i].event_id == (pevent->event_id & 0xFFF))
07785 break;
07786
07787 if (i == MAX_DEFRAG_EVENTS) {
07788
07789 cm_msg(MERROR, "bm_defragement_event",
07790 "Received fragment without first fragment (ID %d) Ser#:%d",
07791 pevent->event_id & 0x0FFF, pevent->serial_number);
07792 return;
07793 }
07794
07795
07796 if (pevent->data_size + defrag_buffer[i].received > defrag_buffer[i].data_size) {
07797 free(defrag_buffer[i].pevent);
07798 memset(&defrag_buffer[i].event_id, 0, sizeof(EVENT_DEFRAG_BUFFER));
07799 cm_msg(MERROR, "bm_defragement_event",
07800 "Received fragments with more data (%d) than event size (%d)",
07801 pevent->data_size + defrag_buffer[i].received, defrag_buffer[i].data_size);
07802 return;
07803 }
07804
07805 memcpy(((char *) defrag_buffer[i].pevent) + sizeof(EVENT_HEADER) +
07806 defrag_buffer[i].received, pdata, pevent->data_size);
07807
07808 defrag_buffer[i].received += pevent->data_size;
07809
07810
07811
07812
07813 if (defrag_buffer[i].received == defrag_buffer[i].data_size) {
07814
07815 dispatcher(buffer_handle, request_id, defrag_buffer[i].pevent, defrag_buffer[i].pevent + 1);
07816 free(defrag_buffer[i].pevent);
07817 memset(&defrag_buffer[i].event_id, 0, sizeof(EVENT_DEFRAG_BUFFER));
07818 }
07819 }
07820
07821
07822 #endif
07823
07824
07825
07826
07827
07828
07829
07830
07831
07832
07833 #ifndef DOXYGEN_SHOULD_SKIP_THIS
07834
07835
07836
07837
07838
07839
07840
07841
07842
07843 RPC_CLIENT_CONNECTION _client_connection[MAX_RPC_CONNECTION];
07844 RPC_SERVER_CONNECTION _server_connection;
07845
07846 static int _lsock;
07847 RPC_SERVER_ACCEPTION _server_acception[MAX_RPC_CONNECTION];
07848 static INT _server_acception_index = 0;
07849 static INT _server_type;
07850 static char _server_name[256];
07851
07852 static RPC_LIST *rpc_list = NULL;
07853
07854 int _opt_tcp_size = OPT_TCP_SIZE;
07855
07856
07857
07858
07859
07860
07861 void rpc_calc_convert_flags(INT hw_type, INT remote_hw_type, INT * convert_flags)
07862 {
07863 *convert_flags = 0;
07864
07865
07866 if (((remote_hw_type & DRI_BIG_ENDIAN) &&
07867 (hw_type & DRI_LITTLE_ENDIAN)) || ((remote_hw_type & DRI_LITTLE_ENDIAN)
07868 && (hw_type & DRI_BIG_ENDIAN)))
07869 *convert_flags |= CF_ENDIAN;
07870
07871
07872 if ((remote_hw_type & DRF_G_FLOAT) && (hw_type & DRF_IEEE))
07873 *convert_flags |= CF_VAX2IEEE;
07874
07875
07876 if ((remote_hw_type & DRF_IEEE) && (hw_type & DRF_G_FLOAT))
07877 *convert_flags |= CF_IEEE2VAX;
07878
07879
07880 if (remote_hw_type & DR_ASCII)
07881 *convert_flags |= CF_ASCII;
07882 }
07883
07884
07885 void rpc_get_convert_flags(INT * convert_flags)
07886 {
07887 rpc_calc_convert_flags(rpc_get_option(0, RPC_OHW_TYPE), _server_connection.remote_hw_type, convert_flags);
07888 }
07889
07890
07891 void rpc_ieee2vax_float(float *var)
07892 {
07893 unsigned short int lo, hi;
07894
07895
07896 lo = *((short int *) (var) + 1);
07897 hi = *((short int *) (var));
07898
07899
07900 if (lo != 0)
07901 lo += 0x100;
07902
07903 *((short int *) (var) + 1) = hi;
07904 *((short int *) (var)) = lo;
07905 }
07906
07907 void rpc_vax2ieee_float(float *var)
07908 {
07909 unsigned short int lo, hi;
07910
07911
07912 lo = *((short int *) (var) + 1);
07913 hi = *((short int *) (var));
07914
07915
07916 if (hi != 0)
07917 hi -= 0x100;
07918
07919 *((short int *) (var) + 1) = hi;
07920 *((short int *) (var)) = lo;
07921
07922 }
07923
07924 void rpc_vax2ieee_double(double *var)
07925 {
07926 unsigned short int i1, i2, i3, i4;
07927
07928
07929 i1 = *((short int *) (var) + 3);
07930 i2 = *((short int *) (var) + 2);
07931 i3 = *((short int *) (var) + 1);
07932 i4 = *((short int *) (var));
07933
07934
07935 if (i4 != 0)
07936 i4 -= 0x20;
07937
07938 *((short int *) (var) + 3) = i4;
07939 *((short int *) (var) + 2) = i3;
07940 *((short int *) (var) + 1) = i2;
07941 *((short int *) (var)) = i1;
07942 }
07943
07944 void rpc_ieee2vax_double(double *var)
07945 {
07946 unsigned short int i1, i2, i3, i4;
07947
07948
07949 i1 = *((short int *) (var) + 3);
07950 i2 = *((short int *) (var) + 2);
07951 i3 = *((short int *) (var) + 1);
07952 i4 = *((short int *) (var));
07953
07954
07955 if (i1 != 0)
07956 i1 += 0x20;
07957
07958 *((short int *) (var) + 3) = i4;
07959 *((short int *) (var) + 2) = i3;
07960 *((short int *) (var) + 1) = i2;
07961 *((short int *) (var)) = i1;
07962 }
07963
07964
07965 void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
07966 {
07967
07968 if (convert_flags & CF_ENDIAN) {
07969 if (tid == TID_WORD || tid == TID_SHORT)
07970 WORD_SWAP(data);
07971 if (tid == TID_DWORD || tid == TID_INT || tid == TID_BOOL || tid == TID_FLOAT)
07972 DWORD_SWAP(data);
07973 if (tid == TID_DOUBLE)
07974 QWORD_SWAP(data);
07975 }
07976
07977 if (((convert_flags & CF_IEEE2VAX) && !(flags & RPC_OUTGOING)) ||
07978 ((convert_flags & CF_VAX2IEEE) && (flags & RPC_OUTGOING))) {
07979 if (tid == TID_FLOAT)
07980 rpc_ieee2vax_float((float *) data);
07981 if (tid == TID_DOUBLE)
07982 rpc_ieee2vax_double((double *) data);
07983 }
07984
07985 if (((convert_flags & CF_IEEE2VAX) && (flags & RPC_OUTGOING)) ||
07986 ((convert_flags & CF_VAX2IEEE) && !(flags & RPC_OUTGOING))) {
07987 if (tid == TID_FLOAT)
07988 rpc_vax2ieee_float((float *) data);
07989 if (tid == TID_DOUBLE)
07990 rpc_vax2ieee_double((double *) data);
07991 }
07992 }
07993
07994 void rpc_convert_data(void *data, INT tid, INT flags, INT total_size, INT convert_flags)
07995
07996
07997
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007
08008
08009
08010
08011
08012
08013
08014
08015
08016
08017
08018
08019
08020
08021
08022 {
08023 INT i, n, single_size;
08024 char *p;
08025
08026
08027 if (flags & (RPC_FIXARRAY | RPC_VARARRAY)) {
08028 single_size = tid_size[tid];
08029
08030 if (single_size == 0)
08031 return;
08032
08033 n = total_size / single_size;
08034
08035 for (i = 0; i < n; i++) {
08036 p = (char *) data + (i * single_size);
08037 rpc_convert_single(p, tid, flags, convert_flags);
08038 }
08039 } else {
08040 rpc_convert_single(data, tid, flags, convert_flags);
08041 }
08042 }
08043
08044
08045
08046
08047
08048 INT rpc_tid_size(INT id)
08049 {
08050 if (id >= 0 && id < TID_LAST)
08051 return tid_size[id];
08052
08053 return 0;
08054 }
08055
08056 char *rpc_tid_name(INT id)
08057 {
08058 if (id >= 0 && id < TID_LAST)
08059 return tid_name[id];
08060 else
08061 return "<unknown>";
08062 }
08063
08064
08065
08066 #endif
08067
08068
08069
08070
08071
08072
08073
08074
08075
08076
08077
08078
08079
08080
08081
08082
08083 INT rpc_register_client(const char *name, RPC_LIST * list)
08084 {
08085 rpc_set_name(name);
08086 rpc_register_functions(rpc_get_internal_list(0), NULL);
08087 rpc_register_functions(list, NULL);
08088
08089 return RPC_SUCCESS;
08090 }
08091
08092
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102
08103 INT rpc_register_functions(const RPC_LIST * new_list, INT(*func) (INT, void **))
08104 {
08105 INT i, j, iold, inew;
08106
08107
08108 for (i = 0; new_list[i].id != 0; i++) {
08109
08110 for (j = 0; rpc_list != NULL && rpc_list[j].id != 0; j++)
08111 if (rpc_list[j].id == new_list[i].id)
08112 return RPC_DOUBLE_DEFINED;
08113 }
08114 inew = i;
08115
08116
08117 for (i = 0; rpc_list != NULL && rpc_list[i].id != 0; i++);
08118 iold = i;
08119
08120
08121 if (rpc_list == NULL)
08122 rpc_list = (RPC_LIST *) M_MALLOC(sizeof(RPC_LIST) * (inew + 1));
08123 else
08124 rpc_list = (RPC_LIST *) realloc(rpc_list, sizeof(RPC_LIST) * (iold + inew + 1));
08125
08126 if (rpc_list == NULL) {
08127 cm_msg(MERROR, "rpc_register_functions", "out of memory");
08128 return RPC_NO_MEMORY;
08129 }
08130
08131
08132 for (i = iold; i < iold + inew; i++) {
08133 memcpy(rpc_list + i, new_list + i - iold, sizeof(RPC_LIST));
08134
08135
08136 if (rpc_list[i].dispatch == NULL)
08137 rpc_list[i].dispatch = func;
08138
08139
08140 if (new_list != rpc_get_internal_list(0) &&
08141 new_list != rpc_get_internal_list(1) && (rpc_list[i].id < RPC_MIN_ID
08142 || rpc_list[i].id > RPC_MAX_ID))
08143 cm_msg(MERROR, "rpc_register_functions", "registered RPC function with invalid ID");
08144 }
08145
08146
08147 rpc_list[i].id = 0;
08148
08149 return RPC_SUCCESS;
08150 }
08151
08152
08153
08154
08155 #ifndef DOXYGEN_SHOULD_SKIP_THIS
08156
08157
08158 INT rpc_deregister_functions()
08159
08160
08161
08162
08163
08164
08165
08166
08167
08168
08169
08170
08171
08172
08173
08174
08175 {
08176 if (rpc_list)
08177 M_FREE(rpc_list);
08178 rpc_list = NULL;
08179
08180 return RPC_SUCCESS;
08181 }
08182
08183
08184
08185 INT rpc_register_function(INT id, INT(*func) (INT, void **))
08186
08187
08188
08189
08190
08191
08192
08193
08194
08195
08196
08197
08198
08199
08200
08201
08202
08203
08204 {
08205 INT i;
08206
08207 for (i = 0; rpc_list != NULL && rpc_list[i].id != 0; i++)
08208 if (rpc_list[i].id == id)
08209 break;
08210
08211 if (rpc_list[i].id == id)
08212 rpc_list[i].dispatch = func;
08213 else
08214 return RPC_INVALID_ID;
08215
08216 return RPC_SUCCESS;
08217 }
08218
08219
08220
08221 INT rpc_client_dispatch(int sock)
08222
08223
08224
08225
08226
08227
08228
08229
08230 {
08231 INT hDB, hKey, n;
08232 NET_COMMAND *nc;
08233 INT status = 0;
08234 char net_buffer[256];
08235
08236 nc = (NET_COMMAND *) net_buffer;
08237
08238 n = recv_tcp(sock, net_buffer, sizeof(net_buffer), 0);
08239 if (n <= 0)
08240 return SS_ABORT;
08241
08242 if (nc->header.routine_id == MSG_ODB) {
08243
08244 hDB = *((INT *) nc->param);
08245 hKey = *((INT *) nc->param + 1);
08246 status = db_update_record(hDB, hKey, 0);
08247 }
08248
08249 else if (nc->header.routine_id == MSG_WATCHDOG) {
08250 nc->header.routine_id = 1;
08251 nc->header.param_size = 0;
08252 send_tcp(sock, net_buffer, sizeof(NET_COMMAND_HEADER), 0);
08253 status = RPC_SUCCESS;
08254 }
08255
08256 else if (nc->header.routine_id == MSG_BM) {
08257 fd_set readfds;
08258 struct timeval timeout;
08259
08260
08261 do {
08262 FD_ZERO(&readfds);
08263 FD_SET(sock, &readfds);
08264
08265 timeout.tv_sec = 0;
08266 timeout.tv_usec = 0;
08267
08268 select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
08269
08270 if (FD_ISSET(sock, &readfds)) {
08271 n = recv_tcp(sock, net_buffer, sizeof(net_buffer), 0);
08272 if (n <= 0)
08273 return SS_ABORT;
08274
08275 if (nc->header.routine_id == MSG_ODB) {
08276
08277 hDB = *((INT *) nc->param);
08278 hKey = *((INT *) nc->param + 1);
08279 status = db_update_record(hDB, hKey, 0);
08280 }
08281
08282 else if (nc->header.routine_id == MSG_WATCHDOG) {
08283 nc->header.routine_id = 1;
08284 nc->header.param_size = 0;
08285 send_tcp(sock, net_buffer, sizeof(NET_COMMAND_HEADER), 0);
08286 status = RPC_SUCCESS;
08287 }
08288 }
08289
08290 } while (FD_ISSET(sock, &readfds));
08291
08292
08293 status = bm_poll_event(FALSE);
08294 }
08295
08296 return status;
08297 }
08298
08299
08300
08301 INT rpc_client_connect(const char *host_name, INT port, const char *client_name, HNDLE * hConnection)
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322
08323
08324 {
08325 INT i, status, idx;
08326 struct sockaddr_in bind_addr;
08327 INT sock;
08328 INT remote_hw_type, hw_type;
08329 char str[200];
08330 char version[32], v1[32];
08331 char local_prog_name[NAME_LENGTH];
08332 char local_host_name[HOST_NAME_LENGTH];
08333 struct hostent *phe;
08334
08335 #ifdef OS_WINNT
08336 {
08337 WSADATA WSAData;
08338
08339
08340 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
08341 return RPC_NET_ERROR;
08342 }
08343 #endif
08344
08345
08346 if (_client_name[0] == 0) {
08347 cm_msg(MERROR, "rpc_client_connect", "cm_connect_experiment/rpc_set_name not called");
08348 return RPC_NOT_REGISTERED;
08349 }
08350
08351
08352 rpc_client_check();
08353
08354
08355 for (i = 0; i < MAX_RPC_CONNECTION; i++)
08356 if (_client_connection[i].send_sock != 0 &&
08357 strcmp(_client_connection[i].host_name, host_name) == 0 && _client_connection[i].port == port) {
08358 *hConnection = i + 1;
08359 return RPC_SUCCESS;
08360 }
08361
08362
08363 for (i = 0; i < MAX_RPC_CONNECTION; i++)
08364 if (_client_connection[i].send_sock == 0)
08365 break;
08366
08367
08368 if (i == MAX_RPC_CONNECTION) {
08369 cm_msg(MERROR, "rpc_client_connect", "maximum number of connections exceeded");
08370 return RPC_NO_CONNECTION;
08371 }
08372
08373
08374 sock = socket(AF_INET, SOCK_STREAM, 0);
08375 if (sock == -1) {
08376 cm_msg(MERROR, "rpc_client_connect", "cannot create socket");
08377 return RPC_NET_ERROR;
08378 }
08379
08380 idx = i;
08381 strcpy(_client_connection[idx].host_name, host_name);
08382 strcpy(_client_connection[idx].client_name, client_name);
08383 _client_connection[idx].port = port;
08384 _client_connection[idx].exp_name[0] = 0;
08385 _client_connection[idx].transport = RPC_TCP;
08386 _client_connection[idx].rpc_timeout = DEFAULT_RPC_TIMEOUT;
08387 _client_connection[idx].rpc_timeout = DEFAULT_RPC_TIMEOUT;
08388
08389
08390 memset(&bind_addr, 0, sizeof(bind_addr));
08391 bind_addr.sin_family = AF_INET;
08392 bind_addr.sin_addr.s_addr = 0;
08393 bind_addr.sin_port = htons((short) port);
08394
08395 #ifdef OS_VXWORKS
08396 {
08397 INT host_addr;
08398
08399 host_addr = hostGetByName(host_name);
08400 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
08401 }
08402 #else
08403 phe = gethostbyname(host_name);
08404 if (phe == NULL) {
08405 cm_msg(MERROR, "rpc_client_connect", "cannot get host name");
08406 return RPC_NET_ERROR;
08407 }
08408 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
08409 #endif
08410
08411 #ifdef OS_UNIX
08412 do {
08413 status = connect(sock, (void *) &bind_addr, sizeof(bind_addr));
08414
08415
08416 } while (status == -1 && errno == EINTR);
08417 #else
08418 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08419 #endif
08420
08421 if (status != 0) {
08422
08423
08424 return RPC_NET_ERROR;
08425 }
08426
08427
08428 i = 1;
08429 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
08430
08431
08432 rpc_get_name(local_prog_name);
08433 gethostname(local_host_name, sizeof(local_host_name));
08434
08435 hw_type = rpc_get_option(0, RPC_OHW_TYPE);
08436 sprintf(str, "%d %s %s %s", hw_type, cm_get_version(), local_prog_name, local_host_name);
08437
08438 send(sock, str, strlen(str) + 1, 0);
08439
08440
08441 i = recv_string(sock, str, sizeof(str), _rpc_connect_timeout);
08442 if (i <= 0) {
08443 cm_msg(MERROR, "rpc_client_connect", "timeout on receive remote computer info: %s", str);
08444 return RPC_NET_ERROR;
08445 }
08446
08447 remote_hw_type = version[0] = 0;
08448 sscanf(str, "%d %s", &remote_hw_type, version);
08449 _client_connection[idx].remote_hw_type = remote_hw_type;
08450 _client_connection[idx].send_sock = sock;
08451
08452
08453 strcpy(v1, version);
08454 if (strchr(v1, '.'))
08455 if (strchr(strchr(v1, '.') + 1, '.'))
08456 *strchr(strchr(v1, '.') + 1, '.') = 0;
08457
08458 strcpy(str, cm_get_version());
08459 if (strchr(str, '.'))
08460 if (strchr(strchr(str, '.') + 1, '.'))
08461 *strchr(strchr(str, '.') + 1, '.') = 0;
08462
08463 if (strcmp(v1, str) != 0) {
08464 sprintf(str, "remote MIDAS version %s differs from local version %s", version, cm_get_version());
08465 cm_msg(MERROR, "rpc_client_connect", str);
08466 }
08467
08468 *hConnection = idx + 1;
08469
08470 return RPC_SUCCESS;
08471 }
08472
08473
08474 void rpc_client_check()
08475
08476
08477
08478
08479
08480
08481
08482
08483
08484
08485
08486
08487
08488 {
08489 INT i, status;
08490
08491
08492 for (i = 0; i < MAX_RPC_CONNECTION; i++)
08493 if (_client_connection[i].send_sock != 0) {
08494 int sock;
08495 fd_set readfds;
08496 struct timeval timeout;
08497 char buffer[64];
08498
08499 sock = _client_connection[i].send_sock;
08500 FD_ZERO(&readfds);
08501 FD_SET(sock, &readfds);
08502
08503 timeout.tv_sec = 0;
08504 timeout.tv_usec = 0;
08505
08506 do {
08507 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
08508 } while (status == -1);
08509
08510 if (FD_ISSET(sock, &readfds)) {
08511 status = recv(sock, (char *) buffer, sizeof(buffer), 0);
08512
08513 if (equal_ustring(buffer, "EXIT")) {
08514
08515 closesocket(sock);
08516 memset(&_client_connection[i], 0, sizeof(RPC_CLIENT_CONNECTION));
08517 }
08518
08519 if (status <= 0) {
08520 cm_msg(MERROR, "rpc_client_check",
08521 "Connection broken to \"%s\" on host %s",
08522 _client_connection[i].client_name, _client_connection[i].host_name);
08523
08524
08525 closesocket(sock);
08526 memset(&_client_connection[i], 0, sizeof(RPC_CLIENT_CONNECTION));
08527 }
08528 }
08529 }
08530 }
08531
08532
08533
08534 INT rpc_server_connect(const char *host_name, const char *exp_name)
08535
08536
08537
08538
08539
08540
08541
08542
08543
08544
08545
08546
08547
08548
08549
08550
08551
08552
08553
08554
08555
08556
08557
08558
08559
08560
08561
08562 {
08563 INT i, status, flag;
08564 struct sockaddr_in bind_addr;
08565 INT sock, lsock1, lsock2, lsock3;
08566 INT listen_port1, listen_port2, listen_port3;
08567 INT remote_hw_type, hw_type;
08568 unsigned int size;
08569 char str[200], version[32], v1[32];
08570 char local_prog_name[NAME_LENGTH];
08571 struct hostent *phe;
08572 fd_set readfds;
08573 struct timeval timeout;
08574 int port = MIDAS_TCP_PORT;
08575 char *s;
08576
08577 #ifdef OS_WINNT
08578 {
08579 WSADATA WSAData;
08580
08581
08582 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
08583 return RPC_NET_ERROR;
08584 }
08585 #endif
08586
08587
08588 if (host_name[0] == 0)
08589 return RPC_SUCCESS;
08590
08591
08592 rpc_register_functions(rpc_get_internal_list(0), NULL);
08593
08594
08595 if (_client_name[0] == 0) {
08596 cm_msg(MERROR, "rpc_server_connect", "cm_connect_experiment/rpc_set_name not called");
08597 return RPC_NOT_REGISTERED;
08598 }
08599
08600
08601 if (_server_connection.send_sock != 0)
08602 return RPC_SUCCESS;
08603
08604 strcpy(_server_connection.host_name, host_name);
08605 strcpy(_server_connection.exp_name, exp_name);
08606 _server_connection.transport = RPC_TCP;
08607 _server_connection.rpc_timeout = DEFAULT_RPC_TIMEOUT;
08608
08609
08610 lsock1 = socket(AF_INET, SOCK_STREAM, 0);
08611 lsock2 = socket(AF_INET, SOCK_STREAM, 0);
08612 lsock3 = socket(AF_INET, SOCK_STREAM, 0);
08613 if (lsock3 == -1) {
08614 cm_msg(MERROR, "rpc_server_connect", "cannot create socket");
08615 return RPC_NET_ERROR;
08616 }
08617
08618 flag = 1;
08619 setsockopt(lsock1, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT));
08620 setsockopt(lsock2, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT));
08621 setsockopt(lsock3, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT));
08622
08623
08624 memset(&bind_addr, 0, sizeof(bind_addr));
08625 bind_addr.sin_family = AF_INET;
08626 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
08627 bind_addr.sin_port = 0;
08628
08629 status = bind(lsock1, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08630 bind_addr.sin_port = 0;
08631 status = bind(lsock2, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08632 bind_addr.sin_port = 0;
08633 status = bind(lsock3, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08634 if (status < 0) {
08635 cm_msg(MERROR, "rpc_server_connect", "cannot bind");
08636 return RPC_NET_ERROR;
08637 }
08638
08639
08640 status = listen(lsock1, 1);
08641 status = listen(lsock2, 1);
08642 status = listen(lsock3, 1);
08643 if (status < 0) {
08644 cm_msg(MERROR, "rpc_server_connect", "cannot listen");
08645 return RPC_NET_ERROR;
08646 }
08647
08648
08649 size = sizeof(bind_addr);
08650 #ifdef OS_WINNT
08651 getsockname(lsock1, (struct sockaddr *) &bind_addr, (int *) &size);
08652 listen_port1 = ntohs(bind_addr.sin_port);
08653 getsockname(lsock2, (struct sockaddr *) &bind_addr, (int *) &size);
08654 listen_port2 = ntohs(bind_addr.sin_port);
08655 getsockname(lsock3, (struct sockaddr *) &bind_addr, (int *) &size);
08656 listen_port3 = ntohs(bind_addr.sin_port);
08657 #else
08658 getsockname(lsock1, (struct sockaddr *) &bind_addr, &size);
08659 listen_port1 = ntohs(bind_addr.sin_port);
08660 getsockname(lsock2, (struct sockaddr *) &bind_addr, &size);
08661 listen_port2 = ntohs(bind_addr.sin_port);
08662 getsockname(lsock3, (struct sockaddr *) &bind_addr, &size);
08663 listen_port3 = ntohs(bind_addr.sin_port);
08664 #endif
08665
08666
08667 sock = socket(AF_INET, SOCK_STREAM, 0);
08668 if (sock == -1) {
08669 cm_msg(MERROR, "rpc_server_connect", "cannot create socket");
08670 return RPC_NET_ERROR;
08671 }
08672
08673
08674 strlcpy(str, host_name, sizeof(str));
08675 s = strchr(str, ':');
08676 if (s) {
08677 *s = 0;
08678 port = strtoul(s + 1, NULL, 0);
08679 }
08680
08681
08682 memset(&bind_addr, 0, sizeof(bind_addr));
08683 bind_addr.sin_family = AF_INET;
08684 bind_addr.sin_addr.s_addr = 0;
08685 bind_addr.sin_port = htons(port);
08686
08687 #ifdef OS_VXWORKS
08688 {
08689 INT host_addr;
08690
08691 host_addr = hostGetByName(str);
08692 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
08693 }
08694 #else
08695 phe = gethostbyname(str);
08696 if (phe == NULL) {
08697 cm_msg(MERROR, "rpc_server_connect", "cannot resolve host name \'%s\'", str);
08698 return RPC_NET_ERROR;
08699 }
08700 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
08701 #endif
08702
08703 #ifdef OS_UNIX
08704 do {
08705 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08706
08707
08708 } while (status == -1 && errno == EINTR);
08709 #else
08710 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
08711 #endif
08712
08713 if (status != 0) {
08714
08715 return RPC_NET_ERROR;
08716 }
08717
08718
08719 if (exp_name[0] == 0)
08720 sprintf(str, "C %d %d %d %s Default", listen_port1, listen_port2, listen_port3, cm_get_version());
08721 else
08722 sprintf(str, "C %d %d %d %s %s", listen_port1, listen_port2, listen_port3, cm_get_version(), exp_name);
08723
08724 send(sock, str, strlen(str) + 1, 0);
08725 i = recv_string(sock, str, sizeof(str), _rpc_connect_timeout);
08726 closesocket(sock);
08727 if (i <= 0) {
08728 cm_msg(MERROR, "rpc_server_connect", "timeout on receive status from server");
08729 return RPC_NET_ERROR;
08730 }
08731
08732 status = version[0] = 0;
08733 sscanf(str, "%d %s", &status, version);
08734
08735 if (status == 2) {
08736
08737 return CM_UNDEF_EXP;
08738 }
08739
08740
08741 strcpy(v1, version);
08742 if (strchr(v1, '.'))
08743 if (strchr(strchr(v1, '.') + 1, '.'))
08744 *strchr(strchr(v1, '.') + 1, '.') = 0;
08745
08746 strcpy(str, cm_get_version());
08747 if (strchr(str, '.'))
08748 if (strchr(strchr(str, '.') + 1, '.'))
08749 *strchr(strchr(str, '.') + 1, '.') = 0;
08750
08751 if (strcmp(v1, str) != 0) {
08752 sprintf(str, "remote MIDAS version %s differs from local version %s", version, cm_get_version());
08753 cm_msg(MERROR, "rpc_server_connect", str);
08754 }
08755
08756
08757 FD_ZERO(&readfds);
08758 FD_SET(lsock1, &readfds);
08759 FD_SET(lsock2, &readfds);
08760 FD_SET(lsock3, &readfds);
08761
08762 timeout.tv_sec = _rpc_connect_timeout / 1000;
08763 timeout.tv_usec = 0;
08764
08765 do {
08766 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
08767
08768
08769 if (status == -1 && timeout.tv_sec >= WATCHDOG_INTERVAL / 1000)
08770 timeout.tv_sec -= WATCHDOG_INTERVAL / 1000;
08771
08772 } while (status == -1);
08773
08774 if (!FD_ISSET(lsock1, &readfds)) {
08775 cm_msg(MERROR, "rpc_server_connect", "mserver subprocess could not be started (check path)");
08776 closesocket(lsock1);
08777 closesocket(lsock2);
08778 closesocket(lsock3);
08779 return RPC_NET_ERROR;
08780 }
08781
08782 size = sizeof(bind_addr);
08783
08784 #ifdef OS_WINNT
08785 _server_connection.send_sock = accept(lsock1, (struct sockaddr *) &bind_addr, (int *) &size);
08786 _server_connection.recv_sock = accept(lsock2, (struct sockaddr *) &bind_addr, (int *) &size);
08787 _server_connection.event_sock = accept(lsock3, (struct sockaddr *) &bind_addr, (int *) &size);
08788 #else
08789 _server_connection.send_sock = accept(lsock1, (struct sockaddr *) &bind_addr, &size);
08790 _server_connection.recv_sock = accept(lsock2, (struct sockaddr *) &bind_addr, &size);
08791 _server_connection.event_sock = accept(lsock3, (struct sockaddr *) &bind_addr, &size);
08792 #endif
08793
08794 if (_server_connection.send_sock == -1 || _server_connection.recv_sock == -1
08795 || _server_connection.event_sock == -1) {
08796 cm_msg(MERROR, "rpc_server_connect", "accept() failed");
08797 return RPC_NET_ERROR;
08798 }
08799
08800 closesocket(lsock1);
08801 closesocket(lsock2);
08802 closesocket(lsock3);
08803
08804
08805 flag = 1;
08806 setsockopt(_server_connection.send_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
08807 setsockopt(_server_connection.event_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag));
08808
08809
08810 flag = 2 * 1024 * 1024;
08811 status = setsockopt(_server_connection.event_sock, SOL_SOCKET, SO_SNDBUF, (char *) &flag, sizeof(flag));
08812 if (status != 0)
08813 cm_msg(MERROR, "rpc_server_connect", "cannot setsockopt(SOL_SOCKET, SO_SNDBUF), errno %d (%s)", errno,
08814 strerror(errno));
08815
08816
08817 rpc_get_name(local_prog_name);
08818 hw_type = rpc_get_option(0, RPC_OHW_TYPE);
08819 sprintf(str, "%d %s", hw_type, local_prog_name);
08820
08821 send(_server_connection.send_sock, str, strlen(str) + 1, 0);
08822
08823
08824 i = recv_string(_server_connection.send_sock, str, sizeof(str), _rpc_connect_timeout);
08825 if (i <= 0) {
08826 cm_msg(MERROR, "rpc_server_connect", "timeout on receive remote computer info");
08827 return RPC_NET_ERROR;
08828 }
08829
08830 sscanf(str, "%d", &remote_hw_type);
08831 _server_connection.remote_hw_type = remote_hw_type;
08832
08833
08834 ss_suspend_set_dispatch(CH_CLIENT, &_server_connection, (int (*)(void)) rpc_client_dispatch);
08835
08836 return RPC_SUCCESS;
08837 }
08838
08839
08840 INT rpc_client_disconnect(HNDLE hConn, BOOL bShutdown)
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852
08853
08854
08855
08856
08857
08858 {
08859 INT i;
08860
08861 if (hConn == -1) {
08862
08863 for (i = MAX_RPC_CONNECTION - 1; i >= 0; i--)
08864 if (_client_connection[i].send_sock != 0)
08865 rpc_client_disconnect(i + 1, FALSE);
08866
08867
08868 for (i = 0; i < MAX_RPC_CONNECTION; i++)
08869 if (_server_acception[i].recv_sock) {
08870 send(_server_acception[i].recv_sock, "EXIT", 5, 0);
08871 closesocket(_server_acception[i].recv_sock);
08872 }
08873 } else {
08874
08875
08876
08877 rpc_set_option(hConn, RPC_OTRANSPORT, RPC_FTCP);
08878 rpc_client_call(hConn, bShutdown ? RPC_ID_SHUTDOWN : RPC_ID_EXIT);
08879
08880
08881 if (_client_connection[hConn - 1].send_sock)
08882 closesocket(_client_connection[hConn - 1].send_sock);
08883
08884 memset(&_client_connection[hConn - 1], 0, sizeof(RPC_CLIENT_CONNECTION));
08885 }
08886
08887 return RPC_SUCCESS;
08888 }
08889
08890
08891
08892 INT rpc_server_disconnect()
08893
08894
08895
08896
08897
08898
08899
08900
08901
08902
08903
08904
08905
08906
08907
08908
08909
08910
08911
08912 {
08913 static int rpc_server_disconnect_recursion_level = 0;
08914
08915 if (rpc_server_disconnect_recursion_level)
08916 return RPC_SUCCESS;
08917
08918 rpc_server_disconnect_recursion_level = 1;
08919
08920
08921 rpc_flush_event();
08922
08923
08924 rpc_call(RPC_ID_EXIT);
08925
08926
08927 closesocket(_server_connection.send_sock);
08928 closesocket(_server_connection.recv_sock);
08929 closesocket(_server_connection.event_sock);
08930
08931 memset(&_server_connection, 0, sizeof(RPC_SERVER_CONNECTION));
08932
08933
08934 if (_mutex_rpc)
08935 ss_mutex_delete(_mutex_rpc);
08936
08937 rpc_server_disconnect_recursion_level = 0;
08938 return RPC_SUCCESS;
08939 }
08940
08941
08942
08943 INT rpc_is_remote(void)
08944
08945
08946
08947
08948
08949
08950
08951
08952
08953
08954
08955
08956
08957
08958
08959
08960 {
08961 return _server_connection.send_sock != 0;
08962 }
08963
08964
08965
08966 INT rpc_get_server_acception(void)
08967
08968
08969
08970
08971
08972
08973
08974
08975
08976
08977
08978
08979
08980
08981
08982
08983 {
08984 return _server_acception_index;
08985 }
08986
08987
08988
08989 INT rpc_set_server_acception(INT idx)
08990
08991
08992
08993
08994
08995
08996
08997
08998
08999
09000
09001
09002
09003
09004
09005
09006 {
09007 _server_acception_index = idx;
09008 return RPC_SUCCESS;
09009 }
09010
09011
09012
09013 INT rpc_get_option(HNDLE hConn, INT item)
09014
09015
09016
09017
09018
09019
09020
09021
09022
09023
09024
09025
09026
09027
09028
09029
09030
09031
09032 {
09033 switch (item) {
09034 case RPC_OTIMEOUT:
09035 if (hConn == -1)
09036 return _server_connection.rpc_timeout;
09037 if (hConn == -2)
09038 return _rpc_connect_timeout;
09039 return _client_connection[hConn - 1].rpc_timeout;
09040
09041 case RPC_OTRANSPORT:
09042 if (hConn == -1)
09043 return _server_connection.transport;
09044 return _client_connection[hConn - 1].transport;
09045
09046 case RPC_OHW_TYPE:
09047 {
09048 INT tmp_type, size;
09049 DWORD dummy;
09050 unsigned char *p;
09051 float f;
09052 double d;
09053
09054 tmp_type = 0;
09055
09056
09057 size = sizeof(p);
09058 if (size == 2)
09059 tmp_type |= DRI_16;
09060 if (size == 4)
09061 tmp_type |= DRI_32;
09062 if (size == 8)
09063 tmp_type |= DRI_64;
09064
09065
09066 dummy = 0x12345678;
09067 p = (unsigned char *) &dummy;
09068 if (*p == 0x78)
09069 tmp_type |= DRI_LITTLE_ENDIAN;
09070 else if (*p == 0x12)
09071 tmp_type |= DRI_BIG_ENDIAN;
09072 else
09073 cm_msg(MERROR, "rpc_get_option", "unknown byte order format");
09074
09075
09076 f = (float) 1.2345;
09077 dummy = 0;
09078 memcpy(&dummy, &f, sizeof(f));
09079 if ((dummy & 0xFF) == 0x19 &&
09080 ((dummy >> 8) & 0xFF) == 0x04 && ((dummy >> 16) & 0xFF) == 0x9E
09081 && ((dummy >> 24) & 0xFF) == 0x3F)
09082 tmp_type |= DRF_IEEE;
09083 else if ((dummy & 0xFF) == 0x9E &&
09084 ((dummy >> 8) & 0xFF) == 0x40 && ((dummy >> 16) & 0xFF) == 0x19
09085 && ((dummy >> 24) & 0xFF) == 0x04)
09086 tmp_type |= DRF_G_FLOAT;
09087 else
09088 cm_msg(MERROR, "rpc_get_option", "unknown floating point format");
09089
09090 d = (double) 1.2345;
09091 dummy = 0;
09092 memcpy(&dummy, &d, sizeof(f));
09093 if ((dummy & 0xFF) == 0x8D &&
09094 ((dummy >> 8) & 0xFF) == 0x97 && ((dummy >> 16) & 0xFF) == 0x6E
09095 && ((dummy >> 24) & 0xFF) == 0x12)
09096 tmp_type |= DRF_IEEE;
09097 else if ((dummy & 0xFF) == 0x83 &&
09098 ((dummy >> 8) & 0xFF) == 0xC0 && ((dummy >> 16) & 0xFF) == 0xF3
09099 && ((dummy >> 24) & 0xFF) == 0x3F)
09100 tmp_type |= DRF_IEEE;
09101 else if ((dummy & 0xFF) == 0x13 &&
09102 ((dummy >> 8) & 0xFF) == 0x40 && ((dummy >> 16) & 0xFF) == 0x83
09103 && ((dummy >> 24) & 0xFF) == 0xC0)
09104 tmp_type |= DRF_G_FLOAT;
09105 else if ((dummy & 0xFF) == 0x9E &&
09106 ((dummy >> 8) & 0xFF) == 0x40 && ((dummy >> 16) & 0xFF) == 0x18
09107 && ((dummy >> 24) & 0xFF) == 0x04)
09108 cm_msg(MERROR, "rpc_get_option",
09109 "MIDAS cannot handle VAX D FLOAT format. Please compile with the /g_float flag");
09110 else
09111 cm_msg(MERROR, "rpc_get_option", "unknown floating point format");
09112
09113 return tmp_type;
09114 }
09115
09116 default:
09117 cm_msg(MERROR, "rpc_get_option", "invalid argument");
09118 break;
09119 }
09120
09121 return 0;
09122 }
09123
09124
09125 #endif
09126
09127
09128
09129
09130
09131
09132
09133
09134
09135 INT rpc_set_option(HNDLE hConn, INT item, INT value)
09136 {
09137 switch (item) {
09138 case RPC_OTIMEOUT:
09139 if (hConn == -1)
09140 _server_connection.rpc_timeout = value;
09141 else if (hConn == -2)
09142 _rpc_connect_timeout = value;
09143 else
09144 _client_connection[hConn - 1].rpc_timeout = value;
09145 break;
09146
09147 case RPC_OTRANSPORT:
09148 if (hConn == -1)
09149 _server_connection.transport = value;
09150 else
09151 _client_connection[hConn - 1].transport = value;
09152 break;
09153
09154 case RPC_NODELAY:
09155 if (hConn == -1)
09156 setsockopt(_server_connection.send_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &value, sizeof(value));
09157 else
09158 setsockopt(_client_connection[hConn - 1].send_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &value,
09159 sizeof(value));
09160 break;
09161
09162 default:
09163 cm_msg(MERROR, "rpc_set_option", "invalid argument");
09164 break;
09165 }
09166
09167 return 0;
09168 }
09169
09170
09171
09172 #ifndef DOXYGEN_SHOULD_SKIP_THIS
09173
09174
09175 POINTER_T rpc_get_server_option(INT item)
09176
09177
09178
09179
09180
09181
09182
09183
09184
09185
09186
09187
09188
09189
09190
09191
09192 {
09193 INT i;
09194
09195 if (item == RPC_OSERVER_TYPE)
09196 return _server_type;
09197
09198 if (item == RPC_OSERVER_NAME)
09199 return (POINTER_T) _server_name;
09200
09201
09202 if (_server_type == ST_NONE)
09203 return 0;
09204
09205
09206 if (_server_type == ST_MTHREAD) {
09207 for (i = 0; i < MAX_RPC_CONNECTION; i++)
09208 if (_server_acception[i].tid == ss_gettid())
09209 break;
09210 } else if (_server_type == ST_SINGLE || _server_type == ST_REMOTE)
09211 i = MAX(0, _server_acception_index - 1);
09212 else
09213 i = 0;
09214
09215 switch (item) {
09216 case RPC_CONVERT_FLAGS:
09217 return _server_acception[i].convert_flags;
09218 case RPC_ODB_HANDLE:
09219 return _server_acception[i].odb_handle;
09220 case RPC_CLIENT_HANDLE:
09221 return _server_acception[i].client_handle;
09222 case RPC_SEND_SOCK:
09223 return _server_acception[i].send_sock;
09224 case RPC_WATCHDOG_TIMEOUT:
09225 return _server_acception[i].watchdog_timeout;
09226 }
09227
09228 return 0;
09229 }
09230
09231
09232
09233 INT rpc_set_server_option(INT item, POINTER_T value)
09234
09235
09236
09237
09238
09239
09240
09241
09242
09243
09244
09245
09246
09247
09248
09249
09250
09251 {
09252 INT i;
09253
09254 if (item == RPC_OSERVER_TYPE) {
09255 _server_type = value;
09256 return RPC_SUCCESS;
09257 }
09258 if (item == RPC_OSERVER_NAME) {
09259 strcpy(_server_name, (char *) value);
09260 return RPC_SUCCESS;
09261 }
09262
09263
09264 if (_server_type == ST_MTHREAD) {
09265 for (i = 0; i < MAX_RPC_CONNECTION; i++)
09266 if (_server_acception[i].tid == ss_gettid())
09267 break;
09268 } else if (_server_type == ST_SINGLE || _server_type == ST_REMOTE)
09269 i = MAX(0, _server_acception_index - 1);
09270 else
09271 i = 0;
09272
09273 switch (item) {
09274 case RPC_CONVERT_FLAGS:
09275 _server_acception[i].convert_flags = value;
09276 break;
09277 case RPC_ODB_HANDLE:
09278 _server_acception[i].odb_handle = value;
09279 break;
09280 case RPC_CLIENT_HANDLE:
09281 _server_acception[i].client_handle = value;
09282 break;
09283 case RPC_WATCHDOG_TIMEOUT:
09284 _server_acception[i].watchdog_timeout = value;
09285 break;
09286 }
09287
09288 return RPC_SUCCESS;
09289 }
09290
09291
09292
09293 INT rpc_get_name(char *name)
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311 {
09312 strcpy(name, _client_name);
09313
09314 return RPC_SUCCESS;
09315 }
09316
09317
09318
09319 INT rpc_set_name(const char *name)
09320
09321
09322
09323
09324
09325
09326
09327
09328
09329
09330
09331
09332
09333
09334
09335
09336
09337 {
09338 strcpy(_client_name, name);
09339
09340 return RPC_SUCCESS;
09341 }
09342
09343
09344
09345 INT rpc_set_debug(void (*func) (char *), INT mode)
09346
09347
09348
09349
09350
09351
09352
09353
09354
09355
09356
09357
09358
09359
09360
09361
09362
09363
09364
09365 {
09366 _debug_print = func;
09367 _debug_mode = mode;
09368 return RPC_SUCCESS;
09369 }
09370
09371
09372 void rpc_debug_printf(const char *format, ...)
09373
09374
09375
09376
09377
09378
09379
09380
09381
09382
09383
09384
09385
09386 {
09387 va_list argptr;
09388 char str[1000];
09389
09390 if (_debug_mode) {
09391 va_start(argptr, format);
09392 vsprintf(str, (char *) format, argptr);
09393 va_end(argptr);
09394
09395 if (_debug_print) {
09396 strcat(str, "\n");
09397 _debug_print(str);
09398 } else
09399 puts(str);
09400 }
09401 }
09402
09403
09404 void rpc_va_arg(va_list * arg_ptr, INT arg_type, void *arg)
09405 {
09406 switch (arg_type) {
09407
09408
09409
09410 case TID_BYTE:
09411 case TID_SBYTE:
09412 case TID_CHAR:
09413 case TID_WORD:
09414 case TID_SHORT:
09415 *((int *) arg) = va_arg(*arg_ptr, int);
09416 break;
09417
09418 case TID_INT:
09419 case TID_BOOL:
09420 *((INT *) arg) = va_arg(*arg_ptr, INT);
09421 break;
09422
09423 case TID_DWORD:
09424 *((DWORD *) arg) = va_arg(*arg_ptr, DWORD);
09425 break;
09426
09427
09428 case TID_FLOAT:
09429 *((float *) arg) = (float) va_arg(*arg_ptr, double);
09430 break;
09431
09432 case TID_DOUBLE:
09433 *((double *) arg) = va_arg(*arg_ptr, double);
09434 break;
09435
09436 case TID_ARRAY:
09437 *((char **) arg) = va_arg(*arg_ptr, char *);
09438 break;
09439 }
09440 }
09441
09442
09443 INT rpc_client_call(HNDLE hConn, const INT routine_id, ...)
09444
09445
09446
09447
09448
09449
09450
09451
09452
09453
09454
09455
09456
09457
09458
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468 {
09469 va_list ap, aptmp;
09470 char arg[8], arg_tmp[8];
09471 INT arg_type, transport, rpc_timeout;
09472 INT i, idx, status, rpc_index;
09473 INT param_size, arg_size, send_size;
09474 INT tid, flags;
09475 fd_set readfds;
09476 struct timeval timeout;
09477 char *param_ptr, str[80];
09478 BOOL bpointer, bbig;
09479 NET_COMMAND *nc;
09480 int send_sock;
09481 time_t start_time;
09482
09483 idx = hConn - 1;
09484
09485 if (_client_connection[idx].send_sock == 0) {
09486 cm_msg(MERROR, "rpc_client_call", "no rpc connection");
09487 return RPC_NO_CONNECTION;
09488 }
09489
09490 send_sock = _client_connection[idx].send_sock;
09491 rpc_timeout = _client_connection[idx].rpc_timeout;
09492 transport = _client_connection[idx].transport;
09493
09494 status = resize_net_send_buffer("rpc_client_call", NET_BUFFER_SIZE);
09495 if (status != SUCCESS)
09496 return RPC_EXCEED_BUFFER;
09497
09498 nc = (NET_COMMAND *) _net_send_buffer;
09499 nc->header.routine_id = routine_id;
09500
09501 if (transport == RPC_FTCP)
09502 nc->header.routine_id |= TCP_FAST;
09503
09504 for (i = 0;; i++)
09505 if (rpc_list[i].id == routine_id || rpc_list[i].id == 0)
09506 break;
09507 rpc_index = i;
09508 if (rpc_list[i].id == 0) {
09509 sprintf(str, "invalid rpc ID (%d)", routine_id);
09510 cm_msg(MERROR, "rpc_client_call", str);
09511 return RPC_INVALID_ID;
09512 }
09513
09514
09515 va_start(ap, routine_id);
09516
09517
09518 bbig = ((rpc_get_option(0, RPC_OHW_TYPE) & DRI_BIG_ENDIAN) > 0);
09519
09520 for (i = 0, param_ptr = nc->param; rpc_list[rpc_index].param[i].tid != 0; i++) {
09521 tid = rpc_list[rpc_index].param[i].tid;
09522 flags = rpc_list[rpc_index].param[i].flags;
09523
09524 bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
09525 (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
09526 tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
09527
09528 if (bpointer)
09529 arg_type = TID_ARRAY;
09530 else
09531 arg_type = tid;
09532
09533
09534 if (tid == TID_FLOAT && !bpointer)
09535 arg_type = TID_DOUBLE;
09536
09537
09538 rpc_va_arg(&ap, arg_type, arg);
09539
09540
09541 if (bbig) {
09542 if (tid == TID_BYTE || tid == TID_CHAR || tid == TID_SBYTE) {
09543 arg[0] = arg[3];
09544 }
09545 if (tid == TID_WORD || tid == TID_SHORT) {
09546 arg[0] = arg[2];
09547 arg[1] = arg[3];
09548 }
09549 }
09550
09551 if (flags & RPC_IN) {
09552 if (bpointer)
09553 arg_size = tid_size[tid];
09554 else
09555 arg_size = tid_size[arg_type];
09556
09557
09558 if (tid == TID_STRING || tid == TID_LINK)
09559 arg_size = 1 + strlen((char *) *((char **) arg));
09560
09561
09562
09563 if (flags & RPC_VARARRAY) {
09564 memcpy(&aptmp, &ap, sizeof(ap));
09565 rpc_va_arg(&aptmp, TID_ARRAY, arg_tmp);
09566
09567 if (flags & RPC_OUT)
09568 arg_size = *((INT *) * ((void **) arg_tmp));
09569 else
09570 arg_size = *((INT *) arg_tmp);
09571
09572 *((INT *) param_ptr) = ALIGN8(arg_size);
09573 param_ptr += ALIGN8(sizeof(INT));
09574 }
09575
09576 if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
09577 arg_size = rpc_list[rpc_index].param[i].n;
09578
09579
09580 param_size = ALIGN8(arg_size);
09581
09582 if ((POINTER_T) param_ptr - (POINTER_T) nc + param_size > _net_send_buffer_size) {
09583 cm_msg(MERROR, "rpc_client_call",
09584 "parameters (%d) too large for network buffer (%d)",
09585 (POINTER_T) param_ptr - (POINTER_T) nc + param_size, _net_send_buffer_size);
09586 return RPC_EXCEED_BUFFER;
09587 }
09588
09589 if (bpointer)
09590 memcpy(param_ptr, (void *) *((void **) arg), arg_size);
09591 else {
09592
09593 if (tid != TID_FLOAT)
09594 memcpy(param_ptr, arg, arg_size);
09595 else
09596 *((float *) param_ptr) = (float) *((double *) arg);
09597 }
09598
09599 param_ptr += param_size;
09600
09601 }
09602 }
09603
09604 va_end(ap);
09605
09606 nc->header.param_size = (POINTER_T) param_ptr - (POINTER_T) nc->param;
09607
09608 send_size = nc->header.param_size + sizeof(NET_COMMAND_HEADER);
09609
09610
09611 if (transport == RPC_FTCP) {
09612 i = send_tcp(send_sock, (char *) nc, send_size, 0);
09613
09614 if (i != send_size) {
09615 cm_msg(MERROR, "rpc_client_call", "send_tcp() failed");
09616 return RPC_NET_ERROR;
09617 }
09618
09619 return RPC_SUCCESS;
09620 }
09621
09622
09623 i = send_tcp(send_sock, (char *) nc, send_size, 0);
09624 if (i != send_size) {
09625 cm_msg(MERROR, "rpc_client_call",
09626 "send_tcp() failed, routine = \"%s\", host = \"%s\"",
09627 rpc_list[rpc_index].name, _client_connection[idx].host_name);
09628 return RPC_NET_ERROR;
09629 }
09630
09631
09632 if (rpc_timeout > 0) {
09633 start_time = ss_time();
09634
09635 do {
09636 FD_ZERO(&readfds);
09637 FD_SET(send_sock, &readfds);
09638
09639 timeout.tv_sec = 1;
09640 timeout.tv_usec = 0;
09641
09642 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
09643
09644 if (status >= 0 && FD_ISSET(send_sock, &readfds))
09645 break;
09646
09647 if (ss_time() - start_time > rpc_timeout / 1000)
09648 break;
09649
09650 } while (status == -1 || status == 0);
09651
09652 if (!FD_ISSET(send_sock, &readfds)) {
09653 cm_msg(MERROR, "rpc_client_call",
09654 "rpc timeout after %d sec, routine = \"%s\", host = \"%s\", connection closed",
09655 (int) (ss_time() - start_time), rpc_list[rpc_index].name, _client_connection[idx].host_name);
09656
09657
09658
09659 rpc_client_disconnect(hConn, FALSE);
09660
09661 return RPC_TIMEOUT;
09662 }
09663 }
09664
09665
09666 i = recv_tcp(send_sock, _net_send_buffer, _net_send_buffer_size, 0);
09667
09668 if (i <= 0) {
09669 cm_msg(MERROR, "rpc_client_call",
09670 "recv_tcp() failed, routine = \"%s\", host = \"%s\"",
09671 rpc_list[rpc_index].name, _client_connection[idx].host_name);
09672 return RPC_NET_ERROR;
09673 }
09674
09675
09676 status = nc->header.routine_id;
09677
09678 va_start(ap, routine_id);
09679
09680 for (i = 0, param_ptr = nc->param; rpc_list[rpc_index].param[i].tid != 0; i++) {
09681 tid = rpc_list[rpc_index].param[i].tid;
09682 flags = rpc_list[rpc_index].param[i].flags;
09683
09684 bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
09685 (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
09686 tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
09687
09688 if (bpointer)
09689 arg_type = TID_ARRAY;
09690 else
09691 arg_type = rpc_list[rpc_index].param[i].tid;
09692
09693 if (tid == TID_FLOAT && !bpointer)
09694 arg_type = TID_DOUBLE;
09695
09696 rpc_va_arg(&ap, arg_type, arg);
09697
09698 if (rpc_list[rpc_index].param[i].flags & RPC_OUT) {
09699 tid = rpc_list[rpc_index].param[i].tid;
09700 flags = rpc_list[rpc_index].param[i].flags;
09701
09702 arg_size = tid_size[tid];
09703
09704 if (tid == TID_STRING || tid == TID_LINK)
09705 arg_size = strlen((char *) (param_ptr)) + 1;
09706
09707 if (flags & RPC_VARARRAY) {
09708 arg_size = *((INT *) param_ptr);
09709 param_ptr += ALIGN8(sizeof(INT));
09710 }
09711
09712 if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
09713 arg_size = rpc_list[rpc_index].param[i].n;
09714
09715
09716 if (*((char **) arg))
09717 memcpy((void *) *((char **) arg), param_ptr, arg_size);
09718
09719
09720 param_size = ALIGN8(arg_size);
09721
09722 param_ptr += param_size;
09723 }
09724 }
09725
09726 va_end(ap);
09727
09728 return status;
09729 }
09730
09731
09732 INT rpc_call(const INT routine_id, ...)
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744
09745
09746
09747
09748
09749
09750
09751
09752
09753
09754
09755
09756 {
09757 va_list ap, aptmp;
09758 char arg[8], arg_tmp[8];
09759 INT arg_type, transport, rpc_timeout;
09760 INT i, idx, status;
09761 INT param_size, arg_size, send_size;
09762 INT tid, flags;
09763 fd_set readfds;
09764 struct timeval timeout;
09765 char *param_ptr, str[80];
09766 BOOL bpointer, bbig;
09767 NET_COMMAND *nc;
09768 int send_sock;
09769 time_t start_time;
09770
09771 send_sock = _server_connection.send_sock;
09772 transport = _server_connection.transport;
09773 rpc_timeout = _server_connection.rpc_timeout;
09774
09775
09776 if (_net_send_buffer_size == 0) {
09777 status = resize_net_send_buffer("rpc_call", NET_BUFFER_SIZE);
09778 if (status != SUCCESS)
09779 return RPC_EXCEED_BUFFER;
09780
09781
09782 ss_mutex_create(&_mutex_rpc);
09783 }
09784
09785 status = ss_mutex_wait_for(_mutex_rpc, 10000 + rpc_timeout);
09786 if (status != SS_SUCCESS) {
09787 cm_msg(MERROR, "rpc_call", "Mutex timeout");
09788 return RPC_MUTEX_TIMEOUT;
09789 }
09790
09791 nc = (NET_COMMAND *) _net_send_buffer;
09792 nc->header.routine_id = routine_id;
09793
09794 if (transport == RPC_FTCP)
09795 nc->header.routine_id |= TCP_FAST;
09796
09797 for (i = 0;; i++)
09798 if (rpc_list[i].id == routine_id || rpc_list[i].id == 0)
09799 break;
09800 idx = i;
09801 if (rpc_list[i].id == 0) {
09802 ss_mutex_release(_mutex_rpc);
09803 sprintf(str, "invalid rpc ID (%d)", routine_id);
09804 cm_msg(MERROR, "rpc_call", str);
09805 return RPC_INVALID_ID;
09806 }
09807
09808
09809 va_start(ap, routine_id);
09810
09811
09812 bbig = ((rpc_get_option(0, RPC_OHW_TYPE) & DRI_BIG_ENDIAN) > 0);
09813
09814 for (i = 0, param_ptr = nc->param; rpc_list[idx].param[i].tid != 0; i++) {
09815 tid = rpc_list[idx].param[i].tid;
09816 flags = rpc_list[idx].param[i].flags;
09817
09818 bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
09819 (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
09820 tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
09821
09822 if (bpointer)
09823 arg_type = TID_ARRAY;
09824 else
09825 arg_type = tid;
09826
09827
09828 if (tid == TID_FLOAT && !bpointer)
09829 arg_type = TID_DOUBLE;
09830
09831
09832 rpc_va_arg(&ap, arg_type, arg);
09833
09834
09835 if (bbig) {
09836 if (tid == TID_BYTE || tid == TID_CHAR || tid == TID_SBYTE) {
09837 arg[0] = arg[3];
09838 }
09839 if (tid == TID_WORD || tid == TID_SHORT) {
09840 arg[0] = arg[2];
09841 arg[1] = arg[3];
09842 }
09843 }
09844
09845 if (flags & RPC_IN) {
09846 if (bpointer)
09847 arg_size = tid_size[tid];
09848 else
09849 arg_size = tid_size[arg_type];
09850
09851
09852 if (tid == TID_STRING || tid == TID_LINK)
09853 arg_size = 1 + strlen((char *) *((char **) arg));
09854
09855
09856
09857 if (flags & RPC_VARARRAY) {
09858 memcpy(&aptmp, &ap, sizeof(ap));
09859 rpc_va_arg(&aptmp, TID_ARRAY, arg_tmp);
09860
09861 if (flags & RPC_OUT)
09862 arg_size = *((INT *) * ((void **) arg_tmp));
09863 else
09864 arg_size = *((INT *) arg_tmp);
09865
09866 *((INT *) param_ptr) = ALIGN8(arg_size);
09867 param_ptr += ALIGN8(sizeof(INT));
09868 }
09869
09870 if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
09871 arg_size = rpc_list[idx].param[i].n;
09872
09873
09874 param_size = ALIGN8(arg_size);
09875
09876 if ((POINTER_T) param_ptr - (POINTER_T) nc + param_size > _net_send_buffer_size) {
09877 ss_mutex_release(_mutex_rpc);
09878 cm_msg(MERROR, "rpc_call",
09879 "parameters (%d) too large for network buffer (%d)",
09880 (POINTER_T) param_ptr - (POINTER_T) nc + param_size, _net_send_buffer_size);
09881 return RPC_EXCEED_BUFFER;
09882 }
09883
09884 if (bpointer)
09885 memcpy(param_ptr, (void *) *((void **) arg), arg_size);
09886 else {
09887
09888 if (tid != TID_FLOAT)
09889 memcpy(param_ptr, arg, arg_size);
09890 else
09891 *((float *) param_ptr) = (float) *((double *) arg);
09892 }
09893
09894 param_ptr += param_size;
09895
09896 }
09897 }
09898
09899 va_end(ap);
09900
09901 nc->header.param_size = (POINTER_T) param_ptr - (POINTER_T) nc->param;
09902
09903 send_size = nc->header.param_size + sizeof(NET_COMMAND_HEADER);
09904
09905
09906 if (transport == RPC_FTCP) {
09907 i = send_tcp(send_sock, (char *) nc, send_size, 0);
09908
09909 if (i != send_size) {
09910 ss_mutex_release(_mutex_rpc);
09911 cm_msg(MERROR, "rpc_call", "send_tcp() failed");
09912 return RPC_NET_ERROR;
09913 }
09914
09915 ss_mutex_release(_mutex_rpc);
09916 return RPC_SUCCESS;
09917 }
09918
09919
09920 i = send_tcp(send_sock, (char *) nc, send_size, 0);
09921 if (i != send_size) {
09922 ss_mutex_release(_mutex_rpc);
09923 cm_msg(MERROR, "rpc_call", "send_tcp() failed");
09924 return RPC_NET_ERROR;
09925 }
09926
09927
09928 if (rpc_timeout > 0) {
09929 start_time = ss_time();
09930
09931 do {
09932 FD_ZERO(&readfds);
09933 FD_SET(send_sock, &readfds);
09934
09935 timeout.tv_sec = 1;
09936 timeout.tv_usec = 0;
09937
09938 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
09939
09940 if (FD_ISSET(send_sock, &readfds))
09941 break;
09942
09943 if (ss_time() - start_time > rpc_timeout / 1000)
09944 break;
09945
09946 } while (status == -1 || status == 0);
09947
09948 if (!FD_ISSET(send_sock, &readfds)) {
09949 ss_mutex_release(_mutex_rpc);
09950 cm_msg(MERROR, "rpc_call", "rpc timeout after %d sec, routine = \"%s\", program abort",
09951 (int) (ss_time() - start_time), rpc_list[idx].name);
09952 abort();
09953 }
09954 }
09955
09956
09957 i = recv_tcp(send_sock, _net_send_buffer, _net_send_buffer_size, 0);
09958
09959 if (i <= 0) {
09960 ss_mutex_release(_mutex_rpc);
09961 cm_msg(MERROR, "rpc_call", "recv_tcp() failed, routine = \"%s\"", rpc_list[idx].name);
09962 return RPC_NET_ERROR;
09963 }
09964
09965
09966 status = nc->header.routine_id;
09967
09968 va_start(ap, routine_id);
09969
09970 for (i = 0, param_ptr = nc->param; rpc_list[idx].param[i].tid != 0; i++) {
09971 tid = rpc_list[idx].param[i].tid;
09972 flags = rpc_list[idx].param[i].flags;
09973
09974 bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
09975 (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
09976 tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
09977
09978 if (bpointer)
09979 arg_type = TID_ARRAY;
09980 else
09981 arg_type = rpc_list[idx].param[i].tid;
09982
09983 if (tid == TID_FLOAT && !bpointer)
09984 arg_type = TID_DOUBLE;
09985
09986 rpc_va_arg(&ap, arg_type, arg);
09987
09988 if (rpc_list[idx].param[i].flags & RPC_OUT) {
09989 tid = rpc_list[idx].param[i].tid;
09990 arg_size = tid_size[tid];
09991
09992 if (tid == TID_STRING || tid == TID_LINK)
09993 arg_size = strlen((char *) (param_ptr)) + 1;
09994
09995 if (flags & RPC_VARARRAY) {
09996 arg_size = *((INT *) param_ptr);
09997 param_ptr += ALIGN8(sizeof(INT));
09998 }
09999
10000 if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
10001 arg_size = rpc_list[idx].param[i].n;
10002
10003
10004 if (*((char **) arg))
10005 memcpy((void *) *((char **) arg), param_ptr, arg_size);
10006
10007
10008 param_size = ALIGN8(arg_size);
10009
10010 param_ptr += param_size;
10011 }
10012 }
10013
10014 va_end(ap);
10015
10016 ss_mutex_release(_mutex_rpc);
10017
10018 return status;
10019 }
10020
10021
10022
10023 INT rpc_set_opt_tcp_size(INT tcp_size)
10024 {
10025 INT old;
10026
10027 old = _opt_tcp_size;
10028 _opt_tcp_size = tcp_size;
10029 return old;
10030 }
10031
10032 INT rpc_get_opt_tcp_size()
10033 {
10034 return _opt_tcp_size;
10035 }
10036
10037
10038 #endif
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062 INT rpc_send_event(INT buffer_handle, void *source, INT buf_size, INT async_flag, INT mode)
10063 {
10064 INT i;
10065 NET_COMMAND *nc;
10066 unsigned long flag;
10067 BOOL would_block = 0;
10068 DWORD aligned_buf_size;
10069
10070 aligned_buf_size = ALIGN8(buf_size);
10071 _rpc_sock = mode == 0 ? _server_connection.send_sock : _server_connection.event_sock;
10072
10073 if ((INT) aligned_buf_size != (INT) (ALIGN8(((EVENT_HEADER *) source)->data_size + sizeof(EVENT_HEADER)))) {
10074 cm_msg(MERROR, "rpc_send_event", "event size mismatch");
10075 return BM_INVALID_PARAM;
10076 }
10077
10078 if (!rpc_is_remote())
10079 return bm_send_event(buffer_handle, source, buf_size, async_flag);
10080
10081
10082 if (!_tcp_buffer)
10083 _tcp_buffer = (char *) M_MALLOC(NET_TCP_SIZE);
10084 if (!_tcp_buffer) {
10085 cm_msg(MERROR, "rpc_send_event", "not enough memory to allocate network buffer");
10086 return RPC_EXCEED_BUFFER;
10087 }
10088
10089
10090 if (aligned_buf_size + 4 * 8 + sizeof(NET_COMMAND_HEADER) >= (DWORD) (_opt_tcp_size - _tcp_wp)
10091 && _tcp_wp != _tcp_rp) {
10092
10093 if (async_flag == ASYNC) {
10094 flag = 1;
10095 #ifdef OS_VXWORKS
10096 ioctlsocket(_rpc_sock, FIONBIO, (int) &flag);
10097 #else
10098 ioctlsocket(_rpc_sock, FIONBIO, &flag);
10099 #endif
10100 }
10101
10102 i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_rp, _tcp_wp - _tcp_rp, 0);
10103
10104 if (i < 0)
10105 #ifdef OS_WINNT
10106 would_block = (WSAGetLastError() == WSAEWOULDBLOCK);
10107 #else
10108 would_block = (errno == EWOULDBLOCK);
10109 #endif
10110
10111
10112 if (async_flag == ASYNC) {
10113 flag = 0;
10114 #ifdef OS_VXWORKS
10115 ioctlsocket(_rpc_sock, FIONBIO, (int) &flag);
10116 #else
10117 ioctlsocket(_rpc_sock, FIONBIO, &flag);
10118 #endif
10119 }
10120
10121
10122 if (i > 0)
10123 _tcp_rp += i;
10124
10125
10126 if (_tcp_rp == _tcp_wp)
10127 _tcp_rp = _tcp_wp = 0;
10128
10129 if (i < 0 && !would_block) {
10130 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10131 return RPC_NET_ERROR;
10132 }
10133
10134
10135 if (_tcp_wp > 0)
10136 return BM_ASYNC_RETURN;
10137 }
10138
10139 if (mode == 0) {
10140 nc = (NET_COMMAND *) (_tcp_buffer + _tcp_wp);
10141 nc->header.routine_id = RPC_BM_SEND_EVENT | TCP_FAST;
10142 nc->header.param_size = 4 * 8 + aligned_buf_size;
10143
10144
10145 *((INT *) (&nc->param[0])) = buffer_handle;
10146 *((INT *) (&nc->param[8])) = buf_size;
10147
10148
10149 if (aligned_buf_size + 4 * 8 + sizeof(NET_COMMAND_HEADER) >= (DWORD) _opt_tcp_size) {
10150
10151 i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_wp, sizeof(NET_COMMAND_HEADER) + 16, 0);
10152 if (i <= 0) {
10153 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10154 return RPC_NET_ERROR;
10155 }
10156
10157
10158 i = send_tcp(_rpc_sock, (char *) source, aligned_buf_size, 0);
10159 if (i <= 0) {
10160 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10161 return RPC_NET_ERROR;
10162 }
10163
10164
10165 *((INT *) (&nc->param[0])) = buf_size;
10166 *((INT *) (&nc->param[8])) = 0;
10167 i = send_tcp(_rpc_sock, &nc->param[0], 16, 0);
10168 if (i <= 0) {
10169 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10170 return RPC_NET_ERROR;
10171 }
10172 } else {
10173
10174 memcpy(&nc->param[16], source, buf_size);
10175
10176
10177 *((INT *) (&nc->param[16 + aligned_buf_size])) = buf_size;
10178 *((INT *) (&nc->param[24 + aligned_buf_size])) = 0;
10179
10180 _tcp_wp += nc->header.param_size + sizeof(NET_COMMAND_HEADER);
10181 }
10182
10183 } else {
10184
10185
10186 if (aligned_buf_size + 4 * 8 + sizeof(INT) >= (DWORD) _opt_tcp_size) {
10187
10188 i = send_tcp(_rpc_sock, (char *) &buffer_handle, sizeof(INT), 0);
10189 if (i <= 0) {
10190 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10191 return RPC_NET_ERROR;
10192 }
10193
10194
10195 i = send_tcp(_rpc_sock, (char *) source, aligned_buf_size, 0);
10196 if (i <= 0) {
10197 cm_msg(MERROR, "rpc_send_event", "send_tcp() failed, return code = %d", i);
10198 return RPC_NET_ERROR;
10199 }
10200 } else {
10201
10202 *((INT *) (_tcp_buffer + _tcp_wp)) = buffer_handle;
10203 _tcp_wp += sizeof(INT);
10204 memcpy(_tcp_buffer + _tcp_wp, source, buf_size);
10205
10206 _tcp_wp += aligned_buf_size;
10207 }
10208 }
10209
10210 return RPC_SUCCESS;
10211 }
10212
10213
10214
10215 #ifndef DOXYGEN_SHOULD_SKIP_THIS
10216
10217
10218 int rpc_get_send_sock()
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236 {
10237 return _server_connection.send_sock;
10238 }
10239
10240
10241
10242 int rpc_get_event_sock()
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
10259
10260 {
10261 return _server_connection.event_sock;
10262 }
10263
10264
10265 #endif
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275 INT rpc_flush_event()
10276 {
10277 INT i;
10278
10279 if (!rpc_is_remote())
10280 return RPC_SUCCESS;
10281
10282
10283 if (!_tcp_buffer || _tcp_wp == 0)
10284 return RPC_SUCCESS;
10285
10286
10287 if (_tcp_wp > 0) {
10288 i = send_tcp(_rpc_sock, _tcp_buffer + _tcp_rp, _tcp_wp - _tcp_rp, 0);
10289
10290 if (i != _tcp_wp - _tcp_rp) {
10291 cm_msg(MERROR, "rpc_flush_event", "send_tcp() failed");
10292 return RPC_NET_ERROR;
10293 }
10294 }
10295
10296 _tcp_rp = _tcp_wp = 0;
10297
10298 return RPC_SUCCESS;
10299 }
10300
10301
10302 #ifndef DOXYGEN_SHOULD_SKIP_THIS
10303
10304
10305
10306 typedef struct {
10307 int transition;
10308 int run_number;
10309 time_t trans_time;
10310 int sequence_number;
10311 } TR_FIFO;
10312
10313 static TR_FIFO tr_fifo[10];
10314 static int trf_wp, trf_rp;
10315
10316 static INT rpc_transition_dispatch(INT idx, void *prpc_param[])
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335 {
10336 INT status, i;
10337
10338
10339 *(CSTRING(2)) = 0;
10340
10341 if (idx == RPC_RC_TRANSITION) {
10342 for (i = 0; i < MAX_TRANSITIONS; i++)
10343 if (_trans_table[i].transition == CINT(0) && _trans_table[i].sequence_number == CINT(4))
10344 break;
10345
10346
10347 if (i < MAX_TRANSITIONS) {
10348 if (_trans_table[i].func)
10349
10350 status = _trans_table[i].func(CINT(1), CSTRING(2));
10351 else {
10352
10353 tr_fifo[trf_wp].transition = CINT(0);
10354 tr_fifo[trf_wp].run_number = CINT(1);
10355 tr_fifo[trf_wp].trans_time = time(NULL);
10356 tr_fifo[trf_wp].sequence_number = CINT(4);
10357 trf_wp = (trf_wp + 1) % 10;
10358 status = RPC_SUCCESS;
10359 }
10360 } else
10361 status = RPC_SUCCESS;
10362
10363 } else {
10364 cm_msg(MERROR, "rpc_transition_dispatch", "received unrecognized command");
10365 status = RPC_INVALID_ID;
10366 }
10367
10368 return status;
10369 }
10370
10371
10372 int cm_query_transition(int *transition, int *run_number, int *trans_time)
10373
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396 {
10397
10398 if (trf_wp == trf_rp)
10399 return FALSE;
10400
10401 if (transition)
10402 *transition = tr_fifo[trf_rp].transition;
10403
10404 if (run_number)
10405 *run_number = tr_fifo[trf_rp].run_number;
10406
10407 if (trans_time)
10408 *trans_time = (int) tr_fifo[trf_rp].trans_time;
10409
10410 trf_rp = (trf_rp + 1) % 10;
10411
10412 return TRUE;
10413 }
10414
10415
10416
10417
10418
10419 #if 0
10420 void debug_dump(unsigned char *p, int size)
10421 {
10422 int i, j;
10423 unsigned char c;
10424
10425 for (i = 0; i < (size - 1) / 16 + 1; i++) {
10426 printf("%p ", p + i * 16);
10427 for (j = 0; j < 16; j++)
10428 if (i * 16 + j < size)
10429 printf("%02X ", p[i * 16 + j]);
10430 else
10431 printf(" ");
10432 printf(" ");
10433
10434 for (j = 0; j < 16; j++) {
10435 c = p[i * 16 + j];
10436 if (i * 16 + j < size)
10437 printf("%c", (c >= 32 && c < 128) ? p[i * 16 + j] : '.');
10438 }
10439 printf("\n");
10440 }
10441
10442 printf("\n");
10443 }
10444 #endif
10445
10446
10447 INT recv_tcp_server(INT idx, char *buffer, DWORD buffer_size, INT flags, INT * remaining)
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475 {
10476 INT size, param_size;
10477 NET_COMMAND *nc;
10478 INT write_ptr, read_ptr, misalign;
10479 char *net_buffer;
10480 INT copied, status;
10481 INT sock;
10482
10483 sock = _server_acception[idx].recv_sock;
10484
10485 if (flags & MSG_PEEK) {
10486 status = recv(sock, buffer, buffer_size, flags);
10487 if (status == -1)
10488 cm_msg(MERROR, "recv_tcp_server",
10489 "recv(%d,MSG_PEEK) returned %d, errno: %d (%s)", buffer_size, status, errno, strerror(errno));
10490 return status;
10491 }
10492
10493 if (!_server_acception[idx].net_buffer) {
10494 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
10495 _server_acception[idx].net_buffer_size = NET_TCP_SIZE;
10496 else
10497 _server_acception[idx].net_buffer_size = NET_BUFFER_SIZE;
10498
10499 _server_acception[idx].net_buffer = (char *) M_MALLOC(_server_acception[idx].net_buffer_size);
10500 _server_acception[idx].write_ptr = 0;
10501 _server_acception[idx].read_ptr = 0;
10502 _server_acception[idx].misalign = 0;
10503 }
10504 if (!_server_acception[idx].net_buffer) {
10505 cm_msg(MERROR, "recv_tcp_server", "Cannot allocate %d bytes for network buffer",
10506 _server_acception[idx].net_buffer_size);
10507 return -1;
10508 }
10509
10510 if (buffer_size < sizeof(NET_COMMAND_HEADER)) {
10511 cm_msg(MERROR, "recv_tcp_server", "parameters too large for network buffer");
10512 return -1;
10513 }
10514
10515 copied = 0;
10516 param_size = -1;
10517
10518 write_ptr = _server_acception[idx].write_ptr;
10519 read_ptr = _server_acception[idx].read_ptr;
10520 misalign = _server_acception[idx].misalign;
10521 net_buffer = _server_acception[idx].net_buffer;
10522
10523 do {
10524 if (write_ptr - read_ptr >= (INT) sizeof(NET_COMMAND_HEADER) - copied) {
10525 if (param_size == -1) {
10526 if (copied > 0) {
10527
10528 memcpy(buffer + copied, net_buffer + read_ptr, (INT) sizeof(NET_COMMAND_HEADER) - copied);
10529 nc = (NET_COMMAND *) (buffer);
10530 } else
10531 nc = (NET_COMMAND *) (net_buffer + read_ptr);
10532
10533 param_size = (INT) nc->header.param_size;
10534
10535 if (_server_acception[idx].convert_flags)
10536 rpc_convert_single(¶m_size, TID_DWORD, 0, _server_acception[idx].convert_flags);
10537 }
10538
10539
10540 if (buffer_size < param_size + sizeof(NET_COMMAND_HEADER)) {
10541 cm_msg(MERROR, "recv_tcp_server", "parameters too large for network buffer");
10542 _server_acception[idx].read_ptr = _server_acception[idx].write_ptr = 0;
10543 return -1;
10544 }
10545
10546
10547 if (write_ptr - read_ptr >= param_size + (INT) sizeof(NET_COMMAND_HEADER) - copied)
10548 break;
10549 }
10550
10551
10552 size = write_ptr - read_ptr;
10553
10554 if (size > 0) {
10555 memcpy(buffer + copied, net_buffer + read_ptr, size);
10556 copied += size;
10557 read_ptr = write_ptr;
10558 }
10559 #ifdef OS_UNIX
10560 do {
10561 write_ptr = recv(sock, net_buffer + misalign, _server_acception[idx].net_buffer_size - 8, flags);
10562
10563
10564 } while (write_ptr == -1 && errno == EINTR);
10565 #else
10566 write_ptr = recv(sock, net_buffer + misalign, _server_acception[idx].net_buffer_size - 8, flags);
10567 #endif
10568
10569
10570 if (write_ptr <= 0) {
10571 if (write_ptr == 0)
10572 cm_msg(MERROR, "recv_tcp_server", "rpc connection from \'%s\' on \'%s\' unexpectedly closed",
10573 _server_acception[idx].prog_name, _server_acception[idx].host_name);
10574 else
10575 cm_msg(MERROR, "recv_tcp_server", "recv() returned %d, errno: %d (%s)", write_ptr, errno,
10576 strerror(errno));
10577
10578 if (remaining)
10579 *remaining = 0;
10580
10581 return write_ptr;
10582 }
10583
10584 read_ptr = misalign;
10585 write_ptr += misalign;
10586
10587 misalign = write_ptr % 8;
10588 } while (TRUE);
10589
10590
10591 size = param_size + sizeof(NET_COMMAND_HEADER) - copied;
10592 memcpy(buffer + copied, net_buffer + read_ptr, size);
10593 read_ptr += size;
10594
10595 if (remaining) {
10596
10597 if (write_ptr - read_ptr < param_size)
10598 *remaining = 0;
10599 else
10600 *remaining = write_ptr - read_ptr;
10601 }
10602
10603 _server_acception[idx].write_ptr = write_ptr;
10604 _server_acception[idx].read_ptr = read_ptr;
10605 _server_acception[idx].misalign = misalign;
10606
10607 return size + copied;
10608 }
10609
10610
10611
10612 INT recv_tcp_check(int sock)
10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630 {
10631 INT idx;
10632
10633
10634 for (idx = 0; idx < MAX_RPC_CONNECTION; idx++)
10635 if (_server_acception[idx].recv_sock == sock)
10636 break;
10637
10638 return _server_acception[idx].write_ptr - _server_acception[idx].read_ptr;
10639 }
10640
10641
10642
10643 INT recv_event_server(INT idx, char *buffer, DWORD buffer_size, INT flags, INT * remaining)
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672 {
10673 INT size, event_size, aligned_event_size = 0, *pbh, header_size;
10674 EVENT_HEADER *pevent;
10675 INT write_ptr, read_ptr, misalign;
10676 char *net_buffer;
10677 INT copied, status;
10678 INT sock;
10679 RPC_SERVER_ACCEPTION *psa;
10680
10681 psa = &_server_acception[idx];
10682 sock = psa->event_sock;
10683
10684
10685
10686 if (flags & MSG_PEEK) {
10687 status = recv(sock, buffer, buffer_size, flags);
10688 if (status == -1)
10689 cm_msg(MERROR, "recv_event_server",
10690 "recv(%d,MSG_PEEK) returned %d, errno: %d (%s)", buffer_size, status, errno, strerror(errno));
10691 return status;
10692 }
10693
10694 if (!psa->ev_net_buffer) {
10695 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
10696 psa->net_buffer_size = NET_TCP_SIZE;
10697 else
10698 psa->net_buffer_size = NET_BUFFER_SIZE;
10699
10700 psa->ev_net_buffer = (char *) M_MALLOC(psa->net_buffer_size);
10701
10702
10703
10704 psa->ev_write_ptr = 0;
10705 psa->ev_read_ptr = 0;
10706 psa->ev_misalign = 0;
10707 }
10708 if (!psa->ev_net_buffer) {
10709 cm_msg(MERROR, "recv_event_server", "Cannot allocate %d bytes for network buffer",
10710 psa->net_buffer_size);
10711 return -1;
10712 }
10713
10714 header_size = (INT) (sizeof(EVENT_HEADER) + sizeof(INT));
10715
10716 if ((INT) buffer_size < header_size) {
10717 cm_msg(MERROR, "recv_event_server", "parameters too large for network buffer");
10718 return -1;
10719 }
10720
10721 copied = 0;
10722 event_size = -1;
10723
10724 write_ptr = psa->ev_write_ptr;
10725 read_ptr = psa->ev_read_ptr;
10726 misalign = psa->ev_misalign;
10727 net_buffer = psa->ev_net_buffer;
10728
10729 do {
10730 if (write_ptr - read_ptr >= header_size - copied) {
10731 if (event_size == -1) {
10732 if (copied > 0) {
10733
10734 memcpy(buffer + copied, net_buffer + read_ptr, header_size - copied);
10735 pbh = (INT *) buffer;
10736 } else
10737 pbh = (INT *) (net_buffer + read_ptr);
10738
10739 pevent = (EVENT_HEADER *) (pbh + 1);
10740
10741 event_size = pevent->data_size;
10742 if (psa->convert_flags)
10743 rpc_convert_single(&event_size, TID_DWORD, 0, psa->convert_flags);
10744
10745 aligned_event_size = ALIGN8(event_size);
10746 }
10747
10748
10749 if ((INT) buffer_size < aligned_event_size + header_size) {
10750 cm_msg(MERROR, "recv_event_server", "event size %d too large for network buffer size %d", aligned_event_size + header_size, buffer_size);
10751 psa->ev_read_ptr = psa->ev_write_ptr = 0;
10752 return -1;
10753 }
10754
10755
10756 if (write_ptr - read_ptr >= aligned_event_size + header_size - copied)
10757 break;
10758 }
10759
10760
10761 size = write_ptr - read_ptr;
10762
10763 if (size > 0) {
10764 memcpy(buffer + copied, net_buffer + read_ptr, size);
10765 copied += size;
10766 read_ptr = write_ptr;
10767 }
10768 #ifdef OS_UNIX
10769 do {
10770 write_ptr = recv(sock, net_buffer + misalign, psa->net_buffer_size - 8, flags);
10771
10772
10773 } while (write_ptr == -1 && errno == EINTR);
10774 #else
10775 write_ptr = recv(sock, net_buffer + misalign, psa->net_buffer_size - 8, flags);
10776 #endif
10777
10778
10779 if (write_ptr <= 0) {
10780 cm_msg(MERROR, "recv_event_server", "recv() returned %d, errno: %d (%s)", write_ptr, errno,
10781 strerror(errno));
10782
10783 if (remaining)
10784 *remaining = 0;
10785
10786 return write_ptr;
10787 }
10788
10789 read_ptr = misalign;
10790 write_ptr += misalign;
10791
10792 misalign = write_ptr % 8;
10793 } while (TRUE);
10794
10795
10796 size = aligned_event_size + header_size - copied;
10797 if (size > 0) {
10798 memcpy(buffer + copied, net_buffer + read_ptr, size);
10799 read_ptr += size;
10800 }
10801
10802 if (remaining)
10803 *remaining = write_ptr - read_ptr;
10804
10805 psa->ev_write_ptr = write_ptr;
10806 psa->ev_read_ptr = read_ptr;
10807 psa->ev_misalign = misalign;
10808
10809
10810 if (psa->convert_flags) {
10811 pevent = (EVENT_HEADER *) (((INT *) buffer) + 1);
10812
10813 rpc_convert_single(buffer, TID_INT, 0, psa->convert_flags);
10814 rpc_convert_single(&pevent->event_id, TID_SHORT, 0, psa->convert_flags);
10815 rpc_convert_single(&pevent->trigger_mask, TID_SHORT, 0, psa->convert_flags);
10816 rpc_convert_single(&pevent->serial_number, TID_DWORD, 0, psa->convert_flags);
10817 rpc_convert_single(&pevent->time_stamp, TID_DWORD, 0, psa->convert_flags);
10818 rpc_convert_single(&pevent->data_size, TID_DWORD, 0, psa->convert_flags);
10819 }
10820
10821 return header_size + event_size;
10822 }
10823
10824
10825
10826 INT recv_event_check(int sock)
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844 {
10845 INT idx;
10846
10847
10848 for (idx = 0; idx < MAX_RPC_CONNECTION; idx++)
10849 if (_server_acception[idx].event_sock == sock)
10850 break;
10851
10852 return _server_acception[idx].ev_write_ptr - _server_acception[idx].ev_read_ptr;
10853 }
10854
10855
10856
10857 INT rpc_register_server(INT server_type, const char *name, INT * port, INT(*func) (INT, void **))
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893 {
10894 struct sockaddr_in bind_addr;
10895 INT status, flag;
10896 unsigned int size;
10897
10898 #ifdef OS_WINNT
10899 {
10900 WSADATA WSAData;
10901
10902
10903 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
10904 return RPC_NET_ERROR;
10905 }
10906 #endif
10907
10908 rpc_set_server_option(RPC_OSERVER_TYPE, server_type);
10909
10910
10911 rpc_register_functions(rpc_get_internal_list(0), func);
10912
10913 if (name != NULL)
10914 rpc_set_server_option(RPC_OSERVER_NAME, (POINTER_T) name);
10915
10916
10917 if (server_type == ST_SUBPROCESS)
10918 return RPC_SUCCESS;
10919
10920
10921 _lsock = socket(AF_INET, SOCK_STREAM, 0);
10922 if (_lsock == -1) {
10923 cm_msg(MERROR, "rpc_register_server", "socket(AF_INET, SOCK_STREAM) failed, errno %d (%s)", errno,
10924 strerror(errno));
10925 return RPC_NET_ERROR;
10926 }
10927
10928
10929 #if defined(F_SETFD) && defined(FD_CLOEXEC)
10930 status = fcntl(_lsock, F_SETFD, fcntl(_lsock, F_GETFD) | FD_CLOEXEC);
10931 if (status < 0) {
10932 cm_msg(MERROR, "rpc_register_server", "fcntl(F_SETFD, FD_CLOEXEC) failed, errno %d (%s)", errno,
10933 strerror(errno));
10934 return RPC_NET_ERROR;
10935 }
10936 #endif
10937
10938
10939 flag = 1;
10940 status = setsockopt(_lsock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT));
10941 if (status < 0) {
10942 cm_msg(MERROR, "rpc_register_server", "setsockopt(SO_REUSEADDR) failed, errno %d (%s)", errno,
10943 strerror(errno));
10944 return RPC_NET_ERROR;
10945 }
10946
10947
10948 memset(&bind_addr, 0, sizeof(bind_addr));
10949 bind_addr.sin_family = AF_INET;
10950 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
10951
10952 if (!port)
10953 bind_addr.sin_port = htons(MIDAS_TCP_PORT);
10954 else
10955 bind_addr.sin_port = htons((short) (*port));
10956
10957 status = bind(_lsock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
10958 if (status < 0) {
10959 cm_msg(MERROR, "rpc_register_server", "bind() failed, errno %d (%s)", errno, strerror(errno));
10960 return RPC_NET_ERROR;
10961 }
10962
10963
10964 #ifdef OS_MSDOS
10965 status = listen(_lsock, 1);
10966 #else
10967 status = listen(_lsock, SOMAXCONN);
10968 #endif
10969 if (status < 0) {
10970 cm_msg(MERROR, "rpc_register_server", "listen() failed, errno %d (%s)", errno, strerror(errno));
10971 return RPC_NET_ERROR;
10972 }
10973
10974
10975 if (port && *port == 0) {
10976 size = sizeof(bind_addr);
10977 #ifdef OS_WINNT
10978 getsockname(_lsock, (struct sockaddr *) &bind_addr, (int *) &size);
10979 #else
10980 getsockname(_lsock, (struct sockaddr *) &bind_addr, &size);
10981 #endif
10982 *port = ntohs(bind_addr.sin_port);
10983 }
10984
10985
10986 if (server_type == ST_REMOTE)
10987 ss_suspend_set_dispatch(CH_LISTEN, &_lsock, (int (*)(void)) rpc_client_accept);
10988 else
10989 ss_suspend_set_dispatch(CH_LISTEN, &_lsock, (int (*)(void)) rpc_server_accept);
10990
10991 return RPC_SUCCESS;
10992 }
10993
10994 typedef struct {
10995 int tid;
10996 int buffer_size;
10997 char *buffer;
10998 } TLS_POINTER;
10999
11000 TLS_POINTER *tls_buffer = NULL;
11001 int tls_size = 0;
11002
11003
11004 INT rpc_execute(INT sock, char *buffer, INT convert_flags)
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031 {
11032 INT i, idx, routine_id, status;
11033 char *in_param_ptr, *out_param_ptr, *last_param_ptr;
11034 INT tid, flags;
11035 NET_COMMAND *nc_in, *nc_out;
11036 INT param_size, max_size;
11037 void *prpc_param[20];
11038 char str[1024], debug_line[1024], *return_buffer;
11039 int return_buffer_size;
11040 int return_buffer_tls;
11041 #ifdef FIXED_BUFFER
11042 int initial_buffer_size = NET_BUFFER_SIZE;
11043 #else
11044 int initial_buffer_size = 1024;
11045 #endif
11046
11047
11048 if (!tls_size) {
11049 tls_buffer = (TLS_POINTER *) malloc(sizeof(TLS_POINTER));
11050 tls_buffer[tls_size].tid = ss_gettid();
11051 tls_buffer[tls_size].buffer_size = initial_buffer_size;
11052 tls_buffer[tls_size].buffer = (char *) malloc(tls_buffer[tls_size].buffer_size);
11053 tls_size = 1;
11054 }
11055 for (i = 0; i < tls_size; i++)
11056 if (tls_buffer[i].tid == ss_gettid())
11057 break;
11058 if (i == tls_size) {
11059
11060 tls_buffer = (TLS_POINTER *) realloc(tls_buffer, (tls_size + 1) * sizeof(TLS_POINTER));
11061 tls_buffer[tls_size].tid = ss_gettid();
11062 tls_buffer[tls_size].buffer_size = initial_buffer_size;
11063 tls_buffer[tls_size].buffer = (char *) malloc(tls_buffer[tls_size].buffer_size);
11064 tls_size++;
11065 }
11066
11067 return_buffer_tls = i;
11068 return_buffer_size = tls_buffer[i].buffer_size;
11069 return_buffer = tls_buffer[i].buffer;
11070 assert(return_buffer);
11071
11072
11073 nc_in = (NET_COMMAND *) buffer;
11074
11075
11076 if (convert_flags) {
11077 rpc_convert_single(&nc_in->header.routine_id, TID_DWORD, 0, convert_flags);
11078 rpc_convert_single(&nc_in->header.param_size, TID_DWORD, 0, convert_flags);
11079 }
11080
11081
11082 if (nc_in->header.routine_id & TCP_FAST)
11083 sock = 0;
11084
11085
11086 routine_id = nc_in->header.routine_id & ~TCP_FAST;
11087
11088 assert(rpc_list != NULL);
11089
11090 for (i = 0;; i++)
11091 if (rpc_list[i].id == 0 || rpc_list[i].id == routine_id)
11092 break;
11093 idx = i;
11094 if (rpc_list[i].id == 0) {
11095 cm_msg(MERROR, "rpc_execute", "Invalid rpc ID (%d)", routine_id);
11096 return RPC_INVALID_ID;
11097 }
11098
11099 again:
11100
11101 in_param_ptr = nc_in->param;
11102
11103 nc_out = (NET_COMMAND *) return_buffer;
11104 out_param_ptr = nc_out->param;
11105
11106 sprintf(debug_line, "%s(", rpc_list[idx].name);
11107
11108 for (i = 0; rpc_list[idx].param[i].tid != 0; i++) {
11109 tid = rpc_list[idx].param[i].tid;
11110 flags = rpc_list[idx].param[i].flags;
11111
11112 if (flags & RPC_IN) {
11113 param_size = ALIGN8(tid_size[tid]);
11114
11115 if (tid == TID_STRING || tid == TID_LINK)
11116 param_size = ALIGN8(1 + strlen((char *) (in_param_ptr)));
11117
11118 if (flags & RPC_VARARRAY) {
11119
11120 param_size = *((INT *) in_param_ptr);
11121 if (convert_flags)
11122 rpc_convert_single(¶m_size, TID_INT, 0, convert_flags);
11123 param_size = ALIGN8(param_size);
11124
11125 in_param_ptr += ALIGN8(sizeof(INT));
11126 }
11127
11128 if (tid == TID_STRUCT)
11129 param_size = ALIGN8(rpc_list[idx].param[i].n);
11130
11131 prpc_param[i] = in_param_ptr;
11132
11133
11134 if (convert_flags) {
11135 if (flags & RPC_VARARRAY)
11136 rpc_convert_data(in_param_ptr, tid, flags, param_size, convert_flags);
11137 else
11138 rpc_convert_data(in_param_ptr, tid, flags, rpc_list[idx].param[i].n * tid_size[tid],
11139 convert_flags);
11140 }
11141
11142 db_sprintf(str, in_param_ptr, param_size, 0, rpc_list[idx].param[i].tid);
11143 if (rpc_list[idx].param[i].tid == TID_STRING) {
11144
11145 if (strlen(debug_line) + strlen(str) + 2 < sizeof(debug_line)) {
11146 strcat(debug_line, "\"");
11147 strcat(debug_line, str);
11148 strcat(debug_line, "\"");
11149 } else
11150 strcat(debug_line, "...");
11151 } else
11152 strcat(debug_line, str);
11153
11154 in_param_ptr += param_size;
11155 }
11156
11157 if (flags & RPC_OUT) {
11158 param_size = ALIGN8(tid_size[tid]);
11159
11160 if (flags & RPC_VARARRAY || tid == TID_STRING) {
11161
11162 max_size = *((INT *) in_param_ptr);
11163 if (convert_flags)
11164 rpc_convert_single(&max_size, TID_INT, 0, convert_flags);
11165 max_size = ALIGN8(max_size);
11166
11167 *((INT *) out_param_ptr) = max_size;
11168
11169
11170 out_param_ptr += ALIGN8(sizeof(INT));
11171
11172
11173 param_size += max_size;
11174 }
11175
11176 if (rpc_list[idx].param[i].tid == TID_STRUCT)
11177 param_size = ALIGN8(rpc_list[idx].param[i].n);
11178
11179 if ((POINTER_T) out_param_ptr - (POINTER_T) nc_out + param_size > return_buffer_size) {
11180 #ifdef FIXED_BUFFER
11181 cm_msg(MERROR, "rpc_execute",
11182 "return parameters (%d) too large for network buffer (%d)",
11183 (POINTER_T) out_param_ptr - (POINTER_T) nc_out + param_size, return_buffer_size);
11184
11185 return RPC_EXCEED_BUFFER;
11186 #else
11187 int itls;
11188 int new_size = (POINTER_T) out_param_ptr - (POINTER_T) nc_out + param_size + 1024;
11189
11190
11191
11192
11193
11194 itls = return_buffer_tls;
11195
11196 tls_buffer[itls].buffer_size = new_size;
11197 tls_buffer[itls].buffer = (char *) realloc(tls_buffer[itls].buffer, new_size);
11198
11199 if (!tls_buffer[itls].buffer) {
11200 cm_msg(MERROR, "rpc_execute", "Cannot allocate return buffer of size %d", new_size);
11201 return RPC_EXCEED_BUFFER;
11202 }
11203
11204 return_buffer_size = tls_buffer[itls].buffer_size;
11205 return_buffer = tls_buffer[itls].buffer;
11206 assert(return_buffer);
11207
11208 goto again;
11209 #endif
11210 }
11211
11212
11213 if (rpc_list[idx].param[i].flags & RPC_IN)
11214 memcpy(out_param_ptr, prpc_param[i], param_size);
11215
11216 if (_debug_print && !(flags & RPC_IN))
11217 strcat(debug_line, "-");
11218
11219 prpc_param[i] = out_param_ptr;
11220 out_param_ptr += param_size;
11221 }
11222
11223 if (rpc_list[idx].param[i + 1].tid)
11224 strcat(debug_line, ", ");
11225 }
11226
11227
11228
11229 strcat(debug_line, ")");
11230 rpc_debug_printf(debug_line);
11231
11232 last_param_ptr = out_param_ptr;
11233
11234
11235
11236
11237 if (rpc_list[idx].dispatch)
11238 status = rpc_list[idx].dispatch(routine_id, prpc_param);
11239 else
11240 status = RPC_INVALID_ID;
11241
11242 if (routine_id == RPC_ID_EXIT || routine_id == RPC_ID_SHUTDOWN || routine_id == RPC_ID_WATCHDOG)
11243 status = RPC_SUCCESS;
11244
11245
11246 if (!sock && routine_id == RPC_ID_EXIT)
11247 return SS_EXIT;
11248
11249 if (!sock && routine_id == RPC_ID_SHUTDOWN)
11250 return RPC_SHUTDOWN;
11251
11252
11253 if (status == SS_ABORT)
11254 return SS_ABORT;
11255
11256
11257 if (!sock)
11258 return RPC_SUCCESS;
11259
11260
11261 out_param_ptr = nc_out->param;
11262 for (i = 0; rpc_list[idx].param[i].tid != 0; i++)
11263 if (rpc_list[idx].param[i].flags & RPC_OUT) {
11264 tid = rpc_list[idx].param[i].tid;
11265 flags = rpc_list[idx].param[i].flags;
11266 param_size = ALIGN8(tid_size[tid]);
11267
11268 if (tid == TID_STRING) {
11269 max_size = *((INT *) out_param_ptr);
11270 param_size = strlen((char *) prpc_param[i]) + 1;
11271 param_size = ALIGN8(param_size);
11272
11273
11274 memcpy(out_param_ptr, out_param_ptr + ALIGN8(sizeof(INT)), param_size);
11275
11276
11277 memcpy(out_param_ptr + param_size,
11278 out_param_ptr + max_size + ALIGN8(sizeof(INT)),
11279 (POINTER_T) last_param_ptr - ((POINTER_T) out_param_ptr + max_size + ALIGN8(sizeof(INT))));
11280 }
11281
11282 if (flags & RPC_VARARRAY) {
11283
11284 max_size = *((INT *) out_param_ptr);
11285 param_size = *((INT *) prpc_param[i + 1]);
11286 *((INT *) out_param_ptr) = param_size;
11287 if (convert_flags)
11288 rpc_convert_single(out_param_ptr, TID_INT, RPC_OUTGOING, convert_flags);
11289
11290 out_param_ptr += ALIGN8(sizeof(INT));
11291
11292 param_size = ALIGN8(param_size);
11293
11294
11295 memcpy(out_param_ptr + param_size,
11296 out_param_ptr + max_size,
11297 (POINTER_T) last_param_ptr - ((POINTER_T) out_param_ptr + max_size));
11298 }
11299
11300 if (tid == TID_STRUCT)
11301 param_size = ALIGN8(rpc_list[idx].param[i].n);
11302
11303
11304 if (convert_flags) {
11305 if (flags & RPC_VARARRAY)
11306 rpc_convert_data(out_param_ptr, tid,
11307 rpc_list[idx].param[i].flags | RPC_OUTGOING, param_size, convert_flags);
11308 else
11309 rpc_convert_data(out_param_ptr, tid,
11310 rpc_list[idx].param[i].flags | RPC_OUTGOING,
11311 rpc_list[idx].param[i].n * tid_size[tid], convert_flags);
11312 }
11313
11314 out_param_ptr += param_size;
11315 }
11316
11317
11318 param_size = (POINTER_T) out_param_ptr - (POINTER_T) nc_out->param;
11319 nc_out->header.routine_id = status;
11320 nc_out->header.param_size = param_size;
11321
11322
11323
11324
11325 if (convert_flags) {
11326 rpc_convert_single(&nc_out->header.routine_id, TID_DWORD, RPC_OUTGOING, convert_flags);
11327 rpc_convert_single(&nc_out->header.param_size, TID_DWORD, RPC_OUTGOING, convert_flags);
11328 }
11329
11330 status = send_tcp(sock, return_buffer, sizeof(NET_COMMAND_HEADER) + param_size, 0);
11331
11332 if (status < 0) {
11333 cm_msg(MERROR, "rpc_execute", "send_tcp() failed");
11334 return RPC_NET_ERROR;
11335 }
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349 if (routine_id == RPC_ID_EXIT)
11350 return SS_EXIT;
11351
11352
11353 if (routine_id == RPC_ID_SHUTDOWN)
11354 return RPC_SHUTDOWN;
11355
11356 return RPC_SUCCESS;
11357 }
11358
11359
11360
11361 INT rpc_execute_ascii(INT sock, char *buffer)
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388 {
11389 #define ASCII_BUFFER_SIZE 64500
11390 #define N_APARAM 1024
11391
11392 INT i, j, idx, status, index_in;
11393 char *in_param_ptr, *out_param_ptr, *last_param_ptr;
11394 INT routine_id, tid, flags, array_tid, n_param;
11395 INT param_size, item_size, num_values;
11396 void *prpc_param[20];
11397 char *arpc_param[N_APARAM], *pc;
11398 char str[1024], debug_line[1024];
11399 char buffer1[ASCII_BUFFER_SIZE];
11400 char buffer2[ASCII_BUFFER_SIZE];
11401 char return_buffer[ASCII_BUFFER_SIZE];
11402
11403
11404 arpc_param[0] = buffer;
11405 for (i = 1; i < N_APARAM; i++) {
11406 arpc_param[i] = strchr(arpc_param[i - 1], '&');
11407 if (arpc_param[i] == NULL)
11408 break;
11409 *arpc_param[i] = 0;
11410 arpc_param[i]++;
11411 }
11412
11413
11414 for (i = 0; i < N_APARAM && arpc_param[i]; i++)
11415 while ((pc = strchr(arpc_param[i], '%')) != NULL) {
11416 if (isxdigit(pc[1]) && isxdigit(pc[2])) {
11417 str[0] = pc[1];
11418 str[1] = pc[2];
11419 str[2] = 0;
11420 sscanf(str, "%02X", &i);
11421
11422 *pc++ = i;
11423 while (pc[2]) {
11424 pc[0] = pc[2];
11425 pc++;
11426 }
11427 }
11428 }
11429
11430
11431 for (i = 0;; i++)
11432 if (rpc_list[i].id == 0 || strcmp(arpc_param[0], rpc_list[i].name) == 0)
11433 break;
11434 idx = i;
11435 routine_id = rpc_list[i].id;
11436 if (rpc_list[i].id == 0) {
11437 cm_msg(MERROR, "rpc_execute", "Invalid rpc name (%s)", arpc_param[0]);
11438 return RPC_INVALID_ID;
11439 }
11440
11441 in_param_ptr = buffer1;
11442 out_param_ptr = buffer2;
11443 index_in = 1;
11444
11445 sprintf(debug_line, "%s(", rpc_list[idx].name);
11446
11447 for (i = 0; rpc_list[idx].param[i].tid != 0; i++) {
11448 tid = rpc_list[idx].param[i].tid;
11449 flags = rpc_list[idx].param[i].flags;
11450
11451 if (flags & RPC_IN) {
11452 if (flags & RPC_VARARRAY) {
11453 sscanf(arpc_param[index_in++], "%d %d", &n_param, &array_tid);
11454
11455 prpc_param[i] = in_param_ptr;
11456 for (j = 0; j < n_param; j++) {
11457 db_sscanf(arpc_param[index_in++], in_param_ptr, ¶m_size, 0, array_tid);
11458 in_param_ptr += param_size;
11459 }
11460 in_param_ptr = (char *) ALIGN8(((POINTER_T) in_param_ptr));
11461
11462 strcat(debug_line, "<array>");
11463 } else {
11464 db_sscanf(arpc_param[index_in++], in_param_ptr, ¶m_size, 0, tid);
11465 param_size = ALIGN8(param_size);
11466
11467 if (tid == TID_STRING || tid == TID_LINK)
11468 param_size = ALIGN8(1 + strlen((char *) (in_param_ptr)));
11469
11470
11471
11472
11473
11474 prpc_param[i] = in_param_ptr;
11475
11476 db_sprintf(str, in_param_ptr, param_size, 0, rpc_list[idx].param[i].tid);
11477 if (rpc_list[idx].param[i].tid == TID_STRING) {
11478
11479 if (strlen(debug_line) + strlen(str) + 2 < sizeof(debug_line)) {
11480 strcat(debug_line, "\"");
11481 strcat(debug_line, str);
11482 strcat(debug_line, "\"");
11483 } else
11484 strcat(debug_line, "...");
11485 } else
11486 strcat(debug_line, str);
11487
11488 in_param_ptr += param_size;
11489 }
11490
11491 if ((POINTER_T) in_param_ptr - (POINTER_T) buffer1 > ASCII_BUFFER_SIZE) {
11492 cm_msg(MERROR, "rpc_ascii_execute",
11493 "parameters (%d) too large for network buffer (%d)", param_size, ASCII_BUFFER_SIZE);
11494 return RPC_EXCEED_BUFFER;
11495 }
11496
11497 }
11498
11499 if (flags & RPC_OUT) {
11500 param_size = ALIGN8(tid_size[tid]);
11501
11502 if (flags & RPC_VARARRAY || tid == TID_STRING) {
11503
11504 param_size = atoi(arpc_param[index_in]);
11505 param_size = ALIGN8(param_size);
11506 }
11507
11508
11509
11510
11511
11512 if ((POINTER_T) out_param_ptr - (POINTER_T) buffer2 + param_size > ASCII_BUFFER_SIZE) {
11513 cm_msg(MERROR, "rpc_execute",
11514 "return parameters (%d) too large for network buffer (%d)",
11515 (POINTER_T) out_param_ptr - (POINTER_T) buffer2 + param_size, ASCII_BUFFER_SIZE);
11516 return RPC_EXCEED_BUFFER;
11517 }
11518
11519
11520 if (rpc_list[idx].param[i].flags & RPC_IN)
11521 memcpy(out_param_ptr, prpc_param[i], param_size);
11522
11523 if (!(flags & RPC_IN))
11524 strcat(debug_line, "-");
11525
11526 prpc_param[i] = out_param_ptr;
11527 out_param_ptr += param_size;
11528 }
11529
11530 if (rpc_list[idx].param[i + 1].tid)
11531 strcat(debug_line, ", ");
11532 }
11533
11534 strcat(debug_line, ")");
11535 rpc_debug_printf(debug_line);
11536
11537 last_param_ptr = out_param_ptr;
11538
11539
11540
11541
11542
11543 if (rpc_list[idx].dispatch)
11544 status = rpc_list[idx].dispatch(routine_id, prpc_param);
11545 else
11546 status = RPC_INVALID_ID;
11547
11548 if (routine_id == RPC_ID_EXIT || routine_id == RPC_ID_SHUTDOWN || routine_id == RPC_ID_WATCHDOG)
11549 status = RPC_SUCCESS;
11550
11551
11552 if (status == SS_ABORT)
11553 return SS_ABORT;
11554
11555
11556 if (!sock)
11557 return RPC_SUCCESS;
11558
11559
11560 out_param_ptr = return_buffer;
11561 sprintf(out_param_ptr, "%d", status);
11562 out_param_ptr += strlen(out_param_ptr);
11563
11564
11565 for (i = 0; rpc_list[idx].param[i].tid != 0; i++)
11566 if (rpc_list[idx].param[i].flags & RPC_OUT) {
11567 *out_param_ptr++ = '&';
11568
11569 tid = rpc_list[idx].param[i].tid;
11570 flags = rpc_list[idx].param[i].flags;
11571 param_size = ALIGN8(tid_size[tid]);
11572
11573 if (tid == TID_STRING && !(flags & RPC_VARARRAY)) {
11574 strcpy(out_param_ptr, (char *) prpc_param[i]);
11575 param_size = strlen((char *) prpc_param[i]);
11576 }
11577
11578 else if (flags & RPC_VARARRAY) {
11579 if (rpc_list[idx].id == RPC_BM_RECEIVE_EVENT) {
11580 param_size = *((INT *) prpc_param[i + 1]);
11581
11582 sprintf(out_param_ptr, "%d", param_size);
11583 out_param_ptr += strlen(out_param_ptr) + 1;
11584 memcpy(out_param_ptr, prpc_param[i], param_size);
11585 out_param_ptr += param_size;
11586 *out_param_ptr = 0;
11587 } else {
11588 if (rpc_list[idx].id == RPC_DB_GET_DATA1) {
11589 param_size = *((INT *) prpc_param[i + 1]);
11590 array_tid = *((INT *) prpc_param[i + 2]);
11591 num_values = *((INT *) prpc_param[i + 3]);
11592 } else if (rpc_list[idx].id == RPC_DB_GET_DATA_INDEX) {
11593 param_size = *((INT *) prpc_param[i + 1]);
11594 array_tid = *((INT *) prpc_param[i + 3]);
11595 num_values = 1;
11596 } else if (rpc_list[idx].id == RPC_HS_READ) {
11597 param_size = *((INT *) prpc_param[i + 1]);
11598 if (i == 6) {
11599 array_tid = TID_DWORD;
11600 num_values = param_size / sizeof(DWORD);
11601 } else {
11602 array_tid = *((INT *) prpc_param[10]);
11603 num_values = *((INT *) prpc_param[11]);
11604 }
11605 } else {
11606
11607 param_size = *((INT *) prpc_param[i + 1]);
11608 array_tid = tid;
11609 if (tid == TID_STRING)
11610 num_values = param_size / NAME_LENGTH;
11611 else
11612 num_values = param_size / tid_size[tid];
11613 }
11614
11615
11616 if (array_tid == TID_STRING)
11617 item_size = param_size / num_values;
11618 else
11619 item_size = tid_size[array_tid];
11620
11621
11622 sprintf(out_param_ptr, "%d", num_values);
11623 out_param_ptr += strlen(out_param_ptr);
11624
11625
11626 for (j = 0; j < num_values; j++) {
11627 *out_param_ptr++ = '&';
11628 db_sprintf(out_param_ptr, prpc_param[i], item_size, j, array_tid);
11629 out_param_ptr += strlen(out_param_ptr);
11630 }
11631 }
11632 }
11633
11634
11635
11636
11637
11638 else
11639 db_sprintf(out_param_ptr, prpc_param[i], param_size, 0, tid);
11640
11641 out_param_ptr += strlen(out_param_ptr);
11642
11643 if ((POINTER_T) out_param_ptr - (POINTER_T) return_buffer > ASCII_BUFFER_SIZE) {
11644 cm_msg(MERROR, "rpc_execute",
11645 "return parameter (%d) too large for network buffer (%d)", param_size, ASCII_BUFFER_SIZE);
11646 return RPC_EXCEED_BUFFER;
11647 }
11648 }
11649
11650
11651 param_size = (POINTER_T) out_param_ptr - (POINTER_T) return_buffer + 1;
11652
11653 status = send_tcp(sock, return_buffer, param_size, 0);
11654
11655 if (status < 0) {
11656 cm_msg(MERROR, "rpc_execute", "send_tcp() failed");
11657 return RPC_NET_ERROR;
11658 }
11659
11660
11661 if (strlen(return_buffer) > sizeof(debug_line)) {
11662 memcpy(debug_line, return_buffer, sizeof(debug_line) - 10);
11663 strcat(debug_line, "...");
11664 } else
11665 sprintf(debug_line, "-> %s", return_buffer);
11666 rpc_debug_printf(debug_line);
11667
11668
11669 if (routine_id == RPC_ID_EXIT)
11670 return SS_EXIT;
11671
11672
11673 if (routine_id == RPC_ID_SHUTDOWN)
11674 return RPC_SHUTDOWN;
11675
11676 return RPC_SUCCESS;
11677 }
11678
11679 #define MAX_N_ALLOWED_HOSTS 100
11680 static char allowed_host[MAX_N_ALLOWED_HOSTS][256];
11681 static int n_allowed_hosts = 0;
11682
11683
11684 INT rpc_clear_allowed_hosts()
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699
11700 {
11701 n_allowed_hosts = 0;
11702 return RPC_SUCCESS;
11703 }
11704
11705
11706 INT rpc_add_allowed_host(const char* hostname)
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723 {
11724 if (n_allowed_hosts >= MAX_N_ALLOWED_HOSTS)
11725 return RPC_NO_MEMORY;
11726
11727 strlcpy(allowed_host[n_allowed_hosts++], hostname, sizeof(allowed_host[0]));
11728 return RPC_SUCCESS;
11729 }
11730
11731
11732 INT rpc_server_accept(int lsock)
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753 {
11754 INT idx, i;
11755 unsigned int size;
11756 int status;
11757 char command;
11758 INT sock;
11759 char version[NAME_LENGTH], v1[32];
11760 char experiment[NAME_LENGTH];
11761 INT port1, port2, port3;
11762 char *ptr;
11763 struct sockaddr_in acc_addr;
11764 struct hostent *phe;
11765 char str[100];
11766 char host_port1_str[30], host_port2_str[30], host_port3_str[30];
11767 char debug_str[30];
11768 char *argv[10];
11769 char net_buffer[256];
11770 struct linger ling;
11771
11772 static struct callback_addr callback;
11773
11774 if (lsock > 0) {
11775 size = sizeof(acc_addr);
11776 #ifdef OS_WINNT
11777 sock = accept(lsock, (struct sockaddr *) &acc_addr, (int *) &size);
11778 #else
11779 sock = accept(lsock, (struct sockaddr *) &acc_addr, &size);
11780 #endif
11781
11782 if (sock == -1)
11783 return RPC_NET_ERROR;
11784 } else {
11785
11786
11787 size = sizeof(acc_addr);
11788 sock = lsock;
11789 #ifdef OS_WINNT
11790 getpeername(sock, (struct sockaddr *) &acc_addr, (int *) &size);
11791 #else
11792 getpeername(sock, (struct sockaddr *) &acc_addr, &size);
11793 #endif
11794 }
11795
11796
11797 if (n_allowed_hosts > 0) {
11798 int allowed = FALSE;
11799 struct hostent *remote_phe;
11800 char hname[256];
11801 struct in_addr remote_addr;
11802
11803
11804 memcpy(&remote_addr, &(acc_addr.sin_addr), sizeof(remote_addr));
11805
11806 remote_phe = gethostbyaddr((char *) &remote_addr, 4, PF_INET);
11807
11808 if (remote_phe == NULL) {
11809
11810 strlcpy(hname, (char *)inet_ntoa(remote_addr), sizeof(hname));
11811 } else
11812 strlcpy(hname, remote_phe->h_name, sizeof(hname));
11813
11814
11815 if (strcmp(hname, "localhost.localdomain") == 0)
11816 allowed = TRUE;
11817 if (strcmp(hname, "localhost") == 0)
11818 allowed = TRUE;
11819
11820 if (!allowed) {
11821 for (i=0 ; i<n_allowed_hosts ; i++)
11822 if (strcmp(hname, allowed_host[i]) == 0) {
11823 allowed = TRUE;
11824 break;
11825 }
11826 }
11827
11828 if (!allowed) {
11829 cm_msg(MERROR, "rpc_server_accept", "rejecting connection from unallowed host \'%s\'", hname);
11830 closesocket(sock);
11831 return RPC_NET_ERROR;
11832 }
11833 }
11834
11835
11836 i = recv_string(sock, net_buffer, 256, 10000);
11837 rpc_debug_printf("Received command: %s", net_buffer);
11838
11839 if (i > 0) {
11840 command = (char) toupper(net_buffer[0]);
11841
11842 switch (command) {
11843 case 'S':
11844
11845
11846 closesocket(sock);
11847 return RPC_SHUTDOWN;
11848
11849 case 'I':
11850
11851
11852 cm_scan_experiments();
11853 for (i = 0; i < MAX_EXPERIMENT && exptab[i].name[0]; i++) {
11854 rpc_debug_printf("Return experiment: %s", exptab[i].name);
11855 sprintf(str, "%s", exptab[i].name);
11856 send(sock, str, strlen(str) + 1, 0);
11857 }
11858 send(sock, "", 1, 0);
11859 closesocket(sock);
11860 break;
11861
11862 case 'C':
11863
11864
11865
11866
11867 callback.experiment[0] = 0;
11868 port1 = port2 = version[0] = 0;
11869
11870
11871
11872
11873
11874
11875 port1 = strtoul(net_buffer + 2, &ptr, 0);
11876 port2 = strtoul(ptr, &ptr, 0);
11877 port3 = strtoul(ptr, &ptr, 0);
11878
11879 while (*ptr == ' ')
11880 ptr++;
11881
11882 i = 0;
11883 for (; *ptr != 0 && *ptr != ' ' && i < (int) sizeof(version) - 1;)
11884 version[i++] = *ptr++;
11885
11886
11887 assert(i < (int) sizeof(version));
11888 version[i] = 0;
11889
11890
11891 for (; *ptr != 0 && *ptr != ' ';)
11892 ptr++;
11893
11894 while (*ptr == ' ')
11895 ptr++;
11896
11897 i = 0;
11898 for (; *ptr != 0 && *ptr != ' ' && *ptr != '\n' && *ptr != '\r' && i < (int) sizeof(experiment) - 1;)
11899 experiment[i++] = *ptr++;
11900
11901
11902 assert(i < (int) sizeof(experiment));
11903 experiment[i] = 0;
11904
11905 strlcpy(callback.experiment, experiment, NAME_LENGTH);
11906
11907
11908 strlcpy(v1, version, sizeof(v1));
11909 if (strchr(v1, '.'))
11910 if (strchr(strchr(v1, '.') + 1, '.'))
11911 *strchr(strchr(v1, '.') + 1, '.') = 0;
11912
11913 strlcpy(str, cm_get_version(), sizeof(str));
11914 if (strchr(str, '.'))
11915 if (strchr(strchr(str, '.') + 1, '.'))
11916 *strchr(strchr(str, '.') + 1, '.') = 0;
11917
11918 if (strcmp(v1, str) != 0) {
11919 sprintf(str, "client MIDAS version %s differs from local version %s", version, cm_get_version());
11920 cm_msg(MERROR, "rpc_server_accept", str);
11921
11922 sprintf(str, "received string: %s", net_buffer + 2);
11923 cm_msg(MERROR, "rpc_server_accept", str);
11924 }
11925
11926 callback.host_port1 = (short) port1;
11927 callback.host_port2 = (short) port2;
11928 callback.host_port3 = (short) port3;
11929 callback.debug = _debug_mode;
11930
11931
11932 #ifdef OS_VXWORKS
11933 {
11934 INT status;
11935 status = hostGetByAddr(acc_addr.sin_addr.s_addr, callback.host_name);
11936 if (status != 0) {
11937 cm_msg(MERROR, "rpc_server_accept", "cannot get host name");
11938 break;
11939 }
11940 }
11941 #else
11942 phe = gethostbyaddr((char *) &acc_addr.sin_addr, 4, PF_INET);
11943 if (phe == NULL) {
11944
11945 strlcpy(callback.host_name, (char *) inet_ntoa(acc_addr.sin_addr), HOST_NAME_LENGTH);
11946 } else
11947 strlcpy(callback.host_name, phe->h_name, HOST_NAME_LENGTH);
11948 #endif
11949
11950 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_MPROCESS) {
11951
11952 cm_scan_experiments();
11953
11954
11955 if (equal_ustring(callback.experiment, "Default"))
11956 idx = 0;
11957 else
11958 for (idx = 0; idx < MAX_EXPERIMENT && exptab[idx].name[0]; idx++)
11959 if (equal_ustring(callback.experiment, exptab[idx].name))
11960 break;
11961
11962 if (idx == MAX_EXPERIMENT || exptab[idx].name[0] == 0) {
11963 sprintf(str, "experiment \'%s\' not defined in exptab\r", callback.experiment);
11964 cm_msg(MERROR, "rpc_server_accept", str);
11965
11966 send(sock, "2", 2, 0);
11967 closesocket(sock);
11968 break;
11969 }
11970
11971 strlcpy(callback.directory, exptab[idx].directory, MAX_STRING_LENGTH);
11972 strlcpy(callback.user, exptab[idx].user, NAME_LENGTH);
11973
11974
11975 sprintf(host_port1_str, "%d", callback.host_port1);
11976 sprintf(host_port2_str, "%d", callback.host_port2);
11977 sprintf(host_port3_str, "%d", callback.host_port3);
11978 sprintf(debug_str, "%d", callback.debug);
11979
11980 argv[0] = (char *) rpc_get_server_option(RPC_OSERVER_NAME);
11981 argv[1] = callback.host_name;
11982 argv[2] = host_port1_str;
11983 argv[3] = host_port2_str;
11984 argv[4] = host_port3_str;
11985 argv[5] = debug_str;
11986 argv[6] = callback.experiment;
11987 argv[7] = callback.directory;
11988 argv[8] = callback.user;
11989 argv[9] = NULL;
11990
11991 rpc_debug_printf("Spawn: %s %s %s %s %s %s %s %s %s %s",
11992 argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8],
11993 argv[9]);
11994
11995 status = ss_spawnv(P_NOWAIT, (char *) rpc_get_server_option(RPC_OSERVER_NAME), argv);
11996
11997 if (status != SS_SUCCESS) {
11998 rpc_debug_printf("Cannot spawn subprocess: %s\n", strerror(errno));
11999
12000 sprintf(str, "3");
12001 send(sock, str, strlen(str) + 1, 0);
12002 closesocket(sock);
12003 break;
12004 }
12005
12006 sprintf(str, "1 %s", cm_get_version());
12007 send(sock, str, strlen(str) + 1, 0);
12008 closesocket(sock);
12009 } else {
12010 sprintf(str, "1 %s", cm_get_version());
12011 send(sock, str, strlen(str) + 1, 0);
12012 closesocket(sock);
12013 }
12014
12015
12016 for (idx = 0; idx < MAX_RPC_CONNECTION; idx++)
12017 if (_server_acception[idx].recv_sock == 0)
12018 break;
12019 if (idx == MAX_RPC_CONNECTION)
12020 return RPC_NET_ERROR;
12021 callback.index = idx;
12022
12023
12024 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_MTHREAD)
12025 ss_thread_create(rpc_server_thread, (void *) (&callback));
12026
12027
12028 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE ||
12029 rpc_get_server_option(RPC_OSERVER_TYPE) == ST_REMOTE)
12030 rpc_server_callback(&callback);
12031
12032 break;
12033
12034 default:
12035 cm_msg(MERROR, "rpc_server_accept", "received unknown command '%c' code %d", command, command);
12036 closesocket(sock);
12037 break;
12038
12039 }
12040 } else {
12041
12042
12043 ling.l_onoff = 1;
12044 ling.l_linger = 0;
12045 setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling));
12046 closesocket(sock);
12047 }
12048
12049 return RPC_SUCCESS;
12050 }
12051
12052
12053 INT rpc_client_accept(int lsock)
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074 {
12075 INT idx, i, version, status;
12076 unsigned int size;
12077 int sock;
12078 struct sockaddr_in acc_addr;
12079 INT client_hw_type = 0, hw_type;
12080 char str[100], client_program[NAME_LENGTH];
12081 char host_name[HOST_NAME_LENGTH];
12082 INT convert_flags;
12083 char net_buffer[256], *p;
12084
12085 size = sizeof(acc_addr);
12086 #ifdef OS_WINNT
12087 sock = accept(lsock, (struct sockaddr *) &acc_addr, (int *) &size);
12088 #else
12089 sock = accept(lsock, (struct sockaddr *) &acc_addr, &size);
12090 #endif
12091
12092 if (sock == -1)
12093 return RPC_NET_ERROR;
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110 strcpy(host_name, "(unknown)");
12111
12112 strcpy(client_program, "(unknown)");
12113
12114
12115 for (idx = 0; idx < MAX_RPC_CONNECTION; idx++)
12116 if (_server_acception[idx].recv_sock == 0)
12117 break;
12118 if (idx == MAX_RPC_CONNECTION) {
12119 closesocket(sock);
12120 return RPC_NET_ERROR;
12121 }
12122
12123
12124 i = recv_string(sock, net_buffer, sizeof(net_buffer), 10000);
12125 if (i <= 0) {
12126 closesocket(sock);
12127 return RPC_NET_ERROR;
12128 }
12129
12130
12131 p = strtok(net_buffer, " ");
12132 if (p != NULL) {
12133 client_hw_type = atoi(p);
12134 p = strtok(NULL, " ");
12135 }
12136 if (p != NULL) {
12137 version = atoi(p);
12138 p = strtok(NULL, " ");
12139 }
12140 if (p != NULL) {
12141 strlcpy(client_program, p, sizeof(client_program));
12142 p = strtok(NULL, " ");
12143 }
12144 if (p != NULL) {
12145 strlcpy(host_name, p, sizeof(host_name));
12146 p = strtok(NULL, " ");
12147 }
12148
12149 if (0)
12150 printf("rpc_client_accept: client_hw_type %d, version %d, client_name \'%s\', hostname \'%s\'\n",
12151 client_hw_type, version, client_program, host_name);
12152
12153
12154 _server_acception[idx].recv_sock = sock;
12155 _server_acception[idx].send_sock = 0;
12156 _server_acception[idx].event_sock = 0;
12157 _server_acception[idx].remote_hw_type = client_hw_type;
12158 strcpy(_server_acception[idx].host_name, host_name);
12159 strcpy(_server_acception[idx].prog_name, client_program);
12160 _server_acception[idx].tid = ss_gettid();
12161 _server_acception[idx].last_activity = ss_millitime();
12162 _server_acception[idx].watchdog_timeout = 0;
12163
12164
12165 hw_type = rpc_get_option(0, RPC_OHW_TYPE);
12166 sprintf(str, "%d %s", hw_type, cm_get_version());
12167 status = send(sock, str, strlen(str) + 1, 0);
12168 if (status != (INT) strlen(str) + 1)
12169 return RPC_NET_ERROR;
12170
12171 rpc_set_server_acception(idx + 1);
12172 rpc_calc_convert_flags(hw_type, client_hw_type, &convert_flags);
12173 rpc_set_server_option(RPC_CONVERT_FLAGS, convert_flags);
12174
12175
12176 ss_suspend_set_dispatch(CH_SERVER, _server_acception, (int (*)(void)) rpc_server_receive);
12177
12178 return RPC_SUCCESS;
12179 }
12180
12181
12182 INT rpc_server_callback(struct callback_addr * pcallback)
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201 {
12202 INT idx, status;
12203 int recv_sock, send_sock, event_sock;
12204 struct sockaddr_in bind_addr;
12205 struct hostent *phe;
12206 char str[100], client_program[NAME_LENGTH];
12207 char host_name[HOST_NAME_LENGTH];
12208 INT client_hw_type, hw_type;
12209 INT convert_flags;
12210 char net_buffer[256];
12211 struct callback_addr callback;
12212 char *p;
12213 int flag;
12214
12215
12216 memcpy(&callback, pcallback, sizeof(callback));
12217 idx = callback.index;
12218
12219
12220 recv_sock = socket(AF_INET, SOCK_STREAM, 0);
12221 send_sock = socket(AF_INET, SOCK_STREAM, 0);
12222 event_sock = socket(AF_INET, SOCK_STREAM, 0);
12223 if (event_sock == -1)
12224 return RPC_NET_ERROR;
12225
12226
12227 memset(&bind_addr, 0, sizeof(bind_addr));
12228 bind_addr.sin_family = AF_INET;
12229 bind_addr.sin_port = htons(callback.host_port1);
12230
12231 #ifdef OS_VXWORKS
12232 {
12233 INT host_addr;
12234
12235 host_addr = hostGetByName(callback.host_name);
12236 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
12237 }
12238 #else
12239 phe = gethostbyname(callback.host_name);
12240 if (phe == NULL) {
12241 cm_msg(MERROR, "rpc_server_callback", "cannot get host name");
12242 return RPC_NET_ERROR;
12243 }
12244 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
12245 #endif
12246
12247
12248 #ifdef OS_UNIX
12249 do {
12250 status = connect(recv_sock, (void *) &bind_addr, sizeof(bind_addr));
12251
12252
12253 } while (status == -1 && errno == EINTR);
12254 #else
12255 status = connect(recv_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
12256 #endif
12257
12258 if (status != 0) {
12259 cm_msg(MERROR, "rpc_server_callback", "cannot connect receive socket");
12260 goto error;
12261 }
12262
12263 bind_addr.sin_port = htons(callback.host_port2);
12264
12265
12266 #ifdef OS_UNIX
12267 do {
12268 status = connect(send_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
12269
12270
12271 } while (status == -1 && errno == EINTR);
12272 #else
12273 status = connect(send_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
12274 #endif
12275
12276 if (status != 0) {
12277 cm_msg(MERROR, "rpc_server_callback", "cannot connect send socket");
12278 goto error;
12279 }
12280
12281 bind_addr.sin_port = htons(callback.host_port3);
12282
12283
12284 #ifdef OS_UNIX
12285 do {
12286 status = connect(event_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
12287
12288
12289 } while (status == -1 && errno == EINTR);
12290 #else
12291 status = connect(event_sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
12292 #endif
12293
12294 if (status != 0) {
12295 cm_msg(MERROR, "rpc_server_callback", "cannot connect event socket");
12296 goto error;
12297 }
12298 #ifndef OS_ULTRIX
12299
12300 flag = 2 * 1024 * 1024;
12301 status = setsockopt(event_sock, SOL_SOCKET, SO_RCVBUF, (char *) &flag, sizeof(INT));
12302 if (status != 0)
12303 cm_msg(MERROR, "rpc_server_callback", "cannot setsockopt(SOL_SOCKET, SO_RCVBUF), errno %d (%s)", errno,
12304 strerror(errno));
12305 #endif
12306
12307 if (recv_string(recv_sock, net_buffer, 256, _rpc_connect_timeout) <= 0) {
12308 cm_msg(MERROR, "rpc_server_callback", "timeout on receive remote computer info");
12309 goto error;
12310 }
12311
12312
12313
12314 client_hw_type = strtoul(net_buffer, &p, 0);
12315
12316 while (*p == ' ')
12317 p++;
12318
12319 strlcpy(client_program, p, sizeof(client_program));
12320
12321
12322
12323
12324 #ifdef OS_VXWORKS
12325 status = hostGetByAddr(bind_addr.sin_addr.s_addr, host_name);
12326 if (status != 0)
12327 strcpy(host_name, "unknown");
12328 #else
12329 phe = gethostbyaddr((char *) &bind_addr.sin_addr, 4, PF_INET);
12330 if (phe == NULL)
12331 strcpy(host_name, "unknown");
12332 else
12333 strcpy(host_name, phe->h_name);
12334 #endif
12335
12336
12337 _server_acception[idx].recv_sock = recv_sock;
12338 _server_acception[idx].send_sock = send_sock;
12339 _server_acception[idx].event_sock = event_sock;
12340 _server_acception[idx].remote_hw_type = client_hw_type;
12341 strcpy(_server_acception[idx].host_name, host_name);
12342 strcpy(_server_acception[idx].prog_name, client_program);
12343 _server_acception[idx].tid = ss_gettid();
12344 _server_acception[idx].last_activity = ss_millitime();
12345 _server_acception[idx].watchdog_timeout = 0;
12346
12347
12348 hw_type = rpc_get_option(0, RPC_OHW_TYPE);
12349 sprintf(str, "%d", hw_type);
12350 send(recv_sock, str, strlen(str) + 1, 0);
12351
12352 rpc_set_server_acception(idx + 1);
12353 rpc_calc_convert_flags(hw_type, client_hw_type, &convert_flags);
12354 rpc_set_server_option(RPC_CONVERT_FLAGS, convert_flags);
12355
12356
12357 ss_suspend_set_dispatch(CH_SERVER, _server_acception, (int (*)(void)) rpc_server_receive);
12358
12359 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
12360 rpc_debug_printf("Connection to %s:%s established\n",
12361 _server_acception[idx].host_name, _server_acception[idx].prog_name);
12362
12363 return RPC_SUCCESS;
12364
12365 error:
12366
12367 closesocket(recv_sock);
12368 closesocket(send_sock);
12369 closesocket(event_sock);
12370
12371 return RPC_NET_ERROR;
12372 }
12373
12374
12375
12376 INT rpc_server_thread(void *pointer)
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394 {
12395 struct callback_addr callback;
12396 int status, semaphore_alarm, semaphore_elog, semaphore_history, semaphore_msg;
12397 static DWORD last_checked = 0;
12398
12399 memcpy(&callback, pointer, sizeof(callback));
12400
12401 status = rpc_server_callback(&callback);
12402
12403 if (status != RPC_SUCCESS)
12404 return status;
12405
12406
12407 ss_semaphore_create("ALARM", &semaphore_alarm);
12408 ss_semaphore_create("ELOG", &semaphore_elog);
12409 ss_semaphore_create("HISTORY", &semaphore_history);
12410 ss_semaphore_create("MSG", &semaphore_msg);
12411 cm_set_experiment_semaphore(semaphore_alarm, semaphore_elog, semaphore_history, semaphore_msg);
12412
12413 do {
12414 status = ss_suspend(5000, 0);
12415
12416 if (rpc_check_channels() == RPC_NET_ERROR)
12417 break;
12418
12419
12420 if (!rpc_is_remote() && ss_time() - last_checked > 10) {
12421 al_check();
12422 last_checked = ss_time();
12423 }
12424
12425 } while (status != SS_ABORT && status != SS_EXIT);
12426
12427
12428 ss_suspend_exit();
12429
12430 return RPC_SUCCESS;
12431 }
12432
12433
12434
12435 INT rpc_server_receive(INT idx, int sock, BOOL check)
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461 {
12462 INT status, n_received;
12463 INT remaining, *pbh, start_time;
12464 char test_buffer[256], str[80];
12465 EVENT_HEADER *pevent;
12466
12467
12468 if (_net_recv_buffer_size == 0) {
12469 int size = MAX_EVENT_SIZE + sizeof(EVENT_HEADER) + 1024;
12470 _net_recv_buffer = (char *) M_MALLOC(size);
12471 if (_net_recv_buffer == NULL) {
12472 cm_msg(MERROR, "rpc_server_receive", "Cannot allocate %d bytes for network buffer", size);
12473 return RPC_EXCEED_BUFFER;
12474 }
12475 _net_recv_buffer_size = size;
12476 _net_recv_buffer_size_odb = 0;
12477
12478 }
12479
12480
12481 if (_net_recv_buffer_size_odb == 0) {
12482 HNDLE hDB;
12483 int size;
12484 int max_event_size = MAX_EVENT_SIZE;
12485
12486
12487 status = cm_get_experiment_database(&hDB, NULL);
12488 assert(status == CM_SUCCESS);
12489
12490 if (hDB) {
12491 size = sizeof(INT);
12492 status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &max_event_size, &size, TID_DWORD, TRUE);
12493
12494 size = max_event_size + sizeof(EVENT_HEADER) + 1024;
12495
12496 _net_recv_buffer_size_odb = size;
12497
12498 if (size > _net_recv_buffer_size) {
12499 _net_recv_buffer = (char *) realloc(_net_recv_buffer, size);
12500 if (_net_recv_buffer == NULL) {
12501 cm_msg(MERROR, "rpc_server_receive", "Cannot allocate %d bytes for network buffer", size);
12502 return RPC_EXCEED_BUFFER;
12503 }
12504 _net_recv_buffer_size = size;
12505
12506 }
12507 }
12508 }
12509
12510
12511 if (check) {
12512 n_received = recv(sock, test_buffer, sizeof(test_buffer), MSG_PEEK);
12513
12514 if (n_received == -1)
12515 cm_msg(MERROR, "rpc_server_receive",
12516 "recv(%d,MSG_PEEK) returned %d, errno: %d (%s)", sizeof(test_buffer),
12517 n_received, errno, strerror(errno));
12518
12519 if (n_received <= 0)
12520 return SS_ABORT;
12521
12522 return SS_SUCCESS;
12523 }
12524
12525 remaining = 0;
12526
12527
12528 if (sock == _server_acception[idx].recv_sock) {
12529 do {
12530 if (_server_acception[idx].remote_hw_type == DR_ASCII)
12531 n_received =
12532 recv_string(_server_acception[idx].recv_sock, _net_recv_buffer, _net_recv_buffer_size, 10000);
12533 else
12534 n_received = recv_tcp_server(idx, _net_recv_buffer, _net_recv_buffer_size, 0, &remaining);
12535
12536 if (n_received <= 0) {
12537 status = SS_ABORT;
12538 cm_msg(MERROR, "rpc_server_receive", "recv_tcp_server() returned %d, abort", n_received);
12539 goto error;
12540 }
12541
12542 rpc_set_server_acception(idx + 1);
12543
12544 if (_server_acception[idx].remote_hw_type == DR_ASCII)
12545 status = rpc_execute_ascii(_server_acception[idx].recv_sock, _net_recv_buffer);
12546 else
12547 status = rpc_execute(_server_acception[idx].recv_sock,
12548 _net_recv_buffer, _server_acception[idx].convert_flags);
12549
12550 if (status == SS_ABORT) {
12551 cm_msg(MERROR, "rpc_server_receive", "rpc_execute() returned %d, abort", status);
12552 goto error;
12553 }
12554
12555 if (status == SS_EXIT || status == RPC_SHUTDOWN) {
12556 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
12557 rpc_debug_printf("Connection to %s:%s closed\n",
12558 _server_acception[idx].host_name, _server_acception[idx].prog_name);
12559 goto exit;
12560 }
12561
12562 } while (remaining);
12563 } else {
12564
12565 if (sock == _server_acception[idx].event_sock) {
12566 start_time = ss_millitime();
12567
12568 do {
12569 n_received = recv_event_server(idx, _net_recv_buffer, _net_recv_buffer_size, 0, &remaining);
12570
12571 if (n_received <= 0) {
12572 status = SS_ABORT;
12573 cm_msg(MERROR, "rpc_server_receive", "recv_event_server() returned %d, abort", n_received);
12574 goto error;
12575 }
12576
12577
12578 pbh = (INT *) _net_recv_buffer;
12579 pevent = (EVENT_HEADER *) (pbh + 1);
12580
12581 status = bm_send_event(*pbh, pevent, pevent->data_size + sizeof(EVENT_HEADER), SYNC);
12582 if (status != BM_SUCCESS)
12583 cm_msg(MERROR, "rpc_server_receive", "bm_send_event() returned %d", status);
12584
12585
12586 } while (ss_millitime() - start_time < 500 && remaining);
12587 }
12588 }
12589
12590 return RPC_SUCCESS;
12591
12592 error:
12593
12594 strlcpy(str, _server_acception[idx].host_name, sizeof(str));
12595 if (strchr(str, '.'))
12596 *strchr(str, '.') = 0;
12597 cm_msg(MTALK, "rpc_server_receive", "Program \'%s\' on host \'%s\' aborted",
12598 _server_acception[idx].prog_name, str);
12599
12600 exit:
12601
12602
12603 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE) {
12604 HNDLE hDB, hKey;
12605
12606 cm_get_experiment_database(&hDB, &hKey);
12607
12608
12609
12610 if (hDB) {
12611 #ifdef LOCAL_ROUTINES
12612 ss_alarm(0, cm_watchdog);
12613 #endif
12614
12615 cm_delete_client_info(hDB, 0);
12616
12617 bm_close_all_buffers();
12618 db_close_all_databases();
12619
12620 rpc_deregister_functions();
12621
12622 cm_set_experiment_database(0, 0);
12623
12624 _msg_buffer = 0;
12625 }
12626 }
12627
12628
12629 if (_server_acception[idx].recv_sock)
12630 closesocket(_server_acception[idx].recv_sock);
12631 if (_server_acception[idx].send_sock)
12632 closesocket(_server_acception[idx].send_sock);
12633 if (_server_acception[idx].event_sock)
12634 closesocket(_server_acception[idx].event_sock);
12635
12636
12637 M_FREE(_server_acception[idx].net_buffer);
12638 _server_acception[idx].net_buffer = NULL;
12639
12640
12641 memset(&_server_acception[idx], 0, sizeof(RPC_SERVER_ACCEPTION));
12642
12643
12644 if (status == RPC_SHUTDOWN)
12645 return status;
12646
12647
12648 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_REMOTE)
12649 return SS_SUCCESS;
12650
12651 return status;
12652 }
12653
12654
12655
12656 INT rpc_server_shutdown(void)
12657
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
12673 {
12674 INT i;
12675 struct linger ling;
12676
12677
12678 for (i = 0; i < MAX_RPC_CONNECTION; i++)
12679 if (_server_acception[i].recv_sock != 0) {
12680
12681 ling.l_onoff = 1;
12682 ling.l_linger = 0;
12683 setsockopt(_server_acception[i].recv_sock, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling));
12684 closesocket(_server_acception[i].recv_sock);
12685
12686 if (_server_acception[i].send_sock) {
12687 setsockopt(_server_acception[i].send_sock, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling));
12688 closesocket(_server_acception[i].send_sock);
12689 }
12690
12691 if (_server_acception[i].event_sock) {
12692 setsockopt(_server_acception[i].event_sock, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling));
12693 closesocket(_server_acception[i].event_sock);
12694 }
12695
12696 _server_acception[i].recv_sock = 0;
12697 _server_acception[i].send_sock = 0;
12698 _server_acception[i].event_sock = 0;
12699 }
12700
12701 if (_lsock) {
12702 closesocket(_lsock);
12703 _lsock = 0;
12704 _server_registered = FALSE;
12705 }
12706
12707
12708 ss_suspend_exit();
12709
12710 return RPC_SUCCESS;
12711 }
12712
12713
12714
12715 INT rpc_check_channels(void)
12716
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733 {
12734 INT status, idx, i, convert_flags;
12735 NET_COMMAND nc;
12736 fd_set readfds;
12737 struct timeval timeout;
12738
12739 for (idx = 0; idx < MAX_RPC_CONNECTION; idx++) {
12740 if (_server_acception[idx].recv_sock &&
12741 _server_acception[idx].tid == ss_gettid() &&
12742 _server_acception[idx].watchdog_timeout &&
12743 (ss_millitime() - _server_acception[idx].last_activity >
12744 (DWORD) _server_acception[idx].watchdog_timeout)) {
12745
12746
12747
12748
12749
12750 nc.header.routine_id = MSG_WATCHDOG;
12751 nc.header.param_size = 0;
12752
12753 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
12754 if (convert_flags) {
12755 rpc_convert_single(&nc.header.routine_id, TID_DWORD, RPC_OUTGOING, convert_flags);
12756 rpc_convert_single(&nc.header.param_size, TID_DWORD, RPC_OUTGOING, convert_flags);
12757 }
12758
12759
12760 i = send_tcp(_server_acception[idx].send_sock, (char *) &nc, sizeof(NET_COMMAND_HEADER), 0);
12761
12762 if (i < 0)
12763 goto exit;
12764
12765
12766 FD_ZERO(&readfds);
12767 FD_SET(_server_acception[idx].send_sock, &readfds);
12768 FD_SET(_server_acception[idx].recv_sock, &readfds);
12769
12770 timeout.tv_sec = _server_acception[idx].watchdog_timeout / 1000;
12771 timeout.tv_usec = (_server_acception[idx].watchdog_timeout % 1000) * 1000;
12772
12773 do {
12774 status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
12775
12776
12777 if (status == -1 && timeout.tv_sec >= WATCHDOG_INTERVAL / 1000)
12778 timeout.tv_sec -= WATCHDOG_INTERVAL / 1000;
12779
12780 } while (status == -1);
12781
12782 if (!FD_ISSET(_server_acception[idx].send_sock, &readfds) &&
12783 !FD_ISSET(_server_acception[idx].recv_sock, &readfds))
12784 goto exit;
12785
12786
12787 if (FD_ISSET(_server_acception[idx].send_sock, &readfds)) {
12788 i = recv_tcp(_server_acception[idx].send_sock, (char *) &nc, sizeof(nc), 0);
12789 if (i <= 0)
12790 goto exit;
12791 }
12792 }
12793 }
12794
12795 return RPC_SUCCESS;
12796
12797 exit:
12798
12799 cm_msg(MINFO, "rpc_check_channels", "client [%s]%s failed watchdog test after %d sec",
12800 _server_acception[idx].host_name,
12801 _server_acception[idx].prog_name, _server_acception[idx].watchdog_timeout / 1000);
12802
12803
12804 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
12805 cm_disconnect_experiment();
12806
12807
12808 if (_server_acception[idx].recv_sock)
12809 closesocket(_server_acception[idx].recv_sock);
12810 if (_server_acception[idx].send_sock)
12811 closesocket(_server_acception[idx].send_sock);
12812 if (_server_acception[idx].event_sock)
12813 closesocket(_server_acception[idx].event_sock);
12814
12815
12816 M_FREE(_server_acception[idx].net_buffer);
12817 _server_acception[idx].net_buffer = NULL;
12818
12819
12820 memset(&_server_acception[idx], 0, sizeof(RPC_SERVER_ACCEPTION));
12821
12822 return RPC_NET_ERROR;
12823 }
12824
12825
12826 #endif
12827
12828
12829
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848 void bk_init(void *event)
12849 {
12850 ((BANK_HEADER *) event)->data_size = 0;
12851 ((BANK_HEADER *) event)->flags = BANK_FORMAT_VERSION;
12852 }
12853
12854
12855 #ifndef DOXYGEN_SHOULD_SKIP_THIS
12856
12857
12858 BOOL bk_is32(void *event)
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874
12875 {
12876 return ((((BANK_HEADER *) event)->flags & BANK_FORMAT_32BIT) > 0);
12877 }
12878
12879
12880 #endif
12881
12882
12883
12884
12885
12886
12887
12888
12889 void bk_init32(void *event)
12890 {
12891 ((BANK_HEADER *) event)->data_size = 0;
12892 ((BANK_HEADER *) event)->flags = BANK_FORMAT_VERSION | BANK_FORMAT_32BIT;
12893 }
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903 INT bk_size(void *event)
12904 {
12905 return ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER);
12906 }
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930 void bk_create(void *event, const char *name, WORD type, void *pdata)
12931 {
12932 if (((BANK_HEADER *) event)->flags & BANK_FORMAT_32BIT) {
12933 BANK32 *pbk32;
12934
12935 pbk32 = (BANK32 *) ((char *) (((BANK_HEADER *) event) + 1) + ((BANK_HEADER *) event)->data_size);
12936 strncpy(pbk32->name, name, 4);
12937 pbk32->type = type;
12938 pbk32->data_size = 0;
12939 *((void **) pdata) = pbk32 + 1;
12940 } else {
12941 BANK *pbk;
12942
12943 pbk = (BANK *) ((char *) (((BANK_HEADER *) event) + 1) + ((BANK_HEADER *) event)->data_size);
12944 strncpy(pbk->name, name, 4);
12945 pbk->type = type;
12946 pbk->data_size = 0;
12947 *((void **) pdata) = pbk + 1;
12948 }
12949 }
12950
12951
12952
12953
12954 #ifndef DOXYGEN_SHOULD_SKIP_THIS
12955
12956
12957 int bk_delete(void *event, const char *name)
12958
12959
12960
12961
12962
12963
12964
12965
12966
12967
12968
12969
12970
12971
12972
12973 {
12974 BANK *pbk;
12975 BANK32 *pbk32;
12976 DWORD dname;
12977 int remaining;
12978
12979 if (((BANK_HEADER *) event)->flags & BANK_FORMAT_32BIT) {
12980
12981 pbk32 = (BANK32 *) (((BANK_HEADER *) event) + 1);
12982 strncpy((char *) &dname, name, 4);
12983 do {
12984 if (*((DWORD *) pbk32->name) == dname) {
12985
12986 remaining = ((char *) event + ((BANK_HEADER *) event)->data_size +
12987 sizeof(BANK_HEADER)) - ((char *) (pbk32 + 1) + ALIGN8(pbk32->data_size));
12988
12989
12990 ((BANK_HEADER *) event)->data_size -= sizeof(BANK32) + ALIGN8(pbk32->data_size);
12991
12992
12993 if (remaining > 0)
12994 memcpy(pbk32, (char *) (pbk32 + 1) + ALIGN8(pbk32->data_size), remaining);
12995 return CM_SUCCESS;
12996 }
12997
12998 pbk32 = (BANK32 *) ((char *) (pbk32 + 1) + ALIGN8(pbk32->data_size));
12999 } while ((DWORD) ((char *) pbk32 - (char *) event) <
13000 ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER));
13001 } else {
13002
13003 pbk = (BANK *) (((BANK_HEADER *) event) + 1);
13004 strncpy((char *) &dname, name, 4);
13005 do {
13006 if (*((DWORD *) pbk->name) == dname) {
13007
13008 remaining = ((char *) event + ((BANK_HEADER *) event)->data_size +
13009 sizeof(BANK_HEADER)) - ((char *) (pbk + 1) + ALIGN8(pbk->data_size));
13010
13011
13012 ((BANK_HEADER *) event)->data_size -= sizeof(BANK) + ALIGN8(pbk->data_size);
13013
13014
13015 if (remaining > 0)
13016 memcpy(pbk, (char *) (pbk + 1) + ALIGN8(pbk->data_size), remaining);
13017 return CM_SUCCESS;
13018 }
13019
13020 pbk = (BANK *) ((char *) (pbk + 1) + ALIGN8(pbk->data_size));
13021 } while ((DWORD) ((char *) pbk - (char *) event) <
13022 ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER));
13023 }
13024
13025 return 0;
13026 }
13027
13028
13029 #endif
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042 INT bk_close(void *event, void *pdata)
13043 {
13044 if (((BANK_HEADER *) event)->flags & BANK_FORMAT_32BIT) {
13045 BANK32 *pbk32;
13046
13047 pbk32 = (BANK32 *) ((char *) (((BANK_HEADER *) event) + 1) + ((BANK_HEADER *) event)->data_size);
13048 pbk32->data_size = (DWORD) ((char *) pdata - (char *) (pbk32 + 1));
13049 if (pbk32->type == TID_STRUCT && pbk32->data_size == 0)
13050 printf("Warning: bank %c%c%c%c has zero size\n",
13051 pbk32->name[0], pbk32->name[1], pbk32->name[2], pbk32->name[3]);
13052 ((BANK_HEADER *) event)->data_size += sizeof(BANK32) + ALIGN8(pbk32->data_size);
13053 return pbk32->data_size;
13054 } else {
13055 BANK *pbk;
13056
13057 pbk = (BANK *) ((char *) (((BANK_HEADER *) event) + 1) + ((BANK_HEADER *) event)->data_size);
13058 pbk->data_size = (WORD) ((char *) pdata - (char *) (pbk + 1));
13059 if (pbk->type == TID_STRUCT && pbk->data_size == 0)
13060 printf("Warning: bank %c%c%c%c has zero size\n", pbk->name[0], pbk->name[1], pbk->name[2],
13061 pbk->name[3]);
13062 ((BANK_HEADER *) event)->data_size += sizeof(BANK) + ALIGN8(pbk->data_size);
13063 return pbk->data_size;
13064 }
13065 }
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092 INT bk_list(void *event, char *bklist)
13093 {
13094 INT nbk, size;
13095 BANK *pmbk = NULL;
13096 BANK32 *pmbk32 = NULL;
13097 char *pdata;
13098
13099
13100 bklist[0] = 0;
13101 nbk = 0;
13102 do {
13103
13104 if (bk_is32(event)) {
13105 size = bk_iterate32(event, &pmbk32, &pdata);
13106 if (pmbk32 == NULL)
13107 break;
13108 } else {
13109 size = bk_iterate(event, &pmbk, &pdata);
13110 if (pmbk == NULL)
13111 break;
13112 }
13113 nbk++;
13114
13115 if (nbk > BANKLIST_MAX) {
13116 cm_msg(MINFO, "bk_list", "over %i banks -> truncated", BANKLIST_MAX);
13117 return (nbk - 1);
13118 }
13119 if (bk_is32(event))
13120 strncat(bklist, (char *) pmbk32->name, 4);
13121 else
13122 strncat(bklist, (char *) pmbk->name, 4);
13123 }
13124 while (1);
13125 return (nbk);
13126 }
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136 INT bk_locate(void *event, const char *name, void *pdata)
13137 {
13138 BANK *pbk;
13139 BANK32 *pbk32;
13140 DWORD dname;
13141
13142 if (bk_is32(event)) {
13143 pbk32 = (BANK32 *) (((BANK_HEADER *) event) + 1);
13144 strncpy((char *) &dname, name, 4);
13145 while ((DWORD) ((char *) pbk32 - (char *) event) <
13146 ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER)) {
13147 if (*((DWORD *) pbk32->name) == dname) {
13148 *((void **) pdata) = pbk32 + 1;
13149 if (tid_size[pbk32->type & 0xFF] == 0)
13150 return pbk32->data_size;
13151 return pbk32->data_size / tid_size[pbk32->type & 0xFF];
13152 }
13153 pbk32 = (BANK32 *) ((char *) (pbk32 + 1) + ALIGN8(pbk32->data_size));
13154 }
13155 } else {
13156 pbk = (BANK *) (((BANK_HEADER *) event) + 1);
13157 strncpy((char *) &dname, name, 4);
13158 while ((DWORD) ((char *) pbk - (char *) event) <
13159 ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER)) {
13160 if (*((DWORD *) pbk->name) == dname) {
13161 *((void **) pdata) = pbk + 1;
13162 if (tid_size[pbk->type & 0xFF] == 0)
13163 return pbk->data_size;
13164 return pbk->data_size / tid_size[pbk->type & 0xFF];
13165 }
13166 pbk = (BANK *) ((char *) (pbk + 1) + ALIGN8(pbk->data_size));
13167 }
13168
13169 }
13170
13171
13172 *((void **) pdata) = NULL;
13173 return 0;
13174 }
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186 INT bk_find(BANK_HEADER * pbkh, const char *name, DWORD * bklen, DWORD * bktype, void **pdata)
13187 {
13188 BANK *pbk;
13189 BANK32 *pbk32;
13190 DWORD dname;
13191
13192 if (bk_is32(pbkh)) {
13193 pbk32 = (BANK32 *) (pbkh + 1);
13194 strncpy((char *) &dname, name, 4);
13195 do {
13196 if (*((DWORD *) pbk32->name) == dname) {
13197 *((void **) pdata) = pbk32 + 1;
13198 if (tid_size[pbk32->type & 0xFF] == 0)
13199 *bklen = pbk32->data_size;
13200 else
13201 *bklen = pbk32->data_size / tid_size[pbk32->type & 0xFF];
13202
13203 *bktype = pbk32->type;
13204 return 1;
13205 }
13206 pbk32 = (BANK32 *) ((char *) (pbk32 + 1) + ALIGN8(pbk32->data_size));
13207 } while ((DWORD) ((char *) pbk32 - (char *) pbkh) < pbkh->data_size + sizeof(BANK_HEADER));
13208 } else {
13209 pbk = (BANK *) (pbkh + 1);
13210 strncpy((char *) &dname, name, 4);
13211 do {
13212 if (*((DWORD *) pbk->name) == dname) {
13213 *((void **) pdata) = pbk + 1;
13214 if (tid_size[pbk->type & 0xFF] == 0)
13215 *bklen = pbk->data_size;
13216 else
13217 *bklen = pbk->data_size / tid_size[pbk->type & 0xFF];
13218
13219 *bktype = pbk->type;
13220 return 1;
13221 }
13222 pbk = (BANK *) ((char *) (pbk + 1) + ALIGN8(pbk->data_size));
13223 } while ((DWORD) ((char *) pbk - (char *) pbkh) < pbkh->data_size + sizeof(BANK_HEADER));
13224 }
13225
13226
13227 *((void **) pdata) = NULL;
13228 return 0;
13229 }
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267 INT bk_iterate(void *event, BANK ** pbk, void *pdata)
13268 {
13269 if (*pbk == NULL)
13270 *pbk = (BANK *) (((BANK_HEADER *) event) + 1);
13271 else
13272 *pbk = (BANK *) ((char *) (*pbk + 1) + ALIGN8((*pbk)->data_size));
13273
13274 *((void **) pdata) = (*pbk) + 1;
13275
13276 if ((DWORD) ((char *) *pbk - (char *) event) >= ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER)) {
13277 *pbk = *((BANK **) pdata) = NULL;
13278 return 0;
13279 }
13280
13281 return (*pbk)->data_size;
13282 }
13283
13284
13285
13286 #ifndef DOXYGEN_SHOULD_SKIP_THIS
13287
13288
13289 INT bk_iterate32(void *event, BANK32 ** pbk, void *pdata)
13290
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300
13301
13302
13303
13304
13305
13306
13307
13308 {
13309 if (*pbk == NULL)
13310 *pbk = (BANK32 *) (((BANK_HEADER *) event) + 1);
13311 else
13312 *pbk = (BANK32 *) ((char *) (*pbk + 1) + ALIGN8((*pbk)->data_size));
13313
13314 *((void **) pdata) = (*pbk) + 1;
13315
13316 if ((DWORD) ((char *) *pbk - (char *) event) >= ((BANK_HEADER *) event)->data_size + sizeof(BANK_HEADER)) {
13317 *pbk = *((BANK32 **) pdata) = NULL;
13318 return 0;
13319 }
13320
13321 return (*pbk)->data_size;
13322 }
13323
13324
13325 #endif
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342 INT bk_swap(void *event, BOOL force)
13343 {
13344 BANK_HEADER *pbh;
13345 BANK *pbk;
13346 BANK32 *pbk32;
13347 void *pdata;
13348 WORD type;
13349 BOOL b32;
13350
13351 pbh = (BANK_HEADER *) event;
13352
13353
13354 if (pbh->flags < 0x10000 && !force)
13355 return 0;
13356
13357
13358 DWORD_SWAP(&pbh->data_size);
13359 DWORD_SWAP(&pbh->flags);
13360
13361
13362 b32 = ((pbh->flags & BANK_FORMAT_32BIT) > 0);
13363
13364 pbk = (BANK *) (pbh + 1);
13365 pbk32 = (BANK32 *) pbk;
13366
13367
13368 while ((char *) pbk - (char *) pbh < (INT) pbh->data_size + (INT) sizeof(BANK_HEADER)) {
13369
13370 if (b32) {
13371 DWORD_SWAP(&pbk32->type);
13372 DWORD_SWAP(&pbk32->data_size);
13373 pdata = pbk32 + 1;
13374 type = (WORD) pbk32->type;
13375 } else {
13376 WORD_SWAP(&pbk->type);
13377 WORD_SWAP(&pbk->data_size);
13378 pdata = pbk + 1;
13379 type = pbk->type;
13380 }
13381
13382
13383 if (b32) {
13384 pbk32 = (BANK32 *) ((char *) (pbk32 + 1) + ALIGN8(pbk32->data_size));
13385 pbk = (BANK *) pbk32;
13386 } else {
13387 pbk = (BANK *) ((char *) (pbk + 1) + ALIGN8(pbk->data_size));
13388 pbk32 = (BANK32 *) pbk;
13389 }
13390
13391 switch (type) {
13392 case TID_WORD:
13393 case TID_SHORT:
13394 while ((char *) pdata < (char *) pbk) {
13395 WORD_SWAP(pdata);
13396 pdata = (void *) (((WORD *) pdata) + 1);
13397 }
13398 break;
13399
13400 case TID_DWORD:
13401 case TID_INT:
13402 case TID_BOOL:
13403 case TID_FLOAT:
13404 while ((char *) pdata < (char *) pbk) {
13405 DWORD_SWAP(pdata);
13406 pdata = (void *) (((DWORD *) pdata) + 1);
13407 }
13408 break;
13409
13410 case TID_DOUBLE:
13411 while ((char *) pdata < (char *) pbk) {
13412 QWORD_SWAP(pdata);
13413 pdata = (void *) (((double *) pdata) + 1);
13414 }
13415 break;
13416 }
13417 }
13418
13419 return CM_SUCCESS;
13420 }
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433 #ifndef DOXYGEN_SHOULD_SKIP_THIS
13434
13435
13436
13437
13438
13439
13440
13441
13442
13443
13444
13445
13446
13447
13448
13449 typedef struct {
13450 unsigned char *buffer;
13451 unsigned int size;
13452 unsigned int max_event_size;
13453 unsigned char *rp;
13454 unsigned char *wp;
13455 unsigned char *ep;
13456 } RING_BUFFER;
13457
13458 #define MAX_RING_BUFFER 100
13459
13460 RING_BUFFER rb[MAX_RING_BUFFER];
13461
13462 volatile int _rb_nonblocking = 0;
13463
13464
13465 #endif
13466
13467
13468
13469
13470
13471
13472
13473 int rb_set_nonblocking()
13474
13475
13476
13477
13478
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488
13489
13490
13491 {
13492 _rb_nonblocking = 1;
13493
13494 return DB_SUCCESS;
13495 }
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514 int rb_create(int size, int max_event_size, int *handle)
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535 {
13536 int i;
13537
13538 for (i = 0; i < MAX_RING_BUFFER; i++)
13539 if (rb[i].buffer == NULL)
13540 break;
13541
13542 if (i == MAX_RING_BUFFER)
13543 return DB_NO_MEMORY;
13544
13545 if (size < max_event_size * 2)
13546 return DB_INVALID_PARAM;
13547
13548 memset(&rb[i], 0, sizeof(RING_BUFFER));
13549 rb[i].buffer = (unsigned char *) M_MALLOC(size);
13550 assert(rb[i].buffer);
13551 rb[i].size = size;
13552 rb[i].max_event_size = max_event_size;
13553 rb[i].rp = rb[i].buffer;
13554 rb[i].wp = rb[i].buffer;
13555 rb[i].ep = rb[i].buffer;
13556
13557 *handle = i + 1;
13558
13559 return DB_SUCCESS;
13560 }
13561
13562
13563
13564
13565
13566
13567
13568 int rb_delete(int handle)
13569
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580
13581
13582
13583
13584 {
13585 if (handle < 0 || handle >= MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13586 return DB_INVALID_HANDLE;
13587
13588 M_FREE(rb[handle - 1].buffer);
13589 memset(&rb[handle - 1], 0, sizeof(RING_BUFFER));
13590
13591 return DB_SUCCESS;
13592 }
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603
13604 int rb_get_wp(int handle, void **p, int millisec)
13605
13606
13607
13608
13609
13610
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624 {
13625 int h, i;
13626 unsigned char *rp;
13627
13628 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13629 return DB_INVALID_HANDLE;
13630
13631 h = handle - 1;
13632
13633 for (i = 0; i <= millisec / 10; i++) {
13634
13635 rp = rb[h].rp;
13636
13637
13638 if (rb[h].wp >= rp
13639 && rb[h].wp + rb[h].max_event_size <= rb[h].buffer + rb[h].size - rb[h].max_event_size) {
13640 *p = rb[h].wp;
13641 return DB_SUCCESS;
13642 }
13643
13644
13645 if (rb[h].wp >= rp && rb[h].wp + rb[h].max_event_size > rb[h].buffer + rb[h].size - rb[h].max_event_size && rb[h].rp > rb[h].buffer) {
13646 *p = rb[h].wp;
13647 return DB_SUCCESS;
13648 }
13649
13650
13651 if (rb[h].wp < rp && rb[h].wp + rb[h].max_event_size < rp) {
13652 *p = rb[h].wp;
13653 return DB_SUCCESS;
13654 }
13655
13656 if (millisec == 0)
13657 return DB_TIMEOUT;
13658
13659 if (_rb_nonblocking)
13660 return DB_TIMEOUT;
13661
13662
13663 ss_sleep(10);
13664 }
13665
13666 return DB_TIMEOUT;
13667 }
13668
13669
13670
13671
13672
13673
13674
13675
13676
13677
13678 int rb_increment_wp(int handle, int size)
13679
13680
13681
13682
13683
13684
13685
13686
13687
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697 {
13698 int h;
13699 unsigned char *old_wp, *new_wp;
13700
13701 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13702 return DB_INVALID_HANDLE;
13703
13704 h = handle - 1;
13705
13706 if ((DWORD) size > rb[h].max_event_size)
13707 return DB_INVALID_PARAM;
13708
13709 old_wp = rb[h].wp;
13710 new_wp = rb[h].wp + size;
13711
13712
13713 if (new_wp > rb[h].buffer + rb[h].size - rb[h].max_event_size) {
13714 rb[h].ep = new_wp;
13715 new_wp = rb[h].buffer;
13716 assert(rb[h].rp != rb[h].buffer);
13717 }
13718
13719 rb[h].wp = new_wp;
13720
13721 return DB_SUCCESS;
13722 }
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740 int rb_get_rp(int handle, void **p, int millisec)
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763 {
13764 int i, h;
13765
13766 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13767 return DB_INVALID_HANDLE;
13768
13769 h = handle - 1;
13770
13771 for (i = 0; i <= millisec / 10; i++) {
13772
13773 if (rb[h].wp != rb[h].rp) {
13774 if (p != NULL)
13775 *p = rb[handle - 1].rp;
13776 return DB_SUCCESS;
13777 }
13778
13779 if (millisec == 0)
13780 return DB_TIMEOUT;
13781
13782 if (_rb_nonblocking)
13783 return DB_TIMEOUT;
13784
13785
13786 ss_sleep(10);
13787 }
13788
13789 return DB_TIMEOUT;
13790 }
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801
13802 int rb_increment_rp(int handle, int size)
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823 {
13824 int h;
13825
13826 unsigned char *new_rp, *old_rp;
13827
13828 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13829 return DB_INVALID_HANDLE;
13830
13831 h = handle - 1;
13832
13833 if ((DWORD) size > rb[h].max_event_size)
13834 return DB_INVALID_PARAM;
13835
13836 old_rp = rb[h].rp;
13837 new_rp = rb[h].rp + size;
13838
13839
13840 if (new_rp + rb[h].max_event_size > rb[h].buffer + rb[h].size)
13841 new_rp = rb[h].buffer;
13842
13843 rb[handle - 1].rp = new_rp;
13844
13845 return DB_SUCCESS;
13846 }
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856 int rb_get_buffer_level(int handle, int *n_bytes)
13857
13858
13859
13860
13861
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874 {
13875 int h;
13876
13877 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
13878 return DB_INVALID_HANDLE;
13879
13880 h = handle - 1;
13881
13882 if (rb[h].wp >= rb[h].rp)
13883 *n_bytes = (POINTER_T) rb[h].wp - (POINTER_T) rb[h].rp;
13884 else
13885 *n_bytes =
13886 (POINTER_T) rb[h].ep - (POINTER_T) rb[h].rp + (POINTER_T) rb[h].wp - (POINTER_T) rb[h].buffer;
13887
13888 return DB_SUCCESS;
13889 }
13890
13891
13892
13893
13894
13895