00001 /*------------------------------------------------------------------------------ 00002 00003 Copyright (c) 2004 Media Development Loan Fund 00004 00005 This file is part of the Campcaster project. 00006 https://www.campware.org/ 00007 To report bugs, send an e-mail to [email protected] 00008 00009 Campcaster is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 Campcaster is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with Campcaster; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 00024 Author : $Author: paul $ 00025 Version : $Revision: 2833 $ 00026 Location : $URL: svn://code.campware.org/campcaster/trunk/campcaster/src/products/scheduler/src/SchedulerDaemon.cxx $ 00027 00028 ------------------------------------------------------------------------------*/ 00029 00030 /* ============================================================ include files */ 00031 00032 #ifdef HAVE_CONFIG_H 00033 #include "configure.h" 00034 #endif 00035 00036 #if HAVE_SIGNAL_H 00037 #include <signal.h> 00038 #else 00039 #error "Need signal.h" 00040 #endif 00041 00042 #if HAVE_SYS_STAT_H 00043 #include <sys/stat.h> 00044 #else 00045 #error "Need sys/stat.h" 00046 #endif 00047 00048 00049 #include <iostream> 00050 #include <sstream> 00051 #include <fstream> 00052 #include <cstdio> 00053 00054 #include <boost/date_time/posix_time/posix_time.hpp> 00055 00056 #include "LiveSupport/Db/ConnectionManagerFactory.h" 00057 #include "LiveSupport/Authentication/AuthenticationClientFactory.h" 00058 #include "LiveSupport/StorageClient/StorageClientFactory.h" 00059 #include "LiveSupport/PlaylistExecutor/AudioPlayerFactory.h" 00060 #include "ScheduleFactory.h" 00061 #include "PlayLogFactory.h" 00062 #include "BackupFactory.h" 00063 #include "PlaylistEventContainer.h" 00064 00065 #include "SchedulerDaemon.h" 00066 00067 using namespace boost::posix_time; 00068 00069 using namespace LiveSupport; 00070 using namespace LiveSupport::Core; 00071 using namespace LiveSupport::Db; 00072 using namespace LiveSupport::StorageClient; 00073 using namespace LiveSupport::Scheduler; 00074 00075 /* =================================================== local data structures */ 00076 00077 00078 /* ================================================ local constants & macros */ 00079 00083 Ptr<SchedulerDaemon>::Ref SchedulerDaemon::schedulerDaemon; 00084 00085 namespace { 00086 00090 const std::string confElement = "scheduler"; 00091 00095 const std::string xmlRpcDaemonConfElement = "xmlRpcDaemon"; 00096 00100 const std::string userConfigElementName = "user"; 00101 00105 const std::string userLoginAttrName = "login"; 00106 00110 const std::string userPasswordAttrName = "password"; 00111 00112 } 00113 00114 /* =============================================== local function prototypes */ 00115 00116 00117 /* ============================================================= module code */ 00118 00119 /*------------------------------------------------------------------------------ 00120 * The default constructor. 00121 *----------------------------------------------------------------------------*/ 00122 SchedulerDaemon :: SchedulerDaemon (void) throw () 00123 : XmlRpcDaemon() 00124 { 00125 displayScheduleMethod.reset(new DisplayScheduleMethod()); 00126 generatePlayReportMethod.reset(new GeneratePlayReportMethod()); 00127 getSchedulerTimeMethod.reset(new GetSchedulerTimeMethod()); 00128 getVersionMethod.reset(new GetVersionMethod()); 00129 removeFromScheduleMethod.reset(new RemoveFromScheduleMethod()); 00130 rescheduleMethod.reset(new RescheduleMethod()); 00131 uploadPlaylistMethod.reset(new UploadPlaylistMethod()); 00132 loginMethod.reset(new LoginMethod()); 00133 logoutMethod.reset(new LogoutMethod()); 00134 resetStorageMethod.reset(new ResetStorageMethod()); 00135 createBackupOpenMethod.reset(new CreateBackupOpenMethod()); 00136 createBackupCheckMethod.reset(new CreateBackupCheckMethod()); 00137 createBackupCloseMethod.reset(new CreateBackupCloseMethod()); 00138 restoreBackupMethod.reset(new RestoreBackupMethod()); 00139 stopCurrentlyPlayingMethod.reset(new StopCurrentlyPlayingMethod()); 00140 } 00141 00142 00143 /*------------------------------------------------------------------------------ 00144 * Return the singleton instnace. 00145 *----------------------------------------------------------------------------*/ 00146 Ptr<SchedulerDaemon>::Ref 00147 SchedulerDaemon :: getInstance (void) throw () 00148 { 00149 if (!schedulerDaemon) { 00150 schedulerDaemon.reset(new SchedulerDaemon()); 00151 } 00152 00153 return schedulerDaemon; 00154 } 00155 00156 00157 /*------------------------------------------------------------------------------ 00158 * Configure the scheduler daemon 00159 *----------------------------------------------------------------------------*/ 00160 void 00161 SchedulerDaemon :: configure(const xmlpp::Element & element) 00162 throw (std::invalid_argument, 00163 std::logic_error) 00164 { 00165 if (element.get_name() != confElement) { 00166 std::string eMsg = "Bad configuration element "; 00167 eMsg += element.get_name(); 00168 throw std::invalid_argument(eMsg); 00169 } 00170 00171 xmlpp::Node::NodeList nodes; 00172 const xmlpp::Element * elem = 0; 00173 const xmlpp::Attribute * attribute = 0; 00174 00175 // read in the user data 00176 00177 nodes = element.get_children(userConfigElementName); 00178 if (nodes.size() < 1) { 00179 throw std::invalid_argument("no user element"); 00180 } 00181 elem = dynamic_cast<const xmlpp::Element*> (*nodes.begin()); 00182 if (!(attribute = elem->get_attribute(userLoginAttrName))) { 00183 throw std::invalid_argument("missing login attribute"); 00184 } 00185 login = attribute->get_value(); 00186 if (!(attribute = elem->get_attribute(userPasswordAttrName))) { 00187 throw std::invalid_argument("missing password attribute"); 00188 } 00189 password = attribute->get_value(); 00190 00191 // configure the ConnectionManagerFactory 00192 nodes = 00193 element.get_children(ConnectionManagerFactory::getConfigElementName()); 00194 if (nodes.size() < 1) { 00195 throw std::invalid_argument("no connectionManagerFactory element"); 00196 } 00197 Ptr<ConnectionManagerFactory>::Ref cmf 00198 = ConnectionManagerFactory::getInstance(); 00199 cmf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00200 00201 // configure the AuthenticationClientFactory 00202 nodes = 00203 element.get_children(AuthenticationClientFactory::getConfigElementName()); 00204 if (nodes.size() < 1) { 00205 throw std::invalid_argument("no authenticationClientFactory element"); 00206 } 00207 Ptr<AuthenticationClientFactory>::Ref acf 00208 = AuthenticationClientFactory::getInstance(); 00209 acf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00210 00211 // configure the StorageClientFactory 00212 nodes = element.get_children(StorageClientFactory::getConfigElementName()); 00213 if (nodes.size() < 1) { 00214 throw std::invalid_argument("no storageClientFactory element"); 00215 } 00216 Ptr<StorageClientFactory>::Ref scf = StorageClientFactory::getInstance(); 00217 scf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00218 00219 // configure the AudioPlayerFactory 00220 nodes = element.get_children(AudioPlayerFactory::getConfigElementName()); 00221 if (nodes.size() < 1) { 00222 throw std::invalid_argument("no audioPlayer element"); 00223 } 00224 Ptr<AudioPlayerFactory>::Ref apf = AudioPlayerFactory::getInstance(); 00225 apf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00226 00227 // configure the ScheduleFactory 00228 nodes = element.get_children(ScheduleFactory::getConfigElementName()); 00229 if (nodes.size() < 1) { 00230 throw std::invalid_argument("no scheduleFactory element"); 00231 } 00232 Ptr<ScheduleFactory>::Ref sf = ScheduleFactory::getInstance(); 00233 sf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00234 00235 // configure the PlayLogFactory 00236 nodes = element.get_children(PlayLogFactory::getConfigElementName()); 00237 if (nodes.size() < 1) { 00238 throw std::invalid_argument("no playLogFactory element"); 00239 } 00240 Ptr<PlayLogFactory>::Ref plf = PlayLogFactory::getInstance(); 00241 plf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00242 00243 // configure the BackupFactory 00244 nodes = element.get_children(BackupFactory::getConfigElementName()); 00245 if (nodes.size() < 1) { 00246 throw std::invalid_argument("no backupFactory element"); 00247 } 00248 Ptr<BackupFactory>::Ref bf = BackupFactory::getInstance(); 00249 bf->configure( *((const xmlpp::Element*) *(nodes.begin())) ); 00250 00251 // configure the XmlRpcDaemon 00252 nodes = element.get_children(XmlRpcDaemon::getConfigElementName()); 00253 if (nodes.size() < 1) { 00254 throw std::invalid_argument("no xmlRpcDaemon element"); 00255 } 00256 configureXmlRpcDaemon( *((const xmlpp::Element*) *(nodes.begin())) ); 00257 00258 // do some initialization, using the configured objects 00259 authentication = acf->getAuthenticationClient(); 00260 connectionManager = cmf->getConnectionManager(); 00261 storage = scf->getStorageClient(); 00262 audioPlayer = apf->getAudioPlayer(); 00263 schedule = sf->getSchedule(); 00264 playLog = plf->getPlayLog(); 00265 } 00266 00267 00268 /*------------------------------------------------------------------------------ 00269 * Destructor. 00270 *----------------------------------------------------------------------------*/ 00271 SchedulerDaemon :: ~SchedulerDaemon(void) throw () 00272 { 00273 if (authentication.get() && sessionId.get()) { 00274 authentication->logout(sessionId); 00275 } 00276 } 00277 00278 00279 /*------------------------------------------------------------------------------ 00280 * Register our XML-RPC methods 00281 *----------------------------------------------------------------------------*/ 00282 void 00283 SchedulerDaemon :: registerXmlRpcFunctions( 00284 Ptr<XmlRpc::XmlRpcServer>::Ref xmlRpcServer) 00285 throw (std::logic_error) 00286 { 00287 xmlRpcServer->addMethod(displayScheduleMethod.get()); 00288 xmlRpcServer->addMethod(generatePlayReportMethod.get()); 00289 xmlRpcServer->addMethod(getSchedulerTimeMethod.get()); 00290 xmlRpcServer->addMethod(getVersionMethod.get()); 00291 xmlRpcServer->addMethod(removeFromScheduleMethod.get()); 00292 xmlRpcServer->addMethod(rescheduleMethod.get()); 00293 xmlRpcServer->addMethod(uploadPlaylistMethod.get()); 00294 xmlRpcServer->addMethod(loginMethod.get()); 00295 xmlRpcServer->addMethod(logoutMethod.get()); 00296 xmlRpcServer->addMethod(resetStorageMethod.get()); 00297 xmlRpcServer->addMethod(createBackupOpenMethod.get()); 00298 xmlRpcServer->addMethod(createBackupCheckMethod.get()); 00299 xmlRpcServer->addMethod(createBackupCloseMethod.get()); 00300 xmlRpcServer->addMethod(restoreBackupMethod.get()); 00301 xmlRpcServer->addMethod(stopCurrentlyPlayingMethod.get()); 00302 } 00303 00304 00305 /*------------------------------------------------------------------------------ 00306 * Execute daemon startup functions. 00307 *----------------------------------------------------------------------------*/ 00308 void 00309 SchedulerDaemon :: startup (void) throw (std::logic_error) 00310 { 00311 try { 00312 sessionId = authentication->login(login, password); 00313 } catch (XmlRpcException &e) { 00314 throw std::logic_error(std::string("authentication problem: ") 00315 + e.what()); 00316 } 00317 00318 try { 00319 audioPlayer->initialize(); 00320 } catch (std::exception &e) { 00321 throw std::logic_error(std::string("audio player initialization " 00322 "problem: ") + e.what()); 00323 } 00324 if (!eventScheduler.get()) { 00325 Ptr<PlaylistEventContainer>::Ref eventContainer; 00326 Ptr<time_duration>::Ref granularity; 00327 eventContainer.reset(new PlaylistEventContainer(sessionId, 00328 storage, 00329 schedule, 00330 audioPlayer, 00331 playLog)); 00332 // TODO: read granularity from config file 00333 granularity.reset(new time_duration(seconds(1))); 00334 00335 eventScheduler.reset( 00336 new LiveSupport::EventScheduler::EventScheduler(eventContainer, 00337 granularity)); 00338 } 00339 eventScheduler->start(); 00340 00341 XmlRpcDaemon::startup(); 00342 } 00343 00344 00345 /*------------------------------------------------------------------------------ 00346 * Shut down the daemon 00347 *----------------------------------------------------------------------------*/ 00348 void 00349 SchedulerDaemon :: shutdown(void) throw (std::logic_error) 00350 { 00351 if (eventScheduler.get()) { 00352 eventScheduler->stop(); 00353 } 00354 audioPlayer->deInitialize(); 00355 00356 XmlRpcDaemon::shutdown(); 00357 } 00358 00359 00360 /*------------------------------------------------------------------------------ 00361 * Re-read the events from the event container. 00362 *----------------------------------------------------------------------------*/ 00363 void 00364 SchedulerDaemon :: update (void) throw (std::logic_error) 00365 { 00366 // TODO: check if we've been configured 00367 if (eventScheduler.get()) { 00368 eventScheduler->update(); 00369 } 00370 } 00371