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