MIDAS
Loading...
Searching...
No Matches
mh2sql.cxx
Go to the documentation of this file.
1//
2// mh2sql: import midas history into an SQL database
3//
4// Author: Konstantin Olchanski / TRIUMF, August-2008
5//
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <stdint.h>
10#include <string.h>
11#include <assert.h>
12#include <errno.h>
13
14#include "midas.h"
15#include "history.h"
16#include "mstrlcpy.h"
17
18#include <map>
19
20std::map<int,const char*> gEventName;
21
22bool print_empty = false;
23bool print_dupe = false;
24bool print_string = false;
25
26bool had_empty = false;
27bool had_dupe = false;
28bool had_string = false;
29
30bool report_empty = true;
31bool report_dupe = true;
32bool report_string = true;
33
34int copyHstFile(const char* filename, FILE*f, MidasHistoryInterface *mh)
35{
36 assert(f!=NULL);
37
38 char *buf = NULL;
39 int bufSize = 0;
40
41 while (1)
42 {
44
45 int rd = fread(&rec, sizeof(rec), 1, f);
46 if (!rd)
47 break;
48
49#if 0
50 printf("HIST_RECORD:\n");
51 printf(" Record type: 0x%x\n", rec.record_type);
52 printf(" Event ID: %d\n", rec.event_id);
53 printf(" Time: %d\n", rec.time);
54 printf(" Offset: 0x%x\n", rec.def_offset);
55 printf(" Size: 0x%x\n", rec.data_size);
56#endif
57
58 switch (rec.record_type)
59 {
60 default:
61 fprintf(stderr, "Error: %s: Unexpected record type: 0x%x\n", filename, rec.record_type);
62 if (buf)
63 free(buf);
64 return -1;
65 break;
66
67 case 0x46445348: // RT_DEF:
68 {
69 char event_name[NAME_LENGTH+1];
70 rd = fread(event_name, 1, NAME_LENGTH, f);
71
72 if (rd != NAME_LENGTH) {
73 fprintf(stderr, "Error: %s: Error reading RT_DEF record, fread(%d) returned %d, errno %d (%s)\n", filename, NAME_LENGTH, rd, errno, strerror(errno));
74 if (buf)
75 free(buf);
76 return -1;
77 break;
78 }
79
80 // make sure event name is NUL terminated
81 event_name[NAME_LENGTH] = 0;
82
83 if (strlen(event_name) == NAME_LENGTH) {
84 //fprintf(stderr, "Warning: %s: Truncated event length in RT_DEF record: [%s]\n", filename, event_name);
85 }
86
87 int size = rec.data_size;
88 int ntags = size/sizeof(TAG);
89
90 // printf("Event %d, \"%s\", size %d, %d tags.\n", rec.event_id, event_name, size, ntags);
91
92 if (!((size > 0) &&
93 (size < 1*1024*1024) &&
94 (size == ntags*(int)sizeof(TAG)))) {
95
96 fprintf(stderr, "Error: %s: Invalid length of RT_DEF record: %d (0x%x)\n", filename, size, size);
97 if (buf)
98 free(buf);
99 return -1;
100 break;
101 }
102
103 TAG *tags = new TAG[ntags];
104 rd = fread(tags, 1, size, f);
105
106 if (rd != size) {
107 fprintf(stderr, "Error: %s: Error reading RT_DEF record, fread(%d) returned %d, errno %d (%s)\n", filename, size, rd, errno, strerror(errno));
108 if (buf)
109 free(buf);
110 return -1;
111 break;
112 }
113
114 // need to sanitize the tag names
115
116 for (int i=0; i<ntags; i++) {
117 if (tags[i].type == TID_STRING) {
118 if (print_string)
119 fprintf(stderr, "Warning: %s: Event \"%s\": Fixed by truncation at forbidden TID_STRING tag \"%s\" at index %d\n", filename, event_name, tags[i].name, i);
120 ntags = i;
121 had_string = true;
122 break;
123 }
124
125 if (strlen(tags[i].name) < 1) {
126 sprintf(tags[i].name, "empty_%d", i);
127 if (print_empty)
128 fprintf(stderr, "Warning: %s: Event \"%s\": Fixed empty tag name for tag %d: replaced with \"%s\"\n", filename, event_name, i, tags[i].name);
129 had_empty = true;
130 }
131
132 for (int j=i+1; j<ntags; j++) {
133 if (strcmp(tags[i].name, tags[j].name) == 0) {
134 char str[256];
135 sprintf(str, "_dup%d", j);
136 mstrlcat(tags[j].name, str, sizeof(tags[j].name));
137 if (print_dupe)
138 fprintf(stderr, "Warning: %s: Event \"%s\": Fixed duplicate tag names: tag \"%s\" at index %d duplicate at index %d replaced with \"%s\"\n", filename, event_name, tags[i].name, i, j, tags[j].name);
139 had_dupe = true;
140 }
141 }
142 }
143
144 mh->hs_define_event(event_name, rec.time, ntags, tags);
145
146 gEventName[rec.event_id] = strdup(event_name);
147
148 delete[] tags;
149 break;
150 }
151
152 case 0x41445348: // RT_DATA:
153 {
154 int size = rec.data_size;
155
156 if (0)
157 printf("Data record, size %d.\n", size);
158
159 if (!((size > 0) &&
160 (size < 1*1024*1024))) {
161
162 fprintf(stderr, "Error: %s: Invalid length of RT_DATA record: %d (0x%x)\n", filename, size, size);
163 if (buf)
164 free(buf);
165 return -1;
166 break;
167 }
168
169 if (size > bufSize)
170 {
171 bufSize = 1024*((size+1023)/1024);
172 char *newbuf = (char*)realloc(buf, bufSize);
173
174 if (newbuf == NULL) {
175 fprintf(stderr, "Error: %s: Cannot realloc(%d), errno %d (%s)\n", filename, bufSize, errno, strerror(errno));
176 if (buf)
177 free(buf);
178 return -1;
179 break;
180 }
181
182 buf = newbuf;
183 }
184
185 rd = fread(buf, 1, size, f);
186
187 if (rd != size) {
188 fprintf(stderr, "Error: %s: Error reading RT_DATA record, fread(%d) returned %d, errno %d (%s)\n", filename, size, rd, errno, strerror(errno));
189 if (buf)
190 free(buf);
191 return -1;
192 break;
193 }
194
195 time_t t = (time_t)rec.time;
196
197 mh->hs_write_event(gEventName[rec.event_id], t, size, buf);
198
199 break;
200 }
201 }
202
204 }
205
206 if (buf)
207 free(buf);
208
209 return 0;
210}
211
213{
214 FILE* f = fopen(name,"r");
215 if (!f)
216 {
217 fprintf(stderr, "Error: Cannot open \'%s\', errno %d (%s)\n", name, errno, strerror(errno));
218 return -1;
219 }
220
221 fprintf(stderr, "Reading %s\n", name);
222 copyHstFile(name, f, mh);
223 fclose(f);
225
226 if (had_empty && report_empty) {
227 report_empty = false;
228 fprintf(stderr, "Notice: Automatically repaired some empty tag names\n");
229 }
230
231 if (had_dupe && report_dupe) {
232 report_dupe = false;
233 fprintf(stderr, "Notice: Automatically repaired some duplicate tag names\n");
234 }
235
236 if (had_string && report_string) {
237 report_string = false;
238 fprintf(stderr, "Notice: Automatically truncated events that contain tags of forbidden type TID_STRING\n");
239 }
240
241 return 0;
242}
243
244void help()
245{
246 fprintf(stderr,"Usage: mh2sql [-h] [switches...] file1.hst file2.hst ...\n");
247 fprintf(stderr,"\n");
248 fprintf(stderr,"Switches:\n");
249 fprintf(stderr," -h --- print this help message\n");
250 fprintf(stderr," --report-repaired-tags --- print messages about all repaired empty and duplicate tag names\n");
251 fprintf(stderr," --hs-debug <hs_debug_flag> --- set the history debug flag\n");
252 fprintf(stderr," --odbc <ODBC_DSN> --- write to ODBC (SQL) history using given ODBC DSN\n");
253 fprintf(stderr," --sqlite <path> --- write to SQLITE database at the given path\n");
254 fprintf(stderr," --mysql mysql_writer.txt --- write to MYSQL database\n");
255 fprintf(stderr," --pgsql pgsql_writer.txt --- write to PGSQL database\n");
256 fprintf(stderr," --file <path> --- write to FILE database at the given path\n");
257 fprintf(stderr,"\n");
258 fprintf(stderr,"Examples:\n");
259 fprintf(stderr," mh2sql --hs-debug 1 --sqlite . 130813.hst\n");
260 exit(1);
261}
262
263int main(int argc,char*argv[])
264{
265 int status;
266 int hs_debug_flag = 0;
267 HNDLE hDB;
269
270 if (argc <= 2)
271 help(); // DOES NOT RETURN
272
273 status = cm_connect_experiment("", "", "mh2sql", NULL);
274 if (status != SUCCESS)
275 exit(1);
276
278 assert(status == HS_SUCCESS);
279
280 // turn off watchdog checks
282
283 for (int iarg=1; iarg<argc; iarg++) {
284 const char* arg = argv[iarg];
285 if (arg[0] != '-')
286 continue;
287
288 if (strcmp(arg, "-h")==0) {
289 help(); // DOES NOT RETURN
290 } else if (strcmp(arg, "--report-repaired-tags") == 0) {
291 print_empty = true;
292 print_dupe = true;
293 print_string = true;
294 } else if (strcmp(arg, "--hs-debug") == 0) {
296 iarg++;
297 } else if (strcmp(arg, "--odbc") == 0) {
299 assert(mh);
302 if (status != HS_SUCCESS)
303 exit(1);
304 iarg++;
305 } else if (strcmp(arg, "--sqlite") == 0) {
307 assert(mh);
310 if (status != HS_SUCCESS)
311 exit(1);
312 iarg++;
313 } else if (strcmp(arg, "--mysql") == 0) {
315 assert(mh);
318 if (status != HS_SUCCESS)
319 exit(1);
320 iarg++;
321 } else if (strcmp(arg, "--pgsql") == 0) {
323 assert(mh);
326 if (status != HS_SUCCESS)
327 exit(1);
328 iarg++;
329 } else if (strcmp(arg, "--file") == 0) {
331 assert(mh);
334 if (status != HS_SUCCESS)
335 exit(1);
336 iarg++;
337 }
338 }
339
340 if (!mh) {
342 assert(status == HS_SUCCESS);
343 assert(mh);
344 }
345
346 for (int iarg=1; iarg<argc; iarg++) {
347 const char* arg = argv[iarg];
348
349 if (arg[0] != '-')
350 continue;
351
352 if (strcmp(arg, "--hs-debug") == 0) {
354 iarg++;
355 }
356 }
357
358 for (int iarg=1; iarg<argc; iarg++) {
359 const char* arg = argv[iarg];
360
361 if (strstr(arg, ".hst") != NULL) {
362 copyHst(arg, mh);
363 }
364 }
365
366 mh->hs_disconnect();
367
369
370 return 0;
371}
372
373/* emacs
374 * Local Variables:
375 * tab-width: 8
376 * c-basic-offset: 3
377 * indent-tabs-mode: nil
378 * End:
379 */
#define FALSE
Definition cfortran.h:309
virtual int hs_set_debug(int debug)=0
set debug level, returns previous debug level
virtual int hs_disconnect()=0
disconnect from history, returns HS_SUCCESS
virtual int hs_connect(const char *connect_string)=0
returns HS_SUCCESS
virtual int hs_flush_buffers()=0
flush buffered data to storage where it is visible to mhttpd
virtual int hs_write_event(const char *event_name, time_t timestamp, int data_size, const char *data)=0
see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
virtual int hs_define_event(const char *event_name, time_t timestamp, int ntags, const TAG tags[])=0
see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3011
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2278
INT cm_disconnect_experiment(void)
Definition midas.cxx:2846
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
Definition midas.cxx:3283
#define HS_SUCCESS
Definition midas.h:727
#define SUCCESS
Definition mcstd.h:54
#define TID_STRING
Definition midas.h:346
INT cm_msg_flush_buffer()
Definition midas.cxx:865
#define HS_GET_WRITER
Definition history.h:36
#define HS_GET_DEFAULT
Definition history.h:38
#define HS_GET_INACTIVE
Definition history.h:37
int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
MidasHistoryInterface * MakeMidasHistoryODBC()
MidasHistoryInterface * MakeMidasHistorySqlite()
MidasHistoryInterface * MakeMidasHistoryMysql()
MidasHistoryInterface * MakeMidasHistoryPgsql()
MidasHistoryInterface * MakeMidasHistoryFile()
int main()
Definition hwtest.cxx:23
INT type
Definition mana.cxx:269
HNDLE hDB
main ODB handle
Definition mana.cxx:207
INT i
Definition mdump.cxx:32
bool print_empty
Definition mh2sql.cxx:22
bool report_string
Definition mh2sql.cxx:32
bool had_empty
Definition mh2sql.cxx:26
bool report_dupe
Definition mh2sql.cxx:31
bool print_string
Definition mh2sql.cxx:24
void help()
Definition mh2sql.cxx:244
bool had_dupe
Definition mh2sql.cxx:27
int copyHstFile(const char *filename, FILE *f, MidasHistoryInterface *mh)
Definition mh2sql.cxx:34
bool print_dupe
Definition mh2sql.cxx:23
bool report_empty
Definition mh2sql.cxx:30
int copyHst(const char *name, MidasHistoryInterface *mh)
Definition mh2sql.cxx:212
std::map< int, const char * > gEventName
Definition mh2sql.cxx:20
bool had_string
Definition mh2sql.cxx:28
INT HNDLE
Definition midas.h:132
#define NAME_LENGTH
Definition midas.h:272
MidasHistoryInterface * mh
#define name(x)
Definition midas_macro.h:24
INT j
Definition odbhist.cxx:40
char str[256]
Definition odbhist.cxx:33
DWORD status
Definition odbhist.cxx:39
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Definition midas.h:1234