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