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