00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <oasys/storage/DurableStore.h>
00040 #include <oasys/storage/StorageConfig.h>
00041 #include <oasys/serialize/TypeShims.h>
00042 #include <oasys/thread/Mutex.h>
00043
00044 #include "GlobalStore.h"
00045 #include "reg/Registration.h"
00046
00047 namespace dtn {
00048
00049 const u_int32_t GlobalStore::CURRENT_VERSION = 2;
00050 static const char* GLOBAL_TABLE = "globals";
00051 static const char* GLOBAL_KEY = "global_key";
00052
00053 class Globals : public oasys::SerializableObject
00054 {
00055 public:
00056 Globals() {}
00057 Globals(const oasys::Builder&) {}
00058
00059 u_int32_t version_;
00060 u_int32_t next_bundleid_;
00061 u_int32_t next_regid_;
00062
00066 virtual void serialize(oasys::SerializeAction* a);
00067
00068 };
00069
00070 void
00071 Globals::serialize(oasys::SerializeAction* a)
00072 {
00073 a->process("version", &version_);
00074 a->process("next_bundleid", &next_bundleid_);
00075 a->process("next_regid", &next_regid_);
00076 }
00077
00078 GlobalStore* GlobalStore::instance_;
00079
00080 GlobalStore::GlobalStore()
00081 : Logger("GlobalStore", "/dtn/storage/%s", GLOBAL_TABLE),
00082 globals_(NULL), store_(NULL)
00083 {
00084 lock_ = new oasys::Mutex(logpath_,
00085 oasys::Mutex::TYPE_RECURSIVE,
00086 true );
00087 }
00088
00089 int
00090 GlobalStore::init(const oasys::StorageConfig& cfg,
00091 oasys::DurableStore* store)
00092 {
00093 if (instance_ != NULL)
00094 {
00095 PANIC("GlobalStore::init called multiple times");
00096 }
00097
00098 instance_ = new GlobalStore();
00099 return instance_->do_init(cfg, store);
00100 }
00101
00102 int
00103 GlobalStore::do_init(const oasys::StorageConfig& cfg,
00104 oasys::DurableStore* store)
00105 {
00106 int flags = 0;
00107
00108 if (cfg.init_) {
00109 flags |= oasys::DS_CREATE;
00110 }
00111
00112 int err = store->get_table(&store_, GLOBAL_TABLE, flags);
00113
00114 if (err != 0) {
00115 log_err("error initializing global store: %s",
00116 (err == oasys::DS_NOTFOUND) ?
00117 "table not found" :
00118 "unknown error");
00119 return err;
00120 }
00121
00122
00123
00124 if (cfg.init_)
00125 {
00126 log_info("initializing global table");
00127
00128 globals_ = new Globals();
00129
00130 globals_->version_ = CURRENT_VERSION;
00131 globals_->next_bundleid_ = 0;
00132 globals_->next_regid_ = Registration::MAX_RESERVED_REGID + 1;
00133
00134
00135 err = store_->put(oasys::StringShim(GLOBAL_KEY), globals_,
00136 oasys::DS_CREATE | oasys::DS_EXCL);
00137
00138 if (err == oasys::DS_EXISTS)
00139 {
00140
00141 __log_err("/dtnd", "Initializing datastore which already exists.");
00142 exit(1);
00143 } else if (err != 0) {
00144 log_err("unknown error initializing global store");
00145 return err;
00146 }
00147
00148 loaded_ = true;
00149
00150 } else {
00151 loaded_ = false;
00152 }
00153
00154 return 0;
00155 }
00156
00157 GlobalStore::~GlobalStore()
00158 {
00159 delete store_;
00160 delete globals_;
00161 delete lock_;
00162 }
00163
00169 u_int32_t
00170 GlobalStore::next_bundleid()
00171 {
00172 oasys::ScopeLock l(lock_, "GlobalStore::next_bundleid");
00173
00174 ASSERT(globals_->next_bundleid_ != 0xffffffff);
00175 log_debug("next_bundleid %d -> %d",
00176 globals_->next_bundleid_,
00177 globals_->next_bundleid_ + 1);
00178
00179 u_int32_t ret = globals_->next_bundleid_++;
00180
00181 update();
00182
00183 return ret;
00184 }
00185
00192 u_int32_t
00193 GlobalStore::next_regid()
00194 {
00195 oasys::ScopeLock l(lock_, "GlobalStore::next_regid");
00196
00197 ASSERT(globals_->next_regid_ != 0xffffffff);
00198 log_debug("next_regid %d -> %d",
00199 globals_->next_regid_,
00200 globals_->next_regid_ + 1);
00201
00202 u_int32_t ret = globals_->next_regid_++;
00203
00204 update();
00205
00206 return ret;
00207 }
00208
00212 bool
00213 GlobalStore::load()
00214 {
00215 log_debug("loading global store");
00216
00217 oasys::StringShim key(GLOBAL_KEY);
00218
00219 if (globals_ != NULL) {
00220 delete globals_;
00221 globals_ = NULL;
00222 }
00223
00224 if (store_->get(key, &globals_) != 0) {
00225 log_crit("error loading global data");
00226 return false;
00227 }
00228 ASSERT(globals_ != NULL);
00229
00230 if (globals_->version_ != CURRENT_VERSION) {
00231 log_crit("datastore version mismatch: "
00232 "expected version %d, database version %d",
00233 CURRENT_VERSION, globals_->version_);
00234 return false;
00235 }
00236
00237 loaded_ = true;
00238 return true;
00239 }
00240
00241 void
00242 GlobalStore::update()
00243 {
00244 ASSERT(lock_->is_locked_by_me());
00245
00246 log_debug("updating global store");
00247
00248
00249
00250 ASSERT(loaded_);
00251
00252 int err = store_->put(oasys::StringShim(GLOBAL_KEY), globals_, 0);
00253
00254 if (err != 0) {
00255 PANIC("GlobalStore::update fatal error updating database: %s",
00256 oasys::durable_strerror(err));
00257 }
00258 }
00259
00260 void
00261 GlobalStore::close()
00262 {
00263
00264
00265
00266 lock_->lock("GlobalStore::close");
00267
00268 delete store_;
00269 store_ = NULL;
00270
00271 delete instance_;
00272 instance_ = NULL;
00273 }
00274
00275 }