MIDAS
Loading...
Searching...
No Matches
history_schema.cxx File Reference
#include "midas.h"
#include "msystem.h"
#include "mstrlcpy.h"
#include <math.h>
#include <vector>
#include <list>
#include <string>
#include <map>
#include <unordered_map>
#include <algorithm>
#include "history.h"
Include dependency graph for history_schema.cxx:

Go to the source code of this file.

Classes

struct  HsSchemaEntry
 
class  HsSchema
 
class  HsSchemaVector
 
class  SqlBase
 
class  HsSqlSchema
 
class  HsFileSchema
 
class  SchemaHistoryBase
 
class  SchemaHistoryBase::ReadBuffer
 
class  SqlHistoryBase
 
class  SqliteHistory
 
class  MysqlHistory
 
class  FileHistory
 

Macros

#define FREE(x)   { if (x) free(x); (x) = NULL; }
 

Functions

static char * skip_spaces (char *s)
 
static std::string TimeToString (time_t t)
 
static std::string SmallIntToString (int i)
 
static bool MatchEventName (const char *event_name, const char *var_event_name)
 
static bool MatchTagName (const char *tag_name, int n_data, const char *var_tag_name, const int var_tag_index)
 
static void PrintTags (int ntags, const TAG tags[])
 
static std::string MidasNameToSqlName (const char *s)
 
static std::string MidasNameToFileName (const char *s)
 
static int event_name_cmp (const std::string &e1, const char *e2)
 
static int var_name_cmp (const std::string &v1, const char *v2)
 
void DoctorPgsqlColumnType (std::string *col_type, const char *index_type)
 
void DoctorSqlColumnType (std::string *col_type, const char *index_type)
 
static int ReadRecord (const char *file_name, int fd, off64_t offset, size_t recsize, off64_t irec, char *rec)
 
static int FindTime (const char *file_name, int fd, off64_t offset, size_t recsize, off64_t nrec, time_t timestamp, off64_t *i1p, time_t *t1p, off64_t *i2p, time_t *t2p, time_t *tstart, time_t *tend, int debug)
 
static HsSqlSchemaNewSqlSchema (HsSchemaVector *sv, const char *table_name, time_t t)
 
static int StartSqlTransaction (SqlBase *sql, const char *table_name, bool *have_transaction)
 
static int CreateSqlTable (SqlBase *sql, const char *table_name, bool *have_transaction, bool set_default_timestamp=false)
 
static int CreateSqlHyperTable (SqlBase *sql, const char *table_name, bool *have_transaction)
 
static int CreateSqlColumn (SqlBase *sql, const char *table_name, const char *column_name, const char *column_type, bool *have_transaction, int debug)
 
static int ReadSqliteTableNames (SqlBase *sql, HsSchemaVector *sv, const char *table_name, int debug)
 
static int ReadSqliteTableSchema (SqlBase *sql, HsSchemaVector *sv, const char *table_name, int debug)
 
static int ReadMysqlTableNames (SqlBase *sql, HsSchemaVector *sv, const char *table_name, int debug, const char *must_have_event_name, const char *must_have_table_name)
 
MidasHistoryInterfaceMakeMidasHistorySqlite ()
 
MidasHistoryInterfaceMakeMidasHistoryMysql ()
 
MidasHistoryInterfaceMakeMidasHistoryPgsql ()
 
MidasHistoryInterfaceMakeMidasHistoryFile ()
 

Variables

const time_t kDay = 24*60*60
 
const time_t kMonth = 30*kDay
 
const double KiB = 1024
 
const double MiB = KiB*KiB
 

Macro Definition Documentation

◆ FREE

#define FREE (   x)    { if (x) free(x); (x) = NULL; }

Definition at line 54 of file history_schema.cxx.

Function Documentation

◆ CreateSqlColumn()

static int CreateSqlColumn ( SqlBase sql,
const char *  table_name,
const char *  column_name,
const char *  column_type,
bool *  have_transaction,
int  debug 
)
static

Definition at line 4771 of file history_schema.cxx.

4772{
4773 if (debug)
4774 printf("CreateSqlColumn: table [%s], column [%s], type [%s]\n", table_name, column_name, column_type);
4775
4776 int status = StartSqlTransaction(sql, table_name, have_transaction);
4777 if (status != HS_SUCCESS)
4778 return status;
4779
4780 std::string cmd;
4781 cmd = "ALTER TABLE ";
4782 cmd += sql->QuoteId(table_name);
4783 cmd += " ADD COLUMN ";
4784 cmd += sql->QuoteId(column_name);
4785 cmd += " ";
4786 cmd += column_type;
4787 cmd += ";";
4788
4789 status = sql->Exec(table_name, cmd.c_str());
4790
4791 cm_msg(MINFO, "CreateSqlColumn", "Adding column \"%s\" to SQL table \"%s\", status %d", column_name, table_name, status);
4793
4794 return status;
4795}
virtual std::string QuoteId(const char *s)=0
virtual int Exec(const char *sql)=0
#define HS_SUCCESS
Definition midas.h:728
#define MINFO
Definition midas.h:560
INT cm_msg_flush_buffer()
Definition midas.cxx:881
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:931
static int StartSqlTransaction(SqlBase *sql, const char *table_name, bool *have_transaction)
BOOL debug
debug printouts
Definition mana.cxx:254
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateSqlHyperTable()

static int CreateSqlHyperTable ( SqlBase sql,
const char *  table_name,
bool *  have_transaction 
)
static

Definition at line 4697 of file history_schema.cxx.

4697 {
4698 int status;
4699
4700 status = StartSqlTransaction(sql, table_name, have_transaction);
4701 if (status != DB_SUCCESS)
4702 return HS_FILE_ERROR;
4703
4704 std::string cmd;
4705
4706 cmd = "CREATE TABLE ";
4707 cmd += sql->QuoteId(table_name);
4708 cmd += " (_t_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, _i_time INTEGER NOT NULL DEFAULT 0);";
4709
4710 status = sql->Exec(table_name, cmd.c_str());
4711
4712 if (status == DB_KEY_EXIST) {
4713 cm_msg(MINFO, "CreateSqlHyperTable", "Adding SQL table \"%s\", but it already exists", table_name);
4715 return status;
4716 }
4717
4718 if (status != DB_SUCCESS) {
4719 cm_msg(MINFO, "CreateSqlHyperTable", "Adding SQL table \"%s\", error status %d", table_name, status);
4721 return HS_FILE_ERROR;
4722 }
4723
4724 cm_msg(MINFO, "CreateSqlHyperTable", "Adding SQL table \"%s\"", table_name);
4726
4727 cmd = "SELECT create_hypertable(";
4728 cmd += sql->QuoteString(table_name);
4729 cmd += ", '_t_time');";
4730
4731 // convert regular table to hypertable
4732 status = sql->Exec(table_name, cmd.c_str());
4733
4734 if (status != DB_SUCCESS) {
4735 cm_msg(MINFO, "CreateSqlHyperTable", "Converting SQL table to hypertable \"%s\", error status %d", table_name, status);
4737 return HS_FILE_ERROR;
4738 }
4739
4740 std::string i_index_name;
4741 i_index_name = table_name;
4742 i_index_name += "_i_time_index";
4743
4744 std::string t_index_name;
4745 t_index_name = table_name;
4746 t_index_name += "_t_time_index";
4747
4748 cmd = "CREATE INDEX ";
4749 cmd += sql->QuoteId(i_index_name.c_str());
4750 cmd += " ON ";
4751 cmd += sql->QuoteId(table_name);
4752 cmd += " (_i_time ASC);";
4753
4754 status = sql->Exec(table_name, cmd.c_str());
4755 if (status != DB_SUCCESS)
4756 return HS_FILE_ERROR;
4757
4758 cmd = "CREATE INDEX ";
4759 cmd += sql->QuoteId(t_index_name.c_str());
4760 cmd += " ON ";
4761 cmd += sql->QuoteId(table_name);
4762 cmd += " (_t_time);";
4763
4764 status = sql->Exec(table_name, cmd.c_str());
4765 if (status != DB_SUCCESS)
4766 return HS_FILE_ERROR;
4767
4768 return status;
4769}
virtual std::string QuoteString(const char *s)=0
#define DB_KEY_EXIST
Definition midas.h:642
#define DB_SUCCESS
Definition midas.h:632
#define HS_FILE_ERROR
Definition midas.h:729
Here is the call graph for this function:

◆ CreateSqlTable()

static int CreateSqlTable ( SqlBase sql,
const char *  table_name,
bool *  have_transaction,
bool  set_default_timestamp = false 
)
static

Definition at line 4630 of file history_schema.cxx.

4631{
4632 int status;
4633
4634 status = StartSqlTransaction(sql, table_name, have_transaction);
4635 if (status != DB_SUCCESS)
4636 return HS_FILE_ERROR;
4637
4638 std::string cmd;
4639
4640 cmd = "CREATE TABLE ";
4641 cmd += sql->QuoteId(table_name);
4642 if (set_default_timestamp) {
4643 cmd += " (_t_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, _i_time INTEGER NOT NULL DEFAULT 0);";
4644 } else {
4645 cmd += " (_t_time TIMESTAMP NOT NULL, _i_time INTEGER NOT NULL);";
4646 }
4647
4648 status = sql->Exec(table_name, cmd.c_str());
4649
4650
4651 if (status == DB_KEY_EXIST) {
4652 cm_msg(MINFO, "CreateSqlTable", "Adding SQL table \"%s\", but it already exists", table_name);
4654 return status;
4655 }
4656
4657 if (status != DB_SUCCESS) {
4658 cm_msg(MINFO, "CreateSqlTable", "Adding SQL table \"%s\", error status %d", table_name, status);
4660 return HS_FILE_ERROR;
4661 }
4662
4663 cm_msg(MINFO, "CreateSqlTable", "Adding SQL table \"%s\"", table_name);
4665
4666 std::string i_index_name;
4667 i_index_name = table_name;
4668 i_index_name += "_i_time_index";
4669
4670 std::string t_index_name;
4671 t_index_name = table_name;
4672 t_index_name += "_t_time_index";
4673
4674 cmd = "CREATE INDEX ";
4675 cmd += sql->QuoteId(i_index_name.c_str());
4676 cmd += " ON ";
4677 cmd += sql->QuoteId(table_name);
4678 cmd += " (_i_time ASC);";
4679
4680 status = sql->Exec(table_name, cmd.c_str());
4681 if (status != DB_SUCCESS)
4682 return HS_FILE_ERROR;
4683
4684 cmd = "CREATE INDEX ";
4685 cmd += sql->QuoteId(t_index_name.c_str());
4686 cmd += " ON ";
4687 cmd += sql->QuoteId(table_name);
4688 cmd += " (_t_time);";
4689
4690 status = sql->Exec(table_name, cmd.c_str());
4691 if (status != DB_SUCCESS)
4692 return HS_FILE_ERROR;
4693
4694 return status;
4695}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DoctorPgsqlColumnType()

void DoctorPgsqlColumnType ( std::string *  col_type,
const char *  index_type 
)

Definition at line 301 of file history_schema.cxx.

302{
303 if (*col_type == index_type)
304 return;
305
306 if (*col_type == "bigint" && strcmp(index_type, "int8")==0) {
307 *col_type = index_type;
308 return;
309 }
310
311 if (*col_type == "integer" && strcmp(index_type, "int4")==0) {
312 *col_type = index_type;
313 return;
314 }
315
316 if (*col_type == "smallint" && strcmp(index_type, "int2")==0) {
317 *col_type = index_type;
318 return;
319 }
320
321 cm_msg(MERROR, "SqlHistory", "Cannot use this SQL database, incompatible column names: created column type [%s] is reported with column type [%s]", index_type, col_type->c_str());
323 abort();
324}
#define MERROR
Definition midas.h:559
Here is the call graph for this function:

◆ DoctorSqlColumnType()

void DoctorSqlColumnType ( std::string *  col_type,
const char *  index_type 
)

Definition at line 326 of file history_schema.cxx.

327{
328 if (*col_type == index_type)
329 return;
330
331 if (*col_type == "int(10) unsigned" && strcmp(index_type, "integer unsigned")==0) {
332 *col_type = index_type;
333 return;
334 }
335
336 if (*col_type == "int(11)" && strcmp(index_type, "integer")==0) {
337 *col_type = index_type;
338 return;
339 }
340
341 if (*col_type == "integer" && strcmp(index_type, "int(11)")==0) {
342 *col_type = index_type;
343 return;
344 }
345
346 // MYSQL 8.0.23
347
348 if (*col_type == "int" && strcmp(index_type, "integer")==0) {
349 *col_type = index_type;
350 return;
351 }
352
353 if (*col_type == "int unsigned" && strcmp(index_type, "integer unsigned")==0) {
354 *col_type = index_type;
355 return;
356 }
357
358 cm_msg(MERROR, "SqlHistory", "Cannot use this SQL database, incompatible column names: created column type [%s] is reported with column type [%s]", index_type, col_type->c_str());
360 abort();
361}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ event_name_cmp()

static int event_name_cmp ( const std::string &  e1,
const char *  e2 
)
static

Definition at line 219 of file history_schema.cxx.

220{
221 return strcasecmp(e1.c_str(), e2);
222}
Here is the caller graph for this function:

◆ FindTime()

static int FindTime ( const char *  file_name,
int  fd,
off64_t  offset,
size_t  recsize,
off64_t  nrec,
time_t  timestamp,
off64_t *  i1p,
time_t *  t1p,
off64_t *  i2p,
time_t *  t2p,
time_t *  tstart,
time_t *  tend,
int  debug 
)
static

Definition at line 2646 of file history_schema.cxx.

2647{
2648 //
2649 // purpose: find location time timestamp inside given file.
2650 // uses binary search
2651 // returns:
2652 // tstart, tend - time of first and last data in a file
2653 // i1p,t1p - data just before timestamp, used as "last_written"
2654 // i2p,t2p - data at timestamp or after timestamp, used as starting point to read data from file
2655 // assertions:
2656 // tstart <= t1p < t2p <= tend
2657 // i1p+1==i2p
2658 // t1p < timestamp <= t2p
2659 //
2660 // special cases:
2661 // 1) timestamp <= tstart - all data is in the future, return i1p==-1, t1p==-1, i2p==0, t2p==tstart
2662 // 2) tend < timestamp - all the data is in the past, return i1p = nrec-1, t1p = tend, i2p = nrec, t2p = 0;
2663 // 3) nrec == 1 only one record in this file and it is older than the timestamp (tstart == tend < timestamp)
2664 //
2665
2666 int status;
2667 char* buf = new char[recsize];
2668
2669 assert(nrec > 0);
2670
2671 off64_t rec1 = 0;
2672 off64_t rec2 = nrec-1;
2673
2674 status = ReadRecord(file_name, fd, offset, recsize, rec1, buf);
2675 if (status != HS_SUCCESS) {
2676 delete[] buf;
2677 return HS_FILE_ERROR;
2678 }
2679
2680 time_t t1 = *(DWORD*)buf;
2681
2682 *tstart = t1;
2683
2684 // timestamp is older than any data in this file
2685 if (timestamp <= t1) {
2686 *i1p = -1;
2687 *t1p = 0;
2688 *i2p = 0;
2689 *t2p = t1;
2690 *tend = 0;
2691 delete[] buf;
2692 return HS_SUCCESS;
2693 }
2694
2695 assert(t1 < timestamp);
2696
2697 if (nrec == 1) {
2698 *i1p = 0;
2699 *t1p = t1;
2700 *i2p = nrec; // == 1
2701 *t2p = 0;
2702 *tend = t1;
2703 delete[] buf;
2704 return HS_SUCCESS;
2705 }
2706
2707 status = ReadRecord(file_name, fd, offset, recsize, rec2, buf);
2708 if (status != HS_SUCCESS) {
2709 delete[] buf;
2710 return HS_FILE_ERROR;
2711 }
2712
2713 time_t t2 = *(DWORD*)buf;
2714
2715 *tend = t2;
2716
2717 // all the data is in the past
2718 if (t2 < timestamp) {
2719 *i1p = rec2;
2720 *t1p = t2;
2721 *i2p = nrec;
2722 *t2p = 0;
2723 delete[] buf;
2724 return HS_SUCCESS;
2725 }
2726
2727 assert(t1 < timestamp);
2728 assert(timestamp <= t2);
2729
2730 if (debug)
2731 printf("FindTime: rec %jd..(x)..%jd, time %s..(%s)..%s\n", (intmax_t)rec1, (intmax_t)rec2, TimeToString(t1).c_str(), TimeToString(timestamp).c_str(), TimeToString(t2).c_str());
2732
2733 // implement binary search
2734
2735 do {
2736 off64_t rec = (rec1+rec2)/2;
2737
2738 assert(rec >= 0);
2739 assert(rec < nrec);
2740
2741 status = ReadRecord(file_name, fd, offset, recsize, rec, buf);
2742 if (status != HS_SUCCESS) {
2743 delete[] buf;
2744 return HS_FILE_ERROR;
2745 }
2746
2747 time_t t = *(DWORD*)buf;
2748
2749 if (timestamp <= t) {
2750 if (debug)
2751 printf("FindTime: rec %jd..(x)..%jd..%jd, time %s..(%s)..%s..%s\n", (intmax_t)rec1, (intmax_t)rec, (intmax_t)rec2, TimeToString(t1).c_str(), TimeToString(timestamp).c_str(), TimeToString(t).c_str(), TimeToString(t2).c_str());
2752
2753 rec2 = rec;
2754 t2 = t;
2755 } else {
2756 if (debug)
2757 printf("FindTime: rec %jd..%jd..(x)..%jd, time %s..%s..(%s)..%s\n", (intmax_t)rec1, (intmax_t)rec, (intmax_t)rec2, TimeToString(t1).c_str(), TimeToString(t).c_str(), TimeToString(timestamp).c_str(), TimeToString(t2).c_str());
2758
2759 rec1 = rec;
2760 t1 = t;
2761 }
2762 } while (rec2 - rec1 > 1);
2763
2764 assert(rec1+1 == rec2);
2765 assert(t1 < timestamp);
2766 assert(timestamp <= t2);
2767
2768 if (debug)
2769 printf("FindTime: rec %jd..(x)..%jd, time %s..(%s)..%s, this is the result.\n", (intmax_t)rec1, (intmax_t)rec2, TimeToString(t1).c_str(), TimeToString(timestamp).c_str(), TimeToString(t2).c_str());
2770
2771 *i1p = rec1;
2772 *t1p = t1;
2773
2774 *i2p = rec2;
2775 *t2p = t2;
2776
2777 delete[] buf;
2778 return HS_SUCCESS;
2779}
unsigned int DWORD
Definition mcstd.h:51
static int ReadRecord(const char *file_name, int fd, off64_t offset, size_t recsize, off64_t irec, char *rec)
static std::string TimeToString(time_t t)
static int offset
Definition mgd.cxx:1500
char file_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeMidasHistoryFile()

MidasHistoryInterface * MakeMidasHistoryFile ( )

Definition at line 7296 of file history_schema.cxx.

7297{
7298 return new FileHistory();
7299}
Here is the caller graph for this function:

◆ MakeMidasHistoryMysql()

MidasHistoryInterface * MakeMidasHistoryMysql ( )

Definition at line 7276 of file history_schema.cxx.

7277{
7278#ifdef HAVE_MYSQL
7279 return new MysqlHistory();
7280#else
7281 cm_msg(MERROR, "MakeMidasHistoryMysql", "Error: Cannot initialize MySQL history - this MIDAS was built without MySQL support - HAVE_MYSQL is not defined");
7282 return NULL;
7283#endif
7284}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeMidasHistoryPgsql()

MidasHistoryInterface * MakeMidasHistoryPgsql ( )

Definition at line 7286 of file history_schema.cxx.

7287{
7288#ifdef HAVE_PGSQL
7289 return new PgsqlHistory();
7290#else
7291 cm_msg(MERROR, "MakeMidasHistoryPgsql", "Error: Cannot initialize PgSQL history - this MIDAS was built without PostgreSQL support - HAVE_PGSQL is not defined");
7292 return NULL;
7293#endif
7294}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeMidasHistorySqlite()

MidasHistoryInterface * MakeMidasHistorySqlite ( )

Definition at line 7266 of file history_schema.cxx.

7267{
7268#ifdef HAVE_SQLITE
7269 return new SqliteHistory();
7270#else
7271 cm_msg(MERROR, "MakeMidasHistorySqlite", "Error: Cannot initialize SQLITE history - this MIDAS was built without SQLITE support - HAVE_SQLITE is not defined");
7272 return NULL;
7273#endif
7274}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MatchEventName()

static bool MatchEventName ( const char *  event_name,
const char *  var_event_name 
)
static

Definition at line 117 of file history_schema.cxx.

118{
119 // new-style event name: "equipment_name/variable_name:tag_name"
120 // old-style event name: "equipment_name:tag_name" ("variable_name" is missing)
121 bool newStyleEventName = (strchr(var_event_name, '/')!=NULL);
122
123 //printf("looking for event_name [%s], try table [%s] event name [%s], new style [%d]\n", var_event_name, table_name, event_name, newStyleEventName);
124
125 if (strcasecmp(event_name, var_event_name) == 0) {
126 return true;
127 } else if (newStyleEventName) {
128 return false;
129 } else { // for old style names, need more parsing
130 bool match = false;
131
132 const char* s = event_name;
133 for (int j=0; s[j]; j++) {
134
135 if ((var_event_name[j]==0) && (s[j]=='/')) {
136 match = true;
137 break;
138 }
139
140 if ((var_event_name[j]==0) && (s[j]=='_')) {
141 match = true;
142 break;
143 }
144
145 if (var_event_name[j]==0) {
146 match = false;
147 break;
148 }
149
150 if (tolower(var_event_name[j]) != tolower(s[j])) { // does not work for UTF-8 Unicode
151 match = false;
152 break;
153 }
154 }
155
156 return match;
157 }
158}
BOOL match(char *pat, char *str)
Definition odbedit.cxx:189
INT j
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MatchTagName()

static bool MatchTagName ( const char *  tag_name,
int  n_data,
const char *  var_tag_name,
const int  var_tag_index 
)
static

Definition at line 160 of file history_schema.cxx.

161{
162 char alt_tag_name[1024]; // maybe this is an array without "Names"?
163 sprintf(alt_tag_name, "%s[%d]", var_tag_name, var_tag_index);
164
165 //printf(" looking for tag [%s] alt [%s], try column name [%s]\n", var_tag_name, alt_tag_name, tag_name);
166
167 if (strcasecmp(tag_name, var_tag_name) == 0)
168 if (var_tag_index >= 0 && var_tag_index < n_data)
169 return true;
170
171 if (strcasecmp(tag_name, alt_tag_name) == 0)
172 return true;
173
174 return false;
175}
Here is the caller graph for this function:

◆ MidasNameToFileName()

static std::string MidasNameToFileName ( const char *  s)
static

Definition at line 202 of file history_schema.cxx.

203{
204 std::string out;
205
206 for (int i=0; s[i]!=0; i++) {
207 char c = s[i];
208 if (isalpha(c) || isdigit(c))
209 out += tolower(c); // does not work for UTF-8 Unicode
210 else
211 out += '_';
212 }
213
214 return out;
215}
INT i
Definition mdump.cxx:32
char c
Definition system.cxx:1312
Here is the caller graph for this function:

◆ MidasNameToSqlName()

static std::string MidasNameToSqlName ( const char *  s)
static

Definition at line 185 of file history_schema.cxx.

186{
187 std::string out;
188
189 for (int i=0; s[i]!=0; i++) {
190 char c = s[i];
191 if (isalpha(c) || isdigit(c))
192 out += tolower(c); // does not work for UTF-8 Unicode
193 else
194 out += '_';
195 }
196
197 return out;
198}
Here is the caller graph for this function:

◆ NewSqlSchema()

static HsSqlSchema * NewSqlSchema ( HsSchemaVector sv,
const char *  table_name,
time_t  t 
)
static

Definition at line 4179 of file history_schema.cxx.

4180{
4181 time_t tt = 0;
4182 int j=-1;
4183 int jjx=-1; // remember oldest schema
4184 time_t ttx = 0;
4185 for (size_t i=0; i<sv->size(); i++) {
4186 HsSqlSchema* s = (HsSqlSchema*)(*sv)[i];
4187 if (s->fTableName != table_name)
4188 continue;
4189
4190 if (s->fTimeFrom == t) {
4191 return s;
4192 }
4193
4194 // remember the last schema before time t
4195 if (s->fTimeFrom < t) {
4196 if (s->fTimeFrom > tt) {
4197 tt = s->fTimeFrom;
4198 j = i;
4199 }
4200 }
4201
4202 if (jjx < 0) {
4203 jjx = i;
4204 ttx = s->fTimeFrom;
4205 }
4206
4207 if (s->fTimeFrom < ttx) {
4208 jjx = i;
4209 ttx = s->fTimeFrom;
4210 }
4211
4212 //printf("table_name [%s], t=%s, i=%d, j=%d %s, tt=%s, dt is %d\n", table_name, TimeToString(t).c_str(), i, j, TimeToString(s->fTimeFrom).c_str(), TimeToString(tt).c_str(), (int)(s->fTimeFrom-t));
4213 }
4214
4215 //printf("NewSqlSchema: will copy schema j=%d, tt=%d at time %d\n", j, tt, t);
4216
4217 //printf("cloned schema at time %s: ", TimeToString(t).c_str());
4218 //(*sv)[j]->print(false);
4219
4220 //printf("schema before:\n");
4221 //sv->print(false);
4222
4223 if (j >= 0) {
4224 HsSqlSchema* s = new HsSqlSchema;
4225 *s = *(HsSqlSchema*)(*sv)[j]; // make a copy
4226 s->fTimeFrom = t;
4227 sv->add(s);
4228
4229 //printf("schema after:\n");
4230 //sv->print(false);
4231
4232 return s;
4233 }
4234
4235 if (jjx >= 0) {
4236 cm_msg(MERROR, "NewSqlSchema", "Error: Unexpected ordering of schema for table \'%s\', good luck!", table_name);
4237
4238 HsSqlSchema* s = new HsSqlSchema;
4239 *s = *(HsSqlSchema*)(*sv)[jjx]; // make a copy
4240 s->fTimeFrom = t;
4241 s->fTimeTo = ttx;
4242 sv->add(s);
4243
4244 //printf("schema after:\n");
4245 //sv->print(false);
4246
4247 return s;
4248 }
4249
4250 cm_msg(MERROR, "NewSqlSchema", "Error: Cannot clone schema for table \'%s\', good luck!", table_name);
4251 return NULL;
4252}
size_t size() const
void add(HsSchema *s)
std::string fTableName
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PrintTags()

static void PrintTags ( int  ntags,
const TAG  tags[] 
)
static

Definition at line 177 of file history_schema.cxx.

178{
179 for (int i=0; i<ntags; i++)
180 printf("tag %d: %s %s[%d]\n", i, rpc_tid_name(tags[i].type), tags[i].name, tags[i].n_data);
181}
const char * rpc_tid_name(INT id)
Definition midas.cxx:11895
INT type
Definition mana.cxx:269
#define name(x)
Definition midas_macro.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadMysqlTableNames()

static int ReadMysqlTableNames ( SqlBase sql,
HsSchemaVector sv,
const char *  table_name,
int  debug,
const char *  must_have_event_name,
const char *  must_have_table_name 
)
static

Definition at line 5604 of file history_schema.cxx.

5605{
5606 if (debug)
5607 printf("ReadMysqlTableNames: table [%s], must have event [%s] table [%s]\n", table_name, must_have_event_name, must_have_table_name);
5608
5609 int status;
5610 std::string cmd;
5611
5612 if (table_name) {
5613 cmd = "SELECT event_name, table_name, itimestamp FROM _history_index WHERE table_name='";
5614 cmd += table_name;
5615 cmd += "';";
5616 } else {
5617 // Only enumerate the table-marker rows (one per table/version), not the far more
5618 // numerous per-column rows. Both carry a non-empty table_name, but the table-marker
5619 // INSERT omits column_name (leaving it NULL) while the column-record INSERT sets it.
5620 // Restricting to column_name IS NULL keeps the reader schema vector at ~(#tables)
5621 // instead of ~(#columns x #versions), which is what blows up on a large _history_index.
5622 cmd = "SELECT event_name, table_name, itimestamp FROM _history_index WHERE table_name!='' AND column_name IS NULL;";
5623 table_name = "_history_index";
5624 }
5625
5626 status = sql->Prepare(table_name, cmd.c_str());
5627
5628 if (status != DB_SUCCESS)
5629 return status;
5630
5631 bool found_must_have_table = false;
5632 int count = 0;
5633
5634 while (1) {
5635 status = sql->Step();
5636
5637 if (status != DB_SUCCESS)
5638 break;
5639
5640 const char* xevent_name = sql->GetText(0);
5641 const char* xtable_name = sql->GetText(1);
5642 time_t xevent_time = sql->GetTime(2);
5643
5644 if (debug == 999) {
5645 printf("entry %d event name [%s] table name [%s] time %s\n", count, xevent_name, xtable_name, TimeToString(xevent_time).c_str());
5646 }
5647
5648 if (must_have_table_name && (strcmp(xtable_name, must_have_table_name) == 0)) {
5649 assert(must_have_event_name != NULL);
5650 if (event_name_cmp(xevent_name, must_have_event_name) == 0) {
5651 found_must_have_table = true;
5652 //printf("Found table [%s]: event name [%s] table name [%s] time %s\n", must_have_table_name, xevent_name, xtable_name, TimeToString(xevent_time).c_str());
5653 } else {
5654 //printf("Found correct table [%s] with wrong event name [%s] expected [%s] time %s\n", must_have_table_name, xevent_name, must_have_event_name, TimeToString(xevent_time).c_str());
5655 }
5656 }
5657
5658 HsSqlSchema* s = new HsSqlSchema;
5659 s->fSql = sql;
5660 s->fEventName = xevent_name;
5661 s->fTimeFrom = xevent_time;
5662 s->fTimeTo = 0;
5663 s->fTableName = xtable_name;
5664 sv->add(s);
5665 count++;
5666 }
5667
5668 status = sql->Finalize();
5669
5670 if (must_have_table_name && !found_must_have_table) {
5671 cm_msg(MERROR, "ReadMysqlTableNames", "Error: Table [%s] for event [%s] missing from the history index\n", must_have_table_name, must_have_event_name);
5672 if (debug == 999)
5673 return HS_FILE_ERROR;
5674 // NB: recursion is broken by setting debug to 999.
5675 ReadMysqlTableNames(sql, sv, table_name, 999, must_have_event_name, must_have_table_name);
5676 cm_msg(MERROR, "ReadMysqlTableNames", "Error: Cannot continue, nothing will work after this error\n");
5678 abort();
5679 return HS_FILE_ERROR;
5680 }
5681
5682 if (0) {
5683 // print accumulated schema
5684 printf("ReadMysqlTableNames: table_name [%s] event_name [%s] table_name [%s]\n", table_name, must_have_event_name, must_have_table_name);
5685 sv->print(false);
5686 }
5687
5688 return HS_SUCCESS;
5689}
std::string fEventName
void print(bool print_tags=true) const
virtual int Finalize()=0
virtual int Prepare(const char *table_name, const char *sql)=0
virtual time_t GetTime(int column)=0
virtual int Step()=0
virtual const char * GetText(int column)=0
static int event_name_cmp(const std::string &e1, const char *e2)
static int ReadMysqlTableNames(SqlBase *sql, HsSchemaVector *sv, const char *table_name, int debug, const char *must_have_event_name, const char *must_have_table_name)
double count
Definition mdump.cxx:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadRecord()

static int ReadRecord ( const char *  file_name,
int  fd,
off64_t  offset,
size_t  recsize,
off64_t  irec,
char *  rec 
)
static

Definition at line 2615 of file history_schema.cxx.

2616{
2617 off64_t fpos = offset + irec*recsize;
2618
2619 off64_t status64 = ::lseek64(fd, fpos, SEEK_SET);
2620
2621 if (status64 < 0) {
2622 cm_msg(MERROR, "FileHistory::ReadRecord", "Cannot read \'%s\', lseek64(%jd) errno %d (%s)", file_name, (intmax_t)fpos, errno, strerror(errno));
2623 return -1;
2624 }
2625
2626 ssize_t rd = ::read(fd, rec, recsize);
2627
2628 if (rd < 0) {
2629 cm_msg(MERROR, "FileHistory::ReadRecord", "Cannot read \'%s\', read() errno %d (%s)", file_name, errno, strerror(errno));
2630 return -1;
2631 }
2632
2633 if (rd == 0) {
2634 cm_msg(MERROR, "FileHistory::ReadRecord", "Cannot read \'%s\', unexpected end of file on read()", file_name);
2635 return -1;
2636 }
2637
2638 if ((size_t)rd != recsize) {
2639 cm_msg(MERROR, "FileHistory::ReadRecord", "Cannot read \'%s\', short read() returned %zd instead of %zu bytes", file_name, rd, recsize);
2640 return -1;
2641 }
2642
2643 return HS_SUCCESS;
2644}
#define read(n, a, f)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadSqliteTableNames()

static int ReadSqliteTableNames ( SqlBase sql,
HsSchemaVector sv,
const char *  table_name,
int  debug 
)
static

Definition at line 5261 of file history_schema.cxx.

5262{
5263 if (debug)
5264 printf("ReadSqliteTableNames: table [%s]\n", table_name);
5265
5266 int status;
5267 std::string cmd;
5268
5269 // FIXME: quotes
5270 cmd = "SELECT event_name, _i_time FROM \'_event_name_";
5271 cmd += table_name;
5272 cmd += "\' WHERE table_name='";
5273 cmd += table_name;
5274 cmd += "';";
5275
5276 status = sql->Prepare(table_name, cmd.c_str());
5277
5278 if (status != DB_SUCCESS)
5279 return status;
5280
5281 while (1) {
5282 status = sql->Step();
5283
5284 if (status != DB_SUCCESS)
5285 break;
5286
5287 std::string xevent_name = sql->GetText(0);
5288 time_t xevent_time = sql->GetTime(1);
5289
5290 //printf("read event name [%s] time %s\n", xevent_name.c_str(), TimeToString(xevent_time).c_str());
5291
5292 HsSqlSchema* s = new HsSqlSchema;
5293 s->fSql = sql;
5294 s->fEventName = xevent_name;
5295 s->fTimeFrom = xevent_time;
5296 s->fTimeTo = 0;
5297 s->fTableName = table_name;
5298 sv->add(s);
5299 }
5300
5301 status = sql->Finalize();
5302
5303 return HS_SUCCESS;
5304}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadSqliteTableSchema()

static int ReadSqliteTableSchema ( SqlBase sql,
HsSchemaVector sv,
const char *  table_name,
int  debug 
)
static

Definition at line 5306 of file history_schema.cxx.

5307{
5308 if (debug)
5309 printf("ReadSqliteTableSchema: table [%s]\n", table_name);
5310
5311 if (1) {
5312 // seed schema with table names
5313 HsSqlSchema* s = new HsSqlSchema;
5314 s->fSql = sql;
5315 s->fEventName = table_name;
5316 s->fTimeFrom = 0;
5317 s->fTimeTo = 0;
5318 s->fTableName = table_name;
5319 sv->add(s);
5320 }
5321
5322 return ReadSqliteTableNames(sql, sv, table_name, debug);
5323}
static int ReadSqliteTableNames(SqlBase *sql, HsSchemaVector *sv, const char *table_name, int debug)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ skip_spaces()

static char * skip_spaces ( char *  s)
static

Definition at line 56 of file history_schema.cxx.

57{
58 while (*s) {
59 if (!isspace(*s))
60 break;
61 s++;
62 }
63 return s;
64}

◆ SmallIntToString()

static std::string SmallIntToString ( int  i)
static

Definition at line 96 of file history_schema.cxx.

97{
98 //int ii = i;
99
100 if (i == 0)
101 return "0";
102
103 assert(i > 0);
104
105 std::string v;
106 while (i) {
107 char c = '0' + (char)(i%10);
108 i /= 10;
109 v = c + v;
110 }
111
112 //printf("SmallIntToString: %d -> %s\n", ii, v.c_str());
113
114 return v;
115}
Here is the caller graph for this function:

◆ StartSqlTransaction()

static int StartSqlTransaction ( SqlBase sql,
const char *  table_name,
bool *  have_transaction 
)
static

Definition at line 4617 of file history_schema.cxx.

4618{
4619 if (*have_transaction)
4620 return HS_SUCCESS;
4621
4622 int status = sql->OpenTransaction(table_name);
4623 if (status != DB_SUCCESS)
4624 return HS_FILE_ERROR;
4625
4626 *have_transaction = true;
4627 return HS_SUCCESS;
4628}
virtual int OpenTransaction(const char *table_name)=0
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TimeToString()

static std::string TimeToString ( time_t  t)
static

Definition at line 66 of file history_schema.cxx.

67{
68 const char* sign = "";
69
70 if (t == 0)
71 return "0";
72
73 time_t tt = t;
74
75 if (t < 0) {
76 sign = "-";
77 tt = -t;
78 }
79
80 assert(tt > 0);
81
82 std::string v;
83 while (tt) {
84 char c = '0' + (char)(tt%10);
85 tt /= 10;
86 v = c + v;
87 }
88
89 v = sign + v;
90
91 //printf("time %.0f -> %s\n", (double)t, v.c_str());
92
93 return v;
94}
Here is the caller graph for this function:

◆ var_name_cmp()

static int var_name_cmp ( const std::string &  v1,
const char *  v2 
)
static

Definition at line 226 of file history_schema.cxx.

227{
228 return strcasecmp(v1.c_str(), v2);
229}
Here is the caller graph for this function:

Variable Documentation

◆ kDay

const time_t kDay = 24*60*60

Definition at line 6456 of file history_schema.cxx.

◆ KiB

const double KiB = 1024

Definition at line 6459 of file history_schema.cxx.

◆ kMonth

const time_t kMonth = 30*kDay

Definition at line 6457 of file history_schema.cxx.

◆ MiB

const double MiB = KiB*KiB

Definition at line 6460 of file history_schema.cxx.