00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "midas.h"
00013 #include "msystem.h"
00014 #include "strlcpy.h"
00015 #include <assert.h>
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #if !defined(OS_VXWORKS)
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00034
00035 static HISTORY *_history;
00036 static INT _history_entries = 0;
00037 static char _hs_path_name[MAX_STRING_LENGTH];
00038
00039
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049 INT hs_set_path(char *path)
00050 {
00051
00052 if (rpc_is_remote())
00053 rpc_call(RPC_HS_SET_PATH, path);
00054
00055 strcpy(_hs_path_name, path);
00056
00057
00058 if (strlen(_hs_path_name) > 0 && _hs_path_name[strlen(_hs_path_name) - 1] != DIR_SEPARATOR)
00059 strcat(_hs_path_name, DIR_SEPARATOR_STR);
00060
00061 return HS_SUCCESS;
00062 }
00063
00064
00065 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 INT hs_open_file(time_t ltime, char *suffix, INT mode, int *fh)
00079 {
00080 struct tm *tms;
00081 char file_name[256];
00082 time_t ttime;
00083
00084
00085 #if !defined(OS_VXWORKS)
00086 #if !defined(OS_VMS)
00087 tzset();
00088 #endif
00089 #endif
00090 ttime = (time_t) ltime;
00091 tms = localtime(&ttime);
00092
00093 sprintf(file_name, "%s%02d%02d%02d.%s", _hs_path_name, tms->tm_year % 100, tms->tm_mon + 1, tms->tm_mday, suffix);
00094
00095
00096 *fh = open(file_name, mode | O_BINARY, 0644);
00097
00098
00099
00100 return HS_SUCCESS;
00101 }
00102
00103
00104 INT hs_gen_index(DWORD ltime)
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 {
00125 char event_name[NAME_LENGTH];
00126 int fh, fhd, fhi;
00127 INT n;
00128 HIST_RECORD rec;
00129 INDEX_RECORD irec;
00130 DEF_RECORD def_rec;
00131 int recovering = 0;
00132
00133
00134 cm_msg(MINFO, "hs_gen_index", "generating index files for time %d", (int) ltime);
00135 printf("Recovering index files...\n");
00136
00137 if (ltime == 0)
00138 ltime = (DWORD) time(NULL);
00139
00140
00141 hs_open_file(ltime, "idx", O_RDWR | O_CREAT | O_TRUNC, &fhi);
00142 hs_open_file(ltime, "idf", O_RDWR | O_CREAT | O_TRUNC, &fhd);
00143
00144 if (fhd < 0 || fhi < 0) {
00145 cm_msg(MERROR, "hs_gen_index", "cannot create index file");
00146 return HS_FILE_ERROR;
00147 }
00148
00149
00150 hs_open_file(ltime, "hst", O_RDONLY, &fh);
00151 if (fh < 0)
00152 return HS_FILE_ERROR;
00153 lseek(fh, 0, SEEK_SET);
00154
00155
00156 do {
00157 n = read(fh, (char *) &rec, sizeof(rec));
00158
00159 if (n < sizeof(rec))
00160 break;
00161
00162
00163 if (rec.record_type == RT_DEF) {
00164
00165 read(fh, event_name, sizeof(event_name));
00166
00167 printf("Event definition %s, ID %d\n", event_name, rec.event_id);
00168
00169
00170 def_rec.event_id = rec.event_id;
00171 memcpy(def_rec.event_name, event_name, sizeof(event_name));
00172 def_rec.def_offset = TELL(fh) - sizeof(event_name) - sizeof(rec);
00173 write(fhd, (char *) &def_rec, sizeof(def_rec));
00174
00175
00176
00177
00178 lseek(fh, rec.data_size, SEEK_CUR);
00179 } else if (rec.record_type == RT_DATA && rec.data_size > 1 && rec.data_size < 1 * 1024 * 1024) {
00180
00181 irec.event_id = rec.event_id;
00182 irec.time = rec.time;
00183 irec.offset = TELL(fh) - sizeof(rec);
00184 write(fhi, (char *) &irec, sizeof(irec));
00185
00186
00187
00188
00189 lseek(fh, rec.data_size, SEEK_CUR);
00190 } else {
00191 if (!recovering)
00192 cm_msg(MERROR, "hs_gen_index", "broken history file for time %d, trying to recover", (int) ltime);
00193
00194 recovering = 1;
00195 lseek(fh, 1 - sizeof(rec), SEEK_CUR);
00196
00197 continue;
00198 }
00199
00200 } while (TRUE);
00201
00202 close(fh);
00203 close(fhi);
00204 close(fhd);
00205
00206 printf("...done.\n");
00207
00208 return HS_SUCCESS;
00209 }
00210
00211
00212
00213 INT hs_search_file(DWORD * ltime, INT direction)
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 {
00235 time_t lt;
00236 int fh, fhd, fhi;
00237 struct tm *tms;
00238
00239 if (*ltime == 0)
00240 *ltime = ss_time();
00241
00242 lt = (time_t) * ltime;
00243 do {
00244
00245 hs_open_file(lt, "hst", O_RDONLY, &fh);
00246
00247
00248 if (fh < 0)
00249 lt += direction * 3600 * 24;
00250
00251
00252 } while (fh < 0 && (INT) * ltime - (INT) lt < 3600 * 24 * 365 && lt <= (time_t) ss_time());
00253
00254 if (fh < 0)
00255 return HS_FILE_ERROR;
00256
00257 if (lt != *ltime) {
00258
00259 tms = localtime(<);
00260 tms->tm_hour = tms->tm_min = tms->tm_sec = 0;
00261 *ltime = (DWORD) mktime(tms);
00262 }
00263
00264
00265 hs_open_file(*ltime, "idf", O_RDONLY, &fhd);
00266 hs_open_file(*ltime, "idx", O_RDONLY, &fhi);
00267
00268 close(fh);
00269 if (fhd > 0)
00270 close(fhd);
00271 if (fhi > 0)
00272 close(fhi);
00273
00274
00275 if (fhd < 0 || fhi < 0)
00276 hs_gen_index(*ltime);
00277
00278 return HS_SUCCESS;
00279 }
00280
00281
00282
00283 INT hs_define_event(DWORD event_id, char *name, TAG * tag, DWORD size)
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 HIST_RECORD rec, prev_rec;
00322 DEF_RECORD def_rec;
00323 time_t ltime;
00324 char str[256], event_name[NAME_LENGTH], *buffer;
00325 int fh, fhi, fhd;
00326 INT i, n, len, index, status, semaphore;
00327 struct tm *tmb;
00328
00329
00330 cm_get_experiment_semaphore(NULL, NULL, &semaphore, NULL);
00331 status = ss_semaphore_wait_for(semaphore, 5 * 1000);
00332 if (status != SS_SUCCESS)
00333 return SUCCESS;
00334
00335
00336 if (_history_entries == 0) {
00337 _history = (HISTORY *) M_MALLOC(sizeof(HISTORY));
00338 memset(_history, 0, sizeof(HISTORY));
00339 if (_history == NULL) {
00340 ss_semaphore_release(semaphore);
00341 return HS_NO_MEMORY;
00342 }
00343
00344 _history_entries = 1;
00345 index = 0;
00346 } else {
00347
00348 for (i = 0; i < _history_entries; i++)
00349 if (_history[i].event_id == event_id)
00350 break;
00351
00352
00353 if (i == _history_entries) {
00354 _history = (HISTORY *) realloc(_history, sizeof(HISTORY) * (_history_entries + 1));
00355 memset(&_history[_history_entries], 0, sizeof(HISTORY));
00356
00357 _history_entries++;
00358 if (_history == NULL) {
00359 _history_entries--;
00360 ss_semaphore_release(semaphore);
00361 return HS_NO_MEMORY;
00362 }
00363 }
00364 index = i;
00365 }
00366
00367
00368 rec.record_type = RT_DEF;
00369 rec.event_id = event_id;
00370 rec.time = (DWORD) time(NULL);
00371 rec.data_size = size;
00372 strncpy(event_name, name, NAME_LENGTH);
00373
00374
00375 for (i = 0; (DWORD) i < size / sizeof(TAG); i++) {
00376 len = strlen(tag[i].name);
00377 memset(tag[i].name + len, 0, NAME_LENGTH - len);
00378 }
00379
00380
00381 if (!_history[index].hist_fh) {
00382
00383 hs_open_file(rec.time, "hst", O_CREAT | O_RDWR, &fh);
00384 if (fh < 0) {
00385 ss_semaphore_release(semaphore);
00386 return HS_FILE_ERROR;
00387 }
00388
00389
00390 hs_open_file(rec.time, "idf", O_CREAT | O_RDWR, &fhd);
00391 hs_open_file(rec.time, "idx", O_CREAT | O_RDWR, &fhi);
00392 lseek(fh, 0, SEEK_END);
00393 lseek(fhi, 0, SEEK_END);
00394 lseek(fhd, 0, SEEK_END);
00395
00396
00397 if (TELL(fh) > 0 && TELL(fhd) == 0) {
00398 close(fh);
00399 close(fhi);
00400 close(fhd);
00401 hs_gen_index(rec.time);
00402 hs_open_file(rec.time, "hst", O_RDWR, &fh);
00403 hs_open_file(rec.time, "idx", O_RDWR, &fhi);
00404 hs_open_file(rec.time, "idf", O_RDWR, &fhd);
00405 lseek(fh, 0, SEEK_END);
00406 lseek(fhi, 0, SEEK_END);
00407 lseek(fhd, 0, SEEK_END);
00408 }
00409
00410 ltime = (time_t) rec.time;
00411 tmb = localtime(<ime);
00412 tmb->tm_hour = tmb->tm_min = tmb->tm_sec = 0;
00413
00414
00415 _history[index].hist_fh = fh;
00416 _history[index].index_fh = fhi;
00417 _history[index].def_fh = fhd;
00418 _history[index].def_offset = TELL(fh);
00419 _history[index].event_id = event_id;
00420 strcpy(_history[index].event_name, event_name);
00421 _history[index].base_time = (DWORD) mktime(tmb);
00422 _history[index].n_tag = size / sizeof(TAG);
00423 _history[index].tag = (TAG *) M_MALLOC(size);
00424 memcpy(_history[index].tag, tag, size);
00425
00426
00427 n = TELL(fhd) / sizeof(def_rec);
00428 def_rec.event_id = 0;
00429 for (i = n - 1; i >= 0; i--) {
00430 lseek(fhd, i * sizeof(def_rec), SEEK_SET);
00431 read(fhd, (char *) &def_rec, sizeof(def_rec));
00432 if (def_rec.event_id == event_id)
00433 break;
00434 }
00435 lseek(fhd, 0, SEEK_END);
00436
00437
00438 if (def_rec.event_id == event_id) {
00439 buffer = (char *) M_MALLOC(size);
00440 memset(buffer, 0, size);
00441
00442 lseek(fh, def_rec.def_offset, SEEK_SET);
00443 read(fh, (char *) &prev_rec, sizeof(prev_rec));
00444 read(fh, str, NAME_LENGTH);
00445 read(fh, buffer, size);
00446 lseek(fh, 0, SEEK_END);
00447
00448 if (prev_rec.data_size != size || strcmp(str, event_name) != 0 || memcmp(buffer, tag, size) != 0) {
00449
00450 write(fh, (char *) &rec, sizeof(rec));
00451 write(fh, event_name, NAME_LENGTH);
00452 write(fh, (char *) tag, size);
00453
00454
00455 def_rec.event_id = event_id;
00456 memcpy(def_rec.event_name, event_name, sizeof(event_name));
00457 def_rec.def_offset = _history[index].def_offset;
00458 write(fhd, (char *) &def_rec, sizeof(def_rec));
00459 } else
00460
00461 _history[index].def_offset = def_rec.def_offset;
00462
00463 M_FREE(buffer);
00464 } else {
00465
00466 write(fh, (char *) &rec, sizeof(rec));
00467 write(fh, event_name, NAME_LENGTH);
00468 write(fh, (char *) tag, size);
00469
00470
00471 def_rec.event_id = event_id;
00472 memcpy(def_rec.event_name, event_name, sizeof(event_name));
00473 def_rec.def_offset = _history[index].def_offset;
00474 write(fhd, (char *) &def_rec, sizeof(def_rec));
00475 }
00476 } else {
00477 fh = _history[index].hist_fh;
00478 fhd = _history[index].def_fh;
00479
00480
00481 buffer = (char *) M_MALLOC(size);
00482 memset(buffer, 0, size);
00483
00484 lseek(fh, _history[index].def_offset, SEEK_SET);
00485 read(fh, (char *) &prev_rec, sizeof(prev_rec));
00486 read(fh, str, NAME_LENGTH);
00487 read(fh, buffer, size);
00488
00489 lseek(fh, 0, SEEK_END);
00490 lseek(fhd, 0, SEEK_END);
00491
00492 if (prev_rec.data_size != size || strcmp(str, event_name) != 0 || memcmp(buffer, tag, size) != 0) {
00493
00494 _history[index].def_offset = TELL(fh);
00495
00496
00497 write(fh, (char *) &rec, sizeof(rec));
00498 write(fh, event_name, NAME_LENGTH);
00499 write(fh, (char *) tag, size);
00500
00501
00502 def_rec.event_id = event_id;
00503 memcpy(def_rec.event_name, event_name, sizeof(event_name));
00504 def_rec.def_offset = _history[index].def_offset;
00505 write(fhd, (char *) &def_rec, sizeof(def_rec));
00506 }
00507
00508 M_FREE(buffer);
00509 }
00510
00511 ss_semaphore_release(semaphore);
00512 }
00513
00514 return HS_SUCCESS;
00515 }
00516
00517
00518
00519 INT hs_write_event(DWORD event_id, void *data, DWORD size)
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 HIST_RECORD rec, drec;
00549 DEF_RECORD def_rec;
00550 INDEX_RECORD irec;
00551 int fh, fhi, fhd, last_pos_data, last_pos_index;
00552 INT index, semaphore, status;
00553 struct tm tmb, tmr;
00554 time_t ltime;
00555
00556
00557 cm_get_experiment_semaphore(NULL, NULL, &semaphore, NULL);
00558 status = ss_semaphore_wait_for(semaphore, 5 * 1000);
00559 if (status != SS_SUCCESS) {
00560 cm_msg(MERROR, "hs_write_event", "semaphore timeout");
00561 return SUCCESS;
00562 }
00563
00564
00565 for (index = 0; index < _history_entries; index++)
00566 if (_history[index].event_id == event_id)
00567 break;
00568 if (index == _history_entries) {
00569 ss_semaphore_release(semaphore);
00570 return HS_UNDEFINED_EVENT;
00571 }
00572
00573
00574 rec.record_type = RT_DATA;
00575 rec.event_id = _history[index].event_id;
00576 rec.time = (DWORD) time(NULL);
00577 rec.def_offset = _history[index].def_offset;
00578 rec.data_size = size;
00579
00580 irec.event_id = _history[index].event_id;
00581 irec.time = rec.time;
00582
00583
00584 ltime = (time_t) rec.time;
00585 memcpy(&tmr, localtime(<ime), sizeof(tmr));
00586 ltime = (time_t) _history[index].base_time;
00587 memcpy(&tmb, localtime(<ime), sizeof(tmb));
00588
00589 if (tmr.tm_yday != tmb.tm_yday) {
00590
00591 close(_history[index].hist_fh);
00592 close(_history[index].def_fh);
00593 close(_history[index].index_fh);
00594
00595
00596 hs_open_file(rec.time, "hst", O_CREAT | O_RDWR, &fh);
00597 if (fh < 0) {
00598 ss_semaphore_release(semaphore);
00599 return HS_FILE_ERROR;
00600 }
00601
00602
00603 hs_open_file(rec.time, "idx", O_CREAT | O_RDWR, &fhi);
00604 if (fhi < 0) {
00605 ss_semaphore_release(semaphore);
00606 return HS_FILE_ERROR;
00607 }
00608
00609
00610 hs_open_file(rec.time, "idf", O_CREAT | O_RDWR, &fhd);
00611 if (fhd < 0) {
00612 ss_semaphore_release(semaphore);
00613 return HS_FILE_ERROR;
00614 }
00615
00616 lseek(fh, 0, SEEK_END);
00617 lseek(fhi, 0, SEEK_END);
00618 lseek(fhd, 0, SEEK_END);
00619
00620
00621 _history[index].hist_fh = fh;
00622 _history[index].index_fh = fhi;
00623 _history[index].def_fh = fhd;
00624
00625 _history[index].def_offset = TELL(fh);
00626 rec.def_offset = _history[index].def_offset;
00627
00628 tmr.tm_hour = tmr.tm_min = tmr.tm_sec = 0;
00629 _history[index].base_time = (DWORD) mktime(&tmr);
00630
00631
00632 drec.record_type = RT_DEF;
00633 drec.event_id = _history[index].event_id;
00634 drec.time = rec.time;
00635 drec.data_size = _history[index].n_tag * sizeof(TAG);
00636
00637 write(fh, (char *) &drec, sizeof(drec));
00638 write(fh, _history[index].event_name, NAME_LENGTH);
00639 write(fh, (char *) _history[index].tag, drec.data_size);
00640
00641
00642 def_rec.event_id = _history[index].event_id;
00643 memcpy(def_rec.event_name, _history[index].event_name, sizeof(def_rec.event_name));
00644 def_rec.def_offset = _history[index].def_offset;
00645 write(fhd, (char *) &def_rec, sizeof(def_rec));
00646 }
00647
00648
00649 lseek(_history[index].hist_fh, 0, SEEK_END);
00650 last_pos_data = irec.offset = TELL(_history[index].hist_fh);
00651
00652
00653 write(_history[index].hist_fh, (char *) &rec, sizeof(rec));
00654
00655
00656 if (write(_history[index].hist_fh, (char *) data, size) < (int) size) {
00657
00658 lseek(_history[index].hist_fh, last_pos_data, SEEK_SET);
00659 TRUNCATE(_history[index].hist_fh);
00660 ss_semaphore_release(semaphore);
00661 return HS_FILE_ERROR;
00662 }
00663
00664
00665 lseek(_history[index].index_fh, 0, SEEK_END);
00666 last_pos_index = TELL(_history[index].index_fh);
00667 if (write(_history[index].index_fh, (char *) &irec, sizeof(irec)) < sizeof(irec)) {
00668
00669 lseek(_history[index].hist_fh, last_pos_data, SEEK_SET);
00670 TRUNCATE(_history[index].hist_fh);
00671 lseek(_history[index].index_fh, last_pos_index, SEEK_SET);
00672 TRUNCATE(_history[index].index_fh);
00673 ss_semaphore_release(semaphore);
00674 return HS_FILE_ERROR;
00675 }
00676
00677 ss_semaphore_release(semaphore);
00678 return HS_SUCCESS;
00679 }
00680
00681
00682
00683 INT hs_enum_events(DWORD ltime, char *event_name, DWORD * name_size, INT event_id[], DWORD * id_size)
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 {
00706 int fh, fhd;
00707 INT status, i, j, n;
00708 DEF_RECORD def_rec;
00709
00710 if (rpc_is_remote())
00711 return rpc_call(RPC_HS_ENUM_EVENTS, ltime, event_name, name_size, event_id, id_size);
00712
00713
00714 status = hs_search_file(<ime, -1);
00715 if (status != HS_SUCCESS) {
00716 cm_msg(MERROR, "hs_enum_events", "cannot find recent history file");
00717 return HS_FILE_ERROR;
00718 }
00719
00720
00721 hs_open_file(ltime, "hst", O_RDONLY, &fh);
00722 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
00723 if (fh < 0 || fhd < 0) {
00724 cm_msg(MERROR, "hs_enum_events", "cannot open index files");
00725 return HS_FILE_ERROR;
00726 }
00727 lseek(fhd, 0, SEEK_SET);
00728
00729
00730 n = 0;
00731 do {
00732
00733 j = read(fhd, (char *) &def_rec, sizeof(def_rec));
00734 if (j < (int) sizeof(def_rec))
00735 break;
00736
00737
00738 for (i = 0; i < n; i++)
00739 if (event_id[i] == (INT) def_rec.event_id) {
00740 strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
00741 break;
00742 }
00743
00744
00745 if (i == n) {
00746 if (i * NAME_LENGTH > (INT) * name_size || i * sizeof(INT) > (INT) * id_size) {
00747 cm_msg(MERROR, "hs_enum_events", "index buffer too small");
00748 close(fh);
00749 close(fhd);
00750 return HS_NO_MEMORY;
00751 }
00752
00753
00754 strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
00755 event_id[i] = def_rec.event_id;
00756 n++;
00757 }
00758 } while (TRUE);
00759
00760 close(fh);
00761 close(fhd);
00762 *name_size = n * NAME_LENGTH;
00763 *id_size = n * sizeof(INT);
00764
00765 return HS_SUCCESS;
00766 }
00767
00768
00769
00770 INT hs_count_events(DWORD ltime, DWORD * count)
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 {
00789 int fh, fhd;
00790 INT status, i, j, n;
00791 DWORD *id;
00792 DEF_RECORD def_rec;
00793
00794 if (rpc_is_remote())
00795 return rpc_call(RPC_HS_COUNT_EVENTS, ltime, count);
00796
00797
00798 status = hs_search_file(<ime, -1);
00799 if (status != HS_SUCCESS) {
00800 cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
00801 return HS_FILE_ERROR;
00802 }
00803
00804
00805 hs_open_file(ltime, "hst", O_RDONLY, &fh);
00806 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
00807 if (fh < 0 || fhd < 0) {
00808 cm_msg(MERROR, "hs_count_events", "cannot open index files");
00809 return HS_FILE_ERROR;
00810 }
00811
00812
00813 lseek(fhd, 0, SEEK_END);
00814 id = (DWORD *) M_MALLOC(TELL(fhd) / sizeof(def_rec) * sizeof(DWORD));
00815 lseek(fhd, 0, SEEK_SET);
00816
00817
00818 n = 0;
00819 do {
00820
00821 j = read(fhd, (char *) &def_rec, sizeof(def_rec));
00822 if (j < (int) sizeof(def_rec))
00823 break;
00824
00825
00826 for (i = 0; i < n; i++)
00827 if (id[i] == def_rec.event_id)
00828 break;
00829
00830
00831 if (i == n) {
00832 id[i] = def_rec.event_id;
00833 n++;
00834 }
00835 } while (TRUE);
00836
00837
00838 M_FREE(id);
00839 close(fh);
00840 close(fhd);
00841 *count = n;
00842
00843 return HS_SUCCESS;
00844 }
00845
00846
00847
00848 INT hs_get_event_id(DWORD ltime, char *name, DWORD * id)
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 {
00869 int fh, fhd;
00870 INT status, i;
00871 DWORD lt;
00872 DEF_RECORD def_rec;
00873
00874 if (rpc_is_remote())
00875 return rpc_call(RPC_HS_GET_EVENT_ID, ltime, name, id);
00876
00877
00878 if (ltime == 0)
00879 ltime = (DWORD) time(NULL);
00880
00881 lt = ltime;
00882
00883 do {
00884 status = hs_search_file(<, -1);
00885 if (status != HS_SUCCESS) {
00886 cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
00887 return HS_FILE_ERROR;
00888 }
00889
00890
00891 hs_open_file(lt, "hst", O_RDONLY, &fh);
00892 hs_open_file(lt, "idf", O_RDONLY, &fhd);
00893 if (fh < 0 || fhd < 0) {
00894 cm_msg(MERROR, "hs_count_events", "cannot open index files");
00895 return HS_FILE_ERROR;
00896 }
00897
00898
00899 *id = 0;
00900 do {
00901
00902 i = read(fhd, (char *) &def_rec, sizeof(def_rec));
00903 if (i < (int) sizeof(def_rec))
00904 break;
00905
00906 if (strcmp(name, def_rec.event_name) == 0) {
00907 *id = def_rec.event_id;
00908 close(fh);
00909 close(fhd);
00910 return HS_SUCCESS;
00911 }
00912 } while (TRUE);
00913
00914 close(fh);
00915 close(fhd);
00916
00917
00918 lt -= 3600 * 24;
00919
00920 } while (lt > ltime - 3600 * 24 * 365 * 10);
00921
00922 return HS_UNDEFINED_EVENT;
00923 }
00924
00925
00926
00927 INT hs_count_vars(DWORD ltime, DWORD event_id, DWORD * count)
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 {
00946 int fh, fhd;
00947 INT i, n, status;
00948 DEF_RECORD def_rec;
00949 HIST_RECORD rec;
00950
00951 if (rpc_is_remote())
00952 return rpc_call(RPC_HS_COUNT_VARS, ltime, event_id, count);
00953
00954
00955 status = hs_search_file(<ime, -1);
00956 if (status != HS_SUCCESS) {
00957 cm_msg(MERROR, "hs_count_tags", "cannot find recent history file");
00958 return HS_FILE_ERROR;
00959 }
00960
00961
00962 hs_open_file(ltime, "hst", O_RDONLY, &fh);
00963 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
00964 if (fh < 0 || fhd < 0) {
00965 cm_msg(MERROR, "hs_count_tags", "cannot open index files");
00966 return HS_FILE_ERROR;
00967 }
00968
00969
00970 lseek(fhd, 0, SEEK_END);
00971 n = TELL(fhd) / sizeof(def_rec);
00972 def_rec.event_id = 0;
00973 for (i = n - 1; i >= 0; i--) {
00974 lseek(fhd, i * sizeof(def_rec), SEEK_SET);
00975 read(fhd, (char *) &def_rec, sizeof(def_rec));
00976 if (def_rec.event_id == event_id)
00977 break;
00978 }
00979 if (def_rec.event_id != event_id) {
00980 cm_msg(MERROR, "hs_count_tags", "event %d not found in index file", event_id);
00981 return HS_FILE_ERROR;
00982 }
00983
00984
00985 lseek(fh, def_rec.def_offset, SEEK_SET);
00986 read(fh, (char *) &rec, sizeof(rec));
00987 *count = rec.data_size / sizeof(TAG);
00988
00989 close(fh);
00990 close(fhd);
00991
00992 return HS_SUCCESS;
00993 }
00994
00995
00996
00997 INT hs_enum_vars(DWORD ltime, DWORD event_id, char *var_name, DWORD * size, DWORD * var_n, DWORD * n_size)
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 {
01021 char str[256];
01022 int fh, fhd;
01023 INT i, n, status;
01024 DEF_RECORD def_rec;
01025 HIST_RECORD rec;
01026 TAG *tag;
01027
01028 if (rpc_is_remote())
01029 return rpc_call(RPC_HS_ENUM_VARS, ltime, event_id, var_name, size);
01030
01031
01032 status = hs_search_file(<ime, -1);
01033 if (status != HS_SUCCESS) {
01034 cm_msg(MERROR, "hs_enum_vars", "cannot find recent history file");
01035 return HS_FILE_ERROR;
01036 }
01037
01038
01039 hs_open_file(ltime, "hst", O_RDONLY, &fh);
01040 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
01041 if (fh < 0 || fhd < 0) {
01042 cm_msg(MERROR, "hs_enum_vars", "cannot open index files");
01043 return HS_FILE_ERROR;
01044 }
01045
01046
01047 lseek(fhd, 0, SEEK_END);
01048 n = TELL(fhd) / sizeof(def_rec);
01049 def_rec.event_id = 0;
01050 for (i = n - 1; i >= 0; i--) {
01051 lseek(fhd, i * sizeof(def_rec), SEEK_SET);
01052 read(fhd, (char *) &def_rec, sizeof(def_rec));
01053 if (def_rec.event_id == event_id)
01054 break;
01055 }
01056 if (def_rec.event_id != event_id) {
01057 cm_msg(MERROR, "hs_enum_vars", "event %d not found in index file", event_id);
01058 return HS_FILE_ERROR;
01059 }
01060
01061
01062 lseek(fh, def_rec.def_offset, SEEK_SET);
01063 read(fh, (char *) &rec, sizeof(rec));
01064 read(fh, str, NAME_LENGTH);
01065
01066
01067 n = rec.data_size / sizeof(TAG);
01068 tag = (TAG *) M_MALLOC(rec.data_size);
01069 read(fh, (char *) tag, rec.data_size);
01070
01071 if (n * NAME_LENGTH > (INT) * size || n * sizeof(DWORD) > *n_size) {
01072
01073
01074 for (i = 0; i < (INT) * size / NAME_LENGTH; i++) {
01075 strcpy(var_name + i * NAME_LENGTH, tag[i].name);
01076 var_n[i] = tag[i].n_data;
01077 }
01078
01079 cm_msg(MERROR, "hs_enum_vars", "tag buffer too small");
01080 M_FREE(tag);
01081 close(fh);
01082 close(fhd);
01083 return HS_NO_MEMORY;
01084 }
01085
01086
01087 for (i = 0; i < n; i++) {
01088 strcpy(var_name + i * NAME_LENGTH, tag[i].name);
01089 var_n[i] = tag[i].n_data;
01090 }
01091 *size = n * NAME_LENGTH;
01092 *n_size = n * sizeof(DWORD);
01093
01094 M_FREE(tag);
01095 close(fh);
01096 close(fhd);
01097
01098 return HS_SUCCESS;
01099 }
01100
01101
01102
01103 INT hs_get_var(DWORD ltime, DWORD event_id, char *var_name, DWORD * type, INT * n_data)
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 {
01127 char str[256];
01128 int fh, fhd;
01129 INT i, n, status;
01130 DEF_RECORD def_rec;
01131 HIST_RECORD rec;
01132 TAG *tag;
01133
01134 if (rpc_is_remote())
01135 return rpc_call(RPC_HS_GET_VAR, ltime, event_id, var_name, type, n_data);
01136
01137
01138 status = hs_search_file(<ime, -1);
01139 if (status != HS_SUCCESS) {
01140 cm_msg(MERROR, "hs_get_var", "cannot find recent history file");
01141 return HS_FILE_ERROR;
01142 }
01143
01144
01145 hs_open_file(ltime, "hst", O_RDONLY, &fh);
01146 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
01147 if (fh < 0 || fhd < 0) {
01148 cm_msg(MERROR, "hs_get_var", "cannot open index files");
01149 return HS_FILE_ERROR;
01150 }
01151
01152
01153 lseek(fhd, 0, SEEK_END);
01154 n = TELL(fhd) / sizeof(def_rec);
01155 def_rec.event_id = 0;
01156 for (i = n - 1; i >= 0; i--) {
01157 lseek(fhd, i * sizeof(def_rec), SEEK_SET);
01158 read(fhd, (char *) &def_rec, sizeof(def_rec));
01159 if (def_rec.event_id == event_id)
01160 break;
01161 }
01162 if (def_rec.event_id != event_id) {
01163 cm_msg(MERROR, "hs_get_var", "event %d not found in index file", event_id);
01164 return HS_FILE_ERROR;
01165 }
01166
01167
01168 lseek(fh, def_rec.def_offset, SEEK_SET);
01169 read(fh, (char *) &rec, sizeof(rec));
01170 read(fh, str, NAME_LENGTH);
01171
01172
01173 n = rec.data_size / sizeof(TAG);
01174 tag = (TAG *) M_MALLOC(rec.data_size);
01175 read(fh, (char *) tag, rec.data_size);
01176
01177
01178 for (i = 0; i < n; i++)
01179 if (strcmp(tag[i].name, var_name) == 0)
01180 break;
01181
01182 close(fh);
01183 close(fhd);
01184
01185 if (i < n) {
01186 *type = tag[i].type;
01187 *n_data = tag[i].n_data;
01188 } else {
01189 *type = *n_data = 0;
01190 cm_msg(MERROR, "hs_get_var", "variable %s not found", var_name);
01191 M_FREE(tag);
01192 return HS_UNDEFINED_VAR;
01193 }
01194
01195 M_FREE(tag);
01196 return HS_SUCCESS;
01197 }
01198
01199
01200
01201 INT hs_get_tags(DWORD ltime, DWORD event_id, char event_name[NAME_LENGTH], int* n_tags, TAG** tags)
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224 {
01225 int fh, fhd;
01226 INT i, n, status;
01227 DEF_RECORD def_rec;
01228 HIST_RECORD rec;
01229
01230 *n_tags = 0;
01231 *tags = NULL;
01232
01233 if (rpc_is_remote())
01234 assert(!"RPC not implemented");
01235
01236
01237 status = hs_search_file(<ime, -1);
01238 if (status != HS_SUCCESS) {
01239 cm_msg(MERROR, "hs_get_tags", "cannot find recent history file");
01240 return HS_FILE_ERROR;
01241 }
01242
01243
01244 hs_open_file(ltime, "hst", O_RDONLY, &fh);
01245 hs_open_file(ltime, "idf", O_RDONLY, &fhd);
01246 if (fh < 0 || fhd < 0) {
01247 cm_msg(MERROR, "hs_get_tags", "cannot open index files");
01248 if (fh>0)
01249 close(fh);
01250 if (fhd>0)
01251 close(fhd);
01252 return HS_FILE_ERROR;
01253 }
01254
01255
01256 lseek(fhd, 0, SEEK_END);
01257 n = TELL(fhd) / sizeof(def_rec);
01258 def_rec.event_id = 0;
01259 for (i = n - 1; i >= 0; i--) {
01260 lseek(fhd, i * sizeof(def_rec), SEEK_SET);
01261 read(fhd, (char *) &def_rec, sizeof(def_rec));
01262 if (def_rec.event_id == event_id)
01263 break;
01264 }
01265
01266 if (def_rec.event_id != event_id) {
01267
01268 close(fh);
01269 close(fhd);
01270 return HS_UNDEFINED_EVENT;
01271 }
01272
01273
01274 lseek(fh, def_rec.def_offset, SEEK_SET);
01275 status = read(fh, (char *) &rec, sizeof(rec));
01276 assert(status == sizeof(rec));
01277
01278 status = read(fh, event_name, NAME_LENGTH);
01279 assert(status == NAME_LENGTH);
01280
01281
01282 *n_tags = rec.data_size / sizeof(TAG);
01283
01284 *tags = (TAG*) malloc(rec.data_size);
01285
01286 status = read(fh, (char *) (*tags), rec.data_size);
01287 assert(status == rec.data_size);
01288
01289 close(fh);
01290 close(fhd);
01291
01292 return HS_SUCCESS;
01293 }
01294
01295
01296 INT hs_read(DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, char *tag_name, DWORD var_index, DWORD * time_buffer, DWORD * tbsize, void *data_buffer, DWORD * dbsize, DWORD * type, DWORD * n)
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 {
01333 DWORD prev_time, last_irec_time;
01334 int fh, fhd, fhi, cp = 0;
01335 INT i, delta, index = 0, status, cache_size;
01336 INDEX_RECORD irec, *pirec;
01337 HIST_RECORD rec, drec;
01338 INT old_def_offset, var_size = 0, var_offset = 0;
01339 TAG *tag;
01340 char str[NAME_LENGTH];
01341 struct tm *tms;
01342 char *cache = NULL;
01343 time_t ltime;
01344 int rd;
01345
01346
01347
01348 #if 0
01349 if (rpc_is_remote())
01350 return rpc_call(RPC_HS_READ, event_id, start_time, end_time, interval, tag_name, var_index, time_buffer, tbsize, data_buffer, dbsize, type, n);
01351 #endif
01352
01353
01354 if (start_time == 0)
01355 start_time = (DWORD) time(NULL) - 3600;
01356 if (end_time == 0)
01357 end_time = (DWORD) time(NULL);
01358
01359 *n = 0;
01360 prev_time = 0;
01361 last_irec_time = start_time;
01362
01363
01364 status = hs_search_file(&start_time, 1);
01365 if (status != HS_SUCCESS) {
01366 cm_msg(MERROR, "hs_read", "cannot find recent history file");
01367 *tbsize = *dbsize = *n = 0;
01368 return HS_FILE_ERROR;
01369 }
01370
01371
01372 hs_open_file(start_time, "hst", O_RDONLY, &fh);
01373 hs_open_file(start_time, "idf", O_RDONLY, &fhd);
01374 hs_open_file(start_time, "idx", O_RDONLY, &fhi);
01375 if (fh < 0 || fhd < 0 || fhi < 0) {
01376 cm_msg(MERROR, "hs_read", "cannot open index files");
01377 *tbsize = *dbsize = *n = 0;
01378 if (fh > 0)
01379 close(fh);
01380 if (fhd > 0)
01381 close(fhd);
01382 if (fhi > 0)
01383 close(fhi);
01384 return HS_FILE_ERROR;
01385 }
01386
01387
01388 lseek(fhi, 0, SEEK_END);
01389 cache_size = TELL(fhi);
01390
01391 if (cache_size == 0) {
01392 goto nextday;
01393 }
01394
01395 if (cache_size > 0) {
01396 cache = (char *) M_MALLOC(cache_size);
01397 if (cache) {
01398 lseek(fhi, 0, SEEK_SET);
01399 i = read(fhi, cache, cache_size);
01400 if (i < cache_size) {
01401 M_FREE(cache);
01402 if (fh > 0)
01403 close(fh);
01404 if (fhd > 0)
01405 close(fhd);
01406 if (fhi > 0)
01407 close(fhi);
01408 return HS_FILE_ERROR;
01409 }
01410 }
01411
01412
01413 if (cache == NULL) {
01414 lseek(fhi, 0, SEEK_END);
01415 delta = (TELL(fhi) / sizeof(irec)) / 2;
01416 lseek(fhi, delta * sizeof(irec), SEEK_SET);
01417 do {
01418 delta = (int) (abs(delta) / 2.0 + 0.5);
01419 rd = read(fhi, (char *) &irec, sizeof(irec));
01420 assert(rd == sizeof(irec));
01421 if (irec.time > start_time)
01422 delta = -delta;
01423
01424 lseek(fhi, (delta - 1) * sizeof(irec), SEEK_CUR);
01425 } while (abs(delta) > 1 && irec.time != start_time);
01426 rd = read(fhi, (char *) &irec, sizeof(irec));
01427 assert(rd == sizeof(irec));
01428 if (irec.time > start_time)
01429 delta = -abs(delta);
01430
01431 i = TELL(fhi) + (delta - 1) * sizeof(irec);
01432 if (i <= 0)
01433 lseek(fhi, 0, SEEK_SET);
01434 else
01435 lseek(fhi, (delta - 1) * sizeof(irec), SEEK_CUR);
01436 rd = read(fhi, (char *) &irec, sizeof(irec));
01437 assert(rd == sizeof(irec));
01438 } else {
01439 delta = (cache_size / sizeof(irec)) / 2;
01440 cp = delta * sizeof(irec);
01441 do {
01442 delta = (int) (abs(delta) / 2.0 + 0.5);
01443 pirec = (INDEX_RECORD *) (cache + cp);
01444
01445
01446
01447 if (pirec->time > start_time)
01448 delta = -delta;
01449
01450 cp = cp + delta * sizeof(irec);
01451
01452 if (cp < 0)
01453 cp = 0;
01454 } while (abs(delta) > 1 && pirec->time != start_time);
01455 pirec = (INDEX_RECORD *) (cache + cp);
01456 if (pirec->time > start_time)
01457 delta = -abs(delta);
01458
01459 if (cp <= delta * (int) sizeof(irec))
01460 cp = 0;
01461 else
01462 cp = cp + delta * sizeof(irec);
01463
01464 if (cp >= cache_size)
01465 cp = cache_size - sizeof(irec);
01466 if (cp < 0)
01467 cp = 0;
01468
01469 memcpy(&irec, (INDEX_RECORD *) (cache + cp), sizeof(irec));
01470 cp += sizeof(irec);
01471 }
01472 } else {
01473
01474 cache = NULL;
01475 irec.time = start_time;
01476 }
01477
01478
01479 old_def_offset = -1;
01480 last_irec_time = start_time - 24 * 60 * 60;
01481 do {
01482
01483
01484 if (irec.time < last_irec_time) {
01485 cm_msg(MERROR, "hs_read", "corrupted history data: time does not increase: %d -> %d", last_irec_time, irec.time);
01486
01487 if (fh > 0)
01488 close(fh);
01489 if (fhd > 0)
01490 close(fhd);
01491 if (fhi > 0)
01492 close(fhi);
01493 hs_gen_index(last_irec_time);
01494 return HS_SUCCESS;
01495 }
01496 last_irec_time = irec.time;
01497 if (irec.event_id == event_id && irec.time <= end_time && irec.time >= start_time) {
01498
01499 if (irec.time >= prev_time + interval) {
01500 prev_time = irec.time;
01501 lseek(fh, irec.offset, SEEK_SET);
01502 rd = read(fh, (char *) &rec, sizeof(rec));
01503 if (rd != sizeof(rec)) {
01504 cm_msg(MERROR, "hs_read", "corrupted history data at time %d: read() of %d bytes returned %d, errno %d (%s)", (int) irec.time, sizeof(rec), rd, errno, strerror(errno));
01505
01506 if (fh > 0)
01507 close(fh);
01508 if (fhd > 0)
01509 close(fhd);
01510 if (fhi > 0)
01511 close(fhi);
01512 hs_gen_index(last_irec_time);
01513 return HS_SUCCESS;
01514 }
01515
01516
01517 if ((INT) rec.def_offset != old_def_offset) {
01518 lseek(fh, rec.def_offset, SEEK_SET);
01519 read(fh, (char *) &drec, sizeof(drec));
01520 read(fh, str, NAME_LENGTH);
01521
01522 tag = (TAG *) M_MALLOC(drec.data_size);
01523 if (tag == NULL) {
01524 *n = *tbsize = *dbsize = 0;
01525 if (cache)
01526 M_FREE(cache);
01527 close(fh);
01528 close(fhd);
01529 close(fhi);
01530 return HS_NO_MEMORY;
01531 }
01532 read(fh, (char *) tag, drec.data_size);
01533
01534
01535 index = -1;
01536 for (i = 0; (DWORD) i < drec.data_size / sizeof(TAG); i++)
01537 if (equal_ustring(tag[i].name, tag_name)) {
01538 index = i;
01539 break;
01540 }
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 if (index >= 0 && var_index >= tag[i].n_data) {
01554 *n = *tbsize = *dbsize = 0;
01555 if (cache)
01556 M_FREE(cache);
01557 M_FREE(tag);
01558 close(fh);
01559 close(fhd);
01560 close(fhi);
01561 return HS_WRONG_INDEX;
01562 }
01563
01564
01565 if (index >= 0) {
01566 *type = tag[i].type;
01567
01568
01569 for (i = 0, var_offset = 0; i < index; i++)
01570 var_offset += rpc_tid_size(tag[i].type) * tag[i].n_data;
01571
01572
01573 if (tag[index].type == TID_STRING)
01574 var_size = tag[i].n_data;
01575 else
01576 var_size = rpc_tid_size(tag[index].type);
01577
01578 var_offset += var_size * var_index;
01579 }
01580
01581 M_FREE(tag);
01582 old_def_offset = rec.def_offset;
01583 lseek(fh, irec.offset + sizeof(rec), SEEK_SET);
01584 }
01585
01586 if (index >= 0) {
01587
01588 if ((*n) * sizeof(DWORD) >= *tbsize || (*n) * var_size >= *dbsize) {
01589 *dbsize = (*n) * var_size;
01590 *tbsize = (*n) * sizeof(DWORD);
01591 if (cache)
01592 M_FREE(cache);
01593 close(fh);
01594 close(fhd);
01595 close(fhi);
01596 return HS_TRUNCATED;
01597 }
01598
01599
01600 time_buffer[*n] = irec.time;
01601
01602
01603 lseek(fh, var_offset, SEEK_CUR);
01604 read(fh, (char *) data_buffer + (*n) * var_size, var_size);
01605
01606
01607 (*n)++;
01608 }
01609 }
01610 }
01611
01612
01613 if (cache) {
01614 if (cp >= cache_size) {
01615 i = -1;
01616 M_FREE(cache);
01617 cache = NULL;
01618 } else {
01619
01620 try_again:
01621
01622 i = sizeof(irec);
01623
01624 memcpy(&irec, cache + cp, sizeof(irec));
01625 cp += sizeof(irec);
01626
01627
01628 if (irec.time < last_irec_time || irec.time > last_irec_time + 24 * 60 * 60) {
01629
01630
01631
01632
01633
01634 while (cp < cache_size) {
01635 DWORD *evidp = (DWORD *) (cache + cp);
01636 if (*evidp == event_id) {
01637
01638 goto try_again;
01639 }
01640
01641 cp++;
01642 }
01643
01644 i = -1;
01645 }
01646 }
01647 } else
01648 i = read(fhi, (char *) &irec, sizeof(irec));
01649
01650
01651 if (i <= 0) {
01652 close(fh);
01653 close(fhd);
01654 close(fhi);
01655 fh = fhd = fhi = 0;
01656
01657 nextday:
01658
01659
01660 ltime = (time_t) last_irec_time;
01661 tms = localtime(<ime);
01662 tms->tm_hour = tms->tm_min = tms->tm_sec = 0;
01663 last_irec_time = (DWORD) mktime(tms);
01664
01665 last_irec_time += 3600 * 24;
01666
01667 if (last_irec_time > end_time)
01668 break;
01669
01670
01671 status = hs_search_file(&last_irec_time, 1);
01672 if (status != HS_SUCCESS)
01673 break;
01674
01675
01676 hs_open_file(last_irec_time, "hst", O_RDONLY, &fh);
01677 hs_open_file(last_irec_time, "idf", O_RDONLY, &fhd);
01678 hs_open_file(last_irec_time, "idx", O_RDONLY, &fhi);
01679 if (fh < 0 || fhd < 0 || fhi < 0) {
01680 cm_msg(MERROR, "hs_read", "cannot open index files");
01681 break;
01682 }
01683
01684
01685 lseek(fhi, 0, SEEK_END);
01686 cache_size = TELL(fhi);
01687
01688 if (cache_size == 0) {
01689 goto nextday;
01690 }
01691
01692 lseek(fhi, 0, SEEK_SET);
01693 cache = (char *) M_MALLOC(cache_size);
01694 if (cache) {
01695 i = read(fhi, cache, cache_size);
01696 if (i < cache_size)
01697 break;
01698
01699 cp = 0;
01700 memcpy(&irec, cache, sizeof(irec));
01701 } else {
01702
01703 i = read(fhi, (char *) &irec, sizeof(irec));
01704 if (i <= 0)
01705 break;
01706 assert(i == sizeof(irec));
01707 }
01708
01709
01710 old_def_offset = -1;
01711 }
01712
01713
01714 } while (irec.time < end_time);
01715
01716 if (cache)
01717 M_FREE(cache);
01718 if (fh)
01719 close(fh);
01720 if (fhd)
01721 close(fhd);
01722 if (fhi)
01723 close(fhi);
01724
01725 *dbsize = *n * var_size;
01726 *tbsize = *n * sizeof(DWORD);
01727
01728 return HS_SUCCESS;
01729 }
01730
01731
01732 #endif
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747 INT hs_dump(DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, BOOL binary_time)
01748 {
01749 DWORD prev_time, last_irec_time;
01750 time_t ltime;
01751 int fh, fhd, fhi;
01752 INT i, j, delta, status, n_tag = 0, old_n_tag = 0;
01753 INDEX_RECORD irec;
01754 HIST_RECORD rec, drec;
01755 INT old_def_offset, offset;
01756 TAG *tag = NULL, *old_tag = NULL;
01757 char str[NAME_LENGTH], data_buffer[10000];
01758 struct tm *tms;
01759
01760
01761 if (start_time == 0)
01762 start_time = (DWORD) time(NULL) - 3600;
01763 if (end_time == 0)
01764 end_time = (DWORD) time(NULL);
01765
01766
01767 status = hs_search_file(&start_time, 1);
01768 if (status != HS_SUCCESS) {
01769 cm_msg(MERROR, "hs_dump", "cannot find recent history file");
01770 return HS_FILE_ERROR;
01771 }
01772
01773
01774 hs_open_file(start_time, "hst", O_RDONLY, &fh);
01775 hs_open_file(start_time, "idf", O_RDONLY, &fhd);
01776 hs_open_file(start_time, "idx", O_RDONLY, &fhi);
01777 if (fh < 0 || fhd < 0 || fhi < 0) {
01778 cm_msg(MERROR, "hs_dump", "cannot open index files");
01779 return HS_FILE_ERROR;
01780 }
01781
01782
01783 lseek(fhi, 0, SEEK_END);
01784 delta = (TELL(fhi) / sizeof(irec)) / 2;
01785 lseek(fhi, delta * sizeof(irec), SEEK_SET);
01786 do {
01787 delta = (int) (abs(delta) / 2.0 + 0.5);
01788 read(fhi, (char *) &irec, sizeof(irec));
01789 if (irec.time > start_time)
01790 delta = -delta;
01791
01792 i = lseek(fhi, (delta - 1) * sizeof(irec), SEEK_CUR);
01793 } while (abs(delta) > 1 && irec.time != start_time);
01794 read(fhi, (char *) &irec, sizeof(irec));
01795 if (irec.time > start_time)
01796 delta = -abs(delta);
01797
01798 i = TELL(fhi) + (delta - 1) * sizeof(irec);
01799 if (i <= 0)
01800 lseek(fhi, 0, SEEK_SET);
01801 else
01802 lseek(fhi, (delta - 1) * sizeof(irec), SEEK_CUR);
01803 read(fhi, (char *) &irec, sizeof(irec));
01804
01805
01806 old_def_offset = -1;
01807 prev_time = 0;
01808 last_irec_time = 0;
01809 do {
01810 if (irec.time < last_irec_time) {
01811 cm_msg(MERROR, "hs_dump", "corrupted history data: time does not increase: %d -> %d", last_irec_time, irec.time);
01812 hs_gen_index(last_irec_time);
01813 return HS_FILE_ERROR;
01814 }
01815 last_irec_time = irec.time;
01816 if (irec.event_id == event_id && irec.time <= end_time && irec.time >= start_time) {
01817 if (irec.time >= prev_time + interval) {
01818 prev_time = irec.time;
01819 lseek(fh, irec.offset, SEEK_SET);
01820 read(fh, (char *) &rec, sizeof(rec));
01821
01822
01823 if ((INT) rec.def_offset != old_def_offset) {
01824 lseek(fh, rec.def_offset, SEEK_SET);
01825 read(fh, (char *) &drec, sizeof(drec));
01826 read(fh, str, NAME_LENGTH);
01827
01828 if (tag == NULL)
01829 tag = (TAG *) M_MALLOC(drec.data_size);
01830 else
01831 tag = (TAG *) realloc(tag, drec.data_size);
01832 if (tag == NULL)
01833 return HS_NO_MEMORY;
01834 read(fh, (char *) tag, drec.data_size);
01835 n_tag = drec.data_size / sizeof(TAG);
01836
01837
01838 if (old_tag == NULL || old_n_tag != n_tag || memcmp(old_tag, tag, drec.data_size) != 0) {
01839 printf("Date\t");
01840 for (i = 0; i < n_tag; i++) {
01841 if (tag[i].n_data == 1 || tag[i].type == TID_STRING)
01842 printf("%s\t", tag[i].name);
01843 else
01844 for (j = 0; j < (INT) tag[i].n_data; j++)
01845 printf("%s%d\t", tag[i].name, j);
01846 }
01847 printf("\n");
01848
01849 if (old_tag == NULL)
01850 old_tag = (TAG *) M_MALLOC(drec.data_size);
01851 else
01852 old_tag = (TAG *) realloc(old_tag, drec.data_size);
01853 memcpy(old_tag, tag, drec.data_size);
01854 old_n_tag = n_tag;
01855 }
01856
01857 old_def_offset = rec.def_offset;
01858 lseek(fh, irec.offset + sizeof(rec), SEEK_SET);
01859 }
01860
01861
01862 if (binary_time)
01863 printf("%d ", irec.time);
01864 else {
01865 ltime = (time_t) irec.time;
01866 sprintf(str, "%s", ctime(<ime) + 4);
01867 str[20] = '\t';
01868 printf(str);
01869 }
01870
01871
01872 read(fh, data_buffer, rec.data_size);
01873
01874
01875 offset = 0;
01876 for (i = 0; i < n_tag; i++) {
01877
01878 if (tag[i].type == TID_STRING) {
01879 printf("%s\t", data_buffer + offset);
01880 offset += tag[i].n_data;
01881 } else if (tag[i].n_data == 1) {
01882
01883 db_sprintf(str, data_buffer + offset, rpc_tid_size(tag[i].type), 0, tag[i].type);
01884 printf("%s\t", str);
01885 offset += rpc_tid_size(tag[i].type);
01886 } else
01887
01888 for (j = 0; j < (INT) tag[i].n_data; j++) {
01889 db_sprintf(str, data_buffer + offset, rpc_tid_size(tag[i].type), 0, tag[i].type);
01890 printf("%s\t", str);
01891 offset += rpc_tid_size(tag[i].type);
01892 }
01893 }
01894 printf("\n");
01895 }
01896 }
01897
01898
01899 i = read(fhi, (char *) &irec, sizeof(irec));
01900
01901
01902 if (i <= 0) {
01903 close(fh);
01904 close(fhd);
01905 close(fhi);
01906
01907
01908 ltime = (time_t) last_irec_time;
01909 tms = localtime(<ime);
01910 tms->tm_hour = tms->tm_min = tms->tm_sec = 0;
01911 last_irec_time = (DWORD) mktime(tms);
01912
01913 last_irec_time += 3600 * 24;
01914 if (last_irec_time > end_time)
01915 break;
01916
01917
01918 status = hs_search_file((DWORD *) & last_irec_time, 1);
01919 if (status != HS_SUCCESS)
01920 break;
01921
01922
01923 hs_open_file(last_irec_time, "hst", O_RDONLY, &fh);
01924 hs_open_file(last_irec_time, "idf", O_RDONLY, &fhd);
01925 hs_open_file(last_irec_time, "idx", O_RDONLY, &fhi);
01926 if (fh < 0 || fhd < 0 || fhi < 0) {
01927 cm_msg(MERROR, "hs_dump", "cannot open index files");
01928 break;
01929 }
01930
01931
01932 i = read(fhi, (char *) &irec, sizeof(irec));
01933 if (i <= 0)
01934 break;
01935
01936
01937 old_def_offset = -1;
01938 }
01939 } while (irec.time < end_time);
01940
01941 M_FREE(tag);
01942 M_FREE(old_tag);
01943 close(fh);
01944 close(fhd);
01945 close(fhi);
01946
01947 return HS_SUCCESS;
01948 }
01949
01950
01951 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01952
01953
01954 INT hs_fdump(char *file_name, DWORD id, BOOL binary_time)
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974 {
01975 int fh;
01976 INT n;
01977 time_t ltime;
01978 HIST_RECORD rec;
01979 char event_name[NAME_LENGTH];
01980 char str[256];
01981
01982
01983 sprintf(str, "%s%s", _hs_path_name, file_name);
01984 fh = open(str, O_RDONLY | O_BINARY, 0644);
01985 if (fh < 0) {
01986 cm_msg(MERROR, "hs_fdump", "cannot open file %s", str);
01987 return HS_FILE_ERROR;
01988 }
01989
01990
01991 do {
01992 n = read(fh, (char *) &rec, sizeof(rec));
01993 if (n < sizeof(rec))
01994 break;
01995
01996
01997 if (rec.record_type == RT_DEF) {
01998
01999 read(fh, event_name, sizeof(event_name));
02000
02001 if (rec.event_id == id || id == 0)
02002 printf("Event definition %s, ID %d\n", event_name, rec.event_id);
02003
02004
02005 lseek(fh, rec.data_size, SEEK_CUR);
02006 } else {
02007
02008 if (binary_time)
02009 sprintf(str, "%d ", rec.time);
02010 else {
02011 ltime = (time_t) rec.time;
02012 strcpy(str, ctime(<ime) + 4);
02013 str[15] = 0;
02014 }
02015 if (rec.event_id == id || id == 0)
02016 printf("ID %d, %s, size %d\n", rec.event_id, str, rec.data_size);
02017
02018
02019 lseek(fh, rec.data_size, SEEK_CUR);
02020 }
02021
02022 } while (TRUE);
02023
02024 close(fh);
02025
02026 return HS_SUCCESS;
02027 }
02028 #endif
02029
02030
02031 #endif
02032
02033
02034
02035
02036