/* * Paglo Crawler * Copyright (C) 2006-2008 Paglo Labs Inc. All rights reserved. * www.paglo.com * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ //--------------------------------------------------------------------------- #include "DataStore.h" #ifdef _WIN32 #include #else #include #endif using namespace std; //--------------------------------------------------------------------------- TDataStore::TDataStore(const char *Filename) { DB = NULL; DBFilename = Filename; if (!access(Filename, 0) == 0) { CreateDatabase(Filename); } OpenDatabase(Filename); } //--------------------------------------------------------------------------- TDataStore::~TDataStore() { CloseDatabase(); } //--------------------------------------------------------------------------- void TDataStore::UpdateScanSummary(int WeekHour, int CompletedScans) { static int LastCompletedScans = 0; int Tmp = CompletedScans; time_t Now = time(NULL); CompletedScans = CompletedScans - LastCompletedScans; LastCompletedScans = Tmp; string S = "update scanning_summary set completed_scans = " + Int2String(CompletedScans) + ", timestamp = " + Int2String(Now) + " where week_hour = " + Int2String(WeekHour); ExecuteStmt(S.c_str()); } //--------------------------------------------------------------------------- int *TDataStore::GetScanSummary(void) { int *Data = (int *)malloc(168 * sizeof(int)); for (int i = 0; i < 168; i++) { Data[i] = 0; } CppSQLite3Query Results = ExecuteQuery("select * from scanning_summary order by week_hour"); for (int i = 0; !Results.eof(); Results.nextRow()) { int WeekHour = Results.getIntField("week_hour"); int CompletedScans = Results.getIntField("completed_scans"); int Timestamp = Results.getIntField("timestamp"); Data[i] = CompletedScans; i++; } return Data; } //--------------------------------------------------------------------------- void TDataStore::OpenDatabase(const char *Filename) { if (!DB) { DB = new CppSQLite3DB(); DB->open(Filename); /* * Make sure the schema is up to date. */ Migrate(); } } //--------------------------------------------------------------------------- void TDataStore::CloseDatabase(void) { if (DB) { DB->close(); delete DB; DB = NULL; } } //--------------------------------------------------------------------------- void TDataStore::CreateDatabase(const char *Filename) { /* * Create and configure the DB. */ DB = new CppSQLite3DB(); DB->open(Filename); /* * Create the schema. */ ExecuteStmt("create table scanning_summary ( " "week_hour integer not null, " "completed_scans integer not null, " "timestamp integer not null)"); ExecuteStmt("create index idx_scanning_summary_week_hour " "on scanning_summary (week_hour) "); string S; ExecuteStmt("BEGIN"); for (int i = 0; i < 168; i++) { S = "insert into scanning_summary values ("; S += Int2String(i); S += ", 0, 0)"; ExecuteStmt(S.c_str()); } ExecuteStmt("COMMIT"); /* * Close the DB. We will open it again when we need it. */ CloseDatabase(); } //--------------------------------------------------------------------------- void TDataStore::ExecuteStmt(string SQL) { TLocker Locker(QueryLock); if (!DB) { throw CppSQLite3Exception(1, "Attempt to execute statement on a closed database.", false); } DB->execDML(SQL.c_str()); } //--------------------------------------------------------------------------- CppSQLite3Query TDataStore::ExecuteQuery(string SQL) { if (!DB) { throw CppSQLite3Exception(1, "Attempt to execute query on a closed database.", false); } return DB->execQuery(SQL.c_str()); } //--------------------------------------------------------------------------- typedef void (*TMigration)(TDataStore *Manager); void MigrationAddSchema_001(TDataStore *Manager) { /* * Create the schema table. */ Manager->ExecuteStmt("create table schema_info ( " "version integer not null default 0) "); Manager->ExecuteStmt("insert into schema_info (version) values (0) "); } //--------------------------------------------------------------------------- void MigrationAddScanStatus_002(TDataStore *Manager) { } //--------------------------------------------------------------------------- /* * When a new migration is necessary, simply add it to this list. */ TMigration Migrations[] = { MigrationAddSchema_001, //MigrationAddScanStatus_002 }; //--------------------------------------------------------------------------- /* * Determine the current schema version. If the schema_info table * is not present then the version is 0. */ int TDataStore::GetDBVersion() { TLocker Locker(QueryLock); try { CppSQLite3Query Results = ExecuteQuery("select version from schema_info"); if (Results.eof()) { return 0; } else { return Results.getIntField("version"); } } catch (...) { return 0; } } //--------------------------------------------------------------------------- void TDataStore::Migrate() { int StartingVersion = GetDBVersion(); for (unsigned int V = StartingVersion; V < sizeof(Migrations)/sizeof(*Migrations); V++) { LogMesg("Migrating data schema from %d to %d", V, V+1); Migrations[V](this); ExecuteStmt("update schema_info set version = " + Int2String(V+1)); } } //---------------------------------------------------------------------------