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