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