39 const std::string SQLiteDatabase::TAG =
"SQLiteDatabase";
41 const std::string SQLiteDatabase::_select_names[] = {
42 "source, destination, reportto, custodian, procflags, timestamp, sequencenumber, lifetime, expiretime, fragmentoffset, appdatalength, hopcount, netpriority, payloadlength, bytes",
43 "source, timestamp, sequencenumber, fragmentoffset, payloadlength, bytes",
44 "`source`, `timestamp`, `sequencenumber`, `fragmentoffset`, `fragmentlength`, `expiretime`"
47 const std::string SQLiteDatabase::_where_filter[] = {
48 "source = ? AND timestamp = ? AND sequencenumber = ? AND fragmentoffset = ? AND fragmentlength = ?",
49 "a.source = b.source AND a.timestamp = b.timestamp AND a.sequencenumber = b.sequencenumber AND a.fragmentoffset = b.fragmentoffset AND a.fragmentlength = b.fragmentlength"
52 const std::string SQLiteDatabase::_tables[] =
53 {
"bundles",
"blocks",
"routing",
"routing_bundles",
"routing_nodes",
"properties",
"bundle_set",
"bundle_set_names" };
56 const int SQLiteDatabase::DBSCHEMA_FRESH_VERSION = 8;
58 const int SQLiteDatabase::DBSCHEMA_VERSION = 8;
60 const std::string SQLiteDatabase::QUERY_SCHEMAVERSION =
"SELECT `value` FROM " + SQLiteDatabase::_tables[SQLiteDatabase::SQL_TABLE_PROPERTIES] +
" WHERE `key` = 'version' LIMIT 0,1;";
61 const std::string SQLiteDatabase::SET_SCHEMAVERSION =
"INSERT INTO " + SQLiteDatabase::_tables[SQLiteDatabase::SQL_TABLE_PROPERTIES] +
" (`key`, `value`) VALUES ('version', ?);";
63 const std::string SQLiteDatabase::_sql_queries[SQL_QUERIES_END] =
65 "SELECT " + _select_names[0] +
" FROM " + _tables[SQL_TABLE_BUNDLE],
66 "SELECT " + _select_names[0] +
" FROM " + _tables[SQL_TABLE_BUNDLE] +
" ORDER BY priority DESC, timestamp, sequencenumber, fragmentoffset, fragmentlength LIMIT ?,?;",
67 "SELECT " + _select_names[0] +
" FROM "+ _tables[SQL_TABLE_BUNDLE] +
" WHERE " + _where_filter[0] +
" LIMIT 1;",
68 "SELECT bytes FROM "+ _tables[SQL_TABLE_BUNDLE] +
" WHERE " + _where_filter[0] +
" LIMIT 1;",
69 "SELECT DISTINCT destination FROM " + _tables[SQL_TABLE_BUNDLE],
72 "SELECT " + _select_names[1] +
" FROM "+ _tables[SQL_TABLE_BUNDLE] +
" WHERE expiretime <= ?;",
73 "SELECT filename FROM "+ _tables[SQL_TABLE_BUNDLE] +
" as a, "+ _tables[SQL_TABLE_BLOCK] +
" as b WHERE " + _where_filter[1] +
" AND a.expiretime <= ?;",
74 "DELETE FROM "+ _tables[SQL_TABLE_BUNDLE] +
" WHERE expiretime <= ?;",
75 "SELECT expiretime FROM "+ _tables[SQL_TABLE_BUNDLE] +
" ORDER BY expiretime ASC LIMIT 1;",
77 "SELECT ROWID FROM "+ _tables[SQL_TABLE_BUNDLE] +
" LIMIT 1;",
78 "SELECT COUNT(ROWID) FROM "+ _tables[SQL_TABLE_BUNDLE] +
";",
80 "DELETE FROM "+ _tables[SQL_TABLE_BUNDLE] +
" WHERE " + _where_filter[0] +
";",
81 "DELETE FROM "+ _tables[SQL_TABLE_BUNDLE] +
";",
82 "INSERT INTO "+ _tables[SQL_TABLE_BUNDLE] +
" (source, timestamp, sequencenumber, fragmentoffset, fragmentlength, destination, reportto, custodian, procflags, lifetime, appdatalength, expiretime, priority, hopcount, netpriority, payloadlength, bytes) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);",
83 "UPDATE "+ _tables[SQL_TABLE_BUNDLE] +
" SET custodian = ? WHERE " + _where_filter[0] +
";",
85 "UPDATE "+ _tables[SQL_TABLE_BUNDLE] +
" SET procflags = ? WHERE " + _where_filter[0] +
";",
88 "SELECT filename, blocktype FROM "+ _tables[SQL_TABLE_BLOCK] +
" WHERE " + _where_filter[0] +
" ORDER BY ordernumber ASC;",
89 "SELECT filename, blocktype FROM "+ _tables[SQL_TABLE_BLOCK] +
" WHERE " + _where_filter[0] +
" AND ordernumber = ?;",
90 "DELETE FROM "+ _tables[SQL_TABLE_BLOCK] +
";",
91 "INSERT INTO "+ _tables[SQL_TABLE_BLOCK] +
" (source, timestamp, sequencenumber, fragmentoffset, fragmentlength, blocktype, filename, ordernumber) VALUES (?,?,?,?,?,?,?,?);",
94 "INSERT INTO " + _tables[SQL_TABLE_BUNDLE_SET] +
" (set_id, source, timestamp, sequencenumber, fragmentoffset, fragmentlength, expiretime) VALUES (?,?,?,?,?,?,?);",
95 "DELETE FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ?;",
96 "SELECT " + _select_names[2] +
" FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ? AND " + _where_filter[0] +
" LIMIT 1;",
97 "SELECT " + _select_names[2] +
" FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ? AND expiretime <= ?;",
98 "DELETE FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ? AND expiretime <= ?;",
99 "SELECT " + _select_names[2] +
" FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ?;",
100 "SELECT COUNT(*) FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ?;",
101 "SELECT expiretime FROM "+ _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ? ORDER BY expiretime ASC LIMIT 1;",
102 "INSERT INTO " + _tables[SQL_TABLE_BUNDLE_SET] +
" SELECT " + _select_names[2] +
", ? FROM " + _tables[SQL_TABLE_BUNDLE_SET] +
" WHERE set_id = ?;",
105 "INSERT INTO " + _tables[SQL_TABLE_BUNDLE_SET_NAME] +
" (name, persistent) VALUES (?, ?);",
106 "SELECT id FROM " + _tables[SQL_TABLE_BUNDLE_SET_NAME] +
" WHERE name = ? AND persistent = ? LIMIT 0, 1;",
107 "DELETE FROM " + _tables[SQL_TABLE_BUNDLE_SET_NAME] +
" WHERE id = ? LIMIT 0, 1;",
112 const std::string SQLiteDatabase::_db_structure[SQLiteDatabase::DB_STRUCTURE_END] =
114 "CREATE TABLE IF NOT EXISTS `" + _tables[SQL_TABLE_BLOCK] +
"` ( `key` INTEGER PRIMARY KEY ASC, `source` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `sequencenumber` INTEGER NOT NULL, `fragmentoffset` INTEGER NOT NULL DEFAULT 0, `fragmentlength` INTEGER NOT NULL DEFAULT 0, `blocktype` INTEGER NOT NULL, `filename` TEXT NOT NULL, `ordernumber` INTEGER NOT NULL);",
115 "CREATE TABLE IF NOT EXISTS `" + _tables[SQL_TABLE_BUNDLE] +
"` ( `key` INTEGER PRIMARY KEY ASC, `source` TEXT NOT NULL, `destination` TEXT NOT NULL, `reportto` TEXT NOT NULL, `custodian` TEXT NOT NULL, `procflags` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `sequencenumber` INTEGER NOT NULL, `lifetime` INTEGER NOT NULL, `fragmentoffset` INTEGER NOT NULL DEFAULT 0, `appdatalength` INTEGER NOT NULL DEFAULT 0, `fragmentlength` INTEGER NOT NULL DEFAULT 0, `expiretime` INTEGER NOT NULL, `priority` INTEGER NOT NULL, `hopcount` INTEGER DEFAULT NULL, `netpriority` INTEGER NOT NULL DEFAULT 0, `payloadlength` INTEGER NOT NULL DEFAULT 0, `bytes` INTEGER NOT NULL DEFAULT 0);",
116 "CREATE TABLE IF NOT EXISTS "+ _tables[SQL_TABLE_ROUTING] +
" (INTEGER PRIMARY KEY ASC, KEY INT, Routing TEXT);",
117 "CREATE TABLE IF NOT EXISTS "+ _tables[SQL_TABLE_BUNDLE_ROUTING_INFO] +
" (INTEGER PRIMARY KEY ASC, BundleID TEXT, KEY INT, Routing TEXT);",
118 "CREATE TABLE IF NOT EXISTS "+ _tables[SQL_TABLE_NODE_ROUTING_INFO] +
" (INTEGER PRIMARY KEY ASC, EID text, KEY INT, Routing TEXT);",
119 "CREATE TRIGGER IF NOT EXISTS blocks_autodelete AFTER DELETE ON " + _tables[SQL_TABLE_BUNDLE] +
" FOR EACH ROW BEGIN DELETE FROM " + _tables[SQL_TABLE_BLOCK] +
" WHERE " + _tables[SQL_TABLE_BLOCK] +
".source = OLD.source AND " + _tables[SQL_TABLE_BLOCK] +
".timestamp = OLD.timestamp AND " + _tables[SQL_TABLE_BLOCK] +
".sequencenumber = OLD.sequencenumber AND " + _tables[SQL_TABLE_BLOCK] +
".fragmentoffset = OLD.fragmentoffset AND " + _tables[SQL_TABLE_BLOCK] +
".fragmentlength = OLD.fragmentlength; END;",
120 "CREATE INDEX IF NOT EXISTS blocks_bid ON " + _tables[SQL_TABLE_BLOCK] +
" (source, timestamp, sequencenumber, fragmentoffset, fragmentlength);",
121 "CREATE INDEX IF NOT EXISTS bundles_destination ON " + _tables[SQL_TABLE_BUNDLE] +
" (destination);",
122 "CREATE INDEX IF NOT EXISTS bundles_destination_priority ON " + _tables[SQL_TABLE_BUNDLE] +
" (destination, priority);",
123 "CREATE UNIQUE INDEX IF NOT EXISTS bundles_id ON " + _tables[SQL_TABLE_BUNDLE] +
" (source, timestamp, sequencenumber, fragmentoffset, fragmentlength);"
124 "CREATE INDEX IF NOT EXISTS bundles_expire ON " + _tables[SQL_TABLE_BUNDLE] +
" (source, timestamp, sequencenumber, fragmentoffset, fragmentlength, expiretime);",
125 "CREATE TABLE IF NOT EXISTS '" + _tables[SQL_TABLE_PROPERTIES] +
"' ( `key` TEXT PRIMARY KEY ASC ON CONFLICT REPLACE, `value` TEXT NOT NULL);",
126 "CREATE TABLE IF NOT EXISTS " + _tables[SQL_TABLE_BUNDLE_SET] +
" (`source` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `sequencenumber` INTEGER NOT NULL, `fragmentoffset` INTEGER NOT NULL, `fragmentlength` INTEGER NOT NULL, `expiretime` INTEGER, `set_id` INTEGER, PRIMARY KEY(`set_id`, `source`, `timestamp`, `sequencenumber`, `fragmentoffset`, `fragmentlength`));",
127 "CREATE TABLE IF NOT EXISTS " + _tables[SQL_TABLE_BUNDLE_SET_NAME] +
" (`id` INTEGER PRIMARY KEY, `name` TEXT NOT NULL, `persistent` INTEGER NOT NULL);",
128 "CREATE UNIQUE INDEX IF NOT EXISTS bundle_set_names_index ON " + _tables[SQL_TABLE_BUNDLE_SET_NAME] +
" (`name`, `persistent`);"
139 : _database(database), _st(NULL), _query(query)
147 sqlite3_finalize(_st);
160 sqlite3_clear_bindings(_st);
167 throw SQLiteQueryException(
"statement not prepared");
169 int ret = sqlite3_step(_st);
175 throw SQLiteQueryException(
"Database is corrupt: " + std::string(sqlite3_errmsg(_database)));
177 case SQLITE_INTERRUPT:
178 throw SQLiteQueryException(
"Database interrupt: " + std::string(sqlite3_errmsg(_database)));
181 throw SQLiteQueryException(
"Database schema error: " + std::string(sqlite3_errmsg(_database)));
184 throw SQLiteQueryException(
"Database error: " + std::string(sqlite3_errmsg(_database)));
194 throw SQLiteQueryException(
"already prepared");
196 int err = sqlite3_prepare_v2(_database, _query.c_str(),
static_cast<int>(_query.length()), &_st, 0);
198 if ( err != SQLITE_OK )
199 throw SQLiteQueryException(
"failed to prepare statement: " + _query);
205 : _file(file), _database(NULL), _next_expiration(0), _listener(listener), _faulty(false)
213 int SQLiteDatabase::getVersion() throw (
SQLiteDatabase::SQLiteQueryException)
219 Statement st(_database, QUERY_SCHEMAVERSION);
225 if (err == SQLITE_ROW)
227 std::string dbversion = (
const char*) sqlite3_column_text(*st, 0);
228 std::stringstream ss(dbversion);
235 void SQLiteDatabase::setVersion(
int version)
throw (SQLiteDatabase::SQLiteQueryException)
237 std::stringstream ss; ss << version;
238 Statement st(_database, SET_SCHEMAVERSION);
241 sqlite3_bind_text(*st, 1, ss.str().c_str(),
static_cast<int>(ss.str().length()), SQLITE_TRANSIENT);
244 if(err != SQLITE_DONE)
252 if (oldVersion > newVersion)
258 if ((oldVersion != 0) && (oldVersion < DBSCHEMA_FRESH_VERSION))
265 for (
int j = oldVersion; j < newVersion; ++j)
271 for (
size_t i = 0; i < SQL_TABLE_END; ++i)
273 Statement st(_database,
"DROP TABLE IF EXISTS " + _tables[i] +
";");
275 if(err != SQLITE_DONE)
282 for (
size_t i = 0; i < (DB_STRUCTURE_END - 1); ++i)
284 Statement st(_database, _db_structure[i]);
286 if(err != SQLITE_DONE)
293 setVersion(DBSCHEMA_FRESH_VERSION);
294 j = DBSCHEMA_FRESH_VERSION;
299 if (DBSCHEMA_FRESH_VERSION > j)
311 if (sqlite3_threadsafe() == 0)
318 if (sqlite3_open_v2(_file.
getPath().c_str(), &_database, SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL))
321 sqlite3_close(_database);
326 int version = getVersion();
330 if (version != DBSCHEMA_VERSION)
332 doUpgrade(version, DBSCHEMA_VERSION);
336 doUpgrade(0, DBSCHEMA_VERSION);
340 sqlite3_exec(_database,
"PRAGMA synchronous = OFF;", NULL, NULL, NULL);
349 update_expire_time();
355 if (sqlite3_close(_database) != SQLITE_OK)
367 Statement st(_database, _sql_queries[BUNDLE_GET_ID]);
370 set_bundleid(st,
id);
373 if ((st.
step() != SQLITE_ROW) || _faulty)
376 error <<
"No Bundle found with BundleID: " <<
id.toString();
378 throw SQLiteQueryException(error.str());
388 bundle.source =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset) );
389 bundle.destination =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 1) );
390 bundle.reportto =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 2) );
391 bundle.custodian =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 3) );
394 throw SQLiteDatabase::SQLiteQueryException(
"unable to read EIDs from database");
397 bundle.procflags = sqlite3_column_int(*st, offset + 4);
398 bundle.timestamp = sqlite3_column_int64(*st, offset + 5);
399 bundle.sequencenumber = sqlite3_column_int64(*st, offset + 6);
400 bundle.lifetime = sqlite3_column_int64(*st, offset + 7);
401 bundle.expiretime = sqlite3_column_int64(*st, offset + 8);
405 bundle.setFragment(
true);
406 bundle.fragmentoffset = sqlite3_column_int64(*st, offset + 9);
407 bundle.appdatalength = sqlite3_column_int64(*st, offset + 10);
411 bundle.setFragment(
false);
412 bundle.fragmentoffset = 0;
413 bundle.appdatalength = 0;
416 if (sqlite3_column_type(*st, offset + 11) != SQLITE_NULL)
418 bundle.hopcount = sqlite3_column_int64(*st, 11);
426 bundle.net_priority = sqlite3_column_int(*st, 12);
429 bundle.setPayloadLength(sqlite3_column_int64(*st, offset + 13));
435 bundle.source =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 0) );
436 bundle.destination =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 1) );
437 bundle.reportto =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 2) );
438 bundle.custodian =
dtn::data::EID( (
const char*) sqlite3_column_text(*st, offset + 3) );
441 throw SQLiteDatabase::SQLiteQueryException(
"unable to read EIDs from database");
444 bundle.procflags = sqlite3_column_int(*st, offset + 4);
445 bundle.timestamp = sqlite3_column_int64(*st, offset + 5);
446 bundle.sequencenumber = sqlite3_column_int64(*st, offset + 6);
447 bundle.lifetime = sqlite3_column_int64(*st, offset + 7);
452 bundle.fragmentoffset = sqlite3_column_int64(*st, offset + 9);
453 bundle.appdatalength = sqlite3_column_int64(*st, offset + 10);
459 Statement st(_database, _sql_queries[BUNDLE_GET_ITERATOR]);
461 while (st.
step() == SQLITE_ROW)
477 size_t items_added = 0;
479 const std::string base_query =
480 "SELECT " + _select_names[0] +
" FROM " + _tables[SQL_TABLE_BUNDLE];
483 const bool unlimited = (cb.limit() <= 0);
484 const size_t query_limit = 50;
491 const std::string query_string = base_query +
" WHERE " + query.
getWhere() +
" ORDER BY priority DESC, timestamp, sequencenumber, fragmentoffset, fragmentlength LIMIT ?,?;";
496 while (unlimited || (items_added < query_limit))
499 int bind_offset = query.
bind(*st, 1);
502 __get(cb, st, ret, items_added, bind_offset, offset, query_limit);
505 offset += query_limit;
507 }
catch (
const std::bad_cast&) {
508 Statement st(_database, _sql_queries[BUNDLE_GET_FILTER]);
510 while (unlimited || (items_added < query_limit))
513 __get(cb, st, ret, items_added, 1, offset, query_limit);
516 offset += query_limit;
528 const bool unlimited = (cb.limit() <= 0);
531 sqlite3_bind_int64(*st, bind_offset, offset);
532 sqlite3_bind_int64(*st, bind_offset + 1, query_limit);
535 if ((st.step() == SQLITE_DONE) || _faulty)
539 while (unlimited || (items_added < query_limit))
560 if (st.step() != SQLITE_ROW)
break;
573 Statement st(_database, _sql_queries[BUNDLE_GET_ID]);
576 set_bundleid(st,
id);
579 if (((err = st.
step()) != SQLITE_ROW) || _faulty)
593 Statement st(_database, _sql_queries[BLOCK_GET_ID]);
596 set_bundleid(st,
id);
599 while ((err = st.
step()) == SQLITE_ROW)
602 int blocktyp = sqlite3_column_int(*st, 1);
607 if (err == SQLITE_DONE)
609 if (blocks.size() == 0)
612 throw SQLiteQueryException(
"no blocks found");
618 throw SQLiteQueryException(
"can not query for blocks");
631 Statement st(_database, _sql_queries[BUNDLE_STORE]);
633 set_bundleid(st, bundle);
635 sqlite3_bind_text(*st, 6, bundle.destination.getString().c_str(),
static_cast<int>(bundle.destination.getString().length()), SQLITE_TRANSIENT);
636 sqlite3_bind_text(*st, 7, bundle.reportto.getString().c_str(),
static_cast<int>(bundle.reportto.getString().length()), SQLITE_TRANSIENT);
637 sqlite3_bind_text(*st, 8, bundle.custodian.getString().c_str(),
static_cast<int>(bundle.custodian.getString().length()), SQLITE_TRANSIENT);
638 sqlite3_bind_int(*st, 9, bundle.procflags.get<uint32_t>());
639 sqlite3_bind_int64(*st, 10, bundle.lifetime.get<uint64_t>());
643 sqlite3_bind_int64(*st, 11, bundle.appdatalength.get<uint64_t>());
647 sqlite3_bind_int64(*st, 11, -1);
651 sqlite3_bind_int64(*st, 12, expire_time.
get<uint64_t>());
653 sqlite3_bind_int64(*st, 13, bundle.getPriority());
659 sqlite3_bind_null(*st, 14 );
666 sqlite3_bind_int64(*st, 15, 0 );
670 sqlite3_bind_int64(*st, 16, bundle.getPayloadLength());
673 sqlite3_bind_int64(*st, 17, size);
677 if (err == SQLITE_CONSTRAINT)
682 error <<
"store() failure: " << err <<
" " << sqlite3_errmsg(_database);
683 throw SQLiteQueryException(error.str());
685 else if ((err != SQLITE_DONE) || _faulty)
688 error <<
"store() failure: " << err <<
" " << sqlite3_errmsg(_database);
691 throw SQLiteQueryException(error.str());
695 new_expire_time(expire_time);
700 int blocktyp = (int)block.getType();
703 Statement st(_database, _sql_queries[BLOCK_STORE]);
706 set_bundleid(st,
id);
709 sqlite3_bind_int(*st, 6, blocktyp);
712 sqlite3_bind_text(*st, 7, file.getPath().c_str(),
static_cast<int>(file.getPath().size()), SQLITE_TRANSIENT);
715 sqlite3_bind_int(*st, 8, index);
718 if (st.
step() != SQLITE_DONE)
720 throw SQLiteQueryException(
"can not store block of bundle");
729 int ret = sqlite3_exec(_database,
"BEGIN TRANSACTION;", NULL, NULL, &zErrMsg);
732 if ( ret != SQLITE_OK )
734 sqlite3_free( zErrMsg );
735 throw SQLiteQueryException( zErrMsg );
744 int ret = sqlite3_exec(_database,
"ROLLBACK TRANSACTION;", NULL, NULL, &zErrMsg);
747 if ( ret != SQLITE_OK )
749 sqlite3_free( zErrMsg );
750 throw SQLiteQueryException( zErrMsg );
759 int ret = sqlite3_exec(_database,
"END TRANSACTION;", NULL, NULL, &zErrMsg);
762 if ( ret != SQLITE_OK )
764 sqlite3_free( zErrMsg );
765 throw SQLiteQueryException( zErrMsg );
776 Statement st(_database, _sql_queries[BUNDLE_GET_LENGTH_ID]);
779 set_bundleid(st,
id);
782 if (st.
step() != SQLITE_ROW)
789 ret = sqlite3_column_int(*st, 0);
795 Statement st(_database, _sql_queries[BLOCK_GET_ID]);
798 set_bundleid(st,
id);
801 while (st.
step() == SQLITE_ROW)
811 Statement st(_database, _sql_queries[BUNDLE_DELETE]);
814 set_bundleid(st,
id);
821 update_expire_time();
830 Statement bundle_clear(_database, _sql_queries[BUNDLE_CLEAR]);
831 Statement block_clear(_database, _sql_queries[BLOCK_CLEAR]);
836 if (SQLITE_DONE != vacuum.
step())
838 throw SQLiteQueryException(
"SQLiteBundleStore: clear(): vacuum failed.");
847 Statement st(_database, _sql_queries[BUNDLE_GET_ID]);
850 set_bundleid(st,
id);
853 return !((st.
step() != SQLITE_ROW) || _faulty);
858 Statement st(_database, _sql_queries[EMPTY_CHECK]);
860 if (SQLITE_DONE == st.
step())
875 Statement st(_database, _sql_queries[COUNT_ENTRIES]);
877 if ((err = st.
step()) == SQLITE_ROW)
879 rows = sqlite3_column_int(*st, 0);
884 error <<
"count: failure " << err <<
" " << sqlite3_errmsg(_database);
885 throw SQLiteQueryException(error.str());
893 std::set<dtn::data::EID> ret;
895 Statement st(_database, _sql_queries[GET_DISTINCT_DESTINATIONS]);
898 while (st.
step() == SQLITE_ROW)
901 const std::string destination( (
const char*)sqlite3_column_text(*st, 0) );
902 ret.insert(destination);
908 void SQLiteDatabase::update_expire_time() throw (
SQLiteDatabase::SQLiteQueryException)
910 Statement st(_database, _sql_queries[EXPIRE_NEXT_TIMESTAMP]);
914 if (err == SQLITE_ROW)
916 _next_expiration = sqlite3_column_int64(*st, 0);
920 _next_expiration = 0;
930 if ((timestamp < exp_time) || (exp_time == 0))
return;
939 Statement st(_database, _sql_queries[EXPIRE_BUNDLE_FILENAMES]);
942 sqlite3_bind_int64(*st, 1, timestamp.get<uint64_t>());
943 while (st.
step() == SQLITE_ROW)
953 Statement st(_database, _sql_queries[EXPIRE_BUNDLES]);
958 sqlite3_bind_int64(*st, 1, timestamp.get<uint64_t>());
959 while (st.
step() == SQLITE_ROW)
961 id.source =
dtn::data::EID((
const char*)sqlite3_column_text(*st, 0));
962 id.timestamp = sqlite3_column_int64(*st, 1);
963 id.sequencenumber = sqlite3_column_int64(*st, 2);
965 id.setFragment(sqlite3_column_int64(*st, 3) >= 0);
967 if (
id.isFragment()) {
968 id.fragmentoffset = sqlite3_column_int64(*st, 3);
970 id.fragmentoffset = 0;
973 id.setPayloadLength(sqlite3_column_int64(*st, 4));
978 _listener.eventBundleExpired(
id, sqlite3_column_int(*st, 5));
985 Statement st(_database, _sql_queries[EXPIRE_BUNDLE_DELETE]);
988 sqlite3_bind_int64(*st, 1, timestamp.get<uint64_t>());
996 update_expire_time();
1004 Statement st(_database, _sql_queries[VACUUM]);
1010 if (mode == UPDATE_CUSTODIAN)
1013 Statement st(_database, _sql_queries[BUNDLE_UPDATE_CUSTODIAN]);
1015 sqlite3_bind_text(*st, 1, eid.getString().c_str(),
static_cast<int>(eid.getString().length()), SQLITE_TRANSIENT);
1016 set_bundleid(st,
id, 1);
1019 int err = st.
step();
1021 if (err != SQLITE_DONE)
1024 error <<
"update_custodian() failure: " << err <<
" " << sqlite3_errmsg(_database);
1032 if (_next_expiration == 0 || ttl < _next_expiration)
1034 _next_expiration = ttl;
1038 void SQLiteDatabase::reset_expire_time() throw ()
1040 _next_expiration = 0;
1045 return _next_expiration;
1048 void SQLiteDatabase::set_bundleid(Statement &st,
const dtn::data::BundleID &
id,
int offset)
const throw (SQLiteDatabase::SQLiteQueryException)
1050 sqlite3_bind_text(*st, offset + 1,
id.source.getString().c_str(),
static_cast<int>(
id.source.getString().length()), SQLITE_TRANSIENT);
1051 sqlite3_bind_int64(*st, offset + 2,
id.timestamp.get<uint64_t>());
1052 sqlite3_bind_int64(*st, offset + 3,
id.sequencenumber.get<uint64_t>());
1054 if (
id.isFragment())
1056 sqlite3_bind_int64(*st, offset + 4,
id.fragmentoffset.get<uint64_t>());
1057 sqlite3_bind_int64(*st, offset + 5,
id.getPayloadLength());
1061 sqlite3_bind_int64(*st, offset + 4, -1);
1062 sqlite3_bind_int64(*st, offset + 5, -1);