summaryrefslogtreecommitdiff
path: root/CIAO/DAnCE/NodeApplicationManager/NodeApplicationManager_Impl.h
blob: 1cfbc313cc97866705505155b8b789f314f1629b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// $Id$

// -*- C++ -*-

//=============================================================================
/**
 *  @file    NodeApplicationManager_Impl.h
 *
 *  @author  Tao Lu <lu@dre.vanderbilt.edu>
 *  @author  Gan Deng <dengg@dre.vanderbilt.edu>
 *
 *  This file contains implementation for the servant of
 *  Deployment::NodeApplicationManager.
 */
//=============================================================================


#ifndef CIAO_NODEAPPLICATIONMANAGER_IMPL_H
#define CIAO_NODEAPPLICATIONMANAGER_IMPL_H
#include /**/ "ace/pre.h"

#include "ace/config-all.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/SString.h"
#include "ace/Hash_Map_Manager_T.h"
#include "ace/OS_NS_sys_wait.h"
#include "ace/Process_Manager.h"
#include "DAnCE/Deployment/NodeApp_CB_Impl.h"
#include "DAnCE/Deployment/Deployment_NodeApplicationManagerS.h"
#include "ciao/CIAO_common.h"
#include "CIAO_NAM_Export.h"
#include "ImplementationInfo.h"
#include "NodeManager/NodeManager_Impl.h"
#include "NodeApplication/NodeApplication_Core.h"

namespace CIAO
{

  /**
   * @class NodeApplicationManager_Impl_Base
   */
  class CIAO_NAM_Export NodeApplicationManager_Impl_Base
    : public virtual POA_Deployment::NodeApplicationManager
  {
  public:
    /// Constructor
    NodeApplicationManager_Impl_Base (CORBA::ORB_ptr o,
                                      PortableServer::POA_ptr p);

    /*===========================================================
     * Below are operations from the NodeApplicationManager
     *
     *============================================================*/

    /// The return type is NodeApplication_ptr actually.
    /// For "external/shared" components of this child plan, they are
    /// not actaully installed, however, the object references
    /// of the ports of these external components are returned
    /// through <providedReference>.
    virtual Deployment::Application_ptr
    startLaunch (const Deployment::Properties & configProperty,
                 Deployment::Connections_out providedReference,
                 CORBA::Boolean start);

    //@@ Destroy the whole applicaton.
    virtual void destroyApplication (Deployment::Application_ptr);

    virtual Deployment::Application_ptr
    perform_redeployment (const Deployment::Properties & configProperty,
                          Deployment::Connections_out providedReference,
                          CORBA::Boolean add_or_remove,
                          CORBA::Boolean start);

    virtual void
    reset_plan (const ::Deployment::DeploymentPlan & plan);

    virtual void
    set_shared_components (const Deployment::ComponentPlans & shared);

    /**
     * A factory operation to create NodeApplicationManager interface, and return
     * the object reference.
     * Initialize the NodeApplicationManager.  The current implementation
     * of CIAO_NodeApplicationManager can only activate CIAO's own
     * NodeApplication processes.  You should specify the location
     * (pathname) of the NodeApplication and the delay.
     * CIAO_NodeApplicationManager should wait (in second) for NodeApplication to
     * call back.
     *
     * @param nodeapp_location A null-termiated char * string pointing
     *    to the pathname of a NodeApplication executable.
     *
     * @param nodeapp_options A null-terminated char * string
     * containing command line options to be passed to the
     * NodeApplication.
     *
     * @param delay instructs how long (in second) a CIAO_NodeApplicationManager
     *   should wait for a newly spawned NodeApplication to pass back
     *   its IOR.
     *
     * @param plan has all the information needed for the NodeAppManager to
     *        construct the application locally. Note, this includes the properties
     *        of the NodeApplication. For example, ORB config options etc.
     *
     * @param callback_poa contains child poa created for the callback interface.
     *
     * @para nm Pointer to the NodeManager_Impl servant object
     *
     * @return NodeApplicationManager_ptr.
     **/
    virtual PortableServer::ObjectId
    init (const char *nodeapp_location,
          const char *nodeapp_options,
          const CORBA::ULong delay,
          const Deployment::DeploymentPlan & plan,
          const PortableServer::POA_ptr callback_poa,
          NodeManager_Impl_Base * nm)
      =0;

    /// @note This method doesn't do duplicate.
    Deployment::NodeApplicationManager_ptr get_nodeapp_manager (void);

    /// Set the priority of the NodeApplication process which this NAM manages
    virtual ::CORBA::Long set_priority (
        const char * cid,
        const ::Deployment::Sched_Params & params);

  protected:
    /// Destructor
    virtual ~NodeApplicationManager_Impl_Base (void);

    /// Add new components
    virtual void
    add_new_components (void);

    /// Remove existing components
    virtual void
    remove_existing_components (void);

    /// Determine whether a component is absent in the new_plan
    /// Return true if absent
    virtual bool
    is_to_be_removed (const char * name);

    /// Internal help function to create new NodeApplicationProcess
    virtual Deployment::NodeApplication_ptr
    create_node_application (const ACE_CString & options) = 0;

    /// Helper function to get the connection.
    virtual Deployment::Connections * create_connections ();

    /**
     * Find the configurations in the plan and prepare them to pass to the
     * NodeApplication, from command line probably.
     */
    void parse_config_value (ACE_CString & str);

    /// Helper function to check wheather a component instance
    /// is in the "shared components list".
    bool is_shared_component (ACE_CString & name);

    /// Helper function to check wheather a component instance
    /// is in the "shared components list".
    bool is_external_component (ACE_CString & name);

  protected:
    /// location of the Nodeapplication
    ACE_CString nodeapp_path_;

    /// Keep a pointer to the managing ORB serving this servant.
    CORBA::ORB_var orb_;

    /// Keep a pointer to the managing POA.
    PortableServer::POA_var poa_;

    /// Pointer to the NodeManager_Impl servant object
    /// We could do this because NodeManager and NodeApplicationManager
    /// are always collocated in the same process, so we don't have
    /// to pass CORBA object reference back and forth.
    NodeManager_Impl_Base * node_manager_;

    /// ObjectRef of ourself which will be needed by the callback
    Deployment::NodeApplicationManager_var objref_;

    /// Child poa that uses active object map.
    PortableServer::POA_var callback_poa_;

    /// Cache a object reference of the underlying NodeApplication
    /// Since I have decided to have only 1 NA in NAM so no map is needed.
    Deployment::NodeApplication_var nodeapp_;

    /// Cached plan (This should be the part of the whole plan local to this node)
    /// The plan will be initialized when init is called.
    Deployment::DeploymentPlan plan_;

    /// Specify the time in second NodeApplicationManager will wait for a
    /// child NodeApplication to callback.  Default is 5 second.
    CORBA::ULong spawn_delay_;

    /// Extracted commandline options to pass to the NodeApplication.
    CORBA::String_var nodeapp_command_op_;

    /// A list of components shared across deployment plans
    Deployment::ComponentPlans shared_components_;

    /// A list of components that are "external" to this plan
    Deployment::ComponentPlans external_components_;

    /// A map of the component created on this node.
    typedef ACE_Hash_Map_Manager_Ex<ACE_CString,
                                    Components::CCMObject_var,
                                    ACE_Hash<ACE_CString>,
                                    ACE_Equal_To<ACE_CString>,
                                    ACE_Null_Mutex> CCMComponent_Map;
    typedef CCMComponent_Map::iterator Component_Iterator;
    CCMComponent_Map component_map_;

    /// Synchronize access to the object set.
    TAO_SYNCH_MUTEX lock_;

    /// The Process Manager for this NodeApplicationManager
    ACE_Process_Manager node_app_process_manager_;

    /// The process id of the NA associated with the NAM,
    /// Each NAM will only have one NA associated with it,
    /// so we have only one process associated with it.

    // this is UNIX specific .... not portable
    pid_t process_id_;
  };


  /**
   * @class NAM_Handler
   * @brief The signal handler class for the SIGCHLD
   * handling to avoid zombies
   *
   */
  class NAM_Handler : public ACE_Event_Handler
    {
    public:
      virtual int handle_signal (int sig,
                                 siginfo_t *,
                                 ucontext_t *)
        {
          ACE_UNUSED_ARG (sig);

          // @@ Note that this code is not portable to all OS platforms
          // since it uses print statements within signal handler context.
          //ACE_DEBUG ((LM_DEBUG,
          //            "Executed ACE signal handler for signal %S \n",
          //            sig));

          ACE_exitcode status;
          // makes a claal to the underlying os system call
          // -1 to wait for any child process
          // and WNOHANG so that it retuurns immediately
          ACE_OS::waitpid (-1 ,&status, WNOHANG, 0);

          return 0;
        }
    };


  /**
   * @class NodeApplicationManager_Impl
   */
  class CIAO_NAM_Export NodeApplicationManager_Impl
    : public virtual NodeApplicationManager_Impl_Base
  {
  public:
    /// Constructor
    NodeApplicationManager_Impl (CORBA::ORB_ptr o,
                                 PortableServer::POA_ptr p);

    virtual PortableServer::ObjectId
    init (const char *nodeapp_location,
          const char *nodeapp_options,
          const CORBA::ULong delay,
          const Deployment::DeploymentPlan & plan,
          const PortableServer::POA_ptr callback_poa,
          NodeManager_Impl_Base * nm);

  protected:
    /// Destructor
    virtual ~NodeApplicationManager_Impl (void);

    // Internal help function to create new NodeApplicationProcess
    // Here we override it to create an in-process NodeApplication object
    virtual Deployment::NodeApplication_ptr
    create_node_application (const ACE_CString & options);


    /**
     * @operation push_component_info
     * @brief pushes component info to the NodeManager
     *
     * @param process_id The id of the process of NodeApplication
     */
    void push_component_info (pid_t process_id);

    /// The signal handler
    NAM_Handler child_handler_;
  };


  struct Static_Config_EntryPoints_Maps;

  /**
   * @class Static_NodeApplicationManager_Impl
   */
  class CIAO_NAM_Export Static_NodeApplicationManager_Impl
    : public virtual NodeApplicationManager_Impl_Base
  {
  public:
    /// Constructor
    Static_NodeApplicationManager_Impl (CORBA::ORB_ptr o,
                                        PortableServer::POA_ptr p,
                                        Static_Config_EntryPoints_Maps* static_config_entrypoints_maps);

    virtual PortableServer::ObjectId
    init (const char *nodeapp_location,
          const char *nodeapp_options,
          const CORBA::ULong delay,
          const Deployment::DeploymentPlan & plan,
          const PortableServer::POA_ptr callback_poa,
          NodeManager_Impl_Base * nm);

  protected:
    /// Destructor
    virtual ~Static_NodeApplicationManager_Impl (void);

    /// Internal help function to create new NodeApplicationProcess
    /// Here we override it to create an in-process NodeApplication object
    virtual Deployment::NodeApplication_ptr
    create_node_application (const ACE_CString & options);

    Static_Config_EntryPoints_Maps* static_config_entrypoints_maps_;

    CIAO::NodeApp_Configurator configurator_;
  };
}

#if defined (__ACE_INLINE__)
# include "NodeApplicationManager_Impl.inl"
#endif /* __ACE_INLINE__ */

#include /**/ "ace/post.h"
#endif /* CIAO_NODEAPPLICATIONMANAGER_IMPL_H */