MIDAS
Loading...
Searching...
No Matches
FileHistory Class Reference
Inheritance diagram for FileHistory:
Collaboration diagram for FileHistory:

Public Member Functions

 FileHistory ()
 
int hs_connect (const char *connect_string)
 returns HS_SUCCESS
 
int hs_disconnect ()
 disconnect from history, returns HS_SUCCESS
 
int hs_clear_cache ()
 clear internal cache, returns HS_SUCCESS
 
int read_schema (HsSchemaVector *sv, const char *event_name, const time_t timestamp)
 
HsSchemanew_event (const char *event_name, time_t timestamp, int ntags, const TAG tags[])
 
- Public Member Functions inherited from SchemaHistoryBase
 SchemaHistoryBase ()
 
virtual ~SchemaHistoryBase ()
 
virtual int hs_set_debug (int debug)
 set debug level, returns previous debug level
 
int hs_define_event (const char *event_name, time_t timestamp, int ntags, const TAG tags[])
 see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR
 
int hs_write_event (const char *event_name, time_t timestamp, int buffer_size, const char *buffer)
 see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
 
int hs_flush_buffers ()
 flush buffered data to storage where it is visible to mhttpd
 
int hs_clear_cache ()
 clear internal cache, returns HS_SUCCESS
 
int hs_get_events (time_t t, std::vector< std::string > *pevents)
 get list of events that exist(ed) at given time and later (value 0 means "return all events from beginning of time"), returns HS_SUCCESS
 
int hs_get_tags (const char *event_name, time_t t, std::vector< TAG > *ptags)
 get list of history variables for given event (use event names returned by hs_get_events()) that exist(ed) at given time and later (value 0 means "all variables for this event that ever existed"), also see hs_get_tags(), returns HS_SUCCESS
 
int hs_get_last_written (time_t timestamp, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], time_t last_written[])
 
int hs_read_buffer (time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int hs_status[])
 returns HS_SUCCESS
 
int hs_read (time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int st[])
 see hs_read(), returns HS_SUCCESS
 
int hs_read_binned (time_t start_time, time_t end_time, int num_bins, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], int num_entries[], int *count_bins[], double *mean_bins[], double *rms_bins[], double *min_bins[], double *max_bins[], time_t *bins_first_time[], double *bins_first_value[], time_t *bins_last_time[], double *bins_last_value[], time_t last_time[], double last_value[], int st[])
 returns HS_SUCCESS
 
- Public Member Functions inherited from MidasHistoryInterface
 MidasHistoryInterface ()
 history type: MIDAS, ODBC, SQLITE, etc
 
virtual ~MidasHistoryInterface ()
 

Protected Member Functions

int create_file (const char *event_name, time_t timestamp, const std::vector< HsSchemaEntry > &vars, std::string *filenamep)
 
HsFileSchemaread_file_schema (const char *filename)
 
int read_file_list (bool *pchanged)
 
void clear_file_list ()
 
void tags_to_variables (int ntags, const TAG tags[], std::vector< HsSchemaEntry > &variables)
 
HsSchemamaybe_reopen (const char *event_name, time_t timestamp, HsSchema *s)
 

Protected Attributes

std::string fPath
 
time_t fPathLastMtime = 0
 
std::vector< std::string > fSortedFiles
 
std::vector< boolfSortedRead
 
time_t fConfMaxFileAge = 1*kMonth
 
off64_t fConfMaxFileSize = 100*MiB
 
- Protected Attributes inherited from SchemaHistoryBase
int fDebug = 0
 
std::string fConnectString
 
HsSchemaVector fWriterSchema
 
std::vector< HsSchema * > fWriterEvents
 
HsSchemaVector fReaderSchema
 

Additional Inherited Members

- Public Attributes inherited from MidasHistoryInterface
char name [NAME_LENGTH]
 
char type [NAME_LENGTH]
 history channel name
 

Detailed Description

Definition at line 6449 of file history_schema.cxx.

Constructor & Destructor Documentation

◆ FileHistory()

FileHistory::FileHistory ( )
inline

Definition at line 6460 of file history_schema.cxx.

6461 {
6462 // empty
6463 }

Member Function Documentation

◆ clear_file_list()

void FileHistory::clear_file_list ( )
protected

Definition at line 6518 of file history_schema.cxx.

6519{
6520 fPathLastMtime = 0;
6521 fSortedFiles.clear();
6522 fSortedRead.clear();
6523}
std::vector< std::string > fSortedFiles
std::vector< bool > fSortedRead
Here is the caller graph for this function:

◆ create_file()

int FileHistory::create_file ( const char event_name,
time_t  timestamp,
const std::vector< HsSchemaEntry > &  vars,
std::string *  filenamep 
)
protected

Definition at line 6858 of file history_schema.cxx.

6859{
6860 if (fDebug)
6861 printf("FileHistory::create_file: event [%s]\n", event_name);
6862
6863 // NB: file names are constructed in such a way
6864 // that when sorted lexicographically ("ls -1 | sort")
6865 // they *also* become sorted by time
6866
6867 struct tm tm;
6868 localtime_r(&timestamp, &tm); // somebody must call tzset() before this.
6869
6870 char buf[256];
6871 strftime(buf, sizeof(buf), "%Y%m%d", &tm);
6872
6873 std::string filename;
6874 filename += fPath;
6875 filename += "mhf_";
6876 filename += TimeToString(timestamp);
6877 filename += "_";
6878 filename += buf;
6879 filename += "_";
6880 filename += MidasNameToFileName(event_name);
6881
6882 std::string try_filename = filename + ".dat";
6883
6884 FILE *fp = NULL;
6885 for (int itry=0; itry<10; itry++) {
6886 if (itry > 0) {
6887 char s[256];
6888 sprintf(s, "_%d", rand());
6889 try_filename = filename + s + ".dat";
6890 }
6891
6892 fp = fopen(try_filename.c_str(), "r");
6893 if (fp != NULL) {
6894 // this file already exists, try with a different name
6895 fclose(fp);
6896 continue;
6897 }
6898
6899 fp = fopen(try_filename.c_str(), "w");
6900 if (fp == NULL) {
6901 // somehow cannot create this file, try again
6902 cm_msg(MERROR, "FileHistory::create_file", "Error: Cannot create file \'%s\' for event \'%s\', fopen() errno %d (%s)", try_filename.c_str(), event_name, errno, strerror(errno));
6903 continue;
6904 }
6905
6906 // file opened
6907 break;
6908 }
6909
6910 if (fp == NULL) {
6911 // somehow cannot create any file, whine!
6912 cm_msg(MERROR, "FileHistory::create_file", "Error: Cannot create file \'%s\' for event \'%s\'", filename.c_str(), event_name);
6913 return HS_FILE_ERROR;
6914 }
6915
6916 std::string ss;
6917
6918 ss += "version: 2.0\n";
6919 ss += "event_name: ";
6920 ss += event_name;
6921 ss += "\n";
6922 ss += "time: ";
6923 ss += TimeToString(timestamp);
6924 ss += "\n";
6925
6926 int recsize = 0;
6927
6928 ss += "tag: /DWORD 1 4 /timestamp\n";
6929 recsize += 4;
6930
6931 bool padded = false;
6932 int offset = 0;
6933
6934 bool xdebug = false; // (strcmp(event_name, "u_Beam") == 0);
6935
6936 for (size_t i=0; i<vars.size(); i++) {
6937 int tsize = rpc_tid_size(vars[i].type);
6938 int n_bytes = vars[i].n_data*tsize;
6939 int xalign = (offset % tsize);
6940
6941 if (xdebug)
6942 printf("tag %zu, tsize %d, n_bytes %d, xalign %d\n", i, tsize, n_bytes, xalign);
6943
6944#if 0
6945 // looks like history data does not do alignement and padding
6946 if (xalign != 0) {
6947 padded = true;
6948 int pad_bytes = tsize - xalign;
6949 assert(pad_bytes > 0);
6950
6951 ss += "tag: ";
6952 ss += "XPAD";
6953 ss += " ";
6954 ss += SmallIntToString(1);
6955 ss += " ";
6957 ss += " ";
6958 ss += "pad_";
6959 ss += SmallIntToString(i);
6960 ss += "\n";
6961
6962 offset += pad_bytes;
6963 recsize += pad_bytes;
6964
6965 assert((offset % tsize) == 0);
6966 fprintf(stderr, "FIXME: need to debug padding!\n");
6967 //abort();
6968 }
6969#endif
6970
6971 ss += "tag: ";
6972 ss += rpc_tid_name(vars[i].type);
6973 ss += " ";
6974 ss += SmallIntToString(vars[i].n_data);
6975 ss += " ";
6976 ss += SmallIntToString(n_bytes);
6977 ss += " ";
6978 ss += vars[i].name;
6979 ss += "\n";
6980
6981 recsize += n_bytes;
6982 offset += n_bytes;
6983 }
6984
6985 ss += "record_size: ";
6987 ss += "\n";
6988
6989 // reserve space for "data_offset: ..."
6990 int sslength = ss.length() + 127;
6991
6992 int block = 1024;
6993 int nb = (sslength + block - 1)/block;
6994 int data_offset = block * nb;
6995
6996 ss += "data_offset: ";
6998 ss += "\n";
6999
7000 fprintf(fp, "%s", ss.c_str());
7001
7002 fclose(fp);
7003
7004 if (1 && padded) {
7005 printf("Schema in file %s has padding:\n", try_filename.c_str());
7006 printf("%s", ss.c_str());
7007 }
7008
7009 if (filenamep)
7011
7012 return HS_SUCCESS;
7013}
std::string fPath
char type[NAME_LENGTH]
history channel name
Definition history.h:112
#define HS_SUCCESS
Definition midas.h:727
#define HS_FILE_ERROR
Definition midas.h:728
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
const char * rpc_tid_name(INT id)
Definition midas.cxx:11772
INT rpc_tid_size(INT id)
Definition midas.cxx:11765
static std::string TimeToString(time_t t)
static std::string SmallIntToString(int i)
static std::string MidasNameToFileName(const char *s)
INT i
Definition mdump.cxx:32
static int offset
Definition mgd.cxx:1500
static FILE * fp
MUTEX_T * tm
Definition odbedit.cxx:39
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_clear_cache()

int FileHistory::hs_clear_cache ( )
virtual

clear internal cache, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 6499 of file history_schema.cxx.

6500{
6501 if (fDebug)
6502 printf("FileHistory::hs_clear_cache!\n");
6503 fPathLastMtime = 0;
6505}
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_connect()

int FileHistory::hs_connect ( const char connect_string)
virtual

returns HS_SUCCESS

Implements SchemaHistoryBase.

Definition at line 6480 of file history_schema.cxx.

6481{
6482 if (fDebug)
6483 printf("hs_connect [%s]!\n", connect_string);
6484
6485 hs_disconnect();
6486
6489
6490 // add trailing '/'
6491 if (fPath.length() > 0) {
6492 if (fPath[fPath.length()-1] != DIR_SEPARATOR)
6494 }
6495
6496 return HS_SUCCESS;
6497}
int hs_disconnect()
disconnect from history, returns HS_SUCCESS
#define DIR_SEPARATOR
Definition midas.h:193
#define DIR_SEPARATOR_STR
Definition midas.h:194
Here is the call graph for this function:

◆ hs_disconnect()

int FileHistory::hs_disconnect ( )
virtual

disconnect from history, returns HS_SUCCESS

Implements SchemaHistoryBase.

Definition at line 6507 of file history_schema.cxx.

6508{
6509 if (fDebug)
6510 printf("FileHistory::hs_disconnect!\n");
6511
6514
6515 return HS_SUCCESS;
6516}
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
int hs_flush_buffers()
flush buffered data to storage where it is visible to mhttpd
Here is the call graph for this function:
Here is the caller graph for this function:

◆ maybe_reopen()

HsSchema * FileHistory::maybe_reopen ( const char event_name,
time_t  timestamp,
HsSchema s 
)
protectedvirtual

Implements SchemaHistoryBase.

Definition at line 7184 of file history_schema.cxx.

7185{
7186 HsFileSchema* fs = dynamic_cast<HsFileSchema*>(s);
7187
7188 assert(fs != NULL); // FileHistory::maybe_reopen() must be called only with file history schema.
7189
7190 if (fs->fFileSize <= fConfMaxFileSize) {
7191 // not big enough, let it grow
7192 return s;
7193 }
7194
7195 // must rotate the file
7196
7197 if (fDebug) {
7198 printf("FileHistory::maybe_reopen: reopen file \"%s\", size %jd, max size %jd\n", fs->fFileName.c_str(), fs->fFileSize, fConfMaxFileSize);
7199 }
7200
7201 std::string new_filename;
7202
7203 int status = create_file(event_name, timestamp, fs->fVariables, &new_filename);
7204
7205 if (status != HS_SUCCESS) {
7206 // cannot create new history file
7207 return s;
7208 }
7209
7211
7212 if (!new_fs) {
7213 // cannot open new history file
7214 return s;
7215 }
7216
7217 new_fs->fDisabled = false;
7218
7220 *new_fs_copy = *new_fs; // make a copy
7221
7222 //printf("replacing schema %p %p with %p %p\n", s, fs, new_fs, new_fs_copy);
7223
7224 for (size_t i=0; i<fWriterEvents.size(); i++) {
7225 if (s == fWriterEvents[i]) {
7226 delete fWriterEvents[i];
7228 s = NULL; // pointer to fEvents[i]
7229 fs = NULL; // pointer to fEvents[i]
7230 }
7231 }
7232
7233 assert(s == NULL); // the schema we are replacing must be in fWriterEvents.
7234
7235 fWriterSchema.add(new_fs_copy); // make sure new file is added to the list of files
7236
7237 assert(new_fs->fFileSize < fConfMaxFileSize); // check that we are not returning the original big file
7238
7239 //new_fs->print();
7240
7241 return new_fs;
7242}
HsFileSchema * read_file_schema(const char *filename)
off64_t fConfMaxFileSize
int create_file(const char *event_name, time_t timestamp, const std::vector< HsSchemaEntry > &vars, std::string *filenamep)
void add(HsSchema *s)
HsSchemaVector fWriterSchema
std::vector< HsSchema * > fWriterEvents
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:

◆ new_event()

HsSchema * FileHistory::new_event ( const char event_name,
time_t  timestamp,
int  ntags,
const TAG  tags[] 
)
virtual

Implements SchemaHistoryBase.

Definition at line 6704 of file history_schema.cxx.

6705{
6706 if (fDebug)
6707 printf("FileHistory::new_event: event [%s], timestamp %s, ntags %d\n", event_name, TimeToString(timestamp).c_str(), ntags);
6708
6709 int status;
6710
6711 HsFileSchema* s = (HsFileSchema*)fWriterSchema.find_event(event_name, timestamp);
6712
6713 if (!s) {
6714 //printf("hs_define_event: no schema for event %s\n", event_name);
6715 status = read_schema(&fWriterSchema, event_name, timestamp);
6716 if (status != HS_SUCCESS)
6717 return NULL;
6718 s = (HsFileSchema*)fWriterSchema.find_event(event_name, timestamp);
6719 } else {
6720 //printf("hs_define_event: already have schema for event %s\n", s->fEventName.c_str());
6721 }
6722
6723 bool xdebug = false;
6724
6725 if (s) { // is existing schema the same as new schema?
6726 bool same = true;
6727
6728 if (same) {
6729 if (s->fEventName != event_name) {
6730 if (xdebug)
6731 printf("AAA: [%s] [%s]!\n", s->fEventName.c_str(), event_name);
6732 same = false;
6733 }
6734 }
6735
6736 if (same) {
6737 if (s->fVariables.size() != (size_t)ntags) {
6738 if (xdebug)
6739 printf("BBB: event [%s]: ntags: %zu -> %d!\n", event_name, s->fVariables.size(), ntags);
6740 same = false;
6741 }
6742 }
6743
6744 if (same) {
6745 for (size_t i=0; i<s->fVariables.size(); i++) {
6746 if (s->fVariables[i].name != tags[i].name) {
6747 if (xdebug)
6748 printf("CCC: event [%s] index %zu: name [%s] -> [%s]!\n", event_name, i, s->fVariables[i].name.c_str(), tags[i].name);
6749 same = false;
6750 }
6751 if (s->fVariables[i].type != (int)tags[i].type) {
6752 if (xdebug)
6753 printf("DDD: event [%s] index %zu: type %d -> %d!\n", event_name, i, s->fVariables[i].type, tags[i].type);
6754 same = false;
6755 }
6756 if (s->fVariables[i].n_data != (int)tags[i].n_data) {
6757 if (xdebug)
6758 printf("EEE: event [%s] index %zu: n_data %d -> %d!\n", event_name, i, s->fVariables[i].n_data, tags[i].n_data);
6759 same = false;
6760 }
6761 if (!same)
6762 break;
6763 }
6764 }
6765
6766 if (!same) {
6767 if (xdebug) {
6768 printf("*** Schema for event %s has changed!\n", event_name);
6769
6770 printf("*** Old schema for event [%s] time %s:\n", event_name, TimeToString(timestamp).c_str());
6771 s->print();
6772 printf("*** New tags:\n");
6773 PrintTags(ntags, tags);
6774 }
6775
6776 if (fDebug)
6777 printf("FileHistory::new_event: event [%s], timestamp %s, ntags %d: schema mismatch, starting a new file.\n", event_name, TimeToString(timestamp).c_str(), ntags);
6778
6779 s = NULL;
6780 }
6781 }
6782
6783 if (s) {
6784 // maybe this schema is too old - rotate files every so often
6785 time_t age = timestamp - s->fTimeFrom;
6786 //printf("*** age %s (%.1f months), timestamp %s, time_from %s, file %s\n", TimeToString(age).c_str(), (double)age/(double)kMonth, TimeToString(timestamp).c_str(), TimeToString(s->fTimeFrom).c_str(), s->fFileName.c_str());
6787 if (age > fConfMaxFileAge) {
6788 if (fDebug)
6789 printf("FileHistory::new_event: event [%s], timestamp %s, ntags %d: schema is too old, age %.1f months, starting a new file.\n", event_name, TimeToString(timestamp).c_str(), ntags, (double)age/(double)kMonth);
6790
6791 // force creation of a new file
6792 s = NULL;
6793 }
6794 }
6795
6796 if (s) {
6797 // maybe this file is too big - rotate files to limit maximum size
6798 double size = ss_file_size(s->fFileName.c_str());
6799 //printf("*** size %.0f, file %s\n", size, s->fFileName.c_str());
6800 if (size > fConfMaxFileSize) {
6801 if (fDebug)
6802 printf("FileHistory::new_event: event [%s], timestamp %s, ntags %d: file too big, size %.1f MiBytes, max size %.1f MiBytes, starting a new file.\n", event_name, TimeToString(timestamp).c_str(), ntags, size/MiB, fConfMaxFileSize/MiB);
6803
6804 // force creation of a new file
6805 s = NULL;
6806 }
6807 }
6808
6809 if (!s) {
6810 std::string filename;
6811
6812 std::vector<HsSchemaEntry> vars;
6813
6814 tags_to_variables(ntags, tags, vars);
6815
6816 status = create_file(event_name, timestamp, vars, &filename);
6817 if (status != HS_SUCCESS)
6818 return NULL;
6819
6820 HsFileSchema* ss = read_file_schema(filename.c_str());
6821 if (!ss) {
6822 cm_msg(MERROR, "FileHistory::new_event", "Error: Cannot create schema for event \'%s\', see previous messages", event_name);
6823 return NULL;
6824 }
6825
6827
6828 s = (HsFileSchema*)fWriterSchema.find_event(event_name, timestamp);
6829
6830 if (!s) {
6831 cm_msg(MERROR, "FileHistory::new_event", "Error: Cannot create schema for event \'%s\', see previous messages", event_name);
6832 return NULL;
6833 }
6834
6835 if (xdebug) {
6836 printf("*** New schema for event [%s] time %s:\n", event_name, TimeToString(timestamp).c_str());
6837 s->print();
6838 }
6839 }
6840
6841 assert(s != NULL);
6842
6843#if 0
6844 {
6845 printf("schema for [%s] is %p\n", event_name, s);
6846 if (s)
6847 s->print();
6848 }
6849#endif
6850
6851 HsFileSchema* e = new HsFileSchema();
6852
6853 *e = *s; // make a copy of the schema
6854
6855 return e;
6856}
void tags_to_variables(int ntags, const TAG tags[], std::vector< HsSchemaEntry > &variables)
int read_schema(HsSchemaVector *sv, const char *event_name, const time_t timestamp)
std::string fFileName
void print(bool print_tags=true) const
std::vector< HsSchemaEntry > fVariables
std::string fEventName
HsSchema * find_event(const char *event_name, const time_t timestamp, int debug=0)
double ss_file_size(const char *path)
Definition system.cxx:6978
const time_t kMonth
const double MiB
static void PrintTags(int ntags, const TAG tags[])
static double e(void)
Definition tinyexpr.c:136
Here is the call graph for this function:

◆ read_file_list()

int FileHistory::read_file_list ( bool pchanged)
protected

Definition at line 6525 of file history_schema.cxx.

6526{
6527 int status;
6528 double start_time = ss_time_sec();
6529
6530 if (pchanged)
6531 *pchanged = false;
6532
6533 struct stat stat_buf;
6534 status = stat(fPath.c_str(), &stat_buf);
6535 if (status != 0) {
6536 cm_msg(MERROR, "FileHistory::read_file_list", "Cannot stat(%s), errno %d (%s)", fPath.c_str(), errno, strerror(errno));
6537 return HS_FILE_ERROR;
6538 }
6539
6540 //printf("dir [%s], mtime: %d %d last: %d %d, mtime %s", fPath.c_str(), stat_buf.st_mtimespec.tv_sec, stat_buf.st_mtimespec.tv_nsec, last_mtimespec.tv_sec, last_mtimespec.tv_nsec, ctime(&stat_buf.st_mtimespec.tv_sec));
6541
6542 if (stat_buf.st_mtime == fPathLastMtime) {
6543 if (fDebug)
6544 printf("FileHistory::read_file_list: history directory \"%s\" mtime %d did not change\n", fPath.c_str(), int(stat_buf.st_mtime));
6545 return HS_SUCCESS;
6546 }
6547
6548 fPathLastMtime = stat_buf.st_mtime;
6549
6550 if (fDebug)
6551 printf("FileHistory::read_file_list: reading list of history files in \"%s\"\n", fPath.c_str());
6552
6553 std::vector<std::string> flist;
6554
6555 ss_file_find(fPath.c_str(), "mhf_*.dat", &flist);
6556
6557 double ls_time = ss_time_sec();
6558 double ls_elapsed = ls_time - start_time;
6559 if (ls_elapsed > 5.000) {
6560 cm_msg(MINFO, "FileHistory::read_file_list", "\"ls -l\" of \"%s\" took %.1f sec", fPath.c_str(), ls_elapsed);
6562 }
6563
6564 // note: reverse iterator is used to sort filenames by time, newest first
6565 std::sort(flist.rbegin(), flist.rend());
6566
6567#if 0
6568 {
6569 printf("file names sorted by time:\n");
6570 for (size_t i=0; i<flist.size(); i++) {
6571 printf("%d: %s\n", i, flist[i].c_str());
6572 }
6573 }
6574#endif
6575
6576 std::vector<bool> fread;
6577 fread.resize(flist.size()); // fill with "false"
6578
6579 // loop over the old list of files,
6580 // for files we already read, loop over new file
6581 // list and mark the same file as read. K.O.
6582 for (size_t j=0; j<fSortedFiles.size(); j++) {
6583 if (fSortedRead[j]) {
6584 for (size_t i=0; i<flist.size(); i++) {
6585 if (flist[i] == fSortedFiles[j]) {
6586 fread[i] = true;
6587 break;
6588 }
6589 }
6590 }
6591 }
6592
6595
6596 if (pchanged)
6597 *pchanged = true;
6598
6599 return HS_SUCCESS;
6600}
#define MINFO
Definition midas.h:560
double ss_time_sec()
Definition system.cxx:3467
INT ss_file_find(const char *path, const char *pattern, char **plist)
Definition system.cxx:6719
INT cm_msg_flush_buffer()
Definition midas.cxx:865
INT j
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_file_schema()

HsFileSchema * FileHistory::read_file_schema ( const char filename)
protected

Definition at line 7015 of file history_schema.cxx.

7016{
7017 if (fDebug)
7018 printf("FileHistory::read_file_schema: file %s\n", filename);
7019
7020 FILE* fp = fopen(filename, "r");
7021 if (!fp) {
7022 cm_msg(MERROR, "FileHistory::read_file_schema", "Cannot read \'%s\', fopen() errno %d (%s)", filename, errno, strerror(errno));
7023 return NULL;
7024 }
7025
7026 HsFileSchema* s = NULL;
7027
7028 // File format looks like this:
7029 // version: 2.0
7030 // event_name: u_Beam
7031 // time: 1023174012
7032 // tag: /DWORD 1 4 /timestamp
7033 // tag: FLOAT 1 4 B1
7034 // ...
7035 // tag: FLOAT 1 4 Ref Heater
7036 // record_size: 84
7037 // data_offset: 1024
7038
7039 size_t rd_recsize = 0;
7040 int offset = 0;
7041
7042 while (1) {
7043 char buf[1024];
7044 char* b = fgets(buf, sizeof(buf), fp);
7045
7046 //printf("read: %s\n", b);
7047
7048 if (!b) {
7049 break; // end of file
7050 }
7051
7052 char*bb;
7053
7054 bb = strchr(b, '\n');
7055 if (bb)
7056 *bb = 0;
7057
7058 bb = strchr(b, '\r');
7059 if (bb)
7060 *bb = 0;
7061
7062 bb = strstr(b, "version: 2.0");
7063 if (bb == b) {
7064 s = new HsFileSchema();
7065 assert(s);
7066
7067 s->fFileName = filename;
7068 continue;
7069 }
7070
7071 if (!s) {
7072 // malformed history file
7073 break;
7074 }
7075
7076 bb = strstr(b, "event_name: ");
7077 if (bb == b) {
7078 s->fEventName = bb + 12;
7079 continue;
7080 }
7081
7082 bb = strstr(b, "time: ");
7083 if (bb == b) {
7084 s->fTimeFrom = strtoul(bb + 6, NULL, 10);
7085 continue;
7086 }
7087
7088 // tag format is like this:
7089 //
7090 // tag: FLOAT 1 4 Ref Heater
7091 //
7092 // "FLOAT" is the MIDAS type, "/DWORD" is special tag for the timestamp
7093 // "1" is the number of array elements
7094 // "4" is the total tag size in bytes (n_data*tid_size)
7095 // "Ref Heater" is the tag name
7096
7097 bb = strstr(b, "tag: ");
7098 if (bb == b) {
7099 bb += 5; // now points to the tag MIDAS type
7100 const char* midas_type = bb;
7101 char* bbb = strchr(bb, ' ');
7102 if (bbb) {
7103 *bbb = 0;
7104 HsSchemaEntry t;
7105 if (midas_type[0] == '/') {
7106 t.type = 0;
7107 } else {
7109 if (t.type == 0) {
7110 cm_msg(MERROR, "FileHistory::read_file_schema", "Unknown MIDAS data type \'%s\' in history file \'%s\'", midas_type, filename);
7111 if (s)
7112 delete s;
7113 s = NULL;
7114 break;
7115 }
7116 }
7117 bbb++;
7118 while (*bbb == ' ')
7119 bbb++;
7120 if (*bbb) {
7121 t.n_data = strtoul(bbb, &bbb, 10);
7122 while (*bbb == ' ')
7123 bbb++;
7124 if (*bbb) {
7125 t.n_bytes = strtoul(bbb, &bbb, 10);
7126 while (*bbb == ' ')
7127 bbb++;
7128 t.name = bbb;
7129 }
7130 }
7131
7132 if (midas_type[0] != '/') {
7133 s->fVariables.push_back(t);
7134 s->fOffsets.push_back(offset);
7135 offset += t.n_bytes;
7136 }
7137
7138 rd_recsize += t.n_bytes;
7139 }
7140 continue;
7141 }
7142
7143 bb = strstr(b, "record_size: ");
7144 if (bb == b) {
7145 s->fRecordSize = atoi(bb + 12);
7146 continue;
7147 }
7148
7149 bb = strstr(b, "data_offset: ");
7150 if (bb == b) {
7151 s->fDataOffset = atoi(bb + 12);
7152 // data offset is the last entry in the file
7153 break;
7154 }
7155 }
7156
7157 fclose(fp);
7158
7159 if (!s) {
7160 cm_msg(MERROR, "FileHistory::read_file_schema", "Malformed history schema in \'%s\', maybe it is not a history file", filename);
7161 return NULL;
7162 }
7163
7164 if (rd_recsize != s->fRecordSize) {
7165 cm_msg(MERROR, "FileHistory::read_file_schema", "Record size mismatch in history schema from \'%s\', file says %zu while total of all tags is %zu", filename, s->fRecordSize, rd_recsize);
7166 if (s)
7167 delete s;
7168 return NULL;
7169 }
7170
7171 if (!s) {
7172 cm_msg(MERROR, "FileHistory::read_file_schema", "Could not read history schema from \'%s\', maybe it is not a history file", filename);
7173 if (s)
7174 delete s;
7175 return NULL;
7176 }
7177
7178 if (fDebug > 1)
7179 s->print();
7180
7181 return s;
7182}
std::vector< int > fOffsets
int rpc_name_tid(const char *name)
Definition midas.cxx:11786
int type
int n_data
std::string name
int n_bytes
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_schema()

int FileHistory::read_schema ( HsSchemaVector sv,
const char event_name,
const time_t  timestamp 
)
virtual

Implements SchemaHistoryBase.

Definition at line 6602 of file history_schema.cxx.

6603{
6604 if (fDebug)
6605 printf("FileHistory::read_schema: event [%s] at time %s\n", event_name, TimeToString(timestamp).c_str());
6606
6607 if (sv->size() == 0) {
6608 if (fDebug)
6609 printf("FileHistory::read_schema: schema is empty, do a full reload from disk\n");
6611 }
6612
6614 DWORD old_timeout = 0;
6617
6618 bool changed = false;
6619
6621
6622 if (status != HS_SUCCESS) {
6624 return status;
6625 }
6626
6627 if (!changed) {
6628 if ((*sv).find_event(event_name, timestamp)) {
6629 if (fDebug)
6630 printf("FileHistory::read_schema: event [%s] at time %s, no new history files, already have this schema\n", event_name, TimeToString(timestamp).c_str());
6632 return HS_SUCCESS;
6633 }
6634 }
6635
6636 double start_time = ss_time_sec();
6637
6638 int count_read = 0;
6639
6640 for (size_t i=0; i<fSortedFiles.size(); i++) {
6641 std::string file_name = fPath + fSortedFiles[i];
6642 if (fSortedRead[i])
6643 continue;
6644 //bool dupe = false;
6645 //for (size_t ss=0; ss<sv->size(); ss++) {
6646 // HsFileSchema* ssp = (HsFileSchema*)(*sv)[ss];
6647 // if (file_name == ssp->fFileName) {
6648 // dupe = true;
6649 // break;
6650 // }
6651 //}
6652 //if (dupe)
6653 // continue;
6654 fSortedRead[i] = true;
6656 if (!s)
6657 continue;
6658 sv->add(s);
6659 count_read++;
6660
6661 if (event_name) {
6662 if (s->fEventName == event_name) {
6663 //printf("file %s event_name %s time %s, age %f\n", file_name.c_str(), s->fEventName.c_str(), TimeToString(s->fTimeFrom).c_str(), double(timestamp - s->fTimeFrom));
6664 if (s->fTimeFrom <= timestamp) {
6665 // this file is older than the time requested,
6666 // subsequent files will be even older,
6667 // we can stop reading here.
6668 break;
6669 }
6670 }
6671 }
6672 }
6673
6674 double end_time = ss_time_sec();
6675 double read_elapsed = end_time - start_time;
6676 if (read_elapsed > 5.000) {
6677 cm_msg(MINFO, "FileHistory::read_schema", "Loading schema for event \"%s\" timestamp %s, reading %d history files took %.1f sec", event_name, TimeToString(timestamp).c_str(), count_read, read_elapsed);
6679 }
6680
6682
6683 return HS_SUCCESS;
6684}
#define FALSE
Definition cfortran.h:309
int read_file_list(bool *pchanged)
INT cm_get_watchdog_params(BOOL *call_watchdog, DWORD *timeout)
Definition midas.cxx:3325
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
Definition midas.cxx:3283
unsigned int DWORD
Definition mcstd.h:51
DWORD BOOL
Definition midas.h:105
char file_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tags_to_variables()

void FileHistory::tags_to_variables ( int  ntags,
const TAG  tags[],
std::vector< HsSchemaEntry > &  variables 
)
protected

Definition at line 6686 of file history_schema.cxx.

6687{
6688 for (int i=0; i<ntags; i++) {
6690
6691 int tsize = rpc_tid_size(tags[i].type);
6692
6693 e.tag_name = tags[i].name;
6694 e.tag_type = rpc_tid_name(tags[i].type);
6695 e.name = tags[i].name;
6696 e.type = tags[i].type;
6697 e.n_data = tags[i].n_data;
6698 e.n_bytes = tags[i].n_data*tsize;
6699
6700 variables.push_back(e);
6701 }
6702}
DWORD type
Definition midas.h:1234
DWORD n_data
Definition midas.h:1235
char name[NAME_LENGTH]
Definition midas.h:1233
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ fConfMaxFileAge

time_t FileHistory::fConfMaxFileAge = 1*kMonth
protected

Definition at line 6456 of file history_schema.cxx.

◆ fConfMaxFileSize

off64_t FileHistory::fConfMaxFileSize = 100*MiB
protected

Definition at line 6457 of file history_schema.cxx.

◆ fPath

std::string FileHistory::fPath
protected

Definition at line 6452 of file history_schema.cxx.

◆ fPathLastMtime

time_t FileHistory::fPathLastMtime = 0
protected

Definition at line 6453 of file history_schema.cxx.

◆ fSortedFiles

std::vector<std::string> FileHistory::fSortedFiles
protected

Definition at line 6454 of file history_schema.cxx.

◆ fSortedRead

std::vector<bool> FileHistory::fSortedRead
protected

Definition at line 6455 of file history_schema.cxx.


The documentation for this class was generated from the following file: