[Opensrf-commits] r1935 - trunk/src/libopensrf (scottmk)

svn at svn.open-ils.org svn at svn.open-ils.org
Sun Mar 7 22:26:05 EST 2010


Author: scottmk
Date: 2010-03-07 22:26:03 -0500 (Sun, 07 Mar 2010)
New Revision: 1935

Modified:
   trunk/src/libopensrf/osrf_application.c
Log:
Miscellaneous minor changes. mostly for clarity:

1. Changed return type of _osrfAppRegisterSysMethods from int to void,
since we never looked at the return code anyway.

2. In osrfAppRegisterApplication(): 0pen the shared object before
allocating an osrfApplication, so that we don't have to free the
osrfApplication if the open fails.

3. In osrfAppRegisterExtendedMethod(): when creating an atomic method,
pass the userData pointer to _osrfAppBuildMethod() instead of
installing it on a separate line.

4. In _osrfAppBuildMethod(): for an atomic method, build the method
name correctly the first time, instead of building it incorrectly
and later replacing it.

5. In osrfAppRunMethod(): rearranged things a bit for clarity.
Simplified the declaration and dereferencing of the meth pointer.

6. In osrfAppIntrospect(): Introduced an early return in order to
reduce the level of indentation of the rest of the function.  Moved
some declarations closer to their first uses.

7. In osrfAppIntrospectAll(): moved the declaration of resp into the
loop where it is used.

8. Finished adding doxygen-style comments to document the functions.
Touched up the white space here and there.

M    src/libopensrf/osrf_application.c


Modified: trunk/src/libopensrf/osrf_application.c
===================================================================
--- trunk/src/libopensrf/osrf_application.c	2010-03-02 21:02:33 UTC (rev 1934)
+++ trunk/src/libopensrf/osrf_application.c	2010-03-08 03:26:03 UTC (rev 1935)
@@ -12,7 +12,7 @@
 	methods, using an osrfHash keyed on method name.
 */
 
-// The following macro is commented out because it appears to be unused.
+// The following macro is commented out because it ia no longer used.
 
 // Used internally to make sure the method description provided is OK
 /*
@@ -35,13 +35,18 @@
 		d->returnNotes = "";
 */
 
-/* Some well known parameters */
+/**
+	@name Well known method names
+	@brief These methods are automatically implemented for every application.
+*/
+/*@{*/
 #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.
@@ -55,22 +60,35 @@
 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 void _osrfAppRegisterSysMethods( const char* app );
 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 void _osrfAppSetIntrospectMethod( osrfMethodContext* ctx, const osrfMethod* method,
+		jsonObject* resp );
 static int osrfAppIntrospect( osrfMethodContext* ctx );
 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.
+	@brief Registry of applications.
+
+	The key of the hash is the application name, and the associated data is an osrfApplication.
 */
 static osrfHash* _osrfAppHash = NULL;
 
+/**
+	@brief Register an application.
+	@param appName Name of the application.
+	@param soFile Name of the shared object file to be loaded for this application.
+	@return Zero if successful, or -1 upon error.
+
+	Open the shared object file and call its osrfAppInitialize() function, if it has one.
+	Register the standard system methods for it.  Arrange for the application name to
+	appear in subsequent log messages.
+*/
 int osrfAppRegisterApplication( const char* appName, const char* soFile ) {
 	if(!appName || ! soFile) return -1;
 	char* error;
@@ -80,17 +98,16 @@
 
 	osrfLogInfo( OSRF_LOG_MARK, "Registering application %s with file %s", appName, soFile );
 
-	osrfApplication* app = safe_malloc(sizeof(osrfApplication));
-	app->handle = dlopen (soFile, RTLD_NOW);
-	app->onExit = NULL;
-
-	if(!app->handle) {
-		osrfLogWarning( OSRF_LOG_MARK, "Failed to dlopen library file %s: %s", soFile, dlerror() );
-		dlerror(); /* clear the error */
-		free(app);
+	void* handle = dlopen( soFile, RTLD_NOW );
+	if( ! handle ) {
+		const char* msg = dlerror();
+		osrfLogWarning( OSRF_LOG_MARK, "Failed to dlopen library file %s: %s", soFile, msg );
 		return -1;
 	}
 
+	osrfApplication* app = safe_malloc(sizeof(osrfApplication));
+	app->handle = handle;
+	app->onExit = NULL;
 	app->methods = osrfNewHash();
 	osrfHashSet( _osrfAppHash, app, appName );
 
@@ -101,7 +118,7 @@
 	if( (error = dlerror()) != NULL ) {
 		osrfLogWarning( OSRF_LOG_MARK,
 			"! Unable to locate method symbol [osrfAppInitialize] for app %s: %s",
-    		appName, error );
+			appName, error );
 
 	} else {
 
@@ -127,7 +144,15 @@
 	return 0;
 }
 
+/**
+	@brief Save a pointer to the application's exit function.
+	@param app Pointer to the osrfApplication.
+	@param appName Application name (used only for log messages).
 
+	Look in the shared object for a symbol named "osrfAppChildExit".  If you find one, save
+	it as a pointer to the application's exit function.  If present, this function will be
+	called when a server's child process (a so-called "drone") is shutting down.
+*/
 static void osrfAppSetOnExit(osrfApplication* app, const char* appName) {
 	if(!(app && appName)) return;
 
@@ -145,7 +170,6 @@
 	app->onExit = (*onExit);
 }
 
-
 /**
 	@brief Run the application-specific child initialization function for a given application.
 	@param appname Name of the application.
@@ -179,9 +203,11 @@
 	return 0;
 }
 
-
 /**
 	@brief Call the exit handler for every application that has one.
+
+	Normally a server's child process (a so-called "drone") calls this function just before
+	shutting down.
 */
 void osrfAppRunExitCode( void ) {
 	osrfHashIterator* itr = osrfNewHashIterator(_osrfAppHash);
@@ -196,7 +222,30 @@
 	osrfHashIteratorFree(itr);
 }
 
+/**
+	@brief Register a method for a specified 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.
+	@param argc The minimum number of arguments for the function.
+	@param options Bit switches setting various options.
+	@return Zero on success, or -1 on error.
+
+	Registering a method enables us to call the right function when a client requests a
+	method call.
+
+	The @a options parameter is zero or more of the following macros, OR'd together:
+
+	- OSRF_METHOD_SYSTEM
+	- OSRF_METHOD_STREAMING
+	- OSRF_METHOD_ATOMIC
+	- OSRF_METHOD_CACHABLE
+
+	If the OSRF_METHOD_STREAMING bit is set, also register an ".atomic" version of
+	the method.
+*/
 int osrfAppRegisterMethod( const char* appName, const char* methodName,
 		const char* symbolName, const char* notes, int argc, int options ) {
 
@@ -211,6 +260,22 @@
 	);
 }
 
+/**
+	@brief Register a method for a specified 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.
+	@param argc How many arguments this method expects.
+	@param options Bit switches setting various options.
+	@param user_data Opaque pointer to be passed to the dynamically called function.
+	@return Zero on success, or -1 on error.
+
+	This function is identical to osrfAppRegisterMethod(), except that it also installs
+	a method-specific opaque pointer.  When we call the corresponding function at
+	run time, this pointer will be available to the function via the method context.
+*/
 int osrfAppRegisterExtendedMethod( const char* appName, const char* methodName,
 		const char* symbolName, const char* notes, int argc, int options, void * user_data ) {
 
@@ -234,25 +299,40 @@
 	if( options & OSRF_METHOD_STREAMING ) { /* build the atomic counterpart */
 		int newops = options | OSRF_METHOD_ATOMIC;
 		osrfMethod* atomicMethod = _osrfAppBuildMethod(
-			methodName, symbolName, notes, argc, newops, NULL );
+			methodName, symbolName, notes, argc, newops, user_data );
 		osrfHashSet( app->methods, atomicMethod, atomicMethod->name );
-		atomicMethod->userData = method->userData;
 	}
 
 	return 0;
 }
 
-
-
+/**
+	@brief Allocate and populate an osrfMethod.
+	@param methodName Name of the method.
+	@param symbolName Name of the function that implements the method.
+	@param notes Remarks documenting the method.
+	@param argc Minimum number of arguments to the method.
+	@param options Bit switches setting various options.
+	@param user_data An opaque pointer to be passed in the method context.
+	@return Pointer to the newly allocated osrfMethod.
+*/
 static osrfMethod* _osrfAppBuildMethod( const char* methodName, const char* symbolName,
 		const char* notes, int argc, int options, void* user_data ) {
 
 	osrfMethod* method      = safe_malloc(sizeof(osrfMethod));
 
-	if(methodName)
+	if( !methodName )
+		methodName = "";  // should never happen
+
+	if( options & OSRF_METHOD_ATOMIC ) {
+		// Append ".atomic" to the name, and make the method streaming
+		char mb[ strlen( methodName ) + 8 ];
+		sprintf( mb, "%s.atomic", methodName );
+		method->name        = strdup( mb );
+		options |= OSRF_METHOD_STREAMING;
+	} else {
 		method->name        = strdup(methodName);
-	else
-		method->name        = NULL;
+	}
 
 	if(symbolName)
 		method->symbol      = strdup(symbolName);
@@ -264,29 +344,24 @@
 	else
 		method->notes       = NULL;
 
-	if(user_data)
-		method->userData    = user_data;
-
 	method->argc            = argc;
 	method->options         = options;
 
-	if(options & OSRF_METHOD_ATOMIC) { /* add ".atomic" to the end of the name */
-		char mb[strlen(method->name) + 8];
-		sprintf(mb, "%s.atomic", method->name);
-		free(method->name);
-		method->name = strdup(mb);
-		method->options |= OSRF_METHOD_STREAMING;
-	}
+	if(user_data)
+		method->userData    = user_data;
 
 	return method;
 }
 
+/**
+	@brief Register all of the system methods for this application.
+	@param app Application name.
 
-/**
-	Register all of the system methods for this app so that they may be
-	treated the same as other methods.
+	A client can call these methods the same way it calls application-specific methods,
+	but they are implemented by functions here in this module, not by functions in the
+	shared object.
 */
-static int _osrfAppRegisterSysMethods( const char* app ) {
+static void _osrfAppRegisterSysMethods( const char* app ) {
 
 	osrfAppRegisterMethod(
 			app, OSRF_SYSMETHOD_INTROSPECT, NULL,
@@ -303,8 +378,6 @@
 			app, OSRF_SYSMETHOD_ECHO, NULL,
 			"Echos all data sent to the server back to the client. PARAMS([a, b, ...])", 0,
 			OSRF_METHOD_SYSTEM | OSRF_METHOD_STREAMING );
-
-	return 0;
 }
 
 /**
@@ -332,49 +405,60 @@
 	@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 ) return NULL;
 	return osrfAppFindMethod( _osrfAppFindApplication(appName), methodName );
 }
 
+/**
+	@brief Call the function that implements a specified method.
+	@param appName Name of the application.
+	@param methodName Name of the method.
+	@param ses Pointer to the current application session.
+	@param reqId The request id of the request invoking the method.
+	@param params Pointer to a jsonObject encoding the parameters to the method.
+	@return Zero if successful, or -1 upon failure.
 
+	If we can't find a function corresponding to the method, or if we call it and it returns
+	a negative return code, send a STATUS message to the client to report an exception.
+
+	A return code of -1 means that the @a appName, @a methodName, or @a ses parameter was NULL.
+*/
 int osrfAppRunMethod( const char* appName, const char* methodName,
 		osrfAppSession* ses, int reqId, jsonObject* params ) {
 
 	if( !(appName && methodName && ses) ) return -1;
 
-	char* error;
-	osrfApplication* app;
-	osrfMethod* method;
-	osrfMethodContext context;
-
-	context.session = ses;
-	context.params = params;
-	context.request = reqId;
-	context.responses = NULL;
-
-	/* this is the method we're gonna run */
-	int (*meth) (osrfMethodContext*);
-
-	if( !(app = _osrfAppFindApplication(appName)) )
+	// Find the application, and then find the method for it
+	osrfApplication* app = _osrfAppFindApplication(appName);
+	if( !app )
 		return osrfAppRequestRespondException( ses,
 				reqId, "Application not found: %s", appName );
 
-	if( !(method = osrfAppFindMethod( app, methodName )) )
+	osrfMethod* method = osrfAppFindMethod( app, methodName );
+	if( !method )
 		return osrfAppRequestRespondException( ses, reqId,
 				"Method [%s] not found for service %s", methodName, appName );
 
-	context.method = method;
-
 	#ifdef OSRF_STRICT_PARAMS
 	if( method->argc > 0 ) {
+		// Make sure that the client has passed at least the minimum number of arguments.
 		if(!params || params->type != JSON_ARRAY || params->size < method->argc )
 			return osrfAppRequestRespondException( ses, reqId,
 				"Not enough params for method %s / service %s", methodName, appName );
 	}
 	#endif
 
+	// Build an osrfMethodContext, which we will pass by pointer to the function.
+	osrfMethodContext context;
+
+	context.session = ses;
+	context.method = method;
+	context.params = params;
+	context.request = reqId;
+	context.responses = NULL;
+
 	int retcode = 0;
 
 	if( method->options & OSRF_METHOD_SYSTEM ) {
@@ -382,15 +466,20 @@
 
 	} else {
 
-		/* open and now run the method */
-		*(void **) (&meth) = dlsym(app->handle, method->symbol);
+		// Function pointer through which we will call the function dynamically
+		int (*meth) (osrfMethodContext*);
 
-		if( (error = dlerror()) != NULL ) {
+		// Open the function that implements the method
+		meth = dlsym(app->handle, method->symbol);
+
+		const char* error = dlerror();
+		if( error != NULL ) {
 			return osrfAppRequestRespondException( ses, reqId,
-				"Unable to execute method [%s]  for service %s", methodName, appName );
+				"Unable to execute method [%s] for service %s", methodName, appName );
 		}
 
-		retcode = (*meth) (&context);
+		// Run it
+		retcode = meth( &context );
 	}
 
 	if(retcode < 0)
@@ -398,18 +487,65 @@
 				ses, reqId, "An unknown server error occurred" );
 
 	return _osrfAppPostProcess( &context, retcode );
-
 }
 
+/**
+	@brief Either send or enqueue a response to a client.
+	@param ctx Pointer to the current method context.
+	@param data Pointer to the response, in the form of a jsonObject.
+	@return Zero if successful, or -1 upon error.  The only recognized errors are if either
+	the @a context pointer or its method pointer is NULL.
 
+	For an atomic method, add a copy of the response data to a cache within the method
+	context, to be sent later.  Otherwise, send a RESULT message to the client, with the
+	results in @a data.
+
+	Note that, for an atomic method, this function is equivalent to osrfAppRespondComplete():
+	we send the STATUS message after the method returns, and not before.
+*/
 int osrfAppRespond( osrfMethodContext* ctx, const jsonObject* data ) {
 	return _osrfAppRespond( ctx, data, 0 );
 }
 
+/**
+	@brief Either send or enqueue a response to a client, with a completion notice.
+	@param context Pointer to the current method context.
+	@param data Pointer to the response, in the form of a jsonObject.
+	@return Zero if successful, or -1 upon error.  The only recognized errors are if either
+	the @a context pointer or its method pointer is NULL.
+
+	For an atomic method, add a copy of the response data to a cache within the method
+	context, to be sent later.  Otherwise, send a RESULT message to the client, with the
+	results in @a data.  Also send a STATUS message to indicate that the response is complete.
+
+	Note that, for an atomic method, this function is equivalent to osrfAppRespond(): we
+	send the STATUS message after the method returns, and not before.
+*/
 int osrfAppRespondComplete( osrfMethodContext* context, const jsonObject* data ) {
 	return _osrfAppRespond( context, data, 1 );
 }
 
+/**
+	@brief Either send or enqueue a response to a client, optionally with a completion notice.
+	@param ctx Pointer to the method context.
+	@param data Pointer to the response, in the form of a jsonObject.
+	@param complete Boolean: if true, we will accompany the RESULT message with a STATUS
+	message indicating that the response is complete.
+	@return Zero if successful, or -1 upon error.  The only recognized errors are if either
+	the @a ctx pointer or its method pointer is NULL.
+
+	For an atomic method, add a copy of the response data to a cache within the method
+	context, to be sent later.  In this case the @a complete parameter has no effect,
+	because we'll send the STATUS message later when we send the cached results.
+
+	If the method is cachable but not atomic, do nothing, ignoring the results in @a data.
+	Apparently there are no cachable methods at this writing.  If we ever invent some, we
+	may need to revisit this function.
+
+	If the method is neither atomic nor cachable, then send a RESULT message to the client,
+	with the results in @a data.  If @a complete is true, also send a STATUS message to
+	indicate that the response is complete.
+*/
 static int _osrfAppRespond( osrfMethodContext* ctx, const jsonObject* data, int complete ) {
 	if(!(ctx && ctx->method)) return -1;
 
@@ -417,14 +553,15 @@
 		osrfLogDebug( OSRF_LOG_MARK,
 			"Adding responses to stash for atomic method %s", ctx->method->name );
 
+		// If we don't already have one, create a JSON_ARRAY to serve as a cache.
 		if( ctx->responses == NULL )
 			ctx->responses = jsonNewObjectType( JSON_ARRAY );
 
+		// Add a copy of the data object to the cache.
 		if ( data != NULL )
 			jsonObjectPush( ctx->responses, jsonObjectClone(data) );
 	}
 
-
 	if( !(ctx->method->options & OSRF_METHOD_ATOMIC ) &&
 			!(ctx->method->options & OSRF_METHOD_CACHABLE) ) {
 
@@ -432,28 +569,42 @@
 			osrfAppRequestRespondComplete( ctx->session, ctx->request, data );
 		else
 			osrfAppRequestRespond( ctx->session, ctx->request, data );
-		return 0;
 	}
 
 	return 0;
 }
 
+/**
+	@brief Finish up the processing of a request.
+	@param ctx Pointer to the method context.
+	@param retcode The return code from the method's function.
+	@return 0 if successfull, or -1 upon error.
 
+	For an atomic method: send whatever responses we have been saving up, together with a
+	STATUS message to say that we're finished.
+
+	For a non-atomic method: if the return code from the method is greater than zero, just
+	send the STATUS message.  If the return code is zero, do nothing; the method presumably
+	sent the STATUS message on its own.
+*/
 static int _osrfAppPostProcess( osrfMethodContext* ctx, int retcode ) {
 	if(!(ctx && ctx->method)) return -1;
 
-	osrfLogDebug( OSRF_LOG_MARK,  "Postprocessing method %s with retcode %d",
+	osrfLogDebug( OSRF_LOG_MARK, "Postprocessing method %s with retcode %d",
 			ctx->method->name, retcode );
 
-	if(ctx->responses) { /* we have cached responses to return (no responses have been sent) */
-
+	if(ctx->responses) {
+		// We have cached responses to return, collected in a JSON ARRAY (we haven't sent
+		// any responses yet).  Now send them all at once, followed by a STATUS message
+		// to say that we're finished.
 		osrfAppRequestRespondComplete( ctx->session, ctx->request, ctx->responses );
 		jsonObjectFree(ctx->responses);
 		ctx->responses = NULL;
 
 	} else {
-
+		// We have no cached responses to return.
 		if( retcode > 0 )
+			// Send a STATUS message to say that we're finished.
 			osrfAppSessionStatus( ctx->session, OSRF_STATUS_COMPLETE,
 					"osrfConnectStatus", ctx->request, "Request Complete" );
 	}
@@ -461,6 +612,15 @@
 	return 0;
 }
 
+/**
+	@brief Send a STATUS message to the client, notifying it of an error.
+	@param ses Pointer to the current application session.
+	@param request Request ID of the request.
+	@param msg A printf-style format string defining an explanatory message to be sent to
+	the client.  Subsequent parameters, if any, will be formatted and inserted into the
+	resulting output string.
+	@return -1 if the @a ses parameter is NULL; otherwise zero.
+*/
 int osrfAppRequestRespondException( osrfAppSession* ses, int request, const char* msg, ... ) {
 	if(!ses) return -1;
 	if(!msg) msg = "";
@@ -470,8 +630,17 @@
 	return 0;
 }
 
+/**
+	@brief Introspect a specified method.
+	@param ctx Pointer to the method context.
+	@param method Pointer to the osrfMethod for the specified method.
+	@param resp Pointer to the jsonObject into which method information will be placed.
 
-static void _osrfAppSetIntrospectMethod( osrfMethodContext* ctx, const osrfMethod* method, jsonObject* resp ) {
+	Treating the @a resp object as a JSON_HASH, insert entries for various bits of information
+	about the specified method.
+*/
+static void _osrfAppSetIntrospectMethod( osrfMethodContext* ctx, const osrfMethod* method,
+		jsonObject* resp ) {
 	if(!(ctx && resp)) return;
 
 	jsonObjectSetKey(resp, "api_name",  jsonNewObject(method->name));
@@ -489,14 +658,14 @@
 }
 
 /**
-	Tries to run the requested method as a system method.
-	A system method is a well known method that all
-	servers implement.
-	@param context The current method context
-	@return 0 if the method is run successfully, return < 0 means
-	the method was not run, return > 0 means the method was run
-	and the application code now needs to send a 'request complete'
-	message
+	@brief Run the requested system method.
+	@param ctx The method context.
+	@return Zero if the method is run successfully; -1 if the method was not run; 1 if the
+	method was run and the application code now needs to send a 'request complete' message.
+
+	A system method is a well known method implemented here for all servers.  Instead of
+	looking in the shared object, branch on the method name and call the corresponding
+	function.
 */
 static int _osrfAppRunSystemMethod(osrfMethodContext* ctx) {
 	if( osrfMethodVerifyContext( ctx ) < 0 ) {
@@ -506,84 +675,97 @@
 
 	if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL ) ||
 			!strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC )) {
-
 		return osrfAppIntrospectAll(ctx);
 	}
 
-
 	if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT ) ||
 			!strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ATOMIC )) {
-
 		return osrfAppIntrospect(ctx);
 	}
 
 	if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_ECHO ) ||
 			!strcmp(ctx->method->name, OSRF_SYSMETHOD_ECHO_ATOMIC )) {
-
 		return osrfAppEcho(ctx);
 	}
 
-
 	osrfAppRequestRespondException( ctx->session,
 			ctx->request, "System method implementation not found");
 
 	return 0;
 }
 
+/**
+	@brief Run the introspect method for a specified method or group of methods.
+	@param ctx Pointer to the method context.
+	@return 1 if successful, or if no search target is specified as a parameter; -1 if unable
+	to find a pointer to the application.
 
+	Traverse the list of methods, and report on each one whose name starts with the specified
+	search target.  In effect, the search target ends with an implicit wild card.
+*/
 static int osrfAppIntrospect( osrfMethodContext* ctx ) {
 
-	jsonObject* resp = NULL;
+	// Get the name of the method to introspect
 	const char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
+	if( !methodSubstring )
+		return 1; /* respond with no methods */
+
+	// Get a pointer to the application
 	osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
+	if( !app )
+		return -1;   // Oops, no application...
+
 	int len = 0;
+	osrfHashIterator* itr = osrfNewHashIterator(app->methods);
+	osrfMethod* method;
 
-	if(!methodSubstring) return 1; /* respond with no methods */
-
-	if(app) {
-
-		osrfHashIterator* itr = osrfNewHashIterator(app->methods);
-		osrfMethod* method;
-
-		while( (method = osrfHashIteratorNext(itr)) ) {
-			if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
-				if( !strncmp( method->name, methodSubstring, len) ) {
-					resp = jsonNewObject(NULL);
-					_osrfAppSetIntrospectMethod( ctx, method, resp );
-					osrfAppRespond(ctx, resp);
-					jsonObjectFree(resp);
-				}
+	while( (method = osrfHashIteratorNext(itr)) ) {
+		if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
+			if( !strncmp( method->name, methodSubstring, len) ) {
+				jsonObject* resp = jsonNewObject(NULL);
+				_osrfAppSetIntrospectMethod( ctx, method, resp );
+				osrfAppRespond(ctx, resp);
+				jsonObjectFree(resp);
 			}
 		}
-		osrfHashIteratorFree(itr);
-		return 1;
 	}
 
-	return -1;
-
+	osrfHashIteratorFree(itr);
+	return 1;
 }
 
+/**
+	@brief Run the implement_all method.
+	@param ctx Pointer to the method context.
+	@return 1 if successful, or -1 if unable to find a pointer to the application.
 
+	Report on all of the methods of the application.
+*/
 static int osrfAppIntrospectAll( osrfMethodContext* ctx ) {
-	jsonObject* resp = NULL;
 	osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
 
 	if(app) {
 		osrfHashIterator* itr = osrfNewHashIterator(app->methods);
 		osrfMethod* method;
 		while( (method = osrfHashIteratorNext(itr)) ) {
-			resp = jsonNewObject(NULL);
+			jsonObject* resp = jsonNewObject(NULL);
 			_osrfAppSetIntrospectMethod( ctx, method, resp );
 			osrfAppRespond(ctx, resp);
 			jsonObjectFree(resp);
 		}
 		osrfHashIteratorFree(itr);
 		return 1;
-	}
-
-	return -1;
+	} else
+		return -1;
 }
 
+/**
+	@brief Run the echo method.
+	@param ctx Pointer to the method context.
+	@return -1 if the method context is invalid or corrupted; otherwise 1.
+
+	Send the client a copy of each parameter.
+*/
 static int osrfAppEcho( osrfMethodContext* ctx ) {
 	if( osrfMethodVerifyContext( ctx ) < 0 ) {
 		osrfLogError( OSRF_LOG_MARK,  "osrfAppEcho: Received invalid method context" );
@@ -599,8 +781,9 @@
 }
 
 /**
-	Determine whether the context looks healthy.
-	Return 0 if it does, or -1 if it doesn't.
+	@brief Perform a series of sanity tests on an osrfMethodContext.
+	@param ctx Pointer to the osrfMethodContext to be checked.
+	@return Zero if the osrfMethodContext passes all tests, or -1 if it doesn't.
 */
 int osrfMethodVerifyContext( osrfMethodContext* ctx )
 {



More information about the opensrf-commits mailing list