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