DTNServer.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <unistd.h>
00020 
00021 #include <oasys/storage/BerkeleyDBStore.h>
00022 #include <oasys/io/FileUtils.h>
00023 
00024 #include "config.h"
00025 #include "DTNServer.h"
00026 
00027 #include "applib/APIServer.h"
00028 
00029 #include "bundling/BundleDaemon.h"
00030 
00031 #include "contacts/InterfaceTable.h"
00032 #include "contacts/ContactManager.h"
00033 
00034 #include "cmd/CompletionNotifier.h"
00035 #include "cmd/BundleCommand.h"
00036 #include "cmd/InterfaceCommand.h"
00037 #include "cmd/LinkCommand.h"
00038 #include "cmd/ParamCommand.h"
00039 #include "cmd/RegistrationCommand.h"
00040 #include "cmd/RouteCommand.h"
00041 #include "cmd/DiscoveryCommand.h"
00042 #include "cmd/ProphetCommand.h"
00043 #include "cmd/ShutdownCommand.h"
00044 #include "cmd/StorageCommand.h"
00045 
00046 #include "conv_layers/ConvergenceLayer.h"
00047 #include "discovery/DiscoveryTable.h"
00048 
00049 #include "naming/SchemeTable.h"
00050 
00051 #include "reg/AdminRegistration.h"
00052 #include "reg/RegistrationTable.h"
00053 
00054 #include "routing/BundleRouter.h"
00055 
00056 #include "storage/BundleStore.h"
00057 #include "storage/LinkStore.h"
00058 #include "storage/GlobalStore.h"
00059 #include "storage/RegistrationStore.h"
00060 #include "storage/DTNStorageConfig.h"
00061 
00062 //#include <oasys/storage/MySQLStore.h>
00063 //#include <oasys/storage/PostgresqlStore.h>
00064 
00065 namespace dtn {
00066 
00067 DTNServer::DTNServer(const char* logpath,
00068                      DTNStorageConfig* storage_config)
00069     : Logger("DTNServer", logpath),
00070       init_(false),
00071       in_shutdown_(0),
00072       storage_config_(storage_config),
00073       store_(0)
00074 {}
00075 
00076 DTNServer::~DTNServer()
00077 {
00078     log_notice("daemon exiting...");
00079 }
00080 
00081 void
00082 DTNServer::init()
00083 {
00084     ASSERT(oasys::Thread::start_barrier_enabled());
00085     
00086     init_commands();
00087     init_components();
00088 }
00089 
00090 void
00091 DTNServer::start()
00092 {
00093     BundleDaemon* daemon = BundleDaemon::instance();
00094     daemon->start();
00095     log_debug("started dtn server");
00096 }
00097 
00098 bool
00099 DTNServer::init_datastore()
00100 {
00101     if (storage_config_->tidy_) 
00102     {
00103         storage_config_->init_ = true; // init is implicit with tidy
00104     }
00105     store_ = new oasys::DurableStore("/dtn/storage");
00106     int err = store_->create_store(*storage_config_);
00107     if (err != 0) {
00108         log_crit("error creating storage system");
00109         return false;
00110     }
00111 
00112     if (storage_config_->tidy_)
00113     {
00114         // remove bundle data directory (the db contents are cleaned
00115         // up by the implementation)
00116         if (!tidy_dir(storage_config_->payload_dir_.c_str())) {
00117             return false;
00118         }
00119     }
00120 
00121     if (storage_config_->init_)
00122     {
00123         if (!init_dir(storage_config_->payload_dir_.c_str())) {
00124             return false;
00125         }
00126     }
00127 
00128     if (!validate_dir(storage_config_->payload_dir_.c_str())) {
00129         return false;
00130     }
00131 
00132     if ((GlobalStore::init(*storage_config_, store_)       != 0) || 
00133         (BundleStore::init(*storage_config_, store_)       != 0) ||
00134         (LinkStore::init(*storage_config_, store_)         != 0) ||
00135         (RegistrationStore::init(*storage_config_, store_) != 0))
00136     {
00137         log_crit("error initializing data store");
00138         return false;
00139     }
00140 
00141     // load in the global store here since that will check the
00142     // database version and exit if there's a mismatch
00143     if (!GlobalStore::instance()->load()) {
00144         return false;
00145     }
00146 
00147     return true;
00148 }
00149  
00150 bool
00151 DTNServer::parse_conf_file(std::string& conf_file,
00152                            bool         conf_file_set)
00153 {
00154     // Check the supplied config file and/or check for defaults, as
00155     // long as the user didn't explicitly call with no conf file 
00156     if (conf_file.size() != 0) 
00157     {
00158         if (!oasys::FileUtils::readable(conf_file.c_str(), logpath()))
00159         {
00160             log_err("configuration file \"%s\" not readable",
00161                     conf_file.c_str());
00162             return false;
00163         }
00164     }
00165     else if (!conf_file_set) 
00166     {
00167         const char* default_conf[] = { "/etc/dtn.conf", 
00168                                        "daemon/dtn.conf", 
00169                                        0 };
00170         conf_file.clear();
00171         for (int i=0; default_conf[i] != 0; ++i) 
00172         {
00173             if (oasys::FileUtils::readable(default_conf[i], logpath())) 
00174             {
00175                 conf_file.assign(default_conf[i]);
00176                 break;
00177             }
00178         }
00179         if (conf_file.size() == 0)
00180         {
00181             log_warn("can't read default config file "
00182                      "(tried /etc/dtn.conf and daemon/dtn.conf)...");
00183         }
00184     }
00185 
00186     if (conf_file.size() == 0) {
00187         log_info("No config file specified.");
00188         return false;
00189     }
00190 
00191     log_info("parsing configuration file %s...", conf_file.c_str());
00192     if (oasys::TclCommandInterp::instance()->exec_file(conf_file.c_str()) != 0)
00193     {
00194         return false;
00195     }
00196 
00197     return true;
00198 }
00199 
00200 void
00201 DTNServer::init_commands()
00202 {
00203     oasys::TclCommandInterp* interp = oasys::TclCommandInterp::instance();
00204 
00205     CompletionNotifier::create();
00206     interp->reg(new BundleCommand());
00207     interp->reg(new InterfaceCommand());
00208     interp->reg(new LinkCommand());
00209     interp->reg(new ParamCommand());
00210     interp->reg(new RegistrationCommand());
00211     interp->reg(new RouteCommand());
00212     interp->reg(new DiscoveryCommand());
00213     interp->reg(new ProphetCommand());
00214     interp->reg(new ShutdownCommand(this, "shutdown"));
00215     interp->reg(new ShutdownCommand(this, "quit"));
00216     interp->reg(new StorageCommand(storage_config_));
00217 
00218     log_debug("registered dtn commands");
00219 }
00220 
00221 void
00222 DTNServer::init_components()
00223 {
00224     SchemeTable::create();
00225     ConvergenceLayer::init_clayers();
00226     InterfaceTable::init();
00227     BundleDaemon::init();
00228     DiscoveryTable::init();
00229     
00230     log_debug("intialized dtn components");
00231 }
00232    
00233 void
00234 DTNServer::close_datastore()
00235 {
00236     log_notice("closing persistent data store");
00237     
00238     RegistrationStore::instance()->close();
00239     LinkStore::instance()->close();
00240     BundleStore::instance()->close();
00241     GlobalStore::instance()->close();
00242 
00243     delete_z(store_);
00244 }
00245 
00246 void
00247 DTNServer::shutdown()
00248 {
00249     log_notice("shutting down dtn server");
00250     
00251     // make sure only one thread does this
00252     u_int32_t old_val = atomic_incr_ret(&in_shutdown_);
00253     if (old_val != 1) {
00254         while (1) {
00255             sleep(1000000);
00256         }
00257     }
00258 
00259     oasys::Notifier done("/dtnserver/shutdown");
00260     log_info("DTNServer shutdown called, posting shutdown request to daemon");
00261     BundleDaemon::instance()->post_and_wait(new ShutdownRequest(), &done);
00262 
00263     DiscoveryTable::instance()->shutdown();
00264     close_datastore();
00265 }
00266 
00267 void
00268 DTNServer::set_app_shutdown(ShutdownProc proc, void* data)
00269 {
00270     BundleDaemon::instance()->set_app_shutdown(proc, data);
00271 }
00272 
00273 bool
00274 DTNServer::init_dir(const char* dirname)
00275 {
00276     struct stat st;
00277     int statret;
00278     
00279     statret = stat(dirname, &st);
00280     if (statret == -1 && errno == ENOENT)
00281     {
00282         if (mkdir(dirname, 0700) != 0) {
00283             log_crit("can't create directory %s: %s",
00284                      dirname, strerror(errno));
00285             return false;
00286         }
00287     }
00288     else if (statret == -1)
00289     {
00290         log_crit("invalid path %s: %s", dirname, strerror(errno));
00291         return false;
00292     }
00293 
00294     return true;
00295 }
00296 
00297 bool
00298 DTNServer::tidy_dir(const char* dir)
00299 {
00300     char cmd[256];
00301     struct stat st;
00302 
00303     std::string dirname(dir);
00304     oasys::FileUtils::abspath(&dirname);
00305     
00306     if (stat(dirname.c_str(), &st) == 0)
00307     {
00308         snprintf(cmd, sizeof(cmd), "/bin/rm -rf %s", dirname.c_str());
00309         log_notice("tidy option removing directory '%s'", cmd);
00310         
00311         if (system(cmd))
00312         {
00313             log_crit("error removing directory %s", dirname.c_str());
00314             return false;
00315         }
00316         
00317     }
00318     else if (errno == ENOENT)
00319     {
00320         log_debug("directory already removed %s", dirname.c_str());
00321     }
00322     else
00323     {
00324         log_crit("invalid directory name %s: %s", dirname.c_str(), strerror(errno));
00325         return false;
00326     }
00327 
00328     return true;
00329 }
00330 
00331 bool
00332 DTNServer::validate_dir(const char* dirname)
00333 {
00334     struct stat st;
00335     
00336     if (stat(dirname, &st) == 0 && S_ISDIR(st.st_mode))
00337     {
00338         log_debug("directory validated: %s", dirname);
00339     }
00340     else
00341     {
00342         log_crit("invalid directory name %s: %s", dirname, strerror(errno));
00343         return false;
00344     }
00345 
00346     if (access(dirname, R_OK | W_OK | X_OK) == 0)
00347     {
00348         log_debug("directory access validated: %s", dirname);
00349     }
00350     else
00351     {
00352         log_crit("access failed on directory %s: %s",
00353                  dirname, strerror(errno));
00354         return false;
00355     }
00356 
00357     return true;
00358 }
00359 
00360 } // namespace dtn

Generated on Thu Jun 7 16:56:49 2007 for DTN Reference Implementation by  doxygen 1.5.1