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