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

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