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