GlobalStore.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 /* quiet */);
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     // if we're initializing the database for the first time, then we
00123     // prime the values accordingly and sync the database version
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         // store the new value
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             // YUCK
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     // make certain we don't attempt to write out globals before
00249     // load() has had a chance to load them from the database
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     // we prevent the potential for shutdown race crashes by leaving
00264     // the global store locked after it's been closed so other threads
00265     // will simply block, not crash due to a null store
00266     lock_->lock("GlobalStore::close");
00267     
00268     delete store_;
00269     store_ = NULL;
00270 
00271     delete instance_;
00272     instance_ = NULL;
00273 }
00274 
00275 } // namespace dtn

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1