LocalAPIManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
39 #include "LocalAPIManager.hpp"
40 #include "SysLocalAPIManager.hpp"
41 #include "ClientMessage.hpp"
42 #include "SynchronizedBlock.hpp"
43 #include <list>
44 
45 // initialize static variables
47 SysMutex LocalAPIManager::messageLock("LocalAPIManager::messageLock", true);
48 
49 /**
50  * Get the singleton instance of the local API manager.
51  *
52  * @return The pointer to the created (and initialized) API manager.
53  */
55 {
56  Lock lock(messageLock, "LocalAPIManager::getInstance", 0); // make sure we single thread this
57  if (singleInstance == NULL)
58  {
59  // create an intialize this. If this fails, an exception is thrown
61  // to the process-specific initialization now.
63  }
64  else {
65  // if we shut everything down at interpreter termination, reestablish the connections.
67  {
68  // resetting this will prevent us from going into conversion loops.
70  // we could have been shutdown by a previous interpreter termination.
71  // make sure we have a connection
73  }
74  }
75  return singleInstance;
76 }
77 
78 
79 /**
80  * Shutdown the instance of the API manager.
81  */
83 {
84  Lock lock(messageLock, "LocalAPIManager::deleteInstance", 0); // make sure we single thread this
85  if (singleInstance != NULL)
86  {
87  // shutdown any connections with the server
89  // mark that we need a restart
91  }
92 }
93 
94 
95 /**
96  * Process a service exception, with appropriate error handling.
97  *
98  * @param t The context API manager.
99  * @param e The caught exception object.
100  *
101  * @return The appropriate return value for the exception.
102  */
104 {
105  // process differently based on the target
106  switch (t)
107  {
108  case QueueManager:
109  {
111  }
112 
113  case RegistrationManager:
114  {
116  }
117 
118  case MacroSpaceManager:
119  {
121  }
122 
123  case APIManager: // these should be screened out ahead of time
124  {
125  // all global exceptions are memory failures
126  return RXAPI_MEMFAIL;
127  }
128  }
129  return RXAPI_MEMFAIL; // a catch-all return code
130 }
131 
132 
133 /**
134  * Perform process termination cleanup.
135  */
137 {
138  // terminate each of the subsystems.
139  // start with the queue manager, since it may require access to
140  // the server
144 
145  // shutdown the connections
147 }
148 
149 
150 /**
151  * Perform connection cleanup after an interpreter instance
152  * stops
153  */
155 {
156  // the queue manager needs to terminate the session queue first
157 
158  // clean up the connection pools
159  while (!connections.empty())
160  {
161  SysClientStream *connection = connections.front();
162  connections.pop_front();
163  // tell the server we're going away and clean up
164  closeConnection(connection);
165  }
166  // no active connections
167  connectionEstablished = false;
168 }
169 
170 
171 /**
172  * Perform process-specific client API initialization.
173  */
175 {
176  // we don't need a restart since we're just starting up
177  restartRequired = false;
178 
179  // 1) get our session id and userid information.
182 
183  ServiceException *startError = NULL;
184 
185  try
186  {
187  // Initialization steps:
188  // 2) make sure the global environment is started
190  } catch (ServiceException *e)
191  {
192  // save this for potential rethrowing after the managers are
193  startError = e;
194  }
195 
196  // 3) initialize the API subsystems
200 
201  // if we had an exception trying to connect to rxapi, reraise that exception now.
202  if (startError != NULL)
203  {
204  throw startError;
205  }
206 }
207 
208 
209 /**
210  * Ensure that the daemon process managing the API information is initialized and running
211  * before doing any API related activities.
212  */
214 {
216  {
218  try
219  {
220  // try to establish a connection to the api server. If this returns without an exception,
221  // we're good to go.
222  message.send();
223 
224  if (message.parameter1 != REXXAPI_VERSION)
225  {
226  throw new ServiceException(API_FAILURE, "Open Object REXX version conflict. Incorrect version of RxAPI server detected");
227  }
228  connectionEstablished = true;
229  return;
230  }
231  catch (ServiceException *)
232  {
233  // just fall through.
234  }
235 
236  // Unable to connect, so try to start the server process. We're unsynchronized at this point,
237  // so it is possible multiple processes will launch this at the same time. Only one will bind to
238  // the listening port, the others will silently fail.
240 
241  // now loop multiple times, with a sleep interval, until we finally connect.
242  int count = 100;
243  while (count-- > 0)
244  {
245  try
246  {
247  // try to establish a connection to the api server. If this returns without an exception,
248  // we're good to go.
249  message.send();
250 
251  if (message.parameter1 != REXXAPI_VERSION)
252  {
253  throw new ServiceException(API_FAILURE, "Open Object REXX version conflict. Incorrect version of RxAPI server detected");
254  }
255  connectionEstablished = true;
256  return;
257  }
258  catch (ServiceException *)
259  {
260  // just fall through.
261  }
262  }
263  throw new ServiceException(API_FAILURE, "Object REXX API Manager could not be started. This could be due to a version conflict!");
264  }
265 }
266 
267 /**
268  * Request a connection from the connection pool
269  *
270  * @return An active connection to the data server.
271  */
273 {
274  {
275  Lock lock(messageLock, "LocalAPIManager::getConnection", 0); // make sure we single thread this
276  // if we have an active connection, grab it from the cache and
277  // reuse it.
278  if (!connections.empty())
279  {
280  SysClientStream *connection = connections.front();
281  connections.pop_front();
282  return connection;
283  }
284  }
285 
286  SysClientStream *connection = new SysClientStream();
287 
288  // open the pipe to the connection->
289  if (!connection->open("localhost", REXX_API_PORT))
290  {
291  throw new ServiceException(SERVER_FAILURE, "Failure connecting to rxapi server");
292  }
293  return connection;
294 }
295 
296 
297 /**
298  * Return a connection after use.
299  *
300  * @param connection The returned connection.
301  */
303 {
304  // if we've encountered an error, then just delete the connection
305  if (!connection->isClean())
306  {
307  delete connection;
308  return;
309  }
310 
311  {
312  Lock lock(messageLock, "LocalAPIManager::returnConnection", 0); // make sure we single thread this
313  if (connections.size() < MAX_CONNECTIONS)
314  {
315  connections.push_back(connection);
316  return;
317  }
318  }
319  // not cachable, make sure this is delete.
320  delete connection;
321 }
322 
323 
324 /**
325  * Close a connection to the server.
326  *
327  * @param connection The connection to close.
328  */
330 {
332 
333  try
334  {
335  // this is a one-way message...we don't expect a reply
336  message.writeMessage(*connection);
337  } catch (ServiceException *)
338  {
339  // ignored
340  }
341  delete connection;
342 }
343 
344 
345 /**
346  * Send the shutdown message to the API daemon.
347  */
349 {
350 
351  // first parameter for these calls is ALWAYS the type
353  message.send();
354 }
@ API_FAILURE
@ SERVER_FAILURE
@ CONNECTION_ACTIVE
@ SHUTDOWN_SERVER
@ CLOSE_CONNECTION
ServerManager
@ QueueManager
@ RegistrationManager
@ APIManager
@ MacroSpaceManager
#define REXX_API_PORT
@ REXXAPI_VERSION
RexxReturnCode processServiceException(ServerManager t, ServiceException *e)
void establishServerConnection()
static LocalAPIManager * getInstance()
LocalRegistrationManager registrationManager
static LocalAPIManager * singleInstance
char userid[MAX_USERID_LENGTH]
LocalQueueManager queueManager
void returnConnection(SysClientStream *)
LocalMacroSpaceManager macroSpaceManager
std::list< SysClientStream * > connections
static SysMutex messageLock
static void shutdownInstance()
SysClientStream * getConnection()
void closeConnection(SysClientStream *connection)
virtual void terminateProcess()
virtual void initializeLocal(LocalAPIManager *a)
virtual RexxReturnCode processServiceException(ServiceException *e)
virtual RexxReturnCode processServiceException(ServiceException *e)
void initializeLocal(LocalAPIManager *a)
virtual void terminateProcess()
virtual RexxReturnCode processServiceException(ServiceException *e)
uintptr_t parameter1
void writeMessage(SysClientStream &server)
bool open(const char *)
static pid_t getPid()
static void getUserID(char *buffer)
int RexxReturnCode
Definition: rexx.h:73
#define RXAPI_MEMFAIL
Definition: rexxapidefs.h:61