24 memset(
this, 0,
sizeof(OVERLAPPED));
42 if (
h != INVALID_HANDLE_VALUE)
64 GetQueuedCompletionStatus(
file_complete, &ntrans, &key, (OVERLAPPED**)&overlapped, INFINITE);
65 (*(overlapped->
func))(overlapped->
arg);
73 static SECURITY_ATTRIBUTES sec_attr = {
sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
76 file_complete = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
80 HANDLE h = CreateFile(filename, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE,
81 &sec_attr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
82 if (h != INVALID_HANDLE_VALUE)
95 if (h != INVALID_HANDLE_VALUE)
98 if (close_after_write)
107 WriteFile(h, arg->
data, strlen(message), NULL, overlapped);
118 if (h != INVALID_HANDLE_VALUE)
128 #pragma managed(push, off)
132 DWORD ul_reason_for_call,
136 switch (ul_reason_for_call)
138 case DLL_PROCESS_ATTACH:
139 case DLL_THREAD_ATTACH:
140 case DLL_THREAD_DETACH:
141 case DLL_PROCESS_DETACH:
157 if (strlen(isotime) < 19)
161 n = sscanf(isotime,
"%d-%d-%dT%d:%d:%d",
162 &tm_struct.tm_year, &tm_struct.tm_mon, &tm_struct.tm_mday,
163 &tm_struct.tm_hour, &tm_struct.tm_min, &tm_struct.tm_sec);
167 n = sscanf(isotime,
"%d-%d-%d %d:%d:%d",
168 &tm_struct.tm_year, &tm_struct.tm_mon, &tm_struct.tm_mday,
169 &tm_struct.tm_hour, &tm_struct.tm_min, &tm_struct.tm_sec);
175 tm_struct.tm_year -= 1900;
176 tm_struct.tm_mon -= 1;
177 tm_struct.tm_isdst = -1;
178 return mktime(&tm_struct);
181 static int ISOtime(time_t time,
char* buffer,
int len)
183 struct tm *tm_struct;
185 tm_struct = localtime(&time);
188 strftime(buffer, len,
"%Y-%m-%dT%H:%M:%S", tm_struct);
192 strncpy(buffer,
"1970-01-01T00:00:00", len);
194 buffer[len-1] =
'\0';
219 InterlockedDecrement(&num_async_requests);
224 SetEvent(async_complete_event);
239 se_log_values_t(
long run_number_,
const char* source_,
const std::vector<std::string>& iso_times_,
const std::vector<std::string>& block_names_,
const std::vector<std::string>& block_values_) :
241 se_log_values_t(
long run_number_,
const char* source_,
const char* iso_time_,
const char* block_name_,
const char* block_value_) :
run_number(run_number_),
source(source_)
255 if (WaitForSingleObject(work_queued, 30000 ) == WAIT_OBJECT_0)
257 EnterCriticalSection(&work_critical);
258 while (worklist.size() > 0)
261 worklist.pop_front();
262 LeaveCriticalSection(&work_critical);
265 EnterCriticalSection(&work_critical);
267 if (se_worklist != NULL)
271 LeaveCriticalSection(&work_critical);
276 InterlockedDecrement(&num_async_requests);
280 SetEvent(async_complete_event);
281 EnterCriticalSection(&work_critical);
284 LeaveCriticalSection(&work_critical);
285 Poco::Thread::sleep(200);
292 static volatile bool general_init_done =
false;
293 static SECURITY_ATTRIBUTES sec_attr = {
sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
294 if (!general_init_done)
296 general_init_done =
true;
297 async_complete_event = CreateEvent(&sec_attr, FALSE, FALSE, NULL);
298 InitializeCriticalSection(&work_critical);
299 work_queued = CreateEvent(&sec_attr, FALSE, FALSE, NULL);
308 InterlockedIncrement(&num_async_requests);
309 EnterCriticalSection(&work_critical);
310 worklist.push_back(work);
311 SetEvent(work_queued);
312 LeaveCriticalSection(&work_critical);
319 int* count = (
int*)arg;
325 #define SQLITE_CHECK_RC(__rc) \
326 if (__rc != SQLITE_OK) \
328 _snprintf_s(last_error, sizeof(last_error), _TRUNCATE, "SELOGGER: SQLITE error %s at %s:%d", errmsg, __FILE__, __LINE__); \
329 sqlite3_free(errmsg); \
333 #define SQLITE_HANDLE_EXCEPTION(__func_name) \
334 catch(std::exception& ex) \
336 _snprintf_s(last_error, sizeof(last_error), _TRUNCATE, "SELOGGER: %s: exception %s at %s:%d", #__func_name, ex.what(), __FILE__, __LINE__); \
340 #define OPEN_DATABASE \
342 ISISDB the_database(false);
349 return the_database.version();
351 catch(std::exception& ex)
353 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: %s: exception %s at %s:%d",
"se_version", ex.what(), __FILE__, __LINE__);
358 static int my_sqlite3_exec(sqlite3* db,
const char* sql,
int (*callback)(
void*,
int,
char**,
char**),
void* arg,
char** errmsg)
362 return sqlite3_exec(db, sql, callback, arg, errmsg);
373 sql_line = sqlite3_mprintf(
374 "INSERT OR IGNORE INTO config VALUES ('%q', '%q'); "
375 "UPDATE config SET value='%q' WHERE name='%q'; ", name, value, value, name);
377 sqlite3_free(sql_line);
390 char** pazResult = NULL;
396 sql_line = sqlite3_mprintf(
397 "SELECT value FROM config WHERE name = '%q';", name);
399 rc = sqlite3_get_table(the_database, sql_line, &pazResult, &pnRow, &pnColumn, &errmsg);
400 sqlite3_free(sql_line);
402 if (pnRow == 1 && pnColumn == 1)
404 value = pazResult[1*pnColumn+0];
406 sqlite3_free_table(pazResult);
415 _snprintf_s(buffer,
sizeof(buffer), _TRUNCATE,
"%ld", value);
424 return atol(s.c_str());
437 return atol(s.c_str());
448 double d = strtod(value, &endptr);
449 if (endptr != NULL && endptr != value)
454 int n = strlen(value);
455 char* tmpstr = strdup(value);
457 for(
int i=0; i<n; i++)
459 tmpstr[i] = toupper(tmpstr[i]);
461 if ( (strstr(tmpstr,
"INF") != NULL) || (strstr(tmpstr,
"NAN") != NULL) )
477 std::vector<std::string> block_names;
478 std::vector<std::string> block_values;
479 block_names.push_back(block_name);
480 block_values.push_back(block_value);
488 int nvalues = block_names.size();
489 s.reserve(nvalues*100);
494 ISOtime(unix_time, iso_time,
sizeof(iso_time));
497 std::stringstream sstr;
498 for(
int i=0; i<nvalues; i++)
500 sstr <<
"se_set_block_values: " << block_names[i].c_str() <<
" = " << block_values[i].c_str() << (
isReal(block_values[i].c_str()) ?
" (real)" :
" (string)") <<
"\r\n";
508 s.append(
"BEGIN TRANSACTION; ");
509 for(
int i=0; i<nvalues; i++)
511 sql_line = sqlite3_mprintf(
512 "UPDATE seblocks SET block_value='%q',is_real=%d,source='%q',value_time='%q' WHERE block_name='%q' AND run_number=%d; ",
513 block_values[i].c_str(),
isReal(block_values[i].c_str()),
"UNKNOWN", iso_time, block_names[i].c_str(), run_number);
515 sqlite3_free(sql_line);
517 s.append(
"END TRANSACTION; ");
518 int rc =
my_sqlite3_exec(the_database, s.c_str(), NULL, NULL, &errmsg);
526 const char* block_value)
528 std::vector<std::string> block_names;
529 std::vector<std::string> block_values;
530 std::vector<std::string> block_times;
531 block_names.push_back(block_name);
532 block_values.push_back(block_value);
533 block_times.push_back(iso_time);
534 return se_log_values(run_number, source, block_times, block_names, block_values);
540 EnterCriticalSection(&work_critical);
541 uint64_t end_iter = num_work_iterations + 2;
542 while( (num_async_requests > 0) && (num_work_iterations <= end_iter) )
544 LeaveCriticalSection(&work_critical);
545 WaitForSingleObject(async_complete_event, 30000 );
546 EnterCriticalSection(&work_critical);
548 LeaveCriticalSection(&work_critical);
555 InterlockedIncrement(&num_async_requests);
556 EnterCriticalSection(&work_critical);
557 if (se_worklist == NULL)
559 se_worklist =
new std::list<se_log_values_t*>;
561 se_worklist->push_back(work);
562 SetEvent(work_queued);
563 LeaveCriticalSection(&work_critical);
572 SELOGGER_API int __stdcall
se_log_values_async(
long run_number,
const char* source,
const std::vector<std::string>& iso_times,
const std::vector<std::string>& block_names,
const std::vector<std::string>& block_values)
578 SELOGGER_API int __stdcall
se_log_fvalues(
long run_number,
const char* source,
const std::vector<std::string>& iso_times,
const std::vector<std::string>& block_names,
const std::vector<float>& block_values)
580 std::vector<std::string> svals(block_values.size());
581 for(
int i=0; i<block_values.size(); ++i)
583 svals[i] = Poco::NumberFormatter::format(block_values[i]);
586 return se_log_values(run_number, source, iso_times, block_names, svals);
589 SELOGGER_API int __stdcall
se_log_values(
long run_number,
const char* source,
const std::vector<std::string>& iso_times,
const std::vector<std::string>& block_names,
const std::vector<std::string>& block_values)
594 int nvalues = block_names.size();
597 std::stringstream sstr;
598 for(
int i=0; i<nvalues; i++)
600 sstr <<
"se_log_values: " << iso_times[i].c_str() <<
" " << block_names[i].c_str() <<
" = " << block_values[i].c_str() << (
isReal(block_values[i].c_str()) ?
" (real)" :
" (string)") <<
"\r\n";
611 run_number = atol(s.c_str());
615 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: unable to detremine run number");
620 s.reserve(nvalues*100);
622 s.append(
"BEGIN TRANSACTION; ");
623 for(
int i=0; i<nvalues; i++)
625 unix_time =
unixTime(iso_times[i].c_str());
626 sql_line = sqlite3_mprintf(
627 "INSERT INTO selog VALUES (%ld,'%q','%q',%llu,'%q','%q',%d); ",
628 run_number, source, iso_times[i].c_str(), (
unsigned long long)unix_time,
629 block_names[i].c_str(), block_values[i].c_str(),
isReal(block_values[i].c_str()));
631 sqlite3_free(sql_line);
633 s.append(
"END TRANSACTION; ");
634 int rc =
my_sqlite3_exec(the_database, s.c_str(), NULL, NULL, &errmsg);
647 int current_run_number, run_number;
657 current_run_number = atol(s.c_str());
661 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: unable to detremine run number");
665 s.reserve(nvalues*100);
666 s.append(
"BEGIN TRANSACTION; ");
674 sql_line = sqlite3_mprintf(
675 "INSERT INTO selog VALUES (%ld,'%q','%q',%llu,'%q','%q',%d); ",
676 run_number, item->
source.c_str(), item->
iso_times[i].c_str(), (
unsigned long long)unix_time,
679 sqlite3_free(sql_line);
682 s.append(
"END TRANSACTION; ");
683 int rc =
my_sqlite3_exec(the_database, s.c_str(), NULL, NULL, &errmsg);
702 int run_status,
int is_running,
int is_waiting,
703 int good_frames,
int raw_frames,
704 float good_uamph,
float raw_uamph,
705 int64_t monitor_sum0,
float dae_beam_current, int64_t total_counts,
706 float count_rate,
float npratio_current)
713 sql_line = sqlite3_mprintf(
714 "INSERT INTO run_status VALUES (%d,'%q','%q',%llu,%d,%d,%d,%d,%d,%d,%g,%g,%lld,%g,%lld,%g,%g);",
715 run_number, source, iso_time, static_cast<unsigned long long>(
unixTime(iso_time)), period,
716 run_status, is_running, is_waiting,
717 good_frames, raw_frames,
718 good_uamph, raw_uamph,
719 static_cast<long long>(monitor_sum0), dae_beam_current, static_cast<long long>(total_counts),
720 count_rate, npratio_current);
722 sqlite3_free(sql_line);
748 ISOtime(time(NULL), iso_time,
sizeof(iso_time));
754 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
755 "INSERT INTO run_state VALUES (%d, %d, '%s', '%s', %llu); ",
756 run_number, is_start, state, iso_time, (
unsigned long long)
unixTime(iso_time));
775 char* sql_line = sqlite3_mprintf(
"DELETE FROM seblocks WHERE run_number=%d; ", run_number);
777 sqlite3_free(sql_line);
785 const char* vi_name,
const char* read_control_label,
const char* set_control_label,
const char* button_control_label,
786 unsigned options,
const char* nexus_name,
float low_limit,
float high_limit,
787 const char* units,
const char* current_value)
794 ISOtime(unix_time, iso_time,
sizeof(iso_time));
800 sql_line = sqlite3_mprintf(
801 "INSERT OR REPLACE INTO seblocks VALUES (%d, '%q', '%q', '%q', '%q', '%q', '%q', %u, '%q', %g, %g, '%q', '%q', %d, '%q', '%q', '%q'); ",
802 run_number, block_name, setpoint_value, vi_name, read_control_label,
803 set_control_label, button_control_label,
804 options, nexus_name, low_limit, high_limit, units, current_value,
805 isReal(current_value),
"UNKNOWN", iso_time, iso_time);
807 sqlite3_free(sql_line);
823 SEBLOCK& block = (*blocks)[argv[1]];
834 block.
units = argv[11];
835 block.
is_real = (atol(argv[13]) != 0 ?
true :
false);
876 unsigned char* uuid_str = NULL;
879 ISOtime(time(NULL), iso_time,
sizeof(iso_time));
888 run_number = atol(s.c_str());
890 UuidCreate(&the_uuid);
891 UuidToString(&the_uuid, &uuid_str);
893 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
894 "INSERT INTO measurement VALUES ('%s', %d, '%s', '%s'); ",
895 uuid_str, run_number, iso_time, label);
898 res = (
const char*)uuid_str;
899 RpcStringFree(&uuid_str);
910 char** pazResult = NULL;
916 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
917 "SELECT label FROM measurement WHERE uuid='%s'; ", measurement_id);
919 rc = sqlite3_get_table(the_database, sql_line, &pazResult, &pnRow, &pnColumn, &errmsg);
921 if (pnRow == 1 && pnColumn == 1)
923 res = pazResult[1*pnColumn+0];
925 sqlite3_free_table(pazResult);
939 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
940 "UPDATE measurement SET label='%s' WHERE uuid='%s'; ", label, measurement_id);
952 char** pazResult = NULL;
959 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
960 "SELECT uuid FROM measurement WHERE label='%s' ORDER BY iso_time DESC; ", label);
962 rc = sqlite3_get_table(the_database, sql_line, &pazResult, &pnRow, &pnColumn, &errmsg);
964 if (pnRow >= 1 && pnColumn == 1)
966 measurement_id = pazResult[1*pnColumn+0];
968 sqlite3_free_table(pazResult);
979 char** pazResult = NULL;
985 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
986 "SELECT run_number FROM measurement WHERE uuid='%s'; ", measurement_id);
988 rc = sqlite3_get_table(the_database, sql_line, &pazResult, &pnRow, &pnColumn, &errmsg);
990 if (pnRow == 1 && pnColumn == 1)
992 run_number = atol(pazResult[1*pnColumn+0]);
994 sqlite3_free_table(pazResult);
1003 char* errmsg = NULL;
1007 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1008 "BEGIN TRANSACTION; "
1009 "DELETE FROM run_state WHERE (run_number BETWEEN %d AND %d) OR (run_number=-1); "
1010 "DELETE FROM seperiods WHERE (run_number BETWEEN %d AND %d) OR (run_number=-1); "
1011 "DELETE FROM selog WHERE (run_number BETWEEN %d AND %d) OR (run_number=-1); "
1012 "DELETE FROM run_status WHERE (run_number BETWEEN %d AND %d) OR (run_number=-1); "
1013 "DELETE FROM seblocks WHERE (run_number BETWEEN %d AND %d) OR (run_number=-1); "
1014 "END TRANSACTION; ",
1015 run_start, run_finish, run_start, run_finish, run_start, run_finish, run_start, run_finish, run_start, run_finish);
1016 int rc =
my_sqlite3_exec(the_database, sql_line, NULL, NULL, &errmsg);
1044 int current_run_number;
1047 current_run_number = atol(s.c_str());
1051 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: unable to detremine run number");
1054 run_start = (run_start <= 0 ? current_run_number : run_start);
1055 run_finish = (run_finish <= 0 ? current_run_number : run_finish);
1065 char* errmsg = NULL;
1073 sqlite3_stmt *stmt, *stmt2, *stmt3, *stmt4, *stmt_real0;
1076 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1077 "SELECT * FROM seblocks WHERE run_number=%d;", run_number);
1083 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1084 "SELECT DISTINCT run_number, block_name FROM selog WHERE run_number=%d;", run_number);
1087 seblock_map_t::iterator it;
1088 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1089 "SELECT unix_time, block_value FROM selog WHERE run_number=? AND block_name=?;");
1090 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt, &pzTail);
1092 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1093 "SELECT COUNT(unix_time) FROM selog WHERE run_number=? AND block_name=?;");
1094 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt3, &pzTail);
1097 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1098 "SELECT period, block_setpoint, block_value FROM seperiods "
1099 "WHERE run_number=? AND block_name=? "
1100 "ORDER BY period DESC, unix_time ASC;");
1101 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt2, &pzTail);
1103 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1105 "avg(block_setpoint), avg(block_value), min(block_setpoint), min(block_value), max(block_setpoint), max(block_value) "
1106 "FROM seperiods WHERE run_number=? AND block_name=? AND unix_time>=%lu "
1107 "GROUP BY period ORDER BY period DESC;", ref_time);
1108 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt4, &pzTail);
1110 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1111 "SELECT COUNT(unix_time) FROM selog WHERE run_number=? AND block_name=? AND is_real=0;");
1112 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt_real0, &pzTail);
1114 for(it=blocks.begin(); it != blocks.end(); ++it)
1118 rc = sqlite3_reset(stmt);
1120 rc = sqlite3_bind_int(stmt, 1, run_number);
1122 rc = sqlite3_bind_text(stmt, 2, it->first.c_str(), -1, SQLITE_STATIC);
1124 rc = sqlite3_reset(stmt3);
1126 rc = sqlite3_bind_int(stmt3, 1, run_number);
1128 rc = sqlite3_bind_text(stmt3, 2, it->first.c_str(), -1, SQLITE_STATIC);
1130 if ( (rc = sqlite3_step(stmt3)) == SQLITE_ROW )
1136 n = sqlite3_column_int(stmt3, 0) + 10;
1144 rc = sqlite3_reset(stmt_real0);
1146 rc = sqlite3_bind_int(stmt_real0, 1, run_number);
1148 rc = sqlite3_bind_text(stmt_real0, 2, it->first.c_str(), -1, SQLITE_STATIC);
1150 if ( (rc = sqlite3_step(stmt_real0)) == SQLITE_ROW )
1152 block.
is_real = (sqlite3_column_int(stmt_real0, 0) == 0);
1160 block.
time.reserve(n);
1163 while( (rc = sqlite3_step(stmt)) == SQLITE_ROW )
1165 block.
time.push_back(sqlite3_column_int64(stmt, 0) - ref_time);
1168 block.
fvalues.push_back(sqlite3_column_double(stmt, 1));
1172 block.
svalues.push_back((
const char*)sqlite3_column_text(stmt, 1));
1175 if (rc != SQLITE_DONE)
1179 rc = sqlite3_reset(stmt2);
1181 rc = sqlite3_bind_int(stmt2, 1, run_number);
1183 rc = sqlite3_bind_text(stmt2, 2, it->first.c_str(), -1, SQLITE_STATIC);
1185 while( (rc = sqlite3_step(stmt2)) == SQLITE_ROW )
1187 int period = sqlite3_column_int(stmt2, 0);
1207 block.
setpoint_value[period] = (
const char*)sqlite3_column_text(stmt2, 1);
1208 block.
current_value[period] = (
const char*)sqlite3_column_text(stmt2, 2);
1211 if (rc != SQLITE_DONE)
1215 rc = sqlite3_reset(stmt4);
1217 rc = sqlite3_bind_int(stmt4, 1, run_number);
1219 rc = sqlite3_bind_text(stmt4, 2, it->first.c_str(), -1, SQLITE_STATIC);
1221 while( (rc = sqlite3_step(stmt4)) == SQLITE_ROW )
1223 int period = sqlite3_column_int(stmt4, 0);
1226 block.
fsetpoint_spread[period] = sqlite3_column_double(stmt4, 5) - sqlite3_column_double(stmt4, 3);
1227 block.
fcurrent_spread[period] = sqlite3_column_double(stmt4, 6) - sqlite3_column_double(stmt4, 4);
1230 if (rc != SQLITE_DONE)
1235 rc = sqlite3_finalize(stmt);
1237 rc = sqlite3_finalize(stmt2);
1239 rc = sqlite3_finalize(stmt3);
1241 rc = sqlite3_finalize(stmt4);
1243 rc = sqlite3_finalize(stmt_real0);
1251 sqlite3_stmt *stmt, *stmt2;
1252 char* errmsg = NULL;
1259 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1260 "SELECT * FROM run_status WHERE run_number=%d;", run_number);
1261 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt, &pzTail);
1263 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1264 "SELECT COUNT(unix_time) FROM run_status WHERE run_number=%d;", run_number);
1265 rc = sqlite3_prepare_v2(the_database, sql_line, -1, &stmt2, &pzTail);
1267 if ( (rc = sqlite3_step(stmt2)) == SQLITE_ROW )
1273 n = sqlite3_column_int(stmt2, 0) + 10;
1280 blocks.
time.reserve(n);
1281 blocks.
period.reserve(n);
1294 while( (rc = sqlite3_step(stmt)) == SQLITE_ROW )
1296 blocks.
time.push_back(sqlite3_column_int64(stmt, 3) - blocks.
ref_time);
1297 blocks.
period.push_back(sqlite3_column_int(stmt, 4));
1298 blocks.
run_status.push_back(sqlite3_column_int(stmt, 5));
1299 blocks.
is_running.push_back(sqlite3_column_int(stmt, 6));
1300 blocks.
is_waiting.push_back(sqlite3_column_int(stmt, 7));
1301 blocks.
good_frames.push_back(sqlite3_column_int(stmt, 8));
1302 blocks.
raw_frames.push_back(sqlite3_column_int(stmt, 9));
1303 blocks.
good_uamps.push_back(sqlite3_column_double(stmt, 10));
1304 blocks.
raw_uamps.push_back(sqlite3_column_double(stmt, 11));
1305 blocks.
monitor1_sum.push_back(sqlite3_column_int64(stmt, 12));
1307 blocks.
total_counts.push_back(sqlite3_column_int64(stmt, 14));
1308 blocks.
count_rate.push_back(sqlite3_column_double(stmt, 15));
1309 blocks.
np_ratio.push_back(sqlite3_column_double(stmt, 16));
1311 if (rc != SQLITE_DONE)
1315 rc = sqlite3_finalize(stmt);
1317 rc = sqlite3_finalize(stmt2);
1324 FILE* f = (FILE*)arg;
1325 fprintf(f,
"SQL \"%s\" took %8.3f s\n", sql, (
double)tim / 1e9);
1332 FILE* f = fopen(filename,
"wtN");
1340 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: cannot profile to %s", filename);
1358 static volatile HANDLE h = NULL;
1359 static SECURITY_ATTRIBUTES sec_attr = {
sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
1362 h = CreateEvent(&sec_attr, FALSE, FALSE, NULL);
1390 char* errmsg = NULL;
1397 char* sql_line = sqlite3_mprintf(
"SELECT * FROM seblocks WHERE run_number=%d;", run_number);
1399 sqlite3_free(sql_line);
1406 std::vector<std::string> block_names;
1407 std::vector<std::string> block_setpoints;
1408 block_names.push_back(block_name);
1409 block_setpoints.push_back(block_setpoint);
1417 int nvalues = block_names.size();
1418 s.reserve(nvalues*200);
1419 char* errmsg = NULL;
1423 ISOtime(unix_time, iso_time,
sizeof(iso_time));
1428 s.append(
"BEGIN TRANSACTION; ");
1429 for(
int i=0; i<nvalues; i++)
1431 sql_line = sqlite3_mprintf(
1432 "UPDATE seblocks SET setpoint_value='%q',setpoint_time='%q' WHERE block_name='%q' AND run_number=%d; ",
1433 block_setpoints[i].c_str(), iso_time, block_names[i].c_str(), run_number);
1435 sqlite3_free(sql_line);
1437 s.append(
"END TRANSACTION; ");
1438 int rc =
my_sqlite3_exec(the_database, s.c_str(), NULL, NULL, &errmsg);
1446 SELOGGER_API int __stdcall
se_get_values(
long run_number,
const char* source,
const char* block_name, std::vector<std::string>& iso_times, std::vector<std::string>& block_values)
1448 using namespace Poco::Data;
1450 if (run_number <= 0)
1454 run_number = atol(s.c_str());
1458 _snprintf_s(last_error,
sizeof(last_error), _TRUNCATE,
"SELOGGER: unable to detremine run number");
1467 Statement stmt(ses);
1469 block_values.clear();
1470 stmt <<
"SELECT iso_time, block_value FROM selog WHERE run_number=:run_number AND source=:source AND block_name=:block_name",
1471 into(iso_times), into(block_values), use(run_number), use(source), use(block_name);
1483 using namespace Poco::Data;
1489 Statement stmt(ses);
1490 stmt <<
"SELECT block_name, setpoint_value, vi_name, read_control, set_control, button_control, "
1491 "options, nexus_name, low_limit, high_limit, units, block_value, is_real, source, "
1492 "setpoint_time, value_time FROM seblocks WHERE block_name=:block_name AND run_number=" << run_number,
1493 into(block.
tuple()), use(block_name);
1505 using namespace Poco::Data;
1506 static const int limit_rows_returned = 200;
1511 Statement stmt(ses);
1512 stmt << sql, limit(limit_rows_returned);
1513 unsigned nrows = stmt.execute();
1515 std::stringstream sstr;
1516 for(
int i=0; i < rs.columnCount(); ++i)
1518 sstr << (i > 0 ?
" | " :
"") << rs.columnName(i);
1521 for(
int row=0; row < rs.rowCount(); ++row)
1523 for(
int col=0; col < rs.columnCount(); ++col)
1525 sstr << (col > 0 ?
" | " :
"") << rs.value(col, row).convert<std::string>();
1531 sstr <<
"*** RESULT TRUNCATED AT " << limit_rows_returned <<
" ROWS ***\n";
1533 if ( nrows != rs.rowCount() )
1535 sstr <<
"*** ROW COUNT MISMATCH ***\n";
1537 if ( nrows <= 0 || rs.columnCount() <= 0 )
1539 sstr <<
"*** NULL result: nrows=" << nrows <<
" ncols=" << rs.columnCount() <<
" ***\n";
1541 result = sstr.str();
1551 static int selog_rows_callback(
void *arg,
int argc,
char **argv,
char **azColName)
1556 block->
time.push_back(atoi(argv[0]) - block->
ref_time);
1557 int is_real = atol(argv[2]);
1560 block->
fvalues.push_back(atof(argv[1]));
1564 block->
svalues.push_back(argv[1]);
1570 static int seperiods_rows_callback(
void *arg,
int argc,
char **argv,
char **azColName)
1575 int period = atol(argv[0]);
1603 char* errmsg = NULL;
1611 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1612 "SELECT DISTINCT block_name FROM selog WHERE run_number=%d;", run_number);
1615 seblock_map_t::iterator it;
1616 for(it=blocks.begin(); it != blocks.end(); ++it)
1618 it->second.ref_time = ref_time;
1619 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1620 "SELECT unix_time, block_value, is_real FROM selog WHERE run_number=%d AND block_name='%s';",
1621 run_number, it->first.c_str());
1622 rc =
my_sqlite3_exec(the_database, sql_line, selog_rows_callback, &(it->second), &errmsg);
1624 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1625 "SELECT period, avg(block_setpoint), avg(block_value) FROM seperiods WHERE run_number=%d AND block_name='%s' "
1626 "GROUP BY period ORDER BY period DESC;", run_number, it->first.c_str());
1627 rc =
my_sqlite3_exec(the_database, sql_line, seperiods_rows_callback, &(it->second), &errmsg);
1633 static int run_rows_callback(
void *arg,
int argc,
char **argv,
char **azColName)
1638 blocks->
time.push_back(atoi(argv[3]) - blocks->
ref_time);
1639 blocks->
period.push_back(atoi(argv[4]));
1645 blocks->
good_uamps.push_back(atof(argv[10]));
1646 blocks->
raw_uamps.push_back(atof(argv[11]));
1650 blocks->
count_rate.push_back(atof(argv[15]));;
1651 blocks->
np_ratio.push_back(atof(argv[16]));
1659 char* errmsg = NULL;
1662 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1663 "SELECT * FROM run_status WHERE run_number=%d;", run_number);
1664 int rc =
my_sqlite3_exec(the_database, sql_line, run_rows_callback, &blocks, &errmsg);
1672 char* errmsg = NULL;
1677 _snprintf_s(sql_line,
sizeof(sql_line), _TRUNCATE,
1678 "SELECT block_name FROM seblocks UNION SELECT block_name FROM selog WHERE run_number=%d;", run_number);
static int my_sqlite3_exec(sqlite3 *db, const char *sql, int(*callback)(void *, int, char **, char **), void *arg, char **errmsg)
SELOGGER_API int __stdcall se_clear_values2_async(int run_start, int run_finish)
static void process_requests(void *arg)
static int count_rows_callback(void *arg, int argc, char **argv, char **azColName)
SELOGGER_API int __stdcall se_log_run(int run_number, const char *source, const char *iso_time, int period, int run_status, int is_running, int is_waiting, int good_frames, int raw_frames, float good_uamph, float raw_uamph, int64_t monitor_sum0, float dae_beam_current, int64_t total_counts, float count_rate, float npratio_current)
SELOGGER_API int __stdcall se_new_seci_config(const char *config_name)
workpacket(const workpacket &w)
std::vector< int > raw_frames
std::vector< int64_t > total_counts
std::vector< float > count_rate
static int general_init()
SELOGGER_API int __stdcall se_new_measurement(const char *label, std::string &res)
workpacket & operator=(const workpacket &w)
static volatile HANDLE work_queued
SELOGGER_API int __stdcall se_get_run_status(int run_number, time_t ref_time, RUNBLOCK &blocks)
SELOGGER_API int __stdcall se_get_block_values(seblock_map_t &blocks)
SELOGGER_API int __stdcall se_get_measurement_id(const char *label, std::string &measurement_id)
static int __stdcall se_async(workpacket *work)
SELOGGER_API int __stdcall se_set_run_state_async(int run_number, const char *state, int is_start)
static time_t unixTime(const char *isotime)
SELOGGER_API int __stdcall se_start_epics_thread(epics_thread_data_t *arg)
std::vector< float > fcurrent_spread
per period
static volatile HANDLE async_complete_event
Poco::SingletonHolder< SQLITESessionPool > sqlite_session_pool
void(* overlap_complete_func_t)(void *arg)
SELOGGER_API int __stdcall se_get_num_blocks()
std::vector< std::string > iso_times
std::vector< float > fsetpoint_value
per period
std::map< std::string, SEBLOCK > seblock_map_t
void my_io_complete(void *arg)
std::vector< std::string > setpoint_value
per period
std::vector< float > raw_uamps
std::vector< float > good_uamps
se_set_run_state_t(int run_number_, const char *state_, int is_start_)
static int ISOtime(time_t time, char *buffer, int len)
SELOGGER_API int __stdcall se_log_values(long run_number, const char *source, const std::vector< std::string > &iso_times, const std::vector< std::string > &block_names, const std::vector< std::string > &block_values)
SELOGGER_API const char *__stdcall se_get_errmsg()
static int isReal(const char *value)
SELOGGER_API int __stdcall se_set_period(int period)
static bool database_debug
std::vector< std::string > current_value
per period
std::vector< std::string > block_names
SELOGGER_API int __stdcall se_log_value(long run_number, const char *source, const char *iso_time, const char *block_name, const char *block_value)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
void appendToFileAsync(HANDLE h, const char *message, bool close_after_write)
std::vector< float > np_ratio
static volatile uint64_t num_work_iterations
SELOGGER_API int __stdcall se_profile(const char *filename)
std::vector< float > time
std::string button_control
static void my_overlap(void *arg)
std::vector< int > period
se_log_values_t(long run_number_, const char *source_, const std::vector< std::string > &iso_times_, const std::vector< std::string > &block_names_, const std::vector< std::string > &block_values_)
static int __stdcall se_log_values_list(const std::list< se_log_values_t * > *tlist)
const char *__stdcall se_version()
SELOGGER_API int __stdcall se_get_block_details(const char *block_name, SEBLOCK_DETAILS &block)
SELOGGER_API int __stdcall se_get_measurement_label(const char *measurement_id, std::string &res)
SELOGGER_API int __stdcall se_log_fvalues(long run_number, const char *source, const std::vector< std::string > &iso_times, const std::vector< std::string > &block_names, const std::vector< float > &block_values)
SELOGGER_API int __stdcall se_set_block_setpoints(const std::vector< std::string > &block_names, const std::vector< std::string > &block_setpoints)
#define SQLITE_CHECK_RC(__rc)
HANDLE createAppendFile(const char *filename)
SEBLOCK_DETAILS_tuple & tuple()
static void db_profile_func(void *arg, const char *sql, sqlite3_uint64 tim)
static HANDLE file_complete
static long get_run_number()
SELOGGER_API int __stdcall se_set_run_number(int run_number)
std::vector< std::string > block_values
SELOGGER_API int __stdcall se_set_period_async(int period)
se_clear_values2_t(long run_start_, long run_finish_)
SELOGGER_API int __stdcall se_close()
SELOGGER_API int __stdcall se_get_values(long run_number, const char *source, const char *block_name, std::vector< std::string > &iso_times, std::vector< std::string > &block_values)
std::vector< float > fvalues
std::vector< float > fcurrent_value
per period
SELOGGER_API int __stdcall se_get_seci_config(std::string &seci_config)
std::vector< float > dae_beam_current
static char last_error[1024]
static int se_clear_values2(int run_start, int run_finish)
std::vector< int > is_waiting
std::vector< float > fsetpoint_spread
per period
SELOGGER_API int __stdcall se_get_measurement_first_run(const char *measurement_id, long &run_number)
std::vector< int > is_running
static volatile LONG num_async_requests
static int se_set_config_param(const char *name, const char *value)
SELOGGER_API int __stdcall se_exec_sql(const char *sql, std::string &result)
std::vector< std::string > svalues
SELOGGER_API int __stdcall se_get_blocks(int run_number, time_t ref_time, seblock_map_t &blocks)
SELOGGER_API int __stdcall se_set_run_state(int run_number, const char *state, int is_start)
std::vector< float > time
se_log_values_t(long run_number_, const char *source_, const char *iso_time_, const char *block_name_, const char *block_value_)
SELOGGER_API int __stdcall se_set_block_setpoint(const char *block_name, const char *block_setpoint)
SELOGGER_API int __stdcall se_clear_values(int run_start, int run_finish)
SELOGGER_API int __stdcall se_set_block_value(const char *block_name, const char *block_value)
SELOGGER_API int __stdcall se_set_measurement_label(const char *measurement_id, const char *label)
SELOGGER_API int __stdcall se_set_block_values(const std::vector< std::string > &block_names, const std::vector< std::string > &block_values)
SELOGGER_API int __stdcall se_log_value_async(long run_number, const char *source, const char *iso_time, const char *block_name, const char *block_value)
static int se_get_config_param(const char *name, std::string &value)
static std::list< workpacket * > worklist
static int seblock_rows_callback(void *arg, int argc, char **argv, char **)
SELOGGER_API int __stdcall se_set_block_details(const char *block_name, const char *setpoint_value, const char *vi_name, const char *read_control_label, const char *set_control_label, const char *button_control_label, unsigned options, const char *nexus_name, float low_limit, float high_limit, const char *units, const char *current_value)
SELOGGER_API int __stdcall se_wait_for_async()
unsigned __stdcall run_epics_db(void *arg)
static CRITICAL_SECTION work_critical
#define SQLITE_HANDLE_EXCEPTION(__func_name)
overlap_complete_func_t func
workpacket(HANDLE ev=NULL)
se_set_period_t(int period_, HANDLE ev=NULL)
MyOverlapped(overlap_complete_func_t func_, void *arg_)
std::vector< int > run_status
static const char * database_debug_file
std::vector< int > good_frames
my_overlap_t(HANDLE h_, const char *data_)
SELOGGER_API int __stdcall se_log_values_async(long run_number, const char *source, const std::vector< std::string > &iso_times, const std::vector< std::string > &block_names, const std::vector< std::string > &block_values)
std::vector< int64_t > monitor1_sum
static std::list< se_log_values_t * > * se_worklist