/**
@file osrf_application.h
- @brief Routines to manage dynamically loaded libraries.
+ @brief Routines to load and manage shared object libraries.
*/
#include <opensrf/utils.h>
there is no need to send any further data to the client.
*/
-
-/** This macro verifies methods receive the correct parameters */
+/** This macro verifies that methods receive the correct parameters */
#define _OSRF_METHOD_VERIFY_CONTEXT(d) \
if(!d) return -1; \
- if(!d->session) { osrfLogError( OSRF_LOG_MARK, "Session is NULL in app request" ); return -1; }\
- if(!d->method) { osrfLogError( OSRF_LOG_MARK, "Method is NULL in app request" ); return -1; }\
- if(d->method->argc) {\
- if(!d->params) { osrfLogError( OSRF_LOG_MARK, "Params is NULL in app request %s", d->method->name ); return -1; }\
+ if(!d->session) { \
+ osrfLogError( OSRF_LOG_MARK, "Session is NULL in app request" ); \
+ return -1; \
+ } \
+ if(!d->method) { \
+ osrfLogError( OSRF_LOG_MARK, "Method is NULL in app request" ); \
+ return -1; \
+ } \
+ if(d->method->argc) { \
+ if(!d->params) { \
+ osrfLogError( OSRF_LOG_MARK, "Params is NULL in app request %s", d->method->name ); \
+ return -1; \
+ } \
if( d->params->type != JSON_ARRAY ) { \
- osrfLogError( OSRF_LOG_MARK, "'params' is not a JSON array for method %s", d->method->name);\
- return -1; }\
- }\
- if( !d->method->name ) { osrfLogError( OSRF_LOG_MARK, "Method name is NULL"); return -1; }
+ osrfLogError( OSRF_LOG_MARK, "'params' is not a JSON array for method %s", \
+ d->method->name); \
+ return -1; } \
+ } \
+ if( !d->method->name ) { \
+ osrfLogError( OSRF_LOG_MARK, "Method name is NULL"); return -1; \
+ }
#ifdef OSRF_LOG_PARAMS
#define OSRF_METHOD_VERIFY_CONTEXT(d) \
_OSRF_METHOD_VERIFY_CONTEXT(d); \
- char* __j = jsonObjectToJSON(d->params);\
+ char* __j = jsonObjectToJSON(d->params); \
if(__j) { \
- osrfLogInfo( OSRF_LOG_MARK, "CALL:\t%s %s - %s", d->session->remote_service, d->method->name, __j);\
+ osrfLogInfo( OSRF_LOG_MARK, "CALL:\t%s %s - %s", d->session->remote_service, \
+ d->method->name, __j);\
free(__j); \
}
#else
#define OSRF_METHOD_VERIFY_CONTEXT(d) _OSRF_METHOD_VERIFY_CONTEXT(d);
#endif
-
-
-/* used internally to make sure the method description provided is OK */
-#define OSRF_METHOD_VERIFY_DESCRIPTION(app, d) \
- if(!app) return -1; \
- if(!d) return -1;\
- if(!d->name) { osrfLogError( OSRF_LOG_MARK, "No method name provided in description" ), return -1; } \
- if(!d->symbol) { osrfLogError( OSRF_LOG_MARK, "No method symbol provided in description" ), return -1; } \
- if(!d->notes) d->notes = ""; \
- if(!d->paramNotes) d->paramNotes = "";\
- if(!d->returnNotes) d->returnNotes = "";
-
-
-
-
-/* Some well known parameters */
-#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
-#define OSRF_SYSMETHOD_INTROSPECT_ATOMIC "opensrf.system.method.atomic"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC "opensrf.system.method.all.atomic"
-#define OSRF_SYSMETHOD_ECHO "opensrf.system.echo"
-#define OSRF_SYSMETHOD_ECHO_ATOMIC "opensrf.system.echo.atomic"
-
#define OSRF_METHOD_SYSTEM 1
#define OSRF_METHOD_STREAMING 2
#define OSRF_METHOD_ATOMIC 4
#define OSRF_METHOD_CACHABLE 8
-
-struct _osrfApplicationStruct {
- void* handle; /**< the lib handle. */
- osrfHash* methods;
- void (*onExit) (void);
-};
-typedef struct _osrfApplicationStruct osrfApplication;
-
-
-struct _osrfMethodStruct {
- char* name; /**< the method name */
- char* symbol; /**< the symbol name (function) */
- char* notes; /**< public method documentation */
- int argc; /**< how many args this method expects */
- //char* paramNotes; /**< Description of the params expected for this method */
- int options; /**< describes the various options for this method */
- void* userData; /**< You can put your weeeeeeed in it ... */
+typedef struct {
+ char* name; /**< the method name. */
+ char* symbol; /**< the symbol name (function name). */
+ char* notes; /**< public method documentation. */
+ int argc; /**< how many args this method expects. */
+ //char* paramNotes; /**< Description of the params expected for this method. */
+ int options; /**< bitswitches setting various options for this method. */
+ void* userData; /**< Opaque pointer to application-specific data. */
/*
int sysmethod;
int atomic;
int cachable;
*/
-};
-typedef struct _osrfMethodStruct osrfMethod;
+} osrfMethod;
-struct _osrfMethodContextStruct {
+typedef struct {
osrfAppSession* session; /**< the current session. */
osrfMethod* method; /**< the requested method. */
jsonObject* params; /**< the params to the method. */
int request; /**< request id. */
jsonObject* responses; /**< array of cached responses. */
-};
-typedef struct _osrfMethodContextStruct osrfMethodContext;
-
+} osrfMethodContext;
/**
Register an application
int osrfAppRegisterApplication( const char* appName, const char* soFile );
/**
- Register a method
- Any method with the OSRF_METHOD_STREAMING option set will have a ".atomic"
- version of the method registered automatically
- @param appName The name of the application that implements the method
- @param methodName The fully qualified name of the method
- @param symbolName The symbol name (function) that implements the method
+ @brief Register a method for a given application.
+
+ @param appName Name of the application that implements the method.
+ @param methodName The fully qualified name of the method.
+ @param symbolName The symbol name (function name) that implements the method.
@param notes Public documentation for this method.
- @params argc The number of arguments this method expects
- @param streaming True if this is a streaming method that requires an atomic version
+ @params argc The number of arguments this method expects.
+ @param options Bit switches setting various options.
@return 0 on success, -1 on error
+
+ Any method with the OSRF_METHOD_STREAMING option set will have a ".atomic"
+ version of the method registered automatically.
*/
int osrfAppRegisterMethod( const char* appName, const char* methodName,
const char* symbolName, const char* notes, int argc, int options );
-
int osrfAppRegisterExtendedMethod( const char* appName, const char* methodName,
const char* symbolName, const char* notes, int argc, int options, void* );
-/**
- Finds the given method for the given app
- @param appName The application
- @param methodName The method to find
- @return A method pointer or NULL if no such method
- exists for the given application
-*/
osrfMethod* _osrfAppFindMethod( const char* appName, const char* methodName );
/**
osrfAppSession* ses, int reqId, jsonObject* params );
/**
- Responds to the client with a method exception
- @param ses The current session
- @param request The request id
- @param msg The debug message to send to the client
- @return 0 on successfully sending of the message, -1 otherwise
+ @brief Respond to the client with a method exception.
+ @param ses The current session.
+ @param request The request id.
+ @param msg The debug message to send to the client.
+ @return 0 on successfully sending of the message, -1 otherwise.
*/
int osrfAppRequestRespondException( osrfAppSession* ses, int request, const char* msg, ... );
/* OSRF_METHOD_ATOMIC and/or OSRF_METHOD_CACHABLE and/or 0 for no special options */
//int osrfAppProcessMethodOptions( char* method );
-/** Tells the backend process to run its child init function */
+/** Tell the backend process to run its child init function */
int osrfAppRunChildInit(const char* appname);
-void osrfAppRunExitCode();
+
+void osrfAppRunExitCode( void );
/**
Determine whether the context looks healthy.
/**
@file osrf_application.c
- @brief Routines to manage dynamically loaded libraries.
+ @brief Load and manage shared object libraries.
+
+ Maintain a registry of applications, using an osrfHash keyed on application name,
+
+ For each application, load a shared object library so that we can call
+ application-specific functions dynamically. In order to map method names to the
+ corresponding functions (i.e. symbol names in the library), maintain a registry of
+ methods, using an osrfHash keyed on method name.
*/
+// The following macro is commented out because it appears to be unused.
+
+// Used internally to make sure the method description provided is OK
+/*
+#define OSRF_METHOD_VERIFY_DESCRIPTION(app, d) \
+ if(!app) return -1; \
+ if(!d) return -1;\
+ if(!d->name) { \
+ osrfLogError( OSRF_LOG_MARK, "No method name provided in description" ), \
+ return -1; \
+} \
+ if(!d->symbol) { \
+ osrfLogError( OSRF_LOG_MARK, "No method symbol provided in description" ), \
+ return -1; \
+} \
+ if(!d->notes) \
+ d->notes = ""; \
+ if(!d->paramNotes) \
+ d->paramNotes = "";\
+ if(!d->returnNotes) \
+ d->returnNotes = "";
+*/
+
+/* Some well known parameters */
+#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
+#define OSRF_SYSMETHOD_INTROSPECT_ATOMIC "opensrf.system.method.atomic"
+#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
+#define OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC "opensrf.system.method.all.atomic"
+#define OSRF_SYSMETHOD_ECHO "opensrf.system.echo"
+#define OSRF_SYSMETHOD_ECHO_ATOMIC "opensrf.system.echo.atomic"
+
+/**
+ @brief Represent an Application.
+*/
+typedef struct {
+ void* handle; /**< Handle to the shared object library. */
+ osrfHash* methods; /**< Registry of method names. */
+ void (*onExit) (void); /**< Exit handler for the application. */
+} osrfApplication;
+
static osrfMethod* _osrfAppBuildMethod( const char* methodName, const char* symbolName,
const char* notes, int argc, int options, void* );
static void osrfAppSetOnExit(osrfApplication* app, const char* appName);
static int _osrfAppRegisterSysMethods( const char* app );
-static osrfApplication* _osrfAppFindApplication( const char* name );
-static osrfMethod* osrfAppFindMethod( osrfApplication* app, const char* methodName );
+static inline osrfApplication* _osrfAppFindApplication( const char* name );
+static inline osrfMethod* osrfAppFindMethod( osrfApplication* app, const char* methodName );
static int _osrfAppRespond( osrfMethodContext* context, const jsonObject* data, int complete );
static int _osrfAppPostProcess( osrfMethodContext* context, int retcode );
static int _osrfAppRunSystemMethod(osrfMethodContext* context);
static int osrfAppIntrospectAll( osrfMethodContext* ctx );
static int osrfAppEcho( osrfMethodContext* ctx );
+/**
+ Registry of applications. The key of the hash is the application name, and the associated
+ data is an osrfApplication.
+*/
static osrfHash* _osrfAppHash = NULL;
int osrfAppRegisterApplication( const char* appName, const char* soFile ) {
}
+/**
+ @brief Run the application-specific child initialization function for a given application.
+ @param appname Name of the application.
+ @return Zero if successful, or if the application has no child initialization function; -1
+ if the application is not registered, or if the function returns non-zero.
+
+ The child initialization function must be named "osrfAppChildInit" within the shared
+ object library. It initializes a drone process of a server.
+*/
int osrfAppRunChildInit(const char* appname) {
osrfApplication* app = _osrfAppFindApplication(appname);
if(!app) return -1;
}
-void osrfAppRunExitCode() {
+/**
+ @brief Call the exit handler for every application that has one.
+*/
+void osrfAppRunExitCode( void ) {
osrfHashIterator* itr = osrfNewHashIterator(_osrfAppHash);
osrfApplication* app;
while( (app = osrfHashIteratorNext(itr)) ) {
options,
NULL
);
-
}
int osrfAppRegisterExtendedMethod( const char* appName, const char* methodName,
/**
- Registers all of the system methods for this app so that they may be
- treated the same as other methods
+ Register all of the system methods for this app so that they may be
+ treated the same as other methods.
*/
static int _osrfAppRegisterSysMethods( const char* app ) {
}
/**
- Finds the given app in the list of apps
- @param name The name of the application
- @return The application pointer or NULL if there is no such application
+ @brief Look up an application by name in the application registry.
+ @param name The name of the application.
+ @return Pointer to the corresponding osrfApplication if found, or NULL if not.
*/
-static osrfApplication* _osrfAppFindApplication( const char* name ) {
- if(!name) return NULL;
+static inline osrfApplication* _osrfAppFindApplication( const char* name ) {
return (osrfApplication*) osrfHashGet(_osrfAppHash, name);
}
/**
- @brief Find the given method for the given app.
- @param app The application object.
- @param methodName The method to find.
- @return A method pointer or NULL if no such method exists for the given application.
+ @brief Look up a method by name for a given application.
+ @param app Pointer to the osrfApplication that owns the method.
+ @param methodName Name of the method to find.
+ @return Pointer to the corresponding osrfMethod if found, or NULL if not.
*/
-static osrfMethod* osrfAppFindMethod( osrfApplication* app, const char* methodName ) {
- if(!app || ! methodName) return NULL;
+static inline osrfMethod* osrfAppFindMethod( osrfApplication* app, const char* methodName ) {
+ if( !app ) return NULL;
return (osrfMethod*) osrfHashGet( app->methods, methodName );
}
+/**
+ @brief Look up a method by name for an application with a given name.
+ @param appName Name of the osrfApplication.
+ @param methodName Name of the method to find.
+ @return Pointer to the corresponding osrfMethod if found, or NULL if not.
+ */
osrfMethod* _osrfAppFindMethod( const char* appName, const char* methodName ) {
- if(!appName || ! methodName) return NULL;
+ if( !appName ) return NULL;
return osrfAppFindMethod( _osrfAppFindApplication(appName), methodName );
}
}
if( !ctx->session ) {
- osrfLogError( OSRF_LOG_MARK, "Session is NULL in app request" );
+ osrfLogError( OSRF_LOG_MARK, "Session is NULL in app request" );
return -1;
}