|
IBR-DTNSuite 0.6
|
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_ */