Definition in file history_odbc.h.
Go to the source code of this file.
Functions | |
int | hs_connect_odbc (const char *odbc_dsn) |
int | hs_disconnect_odbc () |
int | hs_debug_odbc (int debug) |
int | hs_set_alarm_odbc (const char *alarm_name) |
int | hs_define_event_odbc (const char *event_name, const TAG tags[], int tags_size) |
int | hs_write_event_odbc (const char *event_name, time_t timestamp, const char *buffer, int buffer_size) |
int | hs_get_tags_odbc (const char *event_name, int *n_tags, TAG **tags) |
int | hs_read_odbc (time_t start_time, time_t end_time, time_t interval, const char *event_name, const char *tag_name, int var_index, int *num_entries, time_t **time_buffer, double **data_buffer) |
int hs_connect_odbc | ( | const char * | odbc_dsn | ) |
connect to given ODBC DSN, defined in $HOME/.odbc.ini, returns HS_SUCCESS
Definition at line 848 of file history_odbc.cxx.
00849 { 00850 int status; 00851 00852 if (gSql && gSql->IsConnected()) 00853 if (strcmp(gOdbcDsn.c_str(), odbc_dsn) == 0) 00854 return HS_SUCCESS; 00855 00856 if (gSql) 00857 hs_disconnect_odbc(); 00858 00859 assert(!gSql); 00860 00861 gOdbcDsn = odbc_dsn; 00862 00863 if (gTrace) 00864 printf("hs_connect_odbc: set DSN to \'%s\'\n", gOdbcDsn.c_str()); 00865 00866 if (gOdbcDsn[0] == '/') 00867 gSql = new SqlStdout(); 00868 else 00869 gSql = new SqlODBC(); 00870 00871 status = gSql->Connect(gOdbcDsn.c_str()); 00872 if (status != 0) 00873 return HS_FILE_ERROR; 00874 00875 return HS_SUCCESS; 00876 }
int hs_debug_odbc | ( | int | debug | ) |
int hs_define_event_odbc | ( | const char * | event_name, | |
const TAG | tags[], | |||
int | tags_size | |||
) |
see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR
Definition at line 922 of file history_odbc.cxx.
00923 { 00924 assert(gSql); 00925 00926 int ntags = tags_size/sizeof(TAG); 00927 00928 if (gTrace) { 00929 printf("define event [%s] with %d tags:\n", event_name, ntags); 00930 PrintTags(ntags, tags); 00931 } 00932 00933 // delete all events with the same name 00934 for (unsigned int i=0; i<gEvents.size(); i++) 00935 if (gEvents[i]) 00936 if (gEvents[i]->event_name == event_name) { 00937 printf("deleting exising event %s\n", event_name); 00938 delete gEvents[i]; 00939 gEvents[i] = NULL; 00940 } 00941 00942 Event* e = new Event(); 00943 00944 e->event_name = event_name; 00945 e->table_name = eventName2tableName(event_name); 00946 e->active = true; 00947 e->create = false; 00948 00949 int offset = 0; 00950 for (int i=0; i<ntags; i++) { 00951 for (unsigned int j=0; j<tags[i].n_data; j++) { 00952 Tag t; 00953 t.create = false; 00954 if (tags[i].n_data == 1) 00955 t.column_name = tagName2columnName(tags[i].name); 00956 else { 00957 char s[256]; 00958 sprintf(s, "_%d", j); 00959 t.column_name = tagName2columnName(tags[i].name) + s; 00960 } 00961 t.offset = offset; 00962 t.tag = tags[i]; 00963 t.tag.n_data = 1; 00964 e->tags.push_back(t); 00965 int size = tid_size[tags[i].type]; 00966 offset += size; 00967 } 00968 } 00969 00970 std::vector<std::string> columns = gSql->ListColumns(e->table_name.c_str()); 00971 00972 if (columns.size() <= 0) 00973 e->create = true; 00974 00975 for (size_t i=0; i<e->tags.size(); i++) { 00976 // check for duplicate column names 00977 for (size_t j=i+1; j<e->tags.size(); j++) 00978 if (e->tags[i].column_name == e->tags[j].column_name) { 00979 cm_msg(MERROR, "hs_define_event_odbc", "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); 00980 e->active = false; 00981 break; 00982 } 00983 00984 // check if new column needs to be created 00985 bool found = false; 00986 for (size_t j=0; j<columns.size(); j+=2) { 00987 if (e->tags[i].column_name == columns[j]) { 00988 // column exists, check data type 00989 //printf("column \'%s\', data type %s\n", e->tags[i].column_name.c_str(), columns[j+1].c_str()); 00990 00991 if (!isCompatible(e->tags[i].tag.type, columns[j+1].c_str())) { 00992 cm_msg(MERROR, "hs_define_event_odbc", "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()); 00993 e->active = false; 00994 } 00995 00996 found = true; 00997 break; 00998 } 00999 } 01000 01001 if (!found) { 01002 // create it 01003 //printf("column \'%s\', data type %s --- create!\n", e->tags[i].column_name.c_str(), midasTypeName(e->tags[i].tag.type)); 01004 e->tags[i].create = true; 01005 } 01006 } 01007 01008 int status = CreateEvent(gSql, e); 01009 01010 if (status != 0) { 01011 // if cannot create event in SQL database, disable this event and carry on. 01012 01013 e->active = false; 01014 01015 if (gAlarmName.length() > 0) { 01016 char buf[256]; 01017 sprintf(buf, "%s cannot define history event \'%s\', see messages", gAlarmName.c_str(), e->event_name.c_str()); 01018 al_trigger_alarm(gAlarmName.c_str(), buf, "Alarm", "", AT_INTERNAL); 01019 } 01020 } 01021 01022 // find empty slot in events list 01023 for (unsigned int i=0; i<gEvents.size(); i++) 01024 if (!gEvents[i]) { 01025 gEvents[i] = e; 01026 e = NULL; 01027 break; 01028 } 01029 01030 // if no empty slots, add at the end 01031 if (e) 01032 gEvents.push_back(e); 01033 01034 return HS_SUCCESS; 01035 }
int hs_disconnect_odbc | ( | ) |
disconnect from ODBC, returns HS_SUCCESS
Definition at line 878 of file history_odbc.cxx.
Referenced by hs_connect_odbc().
00879 { 00880 if (gTrace) 00881 printf("hs_disconnect_odbc!\n"); 00882 00883 if (gSql) { 00884 gSql->Disconnect(); 00885 delete gSql; 00886 gSql = NULL; 00887 } 00888 00889 return HS_SUCCESS; 00890 }
int hs_get_tags_odbc | ( | const char * | event_name, | |
int * | n_tags, | |||
TAG ** | tags | |||
) |
use event names returned by hs_get_events_odbc(), see hs_get_tags(), returns HS_SUCCESS
Definition at line 1125 of file history_odbc.cxx.
01126 { 01127 assert(gSql); 01128 01129 *n_tags = 0; 01130 *tags = NULL; 01131 01132 std::string tname = eventName2tableName(event_name); 01133 01134 std::vector<std::string> columns = gSql->ListColumns(tname.c_str()); 01135 01136 if (columns.size() < 1) { 01137 cm_msg(MERROR, "hs_get_tags_odbc", "Cannot get columns for table \'%s\', try to reconnect to the database", tname.c_str()); 01138 01139 gSql->Disconnect(); 01140 gSql->Connect(gOdbcDsn.c_str()); 01141 if (!gSql->IsConnected()) { 01142 01143 if (gAlarmName.length() > 0) { 01144 char buf[256]; 01145 sprintf(buf, "%s lost connection to the history database", gAlarmName.c_str()); 01146 al_trigger_alarm(gAlarmName.c_str(), buf, "Alarm", "", AT_INTERNAL); 01147 } 01148 01149 return HS_FILE_ERROR; 01150 } 01151 01152 columns = gSql->ListColumns(tname.c_str()); 01153 } 01154 01155 TAG* t = (TAG*)malloc(sizeof(TAG)*columns.size()); 01156 assert(t); 01157 01158 int n=0; 01159 for (unsigned int j=0; j<columns.size(); j+=2) { 01160 if (columns[j] == "_t_time") 01161 continue; 01162 if (columns[j] == "_i_time") 01163 continue; 01164 STRLCPY(t[n].name, columns[j].c_str()); 01165 t[n].type = sql2midasType(columns[j+1].c_str()); 01166 t[n].n_data = 1; 01167 n++; 01168 } 01169 01170 if (0) { 01171 printf("event [%s] table [%s], tags: %d\n", event_name, tname.c_str(), n); 01172 PrintTags(n, t); 01173 } 01174 01175 *n_tags = n; 01176 *tags = t; 01177 01178 return HS_SUCCESS; 01179 }
int hs_read_odbc | ( | time_t | start_time, | |
time_t | end_time, | |||
time_t | interval, | |||
const char * | event_name, | |||
const char * | tag_name, | |||
int | var_index, | |||
int * | num_entries, | |||
time_t ** | time_buffer, | |||
double ** | data_buffer | |||
) |
see hs_read(), returns HS_SUCCESS
Definition at line 1181 of file history_odbc.cxx.
01185 { 01186 assert(gSql); 01187 01188 *num_entries = 0; 01189 *time_buffer = NULL; 01190 *data_buffer = NULL; 01191 01192 //printf("start %d, end %d, dt %d, interval %d, max points %d\n", start_time, end_time, end_time-start_time, interval, (end_time-start_time)/interval); 01193 01194 std::string ename = eventName2tableName(event_name); 01195 std::string tname = tagName2columnName(tag_name); 01196 01197 int status = 1; 01198 01199 std::vector<std::string> tables = gSql->ListTables(); 01200 01201 if (tables.size() <= 1) { 01202 cm_msg(MERROR, "hs_read_odbc", "ListTables() returned nothing, trying to reconnect to the database"); 01203 01204 gSql->Disconnect(); 01205 gSql->Connect(gOdbcDsn.c_str()); 01206 if (!gSql->IsConnected()) { 01207 01208 if (gAlarmName.length() > 0) { 01209 char buf[256]; 01210 sprintf(buf, "%s lost connection to the history database", gAlarmName.c_str()); 01211 al_trigger_alarm(gAlarmName.c_str(), buf, "Alarm", "", AT_INTERNAL); 01212 } 01213 01214 return HS_FILE_ERROR; 01215 } 01216 01217 tables = gSql->ListTables(); 01218 } 01219 01220 int len = strlen(event_name); 01221 for (unsigned int i=0; i<tables.size(); i++) { 01222 //printf("table %s\n", tables[i].c_str()); 01223 01224 const char* t = tables[i].c_str(); 01225 const char* s = strstr(t, ename.c_str()); 01226 01227 if (s==t && (t[len]=='_'||t[len]==0)) { 01228 01229 bool found = false; 01230 std::vector<std::string> columns = gSql->ListColumns(tables[i].c_str()); 01231 for (unsigned int j=0; j<columns.size(); j+=2) { 01232 //printf("column %s\n", columns[j].c_str()); 01233 if (columns[j] == tname) { 01234 found = true; 01235 break; 01236 } 01237 } 01238 01239 if (found) { 01240 char cmd[256]; 01241 sprintf(cmd, "SELECT _i_time, %s FROM %s where _i_time>=%d and _i_time<=%d;", 01242 tname.c_str(), tables[i].c_str(), 01243 (int)start_time, (int)end_time); 01244 01245 status = gSql->Exec(cmd); 01246 01247 if (gTrace) { 01248 printf("hs_read_odbc: event %s, name %s, index %d: Read table %s: status %d, nrows: %d\n", 01249 event_name, tag_name, var_index, 01250 tables[i].c_str(), 01251 status, 01252 gSql->GetNumRows()); 01253 } 01254 01255 if (status) 01256 continue; 01257 01258 if (gSql->GetNumRows() == 0) { 01259 gSql->Done(); 01260 status = SQL_NO_DATA; 01261 continue; 01262 } 01263 01264 break; 01265 } 01266 } 01267 } 01268 01269 if (status == SQL_NO_DATA) 01270 return HS_SUCCESS; 01271 01272 if (status) { 01273 if (gTrace) 01274 printf("hs_read_odbc: event %s, name %s, index %d, could not find the right table? status %d\n", 01275 event_name, tag_name, var_index, 01276 status); 01277 01278 return HS_FILE_ERROR; 01279 } 01280 01281 int nrows = gSql->GetNumRows(); 01282 int ncols = gSql->GetNumColumns(); 01283 01284 if (nrows == 0) 01285 return HS_SUCCESS; 01286 01287 if (gTrace) 01288 printf("hs_read_odbc: event %s, name %s, index %d, nrows: %d, ncols: %d\n", 01289 event_name, tag_name, var_index, 01290 nrows, ncols); 01291 01292 if (nrows < 0) 01293 return HS_FILE_ERROR; 01294 01295 if (ncols < 1) 01296 return HS_FILE_ERROR; 01297 01298 *num_entries = 0; 01299 *time_buffer = (time_t*)malloc(nrows * sizeof(time_t)); 01300 *data_buffer = (double*)malloc(nrows * sizeof(double)); 01301 01302 /* Loop through the rows in the result-set */ 01303 int row = 0; 01304 time_t tt = 0; 01305 int ann = 0; 01306 double att = 0; 01307 double avv = 0; 01308 while (gSql->Fetch()) { 01309 time_t t = 0; 01310 double v = 0; 01311 01312 const char* timedata = gSql->GetColumn(1); 01313 if (timedata) 01314 t = atoi(timedata); 01315 01316 const char* valuedata = gSql->GetColumn(2); 01317 if (valuedata) 01318 v = atof(valuedata); 01319 01320 if (t < start_time || t > end_time) 01321 continue; 01322 01323 //printf("Row %d, time %d, value %f\n", row, t, v); 01324 //printf("tt: %d, ann: %d\n", tt, ann); 01325 01326 if (tt == 0 || t >= tt + interval) { 01327 01328 if (ann > 0) { 01329 assert(row < nrows); 01330 01331 (*time_buffer)[row] = (time_t)(att/ann); 01332 (*data_buffer)[row] = avv/ann; 01333 01334 row++; 01335 (*num_entries) = row; 01336 } 01337 01338 ann = 0; 01339 att = 0; 01340 avv = 0; 01341 tt = t; 01342 01343 } 01344 01345 ann++; 01346 att += t; 01347 avv += v; 01348 } 01349 01350 if (ann > 0) { 01351 assert(row < nrows); 01352 01353 (*time_buffer)[row] = (time_t)(att/ann); 01354 (*data_buffer)[row] = avv/ann; 01355 01356 row++; 01357 (*num_entries) = row; 01358 } 01359 01360 gSql->Done(); 01361 01362 if (gTrace) 01363 printf("hs_read_odbc: return %d events\n", *num_entries); 01364 01365 return HS_SUCCESS; 01366 }
int hs_set_alarm_odbc | ( | const char * | alarm_name | ) |
set alarm name for history failures. Use NULL to disable alarms
Definition at line 839 of file history_odbc.cxx.
00840 { 00841 if (alarm_name) 00842 gAlarmName = alarm_name; 00843 else 00844 gAlarmName = ""; 00845 return HS_SUCCESS; 00846 }
int hs_write_event_odbc | ( | const char * | event_name, | |
time_t | timestamp, | |||
const char * | buffer, | |||
int | buffer_size | |||
) |
see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
Definition at line 1037 of file history_odbc.cxx.
01038 { 01039 if (gTrace) 01040 printf("write event [%s] size %d\n", event_name, buffer_size); 01041 01042 assert(gSql); 01043 01044 // if disconnected, try to reconnect 01045 01046 if (!gSql->IsConnected()) { 01047 time_t now = time(NULL); 01048 01049 // too early to try reconnecting? 01050 if (gConnectRetry!=0 && now < gNextConnect) { 01051 return HS_FILE_ERROR; 01052 } 01053 01054 int status = gSql->Connect(gOdbcDsn.c_str()); 01055 01056 if (status != 0) { 01057 01058 // first retry in 5 seconds 01059 if (gConnectRetry == 0) 01060 gConnectRetry = 5; 01061 01062 gNextConnect = now + gConnectRetry; 01063 01064 // exponential backoff 01065 gConnectRetry *= 2; 01066 01067 // but no more than every 10 minutes 01068 if (gConnectRetry > 10*60) 01069 gConnectRetry = 10*60; 01070 01071 return HS_FILE_ERROR; 01072 } 01073 } 01074 01075 gNextConnect = 0; 01076 gConnectRetry = 0; 01077 01078 Event *e = NULL; 01079 01080 // find this event 01081 for (size_t i=0; i<gEvents.size(); i++) 01082 if (gEvents[i]->event_name == event_name) { 01083 e = gEvents[i]; 01084 break; 01085 } 01086 01087 // not found 01088 if (!e) 01089 return HS_FILE_ERROR; 01090 01091 // deactivated because of error? 01092 if (!e->active) 01093 return HS_FILE_ERROR; 01094 01095 int status = WriteEvent(gSql, e, timestamp, buffer, buffer_size); 01096 01097 // if could not write to SQL? 01098 if (status != 0) { 01099 01100 // if lost SQL connection, try again later 01101 if (!gSql->IsConnected()) { 01102 return HS_FILE_ERROR; 01103 } 01104 01105 // otherwise, deactivate this event, raise alarm 01106 01107 e->active = 0; 01108 01109 if (gAlarmName.length() > 0) { 01110 char buf[256]; 01111 sprintf(buf, "%s cannot write history event \'%s\', see messages", gAlarmName.c_str(), e->event_name.c_str()); 01112 al_trigger_alarm(gAlarmName.c_str(), buf, "Alarm", "", AT_INTERNAL); 01113 } 01114 01115 return HS_FILE_ERROR; 01116 } 01117 01118 return HS_SUCCESS; 01119 }