| 1 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 2 | // Zen Enterprise Framework |
|---|
| 3 | // |
|---|
| 4 | // Copyright (C) 2001 - 2010 Tony Richards |
|---|
| 5 | // Copyright (C) 2008 - 2010 Matthew Alan Gray |
|---|
| 6 | // Copyright (C) 2009 Joshua Cassity |
|---|
| 7 | // |
|---|
| 8 | // This software is provided 'as-is', without any express or implied |
|---|
| 9 | // warranty. In no event will the authors be held liable for any damages |
|---|
| 10 | // arising from the use of this software. |
|---|
| 11 | // |
|---|
| 12 | // Permission is granted to anyone to use this software for any purpose, |
|---|
| 13 | // including commercial applications, and to alter it and redistribute it |
|---|
| 14 | // freely, subject to the following restrictions: |
|---|
| 15 | // |
|---|
| 16 | // 1. The origin of this software must not be misrepresented; you must not |
|---|
| 17 | // claim that you wrote the original software. If you use this software |
|---|
| 18 | // in a product, an acknowledgment in the product documentation would be |
|---|
| 19 | // appreciated but is not required. |
|---|
| 20 | // 2. Altered source versions must be plainly marked as such, and must not be |
|---|
| 21 | // misrepresented as being the original software. |
|---|
| 22 | // 3. This notice may not be removed or altered from any source distribution. |
|---|
| 23 | // |
|---|
| 24 | // Tony Richards trichards@indiezen.com |
|---|
| 25 | // Matthew Alan Gray mgray@indiezen.org |
|---|
| 26 | // Joshua Cassity jcassity@indiezen.org |
|---|
| 27 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 28 | #include "ApplicationServer.hpp" |
|---|
| 29 | |
|---|
| 30 | #include "ResourceLocation.hpp" |
|---|
| 31 | #include "NumericTypeMessageRegistry.hpp" |
|---|
| 32 | |
|---|
| 33 | #include "../I_ApplicationServerManager.hpp" |
|---|
| 34 | #include "../I_ProtocolService.hpp" |
|---|
| 35 | #include "../I_ApplicationService.hpp" |
|---|
| 36 | #include "../I_Message.hpp" |
|---|
| 37 | #include "../I_MessageFactory.hpp" |
|---|
| 38 | #include "../I_Request.hpp" |
|---|
| 39 | #include "../I_Response.hpp" |
|---|
| 40 | #include "../I_ResponseHandler.hpp" |
|---|
| 41 | #include "../I_SessionEvent.hpp" |
|---|
| 42 | |
|---|
| 43 | #include <Zen/Core/Memory/managed_weak_ptr.hpp> |
|---|
| 44 | |
|---|
| 45 | #include <Zen/Core/Utility/runtime_exception.hpp> |
|---|
| 46 | |
|---|
| 47 | #include <Zen/Core/Threading/MutexFactory.hpp> |
|---|
| 48 | #include <Zen/Core/Threading/I_Mutex.hpp> |
|---|
| 49 | #include <Zen/Core/Threading/I_Thread.hpp> |
|---|
| 50 | #include <Zen/Core/Threading/CriticalSection.hpp> |
|---|
| 51 | |
|---|
| 52 | #include <Zen/Core/Scripting/I_ScriptableService.hpp> |
|---|
| 53 | |
|---|
| 54 | #include <Zen/Enterprise/Networking/I_Endpoint.hpp> |
|---|
| 55 | #include <Zen/Enterprise/Networking/I_Address.hpp> |
|---|
| 56 | |
|---|
| 57 | #include <Zen/Enterprise/Database/I_DatabaseManager.hpp> |
|---|
| 58 | #include <Zen/Enterprise/Database/I_DatabaseService.hpp> |
|---|
| 59 | #include <Zen/Enterprise/Database/I_DatabaseConnection.hpp> |
|---|
| 60 | |
|---|
| 61 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 62 | namespace Zen { |
|---|
| 63 | namespace Enterprise { |
|---|
| 64 | namespace AppServer { |
|---|
| 65 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 66 | static void destroy(Memory::managed_weak_ptr<I_MessageRegistry> _pMessageRegistry) |
|---|
| 67 | { |
|---|
| 68 | NumericTypeMessageRegistry* pMessageRegistry = dynamic_cast<NumericTypeMessageRegistry*>(_pMessageRegistry.get()); |
|---|
| 69 | |
|---|
| 70 | if (pMessageRegistry) |
|---|
| 71 | { |
|---|
| 72 | delete pMessageRegistry; |
|---|
| 73 | } |
|---|
| 74 | else |
|---|
| 75 | { |
|---|
| 76 | // TODO Error? |
|---|
| 77 | } |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 81 | |
|---|
| 82 | ApplicationServer::ApplicationServer() |
|---|
| 83 | : m_pEventService(Event::I_EventManager::getSingleton().create("eventService")) |
|---|
| 84 | , m_sharedThreadPool(16, NULL, true, true) |
|---|
| 85 | , m_installQueue(1, NULL, true, false) |
|---|
| 86 | , m_shutdownQueue(1, NULL, true, false) |
|---|
| 87 | , m_pProtocolGuard(Threading::MutexFactory::create()) |
|---|
| 88 | , m_pApplicationGuard(Threading::MutexFactory::create()) |
|---|
| 89 | , m_pMessageRegistry_type(new NumericTypeMessageRegistry(), &destroy) |
|---|
| 90 | , m_databaseConnectionsMap() |
|---|
| 91 | { |
|---|
| 92 | |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 96 | ApplicationServer::~ApplicationServer() |
|---|
| 97 | { |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 101 | Zen::Threading::I_Condition* |
|---|
| 102 | ApplicationServer::start() |
|---|
| 103 | { |
|---|
| 104 | class InstallationCompleteTask |
|---|
| 105 | : public Threading::ThreadPool::Task |
|---|
| 106 | { |
|---|
| 107 | private: |
|---|
| 108 | class PrepareToStartCompleteTask |
|---|
| 109 | : public Threading::ThreadPool::Task |
|---|
| 110 | { |
|---|
| 111 | private: |
|---|
| 112 | class StartCompleteTask |
|---|
| 113 | : public Threading::ThreadPool::Task |
|---|
| 114 | { |
|---|
| 115 | public: |
|---|
| 116 | virtual void call() |
|---|
| 117 | { |
|---|
| 118 | m_condition.assertCondition(); |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | StartCompleteTask(Zen::Threading::I_Condition& _condition) |
|---|
| 122 | : m_condition(_condition) |
|---|
| 123 | { |
|---|
| 124 | } |
|---|
| 125 | private: |
|---|
| 126 | Zen::Threading::I_Condition& m_condition; |
|---|
| 127 | }; |
|---|
| 128 | |
|---|
| 129 | public: |
|---|
| 130 | virtual void call() |
|---|
| 131 | { |
|---|
| 132 | StartCompleteTask* pTask = new StartCompleteTask(m_condition); |
|---|
| 133 | m_installQueue.pushRequest(pTask); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | PrepareToStartCompleteTask(Zen::Threading::I_Condition& _condition, Zen::Threading::ThreadPool& _installQueue) |
|---|
| 137 | : m_condition(_condition) |
|---|
| 138 | , m_installQueue(_installQueue) |
|---|
| 139 | { |
|---|
| 140 | } |
|---|
| 141 | private: |
|---|
| 142 | Zen::Threading::I_Condition& m_condition; |
|---|
| 143 | Zen::Threading::ThreadPool& m_installQueue; |
|---|
| 144 | }; |
|---|
| 145 | public: |
|---|
| 146 | virtual void call() |
|---|
| 147 | { |
|---|
| 148 | PrepareToStartCompleteTask* pTask = new PrepareToStartCompleteTask(m_condition, m_installQueue); |
|---|
| 149 | m_installQueue.pushRequest(pTask); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | InstallationCompleteTask(Zen::Threading::I_Condition& _condition, Zen::Threading::ThreadPool& _installQueue) |
|---|
| 153 | : m_condition(_condition) |
|---|
| 154 | , m_installQueue(_installQueue) |
|---|
| 155 | { |
|---|
| 156 | } |
|---|
| 157 | private: |
|---|
| 158 | Zen::Threading::I_Condition& m_condition; |
|---|
| 159 | Zen::Threading::ThreadPool& m_installQueue; |
|---|
| 160 | }; |
|---|
| 161 | |
|---|
| 162 | // Create an I_Condition to all the caller to know when all the applications have been installed |
|---|
| 163 | Zen::Threading::I_Condition* pCondition = Zen::Threading::ConditionFactory::create(false); |
|---|
| 164 | |
|---|
| 165 | // Create the installation complete task and pass the condition into it. |
|---|
| 166 | InstallationCompleteTask* pTask = new InstallationCompleteTask(*pCondition, m_installQueue); |
|---|
| 167 | |
|---|
| 168 | // Push the task onto the end of the queue |
|---|
| 169 | m_installQueue.pushRequest(pTask); |
|---|
| 170 | |
|---|
| 171 | // Start the installation queue so that protocols and services will be |
|---|
| 172 | // installed. |
|---|
| 173 | m_installQueue.start(); |
|---|
| 174 | |
|---|
| 175 | return pCondition; |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 179 | void |
|---|
| 180 | ApplicationServer::stop() |
|---|
| 181 | { |
|---|
| 182 | class InstallationQueueEmptyTask |
|---|
| 183 | : public Threading::ThreadPool::Task |
|---|
| 184 | { |
|---|
| 185 | public: |
|---|
| 186 | virtual void call() |
|---|
| 187 | { |
|---|
| 188 | m_condition.assertCondition(); |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | InstallationQueueEmptyTask(Zen::Threading::I_Condition& _condition) |
|---|
| 192 | : m_condition(_condition) |
|---|
| 193 | { |
|---|
| 194 | } |
|---|
| 195 | private: |
|---|
| 196 | Zen::Threading::I_Condition& m_condition; |
|---|
| 197 | }; |
|---|
| 198 | |
|---|
| 199 | class ShutdownCompleteTask |
|---|
| 200 | : public Threading::ThreadPool::Task |
|---|
| 201 | { |
|---|
| 202 | public: |
|---|
| 203 | virtual void call() |
|---|
| 204 | { |
|---|
| 205 | m_condition.assertCondition(); |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | ShutdownCompleteTask(Zen::Threading::I_Condition& _condition) |
|---|
| 209 | : m_condition(_condition) |
|---|
| 210 | { |
|---|
| 211 | } |
|---|
| 212 | private: |
|---|
| 213 | Zen::Threading::I_Condition& m_condition; |
|---|
| 214 | }; |
|---|
| 215 | |
|---|
| 216 | // Create an I_Condition to know when the installQueue is empty... |
|---|
| 217 | Zen::Threading::I_Condition* pInstallerCondition = Zen::Threading::ConditionFactory::create(false); |
|---|
| 218 | |
|---|
| 219 | // Create the installation complete task and pass the condition into it. |
|---|
| 220 | InstallationQueueEmptyTask* pInstallerTask = new InstallationQueueEmptyTask(*pInstallerCondition); |
|---|
| 221 | |
|---|
| 222 | // Push the task onto the end of the queue |
|---|
| 223 | m_installQueue.pushRequest(pInstallerTask); |
|---|
| 224 | |
|---|
| 225 | // Prepare to stop the installation queue so that no more protocols or services will |
|---|
| 226 | // be installed (at least not until the app server is restarted, if ever). |
|---|
| 227 | m_installQueue.prepareToStop(); |
|---|
| 228 | |
|---|
| 229 | // Wait for the install queue to be emptied |
|---|
| 230 | pInstallerCondition->requireCondition(); |
|---|
| 231 | |
|---|
| 232 | // Destroy the condition |
|---|
| 233 | Zen::Threading::ConditionFactory::destroy(pInstallerCondition); |
|---|
| 234 | |
|---|
| 235 | // Stop the install queue |
|---|
| 236 | m_installQueue.stop(); |
|---|
| 237 | |
|---|
| 238 | // Create an I_Condition to know when the shutdownQueue is finished. |
|---|
| 239 | Zen::Threading::I_Condition* pShutdownCondition = Zen::Threading::ConditionFactory::create(false); |
|---|
| 240 | |
|---|
| 241 | // Create the shutdown complete task and pass the condition into it. |
|---|
| 242 | ShutdownCompleteTask* pShutdownTask = new ShutdownCompleteTask(*pShutdownCondition); |
|---|
| 243 | |
|---|
| 244 | // Push the task onto the end of the queue |
|---|
| 245 | m_shutdownQueue.pushRequest(pShutdownTask); |
|---|
| 246 | |
|---|
| 247 | // Start the shutdown queue |
|---|
| 248 | m_shutdownQueue.start(); |
|---|
| 249 | |
|---|
| 250 | // Wait on the shutdown queue to completely start |
|---|
| 251 | m_shutdownQueue.requireStarted(); |
|---|
| 252 | |
|---|
| 253 | // Prepare to stop the shutdown queue so that no more tasks will be |
|---|
| 254 | // pushed onto it. |
|---|
| 255 | m_shutdownQueue.prepareToStop(); |
|---|
| 256 | |
|---|
| 257 | // Wait for the shutdown queue to be emptied. |
|---|
| 258 | pShutdownCondition->requireCondition(); |
|---|
| 259 | |
|---|
| 260 | // Destroy the condition |
|---|
| 261 | Zen::Threading::ConditionFactory::destroy(pShutdownCondition); |
|---|
| 262 | |
|---|
| 263 | // Stop the shutdown queue |
|---|
| 264 | m_shutdownQueue.stop(); |
|---|
| 265 | |
|---|
| 266 | // Empty service collections |
|---|
| 267 | { |
|---|
| 268 | Threading::CriticalSection lock(m_pProtocolGuard); |
|---|
| 269 | m_protocolServices.empty(); |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | { |
|---|
| 273 | Threading::CriticalSection lock(m_pApplicationGuard); |
|---|
| 274 | m_applicationServices.empty(); |
|---|
| 275 | } |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 279 | void |
|---|
| 280 | ApplicationServer::registerDefaultScriptEngine(pScriptEngine_type _pEngine) |
|---|
| 281 | { |
|---|
| 282 | // TODO Register with all of the already-installed app services. |
|---|
| 283 | |
|---|
| 284 | m_pScriptEngine = _pEngine; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 288 | ApplicationServer::pScriptEngine_type |
|---|
| 289 | ApplicationServer::getDefaultScriptEngine() |
|---|
| 290 | { |
|---|
| 291 | return m_pScriptEngine; |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 295 | ApplicationServer::pEventService_type |
|---|
| 296 | ApplicationServer::getEventService() |
|---|
| 297 | { |
|---|
| 298 | return m_pEventService; |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 302 | void |
|---|
| 303 | ApplicationServer::installProtocols(pConfig_type _pProtocolsConfig) |
|---|
| 304 | { |
|---|
| 305 | class ConfigVisitor |
|---|
| 306 | : public Zen::Plugins::I_ConfigurationElement::I_ConfigurationElementVisitor |
|---|
| 307 | { |
|---|
| 308 | public: |
|---|
| 309 | virtual void begin() |
|---|
| 310 | { |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | virtual void visit(const Zen::Plugins::I_ConfigurationElement& _element) |
|---|
| 314 | { |
|---|
| 315 | Zen::Enterprise::AppServer::I_ApplicationServerManager& manager = |
|---|
| 316 | Zen::Enterprise::AppServer::I_ApplicationServerManager::getSingleton(); |
|---|
| 317 | |
|---|
| 318 | Zen::Enterprise::AppServer::I_ApplicationServerManager::pProtocolService_type |
|---|
| 319 | pProtocolService = manager.createProtocolService(*m_pAppServer, _element.getAttribute("type")); |
|---|
| 320 | |
|---|
| 321 | if (pProtocolService.isValid()) |
|---|
| 322 | { |
|---|
| 323 | pProtocolService->setConfiguration(_element); |
|---|
| 324 | m_pAppServer->installProtocol(pProtocolService, _element.getAttribute("name")); |
|---|
| 325 | } |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | virtual void end() |
|---|
| 329 | { |
|---|
| 330 | } |
|---|
| 331 | |
|---|
| 332 | ConfigVisitor(I_ApplicationServer* _pAppServer) |
|---|
| 333 | : m_pAppServer(_pAppServer) |
|---|
| 334 | { |
|---|
| 335 | } |
|---|
| 336 | private: |
|---|
| 337 | I_ApplicationServer* m_pAppServer; |
|---|
| 338 | }; |
|---|
| 339 | |
|---|
| 340 | ConfigVisitor visitor(this); |
|---|
| 341 | _pProtocolsConfig->getChildren("protocol", visitor); |
|---|
| 342 | } |
|---|
| 343 | |
|---|
| 344 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 345 | void |
|---|
| 346 | ApplicationServer::installProtocol(pProtocolService_type _pProtocolService, const std::string& _protocolName) |
|---|
| 347 | { |
|---|
| 348 | class InstallProtocolServiceTask |
|---|
| 349 | : public Threading::ThreadPool::Task |
|---|
| 350 | { |
|---|
| 351 | private: |
|---|
| 352 | class PrepareToStartProtocolServiceTask |
|---|
| 353 | : public Threading::ThreadPool::Task |
|---|
| 354 | { |
|---|
| 355 | private: |
|---|
| 356 | class StartProtocolServiceTask |
|---|
| 357 | : public Threading::ThreadPool::Task |
|---|
| 358 | { |
|---|
| 359 | public: |
|---|
| 360 | virtual void call() |
|---|
| 361 | { |
|---|
| 362 | m_pProtocolService->start(); |
|---|
| 363 | } |
|---|
| 364 | |
|---|
| 365 | StartProtocolServiceTask(pProtocolService_type _pProtocolService) |
|---|
| 366 | : m_pProtocolService(_pProtocolService) |
|---|
| 367 | { |
|---|
| 368 | } |
|---|
| 369 | private: |
|---|
| 370 | pProtocolService_type m_pProtocolService; |
|---|
| 371 | }; |
|---|
| 372 | class StopProtocolServiceTask |
|---|
| 373 | : public Threading::ThreadPool::Task |
|---|
| 374 | { |
|---|
| 375 | public: |
|---|
| 376 | virtual void call() |
|---|
| 377 | { |
|---|
| 378 | m_pProtocolService->stop(); |
|---|
| 379 | } |
|---|
| 380 | |
|---|
| 381 | StopProtocolServiceTask(pProtocolService_type _pProtocolService) |
|---|
| 382 | : m_pProtocolService(_pProtocolService) |
|---|
| 383 | { |
|---|
| 384 | } |
|---|
| 385 | private: |
|---|
| 386 | pProtocolService_type m_pProtocolService; |
|---|
| 387 | }; |
|---|
| 388 | public: |
|---|
| 389 | virtual void call() |
|---|
| 390 | { |
|---|
| 391 | Threading::I_Condition* pCondition = m_pProtocolService->prepareToStart(m_server.getSharedThreadPool()); |
|---|
| 392 | if( pCondition != NULL ) |
|---|
| 393 | { |
|---|
| 394 | pCondition->requireCondition(); |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | StartProtocolServiceTask* pStartTask = new StartProtocolServiceTask(m_pProtocolService); |
|---|
| 398 | StopProtocolServiceTask* pStopTask = new StopProtocolServiceTask(m_pProtocolService); |
|---|
| 399 | m_installQueue.pushRequest(pStartTask); |
|---|
| 400 | m_shutdownQueue.pushRequest(pStopTask); |
|---|
| 401 | } |
|---|
| 402 | |
|---|
| 403 | PrepareToStartProtocolServiceTask(ApplicationServer& _server, pProtocolService_type _pProtocolService, Threading::ThreadPool& _installQueue, Threading::ThreadPool& _shutdownQueue) |
|---|
| 404 | : m_server(_server) |
|---|
| 405 | , m_pProtocolService(_pProtocolService) |
|---|
| 406 | , m_installQueue(_installQueue) |
|---|
| 407 | , m_shutdownQueue(_shutdownQueue) |
|---|
| 408 | { |
|---|
| 409 | } |
|---|
| 410 | private: |
|---|
| 411 | ApplicationServer& m_server; |
|---|
| 412 | pProtocolService_type m_pProtocolService; |
|---|
| 413 | Threading::ThreadPool& m_installQueue; |
|---|
| 414 | Threading::ThreadPool& m_shutdownQueue; |
|---|
| 415 | }; |
|---|
| 416 | class PrepareToStopProtocolServiceTask |
|---|
| 417 | : public Threading::ThreadPool::Task |
|---|
| 418 | { |
|---|
| 419 | public: |
|---|
| 420 | virtual void call() |
|---|
| 421 | { |
|---|
| 422 | Threading::I_Condition* pCondition = m_pProtocolService->prepareToStop(); |
|---|
| 423 | if( pCondition != NULL ) |
|---|
| 424 | { |
|---|
| 425 | pCondition->requireCondition(); |
|---|
| 426 | } |
|---|
| 427 | } |
|---|
| 428 | |
|---|
| 429 | PrepareToStopProtocolServiceTask(pProtocolService_type _pProtocolService) |
|---|
| 430 | : m_pProtocolService(_pProtocolService) |
|---|
| 431 | { |
|---|
| 432 | } |
|---|
| 433 | private: |
|---|
| 434 | pProtocolService_type m_pProtocolService; |
|---|
| 435 | }; |
|---|
| 436 | public: |
|---|
| 437 | virtual void call() |
|---|
| 438 | { |
|---|
| 439 | m_server.handleInstallProtocol(m_pProtocolService, m_protocolName); |
|---|
| 440 | PrepareToStartProtocolServiceTask* pStartTask = new PrepareToStartProtocolServiceTask(m_server,m_pProtocolService, m_installQueue, m_shutdownQueue); |
|---|
| 441 | PrepareToStopProtocolServiceTask* pStopTask = new PrepareToStopProtocolServiceTask(m_pProtocolService); |
|---|
| 442 | m_installQueue.pushRequest(pStartTask); |
|---|
| 443 | m_shutdownQueue.pushRequest(pStopTask); |
|---|
| 444 | } |
|---|
| 445 | |
|---|
| 446 | InstallProtocolServiceTask(ApplicationServer& _server, pProtocolService_type _pProtocolService, const std::string& _protocolName, Threading::ThreadPool& _installQueue, Threading::ThreadPool& _shutdownQueue) |
|---|
| 447 | : m_server(_server) |
|---|
| 448 | , m_pProtocolService(_pProtocolService) |
|---|
| 449 | , m_protocolName(_protocolName) |
|---|
| 450 | , m_installQueue(_installQueue) |
|---|
| 451 | , m_shutdownQueue(_shutdownQueue) |
|---|
| 452 | { |
|---|
| 453 | } |
|---|
| 454 | private: |
|---|
| 455 | ApplicationServer& m_server; |
|---|
| 456 | pProtocolService_type m_pProtocolService; |
|---|
| 457 | std::string m_protocolName; |
|---|
| 458 | Threading::ThreadPool& m_installQueue; |
|---|
| 459 | Threading::ThreadPool& m_shutdownQueue; |
|---|
| 460 | }; |
|---|
| 461 | |
|---|
| 462 | // Schedule the installation of the protocol. |
|---|
| 463 | InstallProtocolServiceTask* pTask = new InstallProtocolServiceTask(*this, _pProtocolService, _protocolName,m_installQueue, m_shutdownQueue); |
|---|
| 464 | m_installQueue.pushRequest(pTask); |
|---|
| 465 | } |
|---|
| 466 | |
|---|
| 467 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 468 | ApplicationServer::pProtocolService_type |
|---|
| 469 | ApplicationServer::getProtocol(const std::string& _protocolName) |
|---|
| 470 | { |
|---|
| 471 | Threading::CriticalSection lock(m_pProtocolGuard); |
|---|
| 472 | |
|---|
| 473 | ProtocolServices_type::iterator iter = m_protocolServices.find(_protocolName); |
|---|
| 474 | |
|---|
| 475 | if (iter != m_protocolServices.end()) |
|---|
| 476 | { |
|---|
| 477 | return iter->second; |
|---|
| 478 | } |
|---|
| 479 | else |
|---|
| 480 | { |
|---|
| 481 | // TODO Throw an exception? |
|---|
| 482 | return pProtocolService_type(); |
|---|
| 483 | } |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 487 | void |
|---|
| 488 | ApplicationServer::installApplications(pConfig_type _pAppServicesConfig) |
|---|
| 489 | { |
|---|
| 490 | class ConfigVisitor |
|---|
| 491 | : public Zen::Plugins::I_ConfigurationElement::I_ConfigurationElementVisitor |
|---|
| 492 | { |
|---|
| 493 | |
|---|
| 494 | public: |
|---|
| 495 | virtual void begin() {} |
|---|
| 496 | |
|---|
| 497 | virtual void visit(const Zen::Plugins::I_ConfigurationElement& _element) |
|---|
| 498 | { |
|---|
| 499 | Zen::Enterprise::AppServer::I_ApplicationServerManager& manager = |
|---|
| 500 | Zen::Enterprise::AppServer::I_ApplicationServerManager::getSingleton(); |
|---|
| 501 | |
|---|
| 502 | Zen::Enterprise::AppServer::I_ApplicationServerManager::pApplicationService_type |
|---|
| 503 | pApplicationService = manager.createApplicationService(*m_pAppServer, _element.getAttribute("type")); |
|---|
| 504 | |
|---|
| 505 | if( pApplicationService.isValid() ) |
|---|
| 506 | { |
|---|
| 507 | pApplicationService->setConfiguration(_element); |
|---|
| 508 | m_pAppServer->installApplication(pApplicationService, manager.createLocation(_element.getAttribute("location"))); |
|---|
| 509 | } |
|---|
| 510 | } |
|---|
| 511 | |
|---|
| 512 | virtual void end() {} |
|---|
| 513 | |
|---|
| 514 | ConfigVisitor(ApplicationServer* _pAppServer) |
|---|
| 515 | : m_pAppServer(_pAppServer) |
|---|
| 516 | { |
|---|
| 517 | } |
|---|
| 518 | |
|---|
| 519 | private: |
|---|
| 520 | ApplicationServer* m_pAppServer; |
|---|
| 521 | }; |
|---|
| 522 | |
|---|
| 523 | ConfigVisitor visitor(this); |
|---|
| 524 | _pAppServicesConfig->getChildren("application", visitor); |
|---|
| 525 | } |
|---|
| 526 | |
|---|
| 527 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 528 | void |
|---|
| 529 | ApplicationServer::installApplication(pApplicationService_type _pApplicationService, pResourceLocation_type _pRootLocation) |
|---|
| 530 | { |
|---|
| 531 | class InstallApplicationServiceTask |
|---|
| 532 | : public Threading::ThreadPool::Task |
|---|
| 533 | { |
|---|
| 534 | class PrepareToStartApplicationServiceTask |
|---|
| 535 | : public Threading::ThreadPool::Task |
|---|
| 536 | { |
|---|
| 537 | private: |
|---|
| 538 | class StartApplicationServiceTask |
|---|
| 539 | : public Threading::ThreadPool::Task |
|---|
| 540 | { |
|---|
| 541 | public: |
|---|
| 542 | virtual void call() |
|---|
| 543 | { |
|---|
| 544 | m_pApplicationService->start(); |
|---|
| 545 | } |
|---|
| 546 | |
|---|
| 547 | StartApplicationServiceTask(pApplicationService_type _pApplicationService) |
|---|
| 548 | : m_pApplicationService(_pApplicationService) |
|---|
| 549 | { |
|---|
| 550 | } |
|---|
| 551 | private: |
|---|
| 552 | pApplicationService_type m_pApplicationService; |
|---|
| 553 | }; |
|---|
| 554 | class StopApplicationServiceTask |
|---|
| 555 | : public Threading::ThreadPool::Task |
|---|
| 556 | { |
|---|
| 557 | public: |
|---|
| 558 | virtual void call() |
|---|
| 559 | { |
|---|
| 560 | m_pApplicationService->stop(); |
|---|
| 561 | } |
|---|
| 562 | |
|---|
| 563 | StopApplicationServiceTask(pApplicationService_type _pApplicationService) |
|---|
| 564 | : m_pApplicationService(_pApplicationService) |
|---|
| 565 | { |
|---|
| 566 | } |
|---|
| 567 | private: |
|---|
| 568 | pApplicationService_type m_pApplicationService; |
|---|
| 569 | }; |
|---|
| 570 | public: |
|---|
| 571 | virtual void call() |
|---|
| 572 | { |
|---|
| 573 | Threading::I_Condition* pCondition = m_pApplicationService->prepareToStart(m_server.getSharedThreadPool()); |
|---|
| 574 | if( pCondition != NULL ) |
|---|
| 575 | { |
|---|
| 576 | pCondition->requireCondition(); |
|---|
| 577 | } |
|---|
| 578 | |
|---|
| 579 | StartApplicationServiceTask* pStartTask = new StartApplicationServiceTask(m_pApplicationService); |
|---|
| 580 | StopApplicationServiceTask* pStopTask = new StopApplicationServiceTask(m_pApplicationService); |
|---|
| 581 | m_installQueue.pushRequest(pStartTask); |
|---|
| 582 | m_shutdownQueue.pushRequest(pStopTask); |
|---|
| 583 | } |
|---|
| 584 | |
|---|
| 585 | PrepareToStartApplicationServiceTask(ApplicationServer& _server, pApplicationService_type _pApplicationService, Threading::ThreadPool& _installQueue, Threading::ThreadPool& _shutdownQueue) |
|---|
| 586 | : m_server(_server) |
|---|
| 587 | , m_pApplicationService(_pApplicationService) |
|---|
| 588 | , m_installQueue(_installQueue) |
|---|
| 589 | , m_shutdownQueue(_shutdownQueue) |
|---|
| 590 | { |
|---|
| 591 | } |
|---|
| 592 | private: |
|---|
| 593 | ApplicationServer& m_server; |
|---|
| 594 | pApplicationService_type m_pApplicationService; |
|---|
| 595 | Threading::ThreadPool& m_installQueue; |
|---|
| 596 | Threading::ThreadPool& m_shutdownQueue; |
|---|
| 597 | }; |
|---|
| 598 | |
|---|
| 599 | class PrepareToStopApplicationServiceTask |
|---|
| 600 | : public Threading::ThreadPool::Task |
|---|
| 601 | { |
|---|
| 602 | public: |
|---|
| 603 | virtual void call() |
|---|
| 604 | { |
|---|
| 605 | Threading::I_Condition* pCondition = m_pApplicationService->prepareToStop(); |
|---|
| 606 | if( pCondition != NULL ) |
|---|
| 607 | { |
|---|
| 608 | pCondition->requireCondition(); |
|---|
| 609 | } |
|---|
| 610 | } |
|---|
| 611 | |
|---|
| 612 | PrepareToStopApplicationServiceTask(pApplicationService_type _pApplicationService) |
|---|
| 613 | : m_pApplicationService(_pApplicationService) |
|---|
| 614 | { |
|---|
| 615 | } |
|---|
| 616 | private: |
|---|
| 617 | pApplicationService_type m_pApplicationService; |
|---|
| 618 | }; |
|---|
| 619 | public: |
|---|
| 620 | virtual void call() |
|---|
| 621 | { |
|---|
| 622 | // TODO What about the resource location? |
|---|
| 623 | m_server.handleInstallApplication(m_pApplicationService, m_pRootLocation); |
|---|
| 624 | PrepareToStartApplicationServiceTask* pStartTask = new PrepareToStartApplicationServiceTask(m_server, m_pApplicationService, m_installQueue, m_shutdownQueue); |
|---|
| 625 | PrepareToStopApplicationServiceTask* pStopTask = new PrepareToStopApplicationServiceTask(m_pApplicationService); |
|---|
| 626 | m_installQueue.pushRequest(pStartTask); |
|---|
| 627 | m_shutdownQueue.pushRequest(pStopTask); |
|---|
| 628 | } |
|---|
| 629 | |
|---|
| 630 | InstallApplicationServiceTask(ApplicationServer& _server, pApplicationService_type _pApplicationService, pResourceLocation_type _pRootLocation, Threading::ThreadPool& _installQueue, Threading::ThreadPool& _shutdownQueue) |
|---|
| 631 | : m_server(_server) |
|---|
| 632 | , m_pApplicationService(_pApplicationService) |
|---|
| 633 | , m_pRootLocation(_pRootLocation) |
|---|
| 634 | , m_installQueue(_installQueue) |
|---|
| 635 | , m_shutdownQueue(_shutdownQueue) |
|---|
| 636 | { |
|---|
| 637 | } |
|---|
| 638 | private: |
|---|
| 639 | ApplicationServer& m_server; |
|---|
| 640 | pApplicationService_type m_pApplicationService; |
|---|
| 641 | pResourceLocation_type m_pRootLocation; |
|---|
| 642 | Threading::ThreadPool& m_installQueue; |
|---|
| 643 | Threading::ThreadPool& m_shutdownQueue; |
|---|
| 644 | }; |
|---|
| 645 | |
|---|
| 646 | // Schedule the installation of the application. |
|---|
| 647 | InstallApplicationServiceTask* pTask = new InstallApplicationServiceTask(*this, _pApplicationService, _pRootLocation, m_installQueue, m_shutdownQueue); |
|---|
| 648 | m_installQueue.pushRequest(pTask); |
|---|
| 649 | } |
|---|
| 650 | |
|---|
| 651 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 652 | void |
|---|
| 653 | ApplicationServer::configureApplication(pApplicationService_type _pApplicationService, pConfig_type _pConfig) |
|---|
| 654 | { |
|---|
| 655 | class ConfigureApplicationServiceTask |
|---|
| 656 | : public Threading::ThreadPool::Task |
|---|
| 657 | { |
|---|
| 658 | public: |
|---|
| 659 | virtual void call() |
|---|
| 660 | { |
|---|
| 661 | m_server.handleConfigureApplication(m_pApplicationService, m_pConfig); |
|---|
| 662 | } |
|---|
| 663 | |
|---|
| 664 | ConfigureApplicationServiceTask(ApplicationServer& _server, pApplicationService_type _pApplicationService, pConfig_type _pConfig) |
|---|
| 665 | : m_server(_server) |
|---|
| 666 | , m_pApplicationService(_pApplicationService) |
|---|
| 667 | , m_pConfig(_pConfig) |
|---|
| 668 | { |
|---|
| 669 | } |
|---|
| 670 | |
|---|
| 671 | private: |
|---|
| 672 | ApplicationServer& m_server; |
|---|
| 673 | pApplicationService_type m_pApplicationService; |
|---|
| 674 | pConfig_type m_pConfig; |
|---|
| 675 | }; |
|---|
| 676 | |
|---|
| 677 | // Schedule the configuration of the application. |
|---|
| 678 | ConfigureApplicationServiceTask* pTask = new ConfigureApplicationServiceTask(*this, _pApplicationService, _pConfig); |
|---|
| 679 | m_installQueue.pushRequest(pTask); |
|---|
| 680 | } |
|---|
| 681 | |
|---|
| 682 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 683 | ApplicationServer::pApplicationService_type |
|---|
| 684 | ApplicationServer::getApplication(pResourceLocation_type _pServiceLocation) const |
|---|
| 685 | { |
|---|
| 686 | Threading::CriticalSection lock(m_pApplicationGuard); |
|---|
| 687 | |
|---|
| 688 | ApplicationServices_type::const_iterator iter = m_applicationServices.find(_pServiceLocation); |
|---|
| 689 | |
|---|
| 690 | if( iter != m_applicationServices.end() ) |
|---|
| 691 | { |
|---|
| 692 | return iter->second; |
|---|
| 693 | } |
|---|
| 694 | else |
|---|
| 695 | { |
|---|
| 696 | // TODO Throw an exception? |
|---|
| 697 | return pApplicationService_type(); |
|---|
| 698 | } |
|---|
| 699 | } |
|---|
| 700 | |
|---|
| 701 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 702 | void |
|---|
| 703 | ApplicationServer::getResourceLocations(I_ResourceLocationVisitor& _visitor) const |
|---|
| 704 | { |
|---|
| 705 | _visitor.begin(); |
|---|
| 706 | |
|---|
| 707 | ApplicationServices_type::const_iterator iter = m_applicationServices.begin(); |
|---|
| 708 | while( iter != m_applicationServices.end() ) |
|---|
| 709 | { |
|---|
| 710 | _visitor.visit(iter->first, iter->second); |
|---|
| 711 | iter++; |
|---|
| 712 | } |
|---|
| 713 | |
|---|
| 714 | _visitor.end(); |
|---|
| 715 | } |
|---|
| 716 | |
|---|
| 717 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 718 | ApplicationServer::pMessageRegistry_type |
|---|
| 719 | ApplicationServer::getMessageRegistry() |
|---|
| 720 | { |
|---|
| 721 | return m_pMessageRegistry_type; |
|---|
| 722 | } |
|---|
| 723 | |
|---|
| 724 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 725 | void |
|---|
| 726 | ApplicationServer::handleMessage(pMessage_type _pMessage) |
|---|
| 727 | { |
|---|
| 728 | // Local and remote messages are handled here. |
|---|
| 729 | |
|---|
| 730 | ResourceLocation* pDestination = dynamic_cast<ResourceLocation*>(_pMessage->getDestinationLocation().get()); |
|---|
| 731 | |
|---|
| 732 | if (pDestination != NULL) |
|---|
| 733 | { |
|---|
| 734 | if (isLocalDestination(_pMessage->getDestinationEndpoint())) |
|---|
| 735 | { |
|---|
| 736 | // This is a message received by a protocol adapter or was sent |
|---|
| 737 | // from a local application service to another local application service. |
|---|
| 738 | class HandleMessageTask |
|---|
| 739 | : public Threading::ThreadPool::Task |
|---|
| 740 | { |
|---|
| 741 | public: |
|---|
| 742 | virtual void call() |
|---|
| 743 | { |
|---|
| 744 | if( m_pApplicationService.isValid() ) |
|---|
| 745 | { |
|---|
| 746 | m_pApplicationService->handleMessage(m_pMessage); |
|---|
| 747 | } |
|---|
| 748 | } |
|---|
| 749 | |
|---|
| 750 | HandleMessageTask(pApplicationService_type _pApplicationService, pMessage_type _pMessage) |
|---|
| 751 | : m_pApplicationService(_pApplicationService) |
|---|
| 752 | , m_pMessage(_pMessage) |
|---|
| 753 | { |
|---|
| 754 | } |
|---|
| 755 | |
|---|
| 756 | virtual ~HandleMessageTask() {} |
|---|
| 757 | private: |
|---|
| 758 | pApplicationService_type m_pApplicationService; |
|---|
| 759 | pMessage_type m_pMessage; |
|---|
| 760 | }; |
|---|
| 761 | |
|---|
| 762 | // TODO Use a TaskPool |
|---|
| 763 | HandleMessageTask* pTask = new HandleMessageTask(pDestination->getApplicationService(), _pMessage); |
|---|
| 764 | |
|---|
| 765 | m_sharedThreadPool.pushRequest(pTask); |
|---|
| 766 | } |
|---|
| 767 | else |
|---|
| 768 | { |
|---|
| 769 | // This is an outbound message. |
|---|
| 770 | // This is an outbound request. Send it. |
|---|
| 771 | // TODO Does this end up being asynchronous? If not then we |
|---|
| 772 | // probably should handle it in a worker thread / outbound queue. |
|---|
| 773 | _pMessage->getDestinationEndpoint()->getProtocolAdapter().lock()->sendTo |
|---|
| 774 | ( |
|---|
| 775 | _pMessage, |
|---|
| 776 | _pMessage->getDestinationEndpoint() |
|---|
| 777 | ); |
|---|
| 778 | } |
|---|
| 779 | } |
|---|
| 780 | else |
|---|
| 781 | { |
|---|
| 782 | throw Utility::runtime_exception("ApplicationServer::handleMessage(): Error, invalid destination."); |
|---|
| 783 | } |
|---|
| 784 | } |
|---|
| 785 | |
|---|
| 786 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 787 | void |
|---|
| 788 | ApplicationServer::handleRequest(pRequest_type _pRequest, pResponseHandler_type _pResponseHandler) |
|---|
| 789 | { |
|---|
| 790 | ResourceLocation* pDestination = dynamic_cast<ResourceLocation*>(_pRequest->getDestinationLocation().get()); |
|---|
| 791 | |
|---|
| 792 | if (pDestination != NULL) |
|---|
| 793 | { |
|---|
| 794 | // TODO: If _pRequest destination is not this server then the request is destined for |
|---|
| 795 | // another destination and it should be sent instead of dispatched. |
|---|
| 796 | std::cout << "Sending a request to " |
|---|
| 797 | << _pRequest->getDestinationEndpoint()->toString() |
|---|
| 798 | << "/" |
|---|
| 799 | << pDestination->toString() |
|---|
| 800 | << std::endl; |
|---|
| 801 | |
|---|
| 802 | if (isLocalDestination(_pRequest->getDestinationEndpoint())) |
|---|
| 803 | { |
|---|
| 804 | // All requests that are destined for a local service go through |
|---|
| 805 | // this logic. All requests coming from an external source are |
|---|
| 806 | // processed by ApplicationServer::handleMessage(). |
|---|
| 807 | |
|---|
| 808 | class HandleRequestTask |
|---|
| 809 | : public Threading::ThreadPool::Task |
|---|
| 810 | { |
|---|
| 811 | public: |
|---|
| 812 | virtual void call() |
|---|
| 813 | { |
|---|
| 814 | if( m_pApplicationService.isValid() ) |
|---|
| 815 | { |
|---|
| 816 | m_pApplicationService->handleRequest(m_pRequest, m_pResponseHandler); |
|---|
| 817 | } |
|---|
| 818 | } |
|---|
| 819 | |
|---|
| 820 | HandleRequestTask(pApplicationService_type _pApplicationService, pRequest_type _pRequest, pResponseHandler_type _pResponseHandler) |
|---|
| 821 | : m_pApplicationService(_pApplicationService) |
|---|
| 822 | , m_pRequest(_pRequest) |
|---|
| 823 | , m_pResponseHandler(_pResponseHandler) |
|---|
| 824 | { |
|---|
| 825 | } |
|---|
| 826 | |
|---|
| 827 | virtual ~HandleRequestTask() {} |
|---|
| 828 | private: |
|---|
| 829 | pApplicationService_type m_pApplicationService; |
|---|
| 830 | pRequest_type m_pRequest; |
|---|
| 831 | pResponseHandler_type m_pResponseHandler; |
|---|
| 832 | }; |
|---|
| 833 | |
|---|
| 834 | // TODO Use a TaskPool |
|---|
| 835 | HandleRequestTask* pTask = new HandleRequestTask(pDestination->getApplicationService(), _pRequest, _pResponseHandler); |
|---|
| 836 | |
|---|
| 837 | m_sharedThreadPool.pushRequest(pTask); |
|---|
| 838 | } |
|---|
| 839 | else |
|---|
| 840 | { |
|---|
| 841 | // This is an outbound request. Send it. |
|---|
| 842 | // TODO Does this end up being asynchronous? If not then we |
|---|
| 843 | // probably should handle it in a worker thread / outbound queue. |
|---|
| 844 | _pRequest->getDestinationEndpoint()->getProtocolAdapter().lock()->sendTo |
|---|
| 845 | ( |
|---|
| 846 | _pRequest, |
|---|
| 847 | _pRequest->getDestinationEndpoint() |
|---|
| 848 | ); |
|---|
| 849 | } |
|---|
| 850 | } |
|---|
| 851 | else |
|---|
| 852 | { |
|---|
| 853 | throw Utility::runtime_exception("ApplicationServer::handleRequest(): Error, invalid destination."); |
|---|
| 854 | } |
|---|
| 855 | } |
|---|
| 856 | |
|---|
| 857 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 858 | void |
|---|
| 859 | ApplicationServer::handleSessionEvent(pSessionEvent_type _pSessionEvent) |
|---|
| 860 | { |
|---|
| 861 | throw Utility::runtime_exception("ApplicationServer::handleSessionEvent(): Error, not implemented."); |
|---|
| 862 | } |
|---|
| 863 | |
|---|
| 864 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 865 | ApplicationServer::pDatabaseConnection_type |
|---|
| 866 | ApplicationServer::getDatabaseConnection(const std::string& _database) |
|---|
| 867 | { |
|---|
| 868 | /// Do we need to guard this? |
|---|
| 869 | Zen::Threading::I_Thread::ThreadId _threadId = Threading::I_Thread::getCurrentThreadId(); |
|---|
| 870 | |
|---|
| 871 | DatabaseConnectionsMap_type::iterator iter = m_databaseConnectionsMap.find(_database); |
|---|
| 872 | if( iter != m_databaseConnectionsMap.end() ) |
|---|
| 873 | { |
|---|
| 874 | return iter->second->getConnection(_threadId); |
|---|
| 875 | } |
|---|
| 876 | else |
|---|
| 877 | { |
|---|
| 878 | return pDatabaseConnection_type(); |
|---|
| 879 | // TODO Error? |
|---|
| 880 | } |
|---|
| 881 | } |
|---|
| 882 | |
|---|
| 883 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 884 | void |
|---|
| 885 | ApplicationServer::handleInstallProtocol(pProtocolService_type _pProtocolService, const std::string& _protocolName) |
|---|
| 886 | { |
|---|
| 887 | Threading::CriticalSection lock(m_pProtocolGuard); |
|---|
| 888 | |
|---|
| 889 | m_protocolServices[_protocolName] = _pProtocolService; |
|---|
| 890 | |
|---|
| 891 | // TODO Handle the startup sequence better. All prepareToStart() must be called for both the protocols |
|---|
| 892 | // and the services, then all of the start() methods must be called. |
|---|
| 893 | // start() must be called |
|---|
| 894 | |
|---|
| 895 | #if 0 // deprecated |
|---|
| 896 | _pProtocolService->prepareToStart(m_sharedThreadPool); |
|---|
| 897 | _pProtocolService->start(); |
|---|
| 898 | #endif // deprecated |
|---|
| 899 | } |
|---|
| 900 | |
|---|
| 901 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 902 | void |
|---|
| 903 | ApplicationServer::handleInstallApplication(pApplicationService_type _pApplicationService, pResourceLocation_type _pRootLocation) |
|---|
| 904 | { |
|---|
| 905 | Threading::CriticalSection lock(m_pApplicationGuard); |
|---|
| 906 | |
|---|
| 907 | m_applicationServices[_pRootLocation] = _pApplicationService; |
|---|
| 908 | |
|---|
| 909 | // TODO Get the root resource location and set the application service |
|---|
| 910 | ResourceLocation* pRoot = dynamic_cast<ResourceLocation*>(_pRootLocation.get()); |
|---|
| 911 | pRoot->setApplicationService(_pApplicationService); |
|---|
| 912 | |
|---|
| 913 | if (m_pScriptEngine.isValid()) |
|---|
| 914 | { |
|---|
| 915 | Scripting::I_ScriptableService* const pScriptable = dynamic_cast<Scripting::I_ScriptableService*>(_pApplicationService.get()); |
|---|
| 916 | |
|---|
| 917 | if (pScriptable) |
|---|
| 918 | { |
|---|
| 919 | pScriptable->registerScriptEngine(m_pScriptEngine); |
|---|
| 920 | } |
|---|
| 921 | } |
|---|
| 922 | |
|---|
| 923 | #if 0 // deprecated |
|---|
| 924 | // TODO Handle startup sequence better. |
|---|
| 925 | _pApplicationService->prepareToStart(m_sharedThreadPool); |
|---|
| 926 | _pApplicationService->start(); |
|---|
| 927 | #endif // deprecated |
|---|
| 928 | } |
|---|
| 929 | |
|---|
| 930 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 931 | void |
|---|
| 932 | ApplicationServer::handleConfigureApplication(pApplicationService_type _pApplicationService, pConfig_type _pConfig) |
|---|
| 933 | { |
|---|
| 934 | _pApplicationService->setConfiguration(*_pConfig); |
|---|
| 935 | } |
|---|
| 936 | |
|---|
| 937 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 938 | ApplicationServer::DatabaseConnections::DatabaseConnections(pDatabaseService_type _pService, |
|---|
| 939 | config_type _connectionConfig) |
|---|
| 940 | : m_pDatabaseService(_pService) |
|---|
| 941 | , m_connectionConfig(_connectionConfig) |
|---|
| 942 | , m_databaseConnections() |
|---|
| 943 | , m_databaseConnectionsMutex(Zen::Threading::MutexFactory::create()) |
|---|
| 944 | { |
|---|
| 945 | } |
|---|
| 946 | |
|---|
| 947 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 948 | ApplicationServer::DatabaseConnections::~DatabaseConnections() |
|---|
| 949 | { |
|---|
| 950 | Zen::Threading::MutexFactory::destroy(m_databaseConnectionsMutex); |
|---|
| 951 | } |
|---|
| 952 | |
|---|
| 953 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 954 | ApplicationServer::DatabaseConnections::pDatabaseConnection_type |
|---|
| 955 | ApplicationServer::DatabaseConnections::getConnection(Zen::Threading::I_Thread::ThreadId& _threadId) |
|---|
| 956 | { |
|---|
| 957 | Zen::Threading::CriticalSection guard(m_databaseConnectionsMutex); |
|---|
| 958 | |
|---|
| 959 | DatabaseConnections_type::iterator iter = m_databaseConnections.find(_threadId); |
|---|
| 960 | if( iter != m_databaseConnections.end() ) |
|---|
| 961 | { |
|---|
| 962 | return iter->second; |
|---|
| 963 | } |
|---|
| 964 | else |
|---|
| 965 | { |
|---|
| 966 | pDatabaseConnection_type pDatabaseConnection = m_pDatabaseService->connect(_threadId.toString(), m_connectionConfig); |
|---|
| 967 | m_databaseConnections[_threadId] = pDatabaseConnection; |
|---|
| 968 | return pDatabaseConnection; |
|---|
| 969 | } |
|---|
| 970 | } |
|---|
| 971 | |
|---|
| 972 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 973 | void |
|---|
| 974 | ApplicationServer::installDatabaseConnections(pConfig_type _pDatabasesConfig) |
|---|
| 975 | { |
|---|
| 976 | class DatabaseVisitor |
|---|
| 977 | : public Zen::Plugins::I_ConfigurationElement::I_ConfigurationElementVisitor |
|---|
| 978 | { |
|---|
| 979 | typedef std::map<std::string, std::string> config_type; |
|---|
| 980 | |
|---|
| 981 | class DBConfigVisitor |
|---|
| 982 | : public Zen::Plugins::I_ConfigurationElement::I_ConfigurationElementVisitor |
|---|
| 983 | { |
|---|
| 984 | public: |
|---|
| 985 | virtual void begin() {} |
|---|
| 986 | |
|---|
| 987 | virtual void visit(const Zen::Plugins::I_ConfigurationElement& _element) |
|---|
| 988 | { |
|---|
| 989 | // TODO Instead of getAttributeValue("value") there should |
|---|
| 990 | // be some way to get the text inside of an element. |
|---|
| 991 | m_config[_element.getName()] = _element.getAttribute("value"); |
|---|
| 992 | } |
|---|
| 993 | |
|---|
| 994 | virtual void end() {} |
|---|
| 995 | |
|---|
| 996 | DBConfigVisitor(config_type& _config) |
|---|
| 997 | : m_config(_config) |
|---|
| 998 | { |
|---|
| 999 | } |
|---|
| 1000 | |
|---|
| 1001 | private: |
|---|
| 1002 | config_type& m_config; |
|---|
| 1003 | |
|---|
| 1004 | }; // class DBConfigVisitor |
|---|
| 1005 | |
|---|
| 1006 | public: |
|---|
| 1007 | virtual void begin() {} |
|---|
| 1008 | |
|---|
| 1009 | virtual void visit(const Zen::Plugins::I_ConfigurationElement& _element) |
|---|
| 1010 | { |
|---|
| 1011 | config_type config; |
|---|
| 1012 | |
|---|
| 1013 | DBConfigVisitor visitor(config); |
|---|
| 1014 | _element.getChildren(visitor); |
|---|
| 1015 | |
|---|
| 1016 | m_pAppServer->createDatabaseEntry(_element.getAttribute("name"), |
|---|
| 1017 | _element.getAttribute("type"), config); |
|---|
| 1018 | } |
|---|
| 1019 | |
|---|
| 1020 | virtual void end() {} |
|---|
| 1021 | |
|---|
| 1022 | DatabaseVisitor(ApplicationServer* _pAppServer) |
|---|
| 1023 | : m_pAppServer(_pAppServer) |
|---|
| 1024 | { |
|---|
| 1025 | } |
|---|
| 1026 | |
|---|
| 1027 | private: |
|---|
| 1028 | ApplicationServer* m_pAppServer; |
|---|
| 1029 | |
|---|
| 1030 | }; // class DatabaseVisitor |
|---|
| 1031 | |
|---|
| 1032 | DatabaseVisitor visitor(this); |
|---|
| 1033 | _pDatabasesConfig->getChildren("database", visitor); |
|---|
| 1034 | |
|---|
| 1035 | } |
|---|
| 1036 | |
|---|
| 1037 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 1038 | void |
|---|
| 1039 | ApplicationServer::createDatabaseEntry(const std::string& _connectionName, const std::string& _databaseType, config_type& _config) |
|---|
| 1040 | { |
|---|
| 1041 | DatabaseConnectionsMap_type::iterator iter = m_databaseConnectionsMap.find(_connectionName); |
|---|
| 1042 | if( iter == m_databaseConnectionsMap.end() ) |
|---|
| 1043 | { |
|---|
| 1044 | typedef Zen::Memory::managed_ptr<Zen::Database::I_DatabaseService> pDatabaseService_type; |
|---|
| 1045 | pDatabaseService_type pDatabaseService = |
|---|
| 1046 | Zen::Database::I_DatabaseManager::getSingleton().createDatabaseService( |
|---|
| 1047 | _databaseType, |
|---|
| 1048 | _config |
|---|
| 1049 | ); |
|---|
| 1050 | |
|---|
| 1051 | DatabaseConnections* pRaw = new DatabaseConnections(pDatabaseService, _config); |
|---|
| 1052 | pDatabaseConnections_type pDatabaseConnections(pRaw); |
|---|
| 1053 | m_databaseConnectionsMap[_connectionName] = pDatabaseConnections; |
|---|
| 1054 | } |
|---|
| 1055 | else |
|---|
| 1056 | { |
|---|
| 1057 | // TODO Error? |
|---|
| 1058 | } |
|---|
| 1059 | } |
|---|
| 1060 | |
|---|
| 1061 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 1062 | bool |
|---|
| 1063 | ApplicationServer::isLocalDestination(pEndpoint_type _pDestination) |
|---|
| 1064 | { |
|---|
| 1065 | // TODO Since all endpoints must be constructed via a protocol adapter, first |
|---|
| 1066 | // check the protocol adapter associated with the endpoint. |
|---|
| 1067 | // TODO Only return true if this is true, otherwise consult the |
|---|
| 1068 | // other protocol adapters. We don't want to do this now because |
|---|
| 1069 | // we're testing a situation where we want to forcibly serialize and |
|---|
| 1070 | // send over the wire within a single application. If we check other |
|---|
| 1071 | // protocol adapters then we'll find out that this is indeed a local |
|---|
| 1072 | // destination. |
|---|
| 1073 | //return _pDestination->getProtcolAdapter()->isLocalDestination(); |
|---|
| 1074 | |
|---|
| 1075 | // An invalid pointer here means that it is definitely local. |
|---|
| 1076 | return (!_pDestination.isValid()) || _pDestination->isLocal(); |
|---|
| 1077 | } |
|---|
| 1078 | |
|---|
| 1079 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 1080 | } // namespace AppServer |
|---|
| 1081 | } // namespace Enterprise |
|---|
| 1082 | } // namespace Zen |
|---|
| 1083 | //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ |
|---|
| 1084 | |
|---|