IBR-DTNSuite 0.6

daemon/src/core/SQLiteBundleStorage.h

Go to the documentation of this file.
00001 /*
00002  * SQLiteBundleStorage.h
00003  *
00004  *  Created on: 09.01.2010
00005  *      Author: Myrtus
00006  */
00007 
00008 
00009 #ifndef SQLITEBUNDLESTORAGE_H_
00010 #define SQLITEBUNDLESTORAGE_H_
00011 
00012 #include "BundleStorage.h"
00013 #include "Component.h"
00014 #include "EventReceiver.h"
00015 #include "core/BundleStorage.h"
00016 #include "core/EventReceiver.h"
00017 #include <ibrdtn/data/MetaBundle.h>
00018 
00019 #include <ibrcommon/thread/Thread.h>
00020 #include <ibrcommon/thread/Conditional.h>
00021 #include <ibrcommon/data/File.h>
00022 #include <ibrcommon/thread/Queue.h>
00023 
00024 #include <sqlite3.h>
00025 #include <string>
00026 #include <list>
00027 #include <set>
00028 
00029 //#define SQLITE_STORAGE_EXTENDED 1
00030 
00031 class SQLiteBundleStorageTest;
00032 
00033 namespace dtn
00034 {
00035         namespace core
00036         {
00037                 class SQLiteBundleStorage: public BundleStorage, public EventReceiver, public dtn::daemon::IndependentComponent, public ibrcommon::MutexInterface, public ibrcommon::BLOB::Provider
00038                 {
00039                         enum SQL_TABLES
00040                         {
00041                                 SQL_TABLE_BUNDLE = 0,
00042                                 SQL_TABLE_BLOCK = 1,
00043                                 SQL_TABLE_ROUTING = 2,
00044                                 SQL_TABLE_BUNDLE_ROUTING_INFO = 3,
00045                                 SQL_TABLE_NODE_ROUTING_INFO = 4,
00046                                 SQL_TABLE_END = 5
00047                         };
00048 
00049                         // enum of all possible statements
00050                         enum STORAGE_STMT
00051                         {
00052                                 BUNDLE_GET_FILTER,
00053                                 BUNDLE_GET_ID,
00054                                 FRAGMENT_GET_ID,
00055                                 BUNDLE_GET_FRAGMENT,
00056 
00057                                 EXPIRE_BUNDLES,
00058                                 EXPIRE_BUNDLE_FILENAMES,
00059                                 EXPIRE_BUNDLE_DELETE,
00060                                 EXPIRE_NEXT_TIMESTAMP,
00061 
00062                                 EMPTY_CHECK,
00063                                 COUNT_ENTRIES,
00064 
00065                                 BUNDLE_DELETE,
00066                                 FRAGMENT_DELETE,
00067                                 BUNDLE_CLEAR,
00068                                 BUNDLE_STORE,
00069                                 BUNDLE_UPDATE_CUSTODIAN,
00070                                 FRAGMENT_UPDATE_CUSTODIAN,
00071 
00072                                 PROCFLAGS_SET,
00073 
00074                                 BLOCK_GET_ID,
00075                                 BLOCK_GET_ID_FRAGMENT,
00076                                 BLOCK_GET,
00077                                 BLOCK_GET_FRAGMENT,
00078                                 BLOCK_CLEAR,
00079                                 BLOCK_STORE,
00080 
00081 #ifdef SQLITE_STORAGE_EXTENDED
00082                                 ROUTING_GET,
00083                                 ROUTING_REMOVE,
00084                                 ROUTING_CLEAR,
00085                                 ROUTING_STORE,
00086 
00087                                 NODE_GET,
00088                                 NODE_REMOVE,
00089                                 NODE_CLEAR,
00090                                 NODE_STORE,
00091 
00092                                 INFO_GET,
00093                                 INFO_REMOVE,
00094                                 INFO_STORE,
00095 #endif
00096 
00097                                 VACUUM,
00098                                 SQL_QUERIES_END
00099                         };
00100 
00101                         static const std::string _tables[SQL_TABLE_END];
00102 
00103                         // array of sql queries
00104                         static const std::string _sql_queries[SQL_QUERIES_END];
00105 
00106                         // array of the db structure as sql
00107                         static const std::string _db_structure[10];
00108 
00109                 public:
00110                         friend class ::SQLiteBundleStorageTest;
00111 
00112                         class SQLBundleQuery
00113                         {
00114                         public:
00115                                 SQLBundleQuery();
00116                                 virtual ~SQLBundleQuery() = 0;
00117 
00122                                 virtual const std::string getWhere() const = 0;
00123 
00130                                 virtual size_t bind(sqlite3_stmt*, size_t offset) const
00131                                 {
00132                                         return offset;
00133                                 }
00134 
00138                                 sqlite3_stmt *_statement;
00139                         };
00140 
00141                         class SQLiteQueryException : public ibrcommon::Exception
00142                         {
00143                         public:
00144                                 SQLiteQueryException(string what = "Unable to execute Querry.") throw(): Exception(what)
00145                                 {
00146                                 }
00147                         };
00148 
00153                         ibrcommon::BLOB::Reference create();
00154 
00161                         SQLiteBundleStorage(const ibrcommon::File &path, const size_t &size);
00162 
00166                         virtual ~SQLiteBundleStorage();
00167 
00171                         void openDatabase(const ibrcommon::File &path);
00172 
00177                         void store(const dtn::data::Bundle &bundle);
00178 
00185                         dtn::data::Bundle get(const dtn::data::BundleID &id);
00186 
00190                         const std::list<dtn::data::MetaBundle> get(BundleFilterCallback &cb);
00191 
00192 #ifdef SQLITE_STORAGE_EXTENDED
00193 
00198                         void storeBundleRoutingInfo(const data::BundleID &BundleID, const int &key, const string &routingInfo);
00199 
00205                         void storeNodeRoutingInfo(const data::EID &nodel, const int &key, const std::string &routingInfo);
00206 
00212                         void storeRoutingInfo(const int &key, const std::string &routingInfo);
00213 
00218                         std::string getBundleRoutingInfo(const data::BundleID &bundleID, const int &key);
00219 
00225                         std::string getNodeRoutingInfo(const data::EID &eid, const int &key);
00226 
00232                         std::string getRoutingInfo(const int &key);
00233 
00238                         void removeBundleRoutingInfo(const data::BundleID &bundleID, const int &key);
00239 
00244                         void removeNodeRoutingInfo(const data::EID &eid, const int &key);
00245 
00250                         void removeRoutingInfo(const int &key);
00251 #endif
00252 
00258                         void remove(const dtn::data::BundleID &id);
00259 
00263                         void clear();
00264 
00268                         void clearAll();
00269 
00273                         bool empty();
00274 
00278                         unsigned int count();
00279 
00283                         void releaseCustody(const dtn::data::EID &custodian, const dtn::data::BundleID &id);
00284 
00285 #ifdef SQLITE_STORAGE_EXTENDED
00286 
00291                         void setPriority(const int priority,const dtn::data::BundleID &id);
00292 
00299                         list<data::Block> getBlock(const data::BundleID &bundleID,const char &blocktype);
00300 
00305                         int occupiedSpace();
00306 #endif
00307 
00312                         void raiseEvent(const Event *evt);
00313 
00317                         virtual void trylock() throw (ibrcommon::MutexException);
00318 
00322                         virtual void enter() throw (ibrcommon::MutexException);
00323 
00327                         virtual void leave() throw (ibrcommon::MutexException);
00328 
00329                 protected:
00330                         virtual void componentRun();
00331                         virtual void componentUp();
00332                         virtual void componentDown();
00333                         bool __cancellation();
00334 
00335                 private:
00336                         enum Position
00337                         {
00338                                 FIRST_FRAGMENT  = 0,
00339                                 LAST_FRAGMENT   = 1,
00340                                 BOTH_FRAGMENTS  = 2
00341                         };
00342 
00343                         class AutoResetLock
00344                         {
00345                         public:
00346                                 AutoResetLock(ibrcommon::Mutex &mutex, sqlite3_stmt *st);
00347                                 ~AutoResetLock();
00348 
00349                         private:
00350                                 ibrcommon::MutexLock _lock;
00351                                 sqlite3_stmt *_st;
00352                         };
00353 
00354                         class Task
00355                         {
00356                         public:
00357                                 virtual ~Task() {};
00358                                 virtual void run(SQLiteBundleStorage &storage) = 0;
00359                         };
00360 
00361                         class BlockingTask : public Task
00362                         {
00363                         public:
00364                                 BlockingTask() : _done(false), _abort(false) {};
00365                                 virtual ~BlockingTask() {};
00366                                 virtual void run(SQLiteBundleStorage &storage) = 0;
00367 
00371                                 void wait()
00372                                 {
00373                                         ibrcommon::MutexLock l(_cond);
00374                                         while (!_done && !_abort) _cond.wait();
00375 
00376                                         if (_abort) throw ibrcommon::Exception("Task aborted");
00377                                 }
00378 
00379                                 void abort()
00380                                 {
00381                                         ibrcommon::MutexLock l(_cond);
00382                                         _abort = true;
00383                                         _cond.signal(true);
00384                                 }
00385 
00386                                 void done()
00387                                 {
00388                                         ibrcommon::MutexLock l(_cond);
00389                                         _done = true;
00390                                         _cond.signal(true);
00391                                 }
00392 
00393                         private:
00394                                 ibrcommon::Conditional _cond;
00395                                 bool _done;
00396                                 bool _abort;
00397                         };
00398 
00399                         class TaskRemove : public Task
00400                         {
00401                         public:
00402                                 TaskRemove(const dtn::data::BundleID &id)
00403                                  : _id(id) { };
00404 
00405                                 virtual ~TaskRemove() {};
00406                                 virtual void run(SQLiteBundleStorage &storage);
00407 
00408                         private:
00409                                 const dtn::data::BundleID _id;
00410                         };
00411 
00412                         class TaskIdle : public Task
00413                         {
00414                         public:
00415                                 TaskIdle() { };
00416 
00417                                 virtual ~TaskIdle() {};
00418                                 virtual void run(SQLiteBundleStorage &storage);
00419 
00420                                 static ibrcommon::Mutex _mutex;
00421                                 static bool _idle;
00422                         };
00423 
00424                         class TaskExpire : public Task
00425                         {
00426                         public:
00427                                 TaskExpire(size_t timestamp)
00428                                 : _timestamp(timestamp) { };
00429 
00430                                 virtual ~TaskExpire() {};
00431                                 virtual void run(SQLiteBundleStorage &storage);
00432 
00433                         private:
00434                                 size_t _timestamp;
00435                         };
00436 
00441                         class SQLiteBLOB : public ibrcommon::BLOB
00442                         {
00443                                 friend class SQLiteBundleStorage;
00444                         public:
00445                                 virtual ~SQLiteBLOB();
00446 
00447                                 virtual void clear();
00448 
00449                                 virtual void open();
00450                                 virtual void close();
00451 
00452                         protected:
00453                                 std::iostream &__get_stream()
00454                                 {
00455                                         return _filestream;
00456                                 }
00457 
00458                                 size_t __get_size();
00459 
00460                         private:
00461                                 SQLiteBLOB(const ibrcommon::File &path);
00462                                 std::fstream _filestream;
00463                                 ibrcommon::File _file;
00464                                 ibrcommon::File _blobPath;
00465                         };
00466 
00472                         dtn::data::MetaBundle get_meta(const dtn::data::BundleID &id);
00473 
00474                         void get(sqlite3_stmt *st, dtn::data::MetaBundle &bundle, size_t offset = 0);
00475                         void get(sqlite3_stmt *st, dtn::data::Bundle &bundle, size_t offset = 0);
00476 
00477 #ifdef SQLITE_STORAGE_EXTENDED
00478 
00482                         void storeFragment(const dtn::data::Bundle &bundle);
00483 #endif
00484 
00490                         sqlite3_stmt* prepare(const std::string &sqlquery);
00491 
00499                         int prepareBundle(list<std::string> &filenames, dtn::data::Bundle &bundle);
00500 
00506                         int store_blocks(const data::Bundle &Bundle);
00507 
00513                         void get_blocks(dtn::data::Bundle &bundle, const dtn::data::BundleID &id);
00514 
00518                         void check_consistency();
00519 
00520                         void check_fragments(set<string> &payloadFiles);
00521 
00522                         void check_bundles(set<string> &blockFiles);
00523 
00527                         void update_expire_time();
00528 
00532                         void update_custodian(const dtn::data::BundleID &b, const dtn::data::EID &custodian);
00533 
00538                         void new_expire_time(size_t ttl);
00539                         void reset_expire_time();
00540                         size_t get_expire_time();
00541 
00542                         void set_bundleid(sqlite3_stmt *st, const dtn::data::BundleID &id, size_t offset = 0) const;
00543                         void get_bundleid(sqlite3_stmt *st, dtn::data::BundleID &id, size_t offset = 0) const;
00544 
00548                         virtual const std::string getName() const;
00549 
00550                         ibrcommon::File dbPath;
00551                         ibrcommon::File dbFile;
00552                         ibrcommon::File _blobPath;
00553                         ibrcommon::File _blockPath;
00554 
00555                         int dbSize;
00556 
00557                         // holds the database handle
00558                         sqlite3 *_database;
00559 
00560                         // contains all jobs to do
00561                         ibrcommon::Queue<Task*> _tasks;
00562 
00563                         ibrcommon::Mutex _next_expiration_lock;
00564                         size_t _next_expiration;
00565 
00566                         // array of statements
00567                         sqlite3_stmt* _statements[SQL_QUERIES_END];
00568 
00569                         // array of locks for each statement
00570                         ibrcommon::Mutex _locks[SQL_QUERIES_END];
00571 
00572                         void add_deletion(const dtn::data::BundleID &id);
00573                         void remove_deletion(const dtn::data::BundleID &id);
00574                         bool contains_deletion(const dtn::data::BundleID &id);
00575 
00576                         // set of bundles to delete
00577                         ibrcommon::Mutex _deletion_mutex;
00578                         std::set<dtn::data::BundleID> _deletion_list;
00579                 };
00580         }
00581 }
00582 
00583 #endif /* SQLITEBUNDLESTORAGE_H_ */