root/Enterprise/branches/0075_TR_SCRIPTING/AppServer/src/ApplicationServer.cpp @ 3467

Revision 3467, 38.9 KB (checked in by trichards, 6 months ago)

Misc gcc / ISO Standard fixes in AppServer?.

Line 
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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
62namespace Zen {
63namespace Enterprise {
64namespace AppServer {
65//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
66static 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
82ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
96ApplicationServer::~ApplicationServer()
97{
98}
99
100//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
101Zen::Threading::I_Condition*
102ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
179void
180ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
279void
280ApplicationServer::registerDefaultScriptEngine(pScriptEngine_type _pEngine)
281{
282    // TODO Register with all of the already-installed app services.
283
284    m_pScriptEngine = _pEngine;
285}
286
287//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
288ApplicationServer::pScriptEngine_type
289ApplicationServer::getDefaultScriptEngine()
290{
291    return m_pScriptEngine;
292}
293
294//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
295ApplicationServer::pEventService_type
296ApplicationServer::getEventService()
297{
298    return m_pEventService;
299}
300
301//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
302void
303ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
345void
346ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
468ApplicationServer::pProtocolService_type
469ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
487void
488ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
528void
529ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
652void
653ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
683ApplicationServer::pApplicationService_type
684ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
702void
703ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
718ApplicationServer::pMessageRegistry_type
719ApplicationServer::getMessageRegistry()
720{
721    return m_pMessageRegistry_type;
722}
723
724//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
725void
726ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
787void
788ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
858void
859ApplicationServer::handleSessionEvent(pSessionEvent_type _pSessionEvent)
860{
861    throw Utility::runtime_exception("ApplicationServer::handleSessionEvent(): Error, not implemented.");
862}
863
864//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
865ApplicationServer::pDatabaseConnection_type
866ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
884void
885ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
902void
903ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
931void
932ApplicationServer::handleConfigureApplication(pApplicationService_type _pApplicationService, pConfig_type _pConfig)
933{
934    _pApplicationService->setConfiguration(*_pConfig);
935}
936
937//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
938ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
948ApplicationServer::DatabaseConnections::~DatabaseConnections()
949{
950    Zen::Threading::MutexFactory::destroy(m_databaseConnectionsMutex);
951}
952
953//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
954ApplicationServer::DatabaseConnections::pDatabaseConnection_type
955ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
973void
974ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
1038void
1039ApplicationServer::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//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
1062bool
1063ApplicationServer::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
Note: See TracBrowser for help on using the browser.