SqlHistory Class Reference

Inheritance diagram for SqlHistory:

MidasHistoryInterface

Detailed Description

Definition at line 1158 of file history_sql.cxx.

Public Member Functions

 SqlHistory (SqlBase *b)
 ~SqlHistory ()
int hs_set_debug (int debug)
int hs_connect (const char *connect_string)
int hs_disconnect ()
int Reconnect ()
int hs_clear_cache ()
int XReadIndex ()
int hs_define_event (const char *event_name, int ntags, const TAG tags[])
int hs_write_event (const char *event_name, time_t timestamp, int buffer_size, const char *buffer)
int hs_get_events (std::vector< std::string > *pevents)
int hs_get_tags (const char *event_name, std::vector< TAG > *ptags)
int hs_read_old_style (double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int var_index, int *num_entries, time_t **time_buffer, double **data_buffer)
int hs_read (double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int tag_index, int *num_entries, time_t **time_buffer, double **data_buffer)
int hs_read (time_t start_time, time_t end_time, time_t interval, int num_var, const char *event_name[], const char *tag_name[], const int tag_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int st[])

Data Fields

SqlBasefSql
int fDebug
std::string fConnectString
int fConnectRetry
int fNextConnect
std::vector< Event * > fEvents
std::vector< std::string > fIndexEvents
bool fHaveIndex
bool fHaveXIndex


Constructor & Destructor Documentation

SqlHistory::SqlHistory ( SqlBase b  ) 

Definition at line 1171 of file history_sql.cxx.

01172    {
01173       fDebug = 0;
01174       fConnectRetry = 0;
01175       fNextConnect  = 0;
01176       fSql = b;
01177       fHaveIndex = false;
01178       fHaveXIndex = false;
01179    }

SqlHistory::~SqlHistory (  ) 

Definition at line 1181 of file history_sql.cxx.

01182    {
01183       hs_disconnect();
01184       delete fSql;
01185       fSql = NULL;
01186    }


Member Function Documentation

int SqlHistory::hs_clear_cache (  )  [virtual]

clear internal cache, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1265 of file history_sql.cxx.

Referenced by hs_disconnect().

01266    {
01267       if (fDebug)
01268          printf("hs_clear_cache!\n");
01269 
01270       gHaveIndex = true;
01271       gHaveIndexAll = false;
01272       fHaveXIndex = false;
01273 
01274       for (unsigned i=0; i<gHistoryIndex.size(); i++) {
01275          IndexEntry* ie = gHistoryIndex[i];
01276          delete ie;
01277       }
01278       gHistoryIndex.clear();
01279 
01280       fIndexEvents.clear();
01281 
01282       return HS_SUCCESS;
01283    }

int SqlHistory::hs_connect ( const char *  connect_string  )  [virtual]

returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1197 of file history_sql.cxx.

01198    {
01199       if (fDebug)
01200          printf("hs_connect %s!\n", connect_string);
01201 
01202       assert(fSql);
01203 
01204       if (fSql->IsConnected())
01205          if (strcmp(fConnectString.c_str(), connect_string) == 0)
01206             return HS_SUCCESS;
01207     
01208       hs_disconnect();
01209     
01210       fConnectString = connect_string;
01211     
01212       if (fDebug)
01213          printf("hs_connect: connecting to SQL database \'%s\'\n", fConnectString.c_str());
01214     
01215       int status = fSql->Connect(fConnectString.c_str());
01216       if (status != DB_SUCCESS)
01217          return status;
01218 
01219       std::vector<std::string> tables;
01220 
01221       status = fSql->ListTables(&tables);
01222       if (status != DB_SUCCESS)
01223          return status;
01224 
01225       for (unsigned i=0; i<tables.size(); i++) {
01226          if (tables[i] == "_history_index") {
01227             fHaveIndex = true;
01228             break;
01229          }
01230       }
01231 
01232       return HS_SUCCESS;
01233    }

int SqlHistory::hs_define_event ( const char *  event_name,
int  ntags,
const TAG  tags[] 
) [virtual]

see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR

Implements MidasHistoryInterface.

Definition at line 1346 of file history_sql.cxx.

01347    {
01348       int status;
01349 
01350       if (fDebug) {
01351          printf("define event [%s] with %d tags:\n", event_name, ntags);
01352          PrintTags(ntags, tags);
01353       }
01354 
01355       // delete all events with the same name
01356       for (unsigned int i=0; i<fEvents.size(); i++)
01357          if (fEvents[i])
01358             if (fEvents[i]->event_name == event_name) {
01359                if (fDebug)
01360                   printf("deleting exising event %s\n", event_name);
01361                delete fEvents[i];
01362                fEvents[i] = NULL;
01363             }
01364 
01365       Event* e = new Event();
01366 
01367       e->event_name = event_name;
01368 
01369       if (!fHaveIndex) {
01370          char buf[1024];
01371          sprintf(buf, "CREATE TABLE _history_index (event_name VARCHAR(256) NOT NULL, table_name VARCHAR(256), tag_name VARCHAR(256), column_name VARCHAR(256), itimestamp INTEGER NOT NULL);");
01372          int status = fSql->Exec(buf);
01373          if (status == DB_KEY_EXIST)
01374             /* do nothing */ ;
01375          else if (status != DB_SUCCESS)
01376             return status;
01377          fHaveIndex = true;
01378       }
01379 
01380       IndexEntry* ie = FindIndexByEventName(event_name);
01381 
01382       if (!ie) {
01383          ReadIndex(fSql, event_name);
01384          ie = FindIndexByEventName(event_name);
01385       }
01386 
01387       if (!ie) {
01388          std::string table_name = MidasNameToSqlName(event_name);
01389 
01390          double now = time(NULL);
01391          
01392          char sss[102400];
01393          sprintf(sss, "INSERT INTO _history_index (event_name, table_name, itimestamp) VALUES (\'%s\', \'%s\', \'%.0f\');",
01394                  event_name,
01395                  table_name.c_str(),
01396                  now);
01397          
01398          int status = fSql->Exec(sss);
01399          if (status != DB_SUCCESS)
01400             return HS_FILE_ERROR;
01401 
01402          ReadIndex(fSql, event_name);
01403          ie = FindIndexByEventName(event_name);
01404       }
01405 
01406       if (!ie) {
01407          cm_msg(MERROR, "hs_define_event", "could not add event name to SQL history index table, see messages");
01408          return HS_FILE_ERROR;
01409       }
01410 
01411       e->table_name = ie->table_name;
01412       e->active = true;
01413 
01414       bool create_event = false;
01415 
01416       int offset = 0;
01417       for (int i=0; i<ntags; i++) {
01418          for (unsigned int j=0; j<tags[i].n_data; j++) {
01419             std::string tagname = tags[i].name;
01420             std::string colname = MidasNameToSqlName(tags[i].name);
01421 
01422             if (tags[i].n_data > 1) {
01423                char s[256];
01424                sprintf(s, "[%d]", j);
01425                tagname += s;
01426                
01427                sprintf(s, "_%d", j);
01428                colname += s;
01429             }
01430 
01431             IndexEntryTag *it = FindIndexByTagName(ie, tagname.c_str());
01432             if (!it) {
01433                // check for duplicate names
01434 
01435                while (1) {
01436                   bool dupe = false;
01437 
01438                   for (unsigned i=0; i<e->tags.size(); i++) {
01439                      if (colname == e->tags[i].column_name) {
01440                         //printf("duplicate name %s\n", colname.c_str());
01441                         dupe = true;
01442                         break;
01443                      }
01444                   }
01445 
01446                   if (!dupe)
01447                      break;
01448 
01449                   char s[256];
01450                   sprintf(s, "_%d", rand());
01451                   colname += s;
01452                }
01453 
01454                // add tag name to column name translation to the history index
01455 
01456                double now = time(NULL);
01457       
01458                char sss[102400];
01459                sprintf(sss, "INSERT INTO _history_index (event_name, tag_name, column_name, itimestamp) VALUES (\'%s\', \'%s\', \'%s\', \'%.0f\');",
01460                        event_name,
01461                        tagname.c_str(),
01462                        colname.c_str(),
01463                        now);
01464                
01465                int status = fSql->Exec(sss);
01466                if (status != DB_SUCCESS)
01467                   return HS_FILE_ERROR;
01468 
01469                // reload the history index
01470                
01471                ReadIndex(fSql, event_name);
01472                ie = FindIndexByEventName(event_name);
01473                assert(ie);
01474                it = FindIndexByTagName(ie, tagname.c_str());
01475             }
01476 
01477             if (!it) {
01478                cm_msg(MERROR, "hs_define_event", "could not add event tags to SQL history index table, see messages");
01479                return HS_FILE_ERROR;
01480             }
01481 
01482             Tag t;
01483             t.column_name = it->column_name;
01484             t.create = false;
01485             t.offset = offset;
01486             t.tag = tags[i];
01487             t.tag.n_data = 1;
01488             e->tags.push_back(t);
01489             int size = tid_size[tags[i].type];
01490             offset += size;
01491          }
01492       }
01493 
01494       std::vector<std::string> columns;
01495 
01496       status = fSql->ListColumns(e->table_name.c_str(), &columns);
01497       if (status != DB_SUCCESS)
01498          return status;
01499 
01500       if (columns.size() <= 0)
01501          create_event = true;
01502 
01503       for (size_t i=0; i<e->tags.size(); i++) {
01504          // check for duplicate column names
01505          for (size_t j=i+1; j<e->tags.size(); j++)
01506             if (e->tags[i].column_name == e->tags[j].column_name) {
01507                cm_msg(MERROR, "hs_define_event", "Error: History event \'%s\': Duplicated column name \'%s\' from tags %d \'%s\' and %d \'%s\'", event_name, e->tags[i].column_name.c_str(), i, e->tags[i].tag.name, j, e->tags[j].tag.name);
01508                e->active = false;
01509                break;
01510             }
01511 
01512          // check if new column needs to be created
01513          bool found = false;
01514          for (size_t j=0; j<columns.size(); j+=2) {
01515             if (e->tags[i].column_name == columns[j]) {
01516                // column exists, check data type
01517                //printf("column \'%s\', data type %s\n", e->tags[i].column_name.c_str(), columns[j+1].c_str());
01518 
01519                if (!isCompatible(e->tags[i].tag.type, columns[j+1].c_str())) {
01520                   cm_msg(MERROR, "hs_define_event", "Error: History event \'%s\': Incompatible data type for tag \'%s\' type \'%s\', SQL column \'%s\' type \'%s\'", event_name, e->tags[i].tag.name, midasTypeName(e->tags[i].tag.type), columns[j].c_str(), columns[j+1].c_str());
01521                   e->active = false;
01522                }
01523 
01524                found = true;
01525                break;
01526             }
01527          }
01528 
01529          if (!found) {
01530             // create it
01531             //printf("column \'%s\', data type %s  --- create!\n", e->tags[i].column_name.c_str(), midasTypeName(e->tags[i].tag.type));
01532             e->tags[i].create = true;
01533          }
01534       }
01535 
01536       if (create_event) {
01537          char buf[1024];
01538          sprintf(buf, "CREATE TABLE %s (_t_time TIMESTAMP NOT NULL, _i_time INTEGER NOT NULL, INDEX (_i_time), INDEX (_t_time));", e->table_name.c_str());
01539          status = fSql->Exec(buf);
01540          if (status != DB_SUCCESS) {
01541             e->active = false;
01542             return HS_FILE_ERROR;
01543          }
01544       }
01545    
01546       for (size_t i=0; i<e->tags.size(); i++)
01547          if (e->tags[i].create) {
01548             char buf[1024];
01549             
01550             sprintf(buf, "ALTER TABLE %s ADD COLUMN %s %s;",
01551                     e->table_name.c_str(),
01552                     e->tags[i].column_name.c_str(),
01553                     midas2sqlType(e->tags[i].tag.type));
01554             
01555             status = fSql->Exec(buf);
01556             
01557             if (status != DB_SUCCESS) {
01558                e->active = false;
01559                return HS_FILE_ERROR;
01560             }
01561          }
01562 
01563       // find empty slot in events list
01564       for (unsigned int i=0; i<fEvents.size(); i++)
01565          if (!fEvents[i]) {
01566             fEvents[i] = e;
01567             e = NULL;
01568             break;
01569          }
01570 
01571       // if no empty slots, add at the end
01572       if (e)
01573          fEvents.push_back(e);
01574 
01575       return HS_SUCCESS;
01576    }

int SqlHistory::hs_disconnect (  )  [virtual]

disconnect from history, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1235 of file history_sql.cxx.

Referenced by hs_connect(), and ~SqlHistory().

01236    {
01237       if (fDebug)
01238          printf("hs_disconnect!\n");
01239       
01240       fSql->Disconnect();
01241 
01242       hs_clear_cache();
01243       
01244       return HS_SUCCESS;
01245    }

int SqlHistory::hs_get_events ( std::vector< std::string > *  pevents  )  [virtual]

get list of all events, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1665 of file history_sql.cxx.

01666    {
01667       if (fDebug)
01668          printf("hs_get_events!\n");
01669 
01670       if (fIndexEvents.size() == 0) {
01671 
01672          if (fDebug)
01673             printf("hs_get_events: reading event names!\n");
01674 
01675          ReadIndex(fSql, NULL);
01676 
01677          std::vector<std::string> tables;
01678          int status = fSql->ListTables(&tables);
01679          if (status != DB_SUCCESS)
01680             return status;
01681  
01682          for (unsigned i=0; i<tables.size(); i++) {
01683             if (tables[i] == "_history_index")
01684                continue;
01685 
01686             IndexEntry* ie = FindIndexByTableName(tables[i].c_str());
01687             if (!ie) {
01688                ReadIndex(fSql, NULL);
01689                ie = FindIndexByTableName(tables[i].c_str());
01690             }
01691 
01692             if (ie)
01693                fIndexEvents.push_back(ie->event_name);
01694             else
01695                fIndexEvents.push_back(tables[i]);
01696          }
01697       }
01698 
01699       assert(pevents);
01700       *pevents = fIndexEvents;
01701       
01702       return HS_SUCCESS;
01703    }

int SqlHistory::hs_get_tags ( const char *  event_name,
std::vector< TAG > *  ptags 
) [virtual]

use event names returned by hs_get_events_odbc(), see hs_get_tags(), returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1705 of file history_sql.cxx.

01706    {
01707       if (fDebug)
01708          printf("hs_get_tags for [%s]\n", event_name);
01709 
01710       assert(ptags);
01711 
01712       IndexEntry* ie = FindIndexByEventName(event_name);
01713 
01714       if (!ie) {
01715          ReadIndex(fSql, event_name);
01716          ie = FindIndexByEventName(event_name);
01717       }
01718 
01719       if (!ie) {
01720          XReadIndex();
01721          ie = FindIndexByEventName(event_name);
01722       }
01723 
01724       if (!ie)
01725          return HS_UNDEFINED_EVENT;
01726 
01727       if (ie->tags_cache.size() == 0) {
01728          if (fDebug)
01729             printf("hs_get_tags reading tags for [%s]\n", event_name);
01730 
01731          std::string tname = ie->table_name;
01732 
01733          std::vector<std::string> columns;
01734 
01735          int status = fSql->ListColumns(tname.c_str(), &columns);
01736          if (status != DB_SUCCESS)
01737             return status;
01738 
01739          if (columns.size() < 1) {
01740             cm_msg(MERROR, "hs_get_tags", "Cannot get columns for table \'%s\', try to reconnect to the database", tname.c_str());
01741 
01742             int status = Reconnect();
01743             if (status != HS_SUCCESS)
01744                return status;
01745 
01746             columns.clear();
01747             status = fSql->ListColumns(tname.c_str(), &columns);      
01748             if (status != DB_SUCCESS)
01749                return status;
01750          }
01751 
01752          TAG* t = (TAG*)malloc(sizeof(TAG)*columns.size());
01753          assert(t);
01754 
01755          for (unsigned int j=0; j<columns.size(); j+=2) {
01756             if (columns[j] == "_t_time")
01757                continue;
01758             if (columns[j] == "_i_time")
01759                continue;
01760 
01761             IndexEntryTag* it = FindIndexByColumnName(ie, columns[j].c_str());
01762 
01763             TAG t;
01764             if (it)
01765                STRLCPY(t.name, it->tag_name.c_str());
01766             else
01767                STRLCPY(t.name, columns[j].c_str());
01768             t.type = sql2midasType(columns[j+1].c_str());
01769             t.n_data = 1;
01770 
01771             ie->tags_cache.push_back(t);
01772          }
01773       }
01774       
01775       for (unsigned i=0; i<ie->tags_cache.size(); i++)
01776          ptags->push_back(ie->tags_cache[i]);
01777 
01778       return HS_SUCCESS;
01779    }

int SqlHistory::hs_read ( time_t  start_time,
time_t  end_time,
time_t  interval,
int  num_var,
const char *  event_name[],
const char *  tag_name[],
const int  tag_index[],
int  num_entries[],
time_t *  time_buffer[],
double *  data_buffer[],
int  st[] 
) [virtual]

see hs_read(), returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2033 of file history_sql.cxx.

02039    {
02040       if (fDebug)
02041          printf("hs_read: %d variables\n", num_var);
02042 
02043       if (!fSql->IsConnected())
02044          return HS_FILE_ERROR;
02045 
02046       for (int i=0; i<num_var; i++) {
02047 
02048          if (event_name[i]==NULL) {
02049             st[i] = HS_UNDEFINED_EVENT;
02050             num_entries[i] = 0;
02051             continue;
02052          }
02053 
02054          st[i] = hs_read(start_time, end_time, interval,
02055                          event_name[i], tag_name[i], tag_index[i],
02056                          &num_entries[i],
02057                          &time_buffer[i], &data_buffer[i]);
02058       }
02059       
02060       return HS_SUCCESS;
02061    }

int SqlHistory::hs_read ( double  start_time,
double  end_time,
double  interval,
const char *  event_name,
const char *  tag_name,
int  tag_index,
int *  num_entries,
time_t **  time_buffer,
double **  data_buffer 
)

Definition at line 1854 of file history_sql.cxx.

Referenced by hs_read(), and hs_read_old_style().

01858    {
01859       *num_entries = 0;
01860       *time_buffer = NULL;
01861       *data_buffer = NULL;
01862 
01863       if (fDebug)
01864          printf("hs_read: event [%s], tag [%s], index %d, start %f, end %f, dt %f, interval %f, max points %f\n",
01865                 event_name, tag_name, tag_index,
01866                 start_time, end_time, end_time-start_time, interval, (end_time-start_time)/interval);
01867 
01868       if (event_name==NULL)
01869          return HS_SUCCESS;
01870 
01871       IndexEntry*ie = FindIndexByEventName(event_name);
01872 
01873       if (!ie) {
01874          ReadIndex(fSql, event_name);
01875          ie = FindIndexByEventName(event_name);
01876       }
01877 
01878       if (!ie) {
01879          XReadIndex();
01880          ie = FindIndexByEventName(event_name);
01881       }
01882 
01883       IndexEntryTag *it = NULL;
01884 
01885       if (ie)
01886          it = FindIndexByTagName(ie, tag_name);
01887 
01888       if (ie && !it) { // maybe this is an array without "Names"?
01889          char xxx[256];
01890          sprintf(xxx, "%s[%d]", tag_name, tag_index);
01891          it = FindIndexByTagName(ie, xxx);
01892       }
01893          
01894       // new-style event name: "equipment_name/variable_name:tag_name"
01895       // old style event name: "equipment_name:tag_name" ("variable_name" is missing)
01896       bool oldStyleEventName = (strchr(event_name, '/')==NULL);
01897 
01898       if (oldStyleEventName)
01899          if (!ie || !it) {
01900             return hs_read_old_style(start_time, end_time, interval,
01901                                      event_name, tag_name, tag_index,
01902                                      num_entries,
01903                                      time_buffer, data_buffer);
01904          }
01905 
01906       if (!it)
01907          return HS_UNDEFINED_VAR;
01908 
01909       assert(ie);
01910       assert(it);
01911 
01912       std::string tname = ie->table_name;
01913       std::string cname = it->column_name;
01914 
01915       char cmd[256];
01916       sprintf(cmd, "SELECT _i_time, %s FROM %s WHERE _i_time>=%.0f and _i_time<=%.0f ORDER BY _i_time;",
01917               cname.c_str(), tname.c_str(),
01918               start_time, end_time);
01919            
01920       int status = fSql->Exec(cmd);
01921 
01922       if (fDebug) {
01923          printf("hs_read: event \"%s\", tag \"%s\", index %d: Read table \"%s\" column \"%s\": status %d, nrows: %d, ncolumns: %d\n",
01924                 event_name, tag_name, tag_index,
01925                 tname.c_str(),
01926                 cname.c_str(),
01927                 status,
01928                 fSql->GetNumRows(),
01929                 fSql->GetNumColumns()
01930                 );
01931       }
01932 
01933       if (status != SUCCESS) {
01934          return HS_FILE_ERROR;
01935       }
01936 
01937       if (fSql->GetNumRows() == 0) {
01938          fSql->Done();
01939 
01940          if (oldStyleEventName) {
01941             return hs_read_old_style(start_time, end_time, interval,
01942                                      event_name, tag_name, tag_index,
01943                                      num_entries,
01944                                      time_buffer, data_buffer);
01945          }
01946 
01947          return HS_SUCCESS;
01948       }
01949 
01950       int nrows = fSql->GetNumRows();
01951       int ncols = fSql->GetNumColumns();
01952 
01953       if (nrows < 0)
01954          return HS_FILE_ERROR;
01955 
01956       if (ncols < 1)
01957          return HS_FILE_ERROR;
01958 
01959       *num_entries = 0;
01960       *time_buffer = (time_t*)malloc(nrows * sizeof(time_t));
01961       *data_buffer = (double*)malloc(nrows * sizeof(double));
01962   
01963       /* Loop through the rows in the result-set */
01964       int row = 0;
01965       time_t tt = 0;
01966       int ann = 0;
01967       double att = 0;
01968       double avv = 0;
01969       while (1) {
01970          status = fSql->Fetch();
01971          if (status != DB_SUCCESS)
01972             break;
01973 
01974          time_t t = 0;
01975          double v = 0;
01976      
01977          const char* timedata = fSql->GetColumn(1);
01978          if (timedata)
01979             t = atoi(timedata);
01980      
01981          const char* valuedata = fSql->GetColumn(2);
01982          if (valuedata)
01983             v = atof(valuedata);
01984      
01985          if (t < start_time || t > end_time)
01986             continue;
01987      
01988          //printf("Row %d, time %d, value %f\n", row, t, v);
01989          //printf("tt: %d, ann: %d\n", tt, ann);
01990      
01991          if (tt == 0 || t >= tt + interval) {
01992         
01993             if (ann > 0) {
01994                assert(row < nrows);
01995            
01996                (*time_buffer)[row] = (time_t)(att/ann);
01997                (*data_buffer)[row] = avv/ann;
01998            
01999                row++;
02000                (*num_entries) = row;
02001             }
02002 
02003             ann = 0;
02004             att = 0;
02005             avv = 0;
02006             tt  = t;
02007          
02008          }
02009 
02010          ann++;
02011          att += t;
02012          avv += v;
02013       }
02014 
02015       if (ann > 0) {
02016          assert(row < nrows);
02017 
02018          (*time_buffer)[row] = (time_t)(att/ann);
02019          (*data_buffer)[row] = avv/ann;
02020      
02021          row++;
02022          (*num_entries) = row;
02023       }
02024 
02025       fSql->Done();
02026 
02027       if (fDebug)
02028          printf("hs_read: return %d entries\n", *num_entries);
02029 
02030       return HS_SUCCESS;
02031    }

int SqlHistory::hs_read_old_style ( double  start_time,
double  end_time,
double  interval,
const char *  event_name,
const char *  tag_name,
int  var_index,
int *  num_entries,
time_t **  time_buffer,
double **  data_buffer 
)

Definition at line 1781 of file history_sql.cxx.

Referenced by hs_read().

01785    {
01786       if (fDebug) {
01787          printf("hs_read_old_style: event \"%s\", tag \"%s\"\n", event_name, tag_name);
01788       }
01789 
01790       ReadIndex(fSql, NULL);
01791 
01792       for (unsigned e=0; e<gHistoryIndex.size(); e++) {
01793 
01794          const char* s = gHistoryIndex[e]->event_name.c_str();
01795 
01796          bool match = false;
01797          for (int j=0; s[j]; j++) {
01798 
01799             if ((event_name[j]==0) && (s[j]=='/')) {
01800                match = true;
01801                break;
01802             }
01803 
01804             if ((event_name[j]==0) && (s[j]=='_')) {
01805                match = true;
01806                break;
01807             }
01808 
01809             if (event_name[j]==0) {
01810                match = false;
01811                break;
01812             }
01813 
01814             if (tolower(event_name[j]) != tolower(s[j])) {
01815                match = false;
01816                break;
01817             }
01818          }
01819 
01820          //printf("try %s, match %d\n", s, match);
01821 
01822          if (match) {
01823             bool found_tag = false;
01824             IndexEntry *ie = gHistoryIndex[e];
01825             for (unsigned v=0; v<ie->tags.size(); v++) {
01826                //printf("try tag [%s] looking for [%s]\n", ie->tags[v].tag_name.c_str(), tag_name);
01827                if (equal_ustring(tag_name, ie->tags[v].tag_name.c_str())) {
01828                   found_tag = true;
01829                   break;
01830                }
01831             }
01832 
01833             if (!found_tag)
01834                match = false;
01835          }
01836 
01837          if (match) {
01838             if (fDebug)
01839                printf("hs_read_old_style: event \"%s\", tag \"%s\", try matching event \'%s\'\n", event_name, tag_name, s);
01840 
01841             int status = hs_read(start_time, end_time, interval,
01842                                  s, tag_name, var_index,
01843                                  num_entries,
01844                                  time_buffer, data_buffer);
01845 
01846             if (status==HS_SUCCESS && *num_entries>0)
01847                return HS_SUCCESS;
01848          }
01849       }
01850 
01851       return HS_UNDEFINED_VAR;
01852    }

int SqlHistory::hs_set_debug ( int  debug  )  [virtual]

set debug level, returns previous debug level

Implements MidasHistoryInterface.

Definition at line 1188 of file history_sql.cxx.

01189    {
01190       int old = fDebug;
01191       fDebug = debug;
01192       gTrace = debug;
01193       fSql->SetDebug(debug);
01194       return old;
01195    }

int SqlHistory::hs_write_event ( const char *  event_name,
time_t  timestamp,
int  buffer_size,
const char *  buffer 
) [virtual]

see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR

Implements MidasHistoryInterface.

Definition at line 1578 of file history_sql.cxx.

01579    {
01580       if (fDebug)
01581          printf("hs_write_event: write event \'%s\', time %d, size %d\n", event_name, (int)timestamp, buffer_size);
01582 
01583       // if disconnected, try to reconnect
01584 
01585       if (!fSql->IsConnected()) {
01586          time_t now = time(NULL);
01587 
01588          // too early to try reconnecting?
01589          if (fConnectRetry !=0 && now < fNextConnect) {
01590             return HS_FILE_ERROR;
01591          }
01592 
01593          cm_msg(MINFO, "hs_write_event", "Trying to reconnect to SQL database \'%s\'", fConnectString.c_str());
01594 
01595          int status = fSql->Connect(fConnectString.c_str());
01596 
01597          if (status != DB_SUCCESS) {
01598 
01599             // first retry in 5 seconds
01600             if (fConnectRetry == 0)
01601                fConnectRetry = 5;
01602 
01603             fNextConnect = now + fConnectRetry;
01604 
01605             // exponential backoff
01606             fConnectRetry *= 2;
01607 
01608             // but no more than every 10 minutes
01609             if (fConnectRetry > 10*60)
01610                fConnectRetry = 10*60;
01611 
01612             return HS_FILE_ERROR;
01613          }
01614 
01615          cm_msg(MINFO, "hs_write_event", "Reconnected to SQL database \'%s\'", fConnectString.c_str());
01616       }
01617 
01618       fNextConnect = 0;
01619       fConnectRetry = 0;
01620 
01621       Event *e = NULL;
01622 
01623       // find this event
01624       for (size_t i=0; i<fEvents.size(); i++)
01625          if (fEvents[i]->event_name == event_name) {
01626             e = fEvents[i];
01627             break;
01628          }
01629 
01630       // not found
01631       if (!e)
01632          return HS_UNDEFINED_EVENT;
01633 
01634       // deactivated because of error?
01635       if (!e->active)
01636          return HS_FILE_ERROR;
01637 
01638       int status = WriteEvent(fSql, e, timestamp, buffer, buffer_size);
01639 
01640       // if could not write to SQL?
01641       if (status != HS_SUCCESS) {
01642 
01643          // if lost SQL connection, try again later
01644 
01645          if (!fSql->IsConnected()) {
01646             return HS_FILE_ERROR;
01647          }
01648 
01649          // otherwise, deactivate this event
01650 
01651          e->active = false;
01652 
01653          cm_msg(MERROR, "hs_write_event", "Event \'%s\' disabled after write error %d into SQL database \'%s\'", event_name, status, fConnectString.c_str());
01654 
01655          return HS_FILE_ERROR;
01656       }
01657 
01658       return HS_SUCCESS;
01659    }

int SqlHistory::Reconnect (  ) 

Definition at line 1247 of file history_sql.cxx.

Referenced by hs_get_tags().

01248    {
01249       if (fDebug)
01250          printf("Reconnect to SQL database!\n");
01251       
01252       fSql->Disconnect();
01253       fSql->Connect(fConnectString.c_str());
01254       if (!fSql->IsConnected()) {
01255          return HS_FILE_ERROR;
01256       }
01257       
01258       return HS_SUCCESS;
01259    }

int SqlHistory::XReadIndex (  ) 

Definition at line 1285 of file history_sql.cxx.

Referenced by hs_get_tags(), and hs_read().

01286    {
01287       if (fHaveXIndex)
01288          return HS_SUCCESS;
01289 
01290       if (fDebug)
01291          printf("XReadIndex!\n");
01292 
01293       std::vector<std::string> tables;
01294 
01295       int status = fSql->ListTables(&tables);
01296       if (status != DB_SUCCESS)
01297          return status;
01298       
01299       for (unsigned i=0; i<tables.size(); i++) {
01300          if (tables[i] == "_history_index")
01301             continue;
01302 
01303          IndexEntry* ie = NULL; //FindEventName(tables[i].c_str());
01304 
01305          if (!ie) {
01306             ie = new IndexEntry;
01307 
01308             ie->table_name = tables[i];
01309             ie->event_name = ie->table_name;
01310 
01311             gHistoryIndex.push_back(ie);
01312          }
01313 
01314          std::vector<std::string> columns;
01315 
01316          status = fSql->ListColumns(ie->table_name.c_str(), &columns);
01317          if (status != DB_SUCCESS)
01318             return status;
01319 
01320          for (unsigned int j=0; j<columns.size(); j+=2) {
01321             if (columns[j] == "_t_time")
01322                continue;
01323             if (columns[j] == "_i_time")
01324                continue;
01325 
01326             IndexEntryTag t;
01327             t.column_name = columns[j];
01328             t.tag_name = t.column_name;
01329             t.timestamp = 0;
01330 
01331             ie->tags.push_back(t);
01332          }
01333       }
01334 
01335       fHaveXIndex = true;
01336 
01337       //PrintIndex();
01338 
01339       return HS_SUCCESS;
01340    }


Field Documentation

int SqlHistory::fConnectRetry

Definition at line 1164 of file history_sql.cxx.

Referenced by hs_write_event(), and SqlHistory().

std::string SqlHistory::fConnectString

Definition at line 1163 of file history_sql.cxx.

Referenced by hs_connect(), hs_write_event(), and Reconnect().

int SqlHistory::fDebug

Definition at line 1162 of file history_sql.cxx.

std::vector<Event*> SqlHistory::fEvents

Definition at line 1166 of file history_sql.cxx.

Referenced by hs_define_event(), and hs_write_event().

bool SqlHistory::fHaveIndex

Definition at line 1168 of file history_sql.cxx.

Referenced by hs_connect(), hs_define_event(), and SqlHistory().

bool SqlHistory::fHaveXIndex

Definition at line 1169 of file history_sql.cxx.

Referenced by hs_clear_cache(), SqlHistory(), and XReadIndex().

std::vector<std::string> SqlHistory::fIndexEvents

Definition at line 1167 of file history_sql.cxx.

Referenced by hs_clear_cache(), and hs_get_events().

int SqlHistory::fNextConnect

Definition at line 1165 of file history_sql.cxx.

Referenced by hs_write_event(), and SqlHistory().

SqlBase* SqlHistory::fSql

Definition at line 1161 of file history_sql.cxx.

Referenced by hs_connect(), hs_define_event(), hs_disconnect(), hs_get_events(), hs_get_tags(), hs_read(), hs_read_old_style(), hs_set_debug(), hs_write_event(), Reconnect(), SqlHistory(), XReadIndex(), and ~SqlHistory().


Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk