added atomic method cabilities
authorerickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Tue, 4 Oct 2005 20:22:02 +0000 (20:22 +0000)
committererickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Tue, 4 Oct 2005 20:22:02 +0000 (20:22 +0000)
register the method as streaming and an atomic version will also be registered

left space for adding cachable and potentially other method transformations

ported existing apps to new method structure

automatically initializing the app logger when the app is initialized

ported the application code to osrfHash'es instead of linked lists

git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@543 9efc2488-bf62-4759-914b-345cdb29e865

bin/opensrf_all
src/c-apps/osrf_dbmath.c
src/c-apps/osrf_math.c
src/c-apps/osrf_version.c
src/libstack/osrf_application.c
src/libstack/osrf_application.h

index cdc998c..10eda5b 100755 (executable)
@@ -81,7 +81,7 @@ function startJserver {
 
 
 function startRouter {
-       "$BINDIR/opensrf_router" "$ETCDIR/opensrf_core.xml" 
+       "$BINDIR/opensrf_router" "$ETCDIR/opensrf_core.xml" "router"
 }
 
 function startOpenSRF {
@@ -125,12 +125,12 @@ function stopMe {
        sleep 1;
        
        echo "Stopping The Router...";
-       killall "OpenSRF Router"
+       killall -9 "opensrf_router"
        
        sleep 1;
        
        echo "Stopping Chop Chop...";
-       killall jserver-c;
+       killall -9 jserver-c;
        return 0;
 }
 
index 0acecaf..d05a138 100644 (file)
@@ -12,35 +12,33 @@ int osrfMathRun( osrfMethodContext* );
 
 int osrfAppInitialize() {
 
-       osrfLogInit(MODULENAME);
-
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "add", 
                        "osrfMathRun", 
                        "Addss two numbers",
-                       "[ num1, num2 ]", 2 );
+                       "[ num1, num2 ]", 2, 0 );
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "sub", 
                        "osrfMathRun", 
                        "Subtracts two numbers",
-                       "[ num1, num2 ]", 2 );
+                       "[ num1, num2 ]", 2, 0 );
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "mult", 
                        "osrfMathRun", 
                        "Multiplies two numbers",
-                       "[ num1, num2 ]", 2 );
+                       "[ num1, num2 ]", 2, 0 );
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "div", 
                        "osrfMathRun", 
                        "Divides two numbers",
-                       "[ num1, num2 ]", 2 );
+                       "[ num1, num2 ]", 2, 0 );
 
        return 0;
 }
@@ -73,7 +71,7 @@ int osrfMathRun( osrfMethodContext* ctx ) {
                        if(!strcmp(ctx->method->name, "div"))   r = i / j;
 
                        jsonObject* resp = jsonNewNumberObject(r);
-                       osrfAppRequestRespondComplete( ctx->session, ctx->request, resp );
+                       osrfAppRespondComplete( ctx, resp );
                        jsonObjectFree(resp);
 
                        free(a); free(b);
index 78a9ddc..fc2bc44 100644 (file)
@@ -11,35 +11,36 @@ int osrfMathRun( osrfMethodContext* );
 
 
 int osrfAppInitialize() {
-       osrfLogInit(MODULENAME);
 
        osrfAppRegisterMethod( 
-                       MODULENAME, 
-                       "add", 
-                       "osrfMathRun", 
-                       "Addss two numbers",
-                       "( num1, num2 )", 2 );
+                       MODULENAME,                             /* which application has this method */
+                       "add",                                  /* the name of the method */
+                       "osrfMathRun",                  /* the symbol that runs the method */
+                       "Adds two numbers",     /* description of the method */
+                       "( num1, num2 )",               /* description of the method params */
+                       2,                                                      /* the minimum number of params required to run the method */
+                       0 );                                            /* streaming method? yes / no */
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "sub", 
                        "osrfMathRun", 
                        "Subtracts two numbers",
-                       "( num1, num2 )", 2 );
+                       "( num1, num2 )", 2, 0 );
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "mult", 
                        "osrfMathRun", 
                        "Multiplies two numbers",
-                       "( num1, num2 )", 2 );
+                       "( num1, num2 )", 2, 0 );
 
        osrfAppRegisterMethod( 
                        MODULENAME, 
                        "div", 
                        "osrfMathRun", 
                        "Divides two numbers",
-                       "( num1, num2 )", 2 );
+                       "( num1, num2 )", 2, 0 );
 
        return 0;
 }
@@ -80,7 +81,7 @@ int osrfMathRun( osrfMethodContext* ctx ) {
 
                        if(omsg) {
                                /* return dbmath's response to the user */
-                               osrfAppRequestRespondComplete( ctx->session, ctx->request, osrfMessageGetResult(omsg) ); 
+                               osrfAppRespondComplete( ctx, osrfMessageGetResult(omsg) ); 
                                osrfMessageFree(omsg);
                                osrfAppSessionFree(ses);
                                return 0;
index 2936607..ac0e3fb 100644 (file)
@@ -12,7 +12,6 @@ int osrfVersion( osrfMethodContext* );
 
 
 int osrfAppInitialize() {
-       osrfLogInit("opensrf.version");
 
        osrfAppRegisterMethod( 
                        "opensrf.version", 
@@ -21,7 +20,7 @@ int osrfAppInitialize() {
                        "The data for a service/method/params combination will be retrieved "
                        "from the necessary server and the MD5 sum of the total values received "
                        "will be returned", 
-                       "( serviceName, methodName, [param1, ...] )", 2 );
+                       "( serviceName, methodName, [param1, ...] )", 2, 0 );
        
        return 0;
 }
@@ -43,7 +42,7 @@ int osrfVersion( osrfMethodContext* ctx ) {
        if( cachedmd5 ) {
                osrfLog( OSRF_DEBUG, "Found %s object in cache, returning....", cachedmd5 );
                jsonObject* resp = jsonNewObject(cachedmd5);
-               osrfAppRequestRespondComplete( ctx->session, ctx->request, resp  );
+               osrfAppRespondComplete( ctx, resp  );
                jsonObjectFree(resp);
                free(paramsmd5);
                free(cachedmd5);
@@ -77,7 +76,7 @@ int osrfVersion( osrfMethodContext* ctx ) {
 
                        if( resultmd5 ) {
                                jsonObject* resp = jsonNewObject(resultmd5);
-                               osrfAppRequestRespondComplete( ctx->session, ctx->request, resp );
+                               osrfAppRespondComplete( ctx, resp );
                                jsonObjectFree(resp);
                                osrfAppSessionFree(ses);
                                osrfLog(OSRF_DEBUG, "Found version string %s, caching and returning...", resultmd5 );
index e919208..0feb9b8 100644 (file)
@@ -2,13 +2,17 @@
 #include "osrf_log.h"
 #include "objson/object.h"
 
-osrfApplication* __osrfAppList = NULL; 
+//osrfApplication* __osrfAppList = NULL; 
+
+osrfHash* __osrfAppHash = NULL;
 
 
 int osrfAppRegisterApplication( char* appName, char* soFile ) {
        if(!appName || ! soFile) return -1;
        char* error;
 
+       if(!__osrfAppHash) __osrfAppHash = osrfNewHash();
+
        info_handler("Registering application %s with file %s", appName, soFile );
 
        osrfApplication* app = safe_malloc(sizeof(osrfApplication));
@@ -21,12 +25,8 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
                return -1;
        }
 
-       app->name = strdup(appName);
-
-       /* this has to be done before initting the application */
-       app->next = __osrfAppList;
-       __osrfAppList = app;
-
+       app->methods = osrfNewHash();
+       osrfHashSet( __osrfAppHash, app, appName );
 
        /* see if we can run the initialize method */
        int (*init) (void);
@@ -52,14 +52,23 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
 
        info_handler("Application %s registered successfully", appName );
 
+       osrfLogInit(appName);
 
        return 0;
 }
 
-int osrfAppRegisterMethod( char* appName, 
-               char* methodName, char* symbolName, char* notes, char* params, int argc ) {
 
-       if( !appName || ! methodName || ! symbolName ) return -1;
+int osrfAppRegisterMethod( char* appName, char* methodName, 
+               char* symbolName, char* notes, char* params, int argc, int streaming ) {
+
+       return _osrfAppRegisterMethod(appName, methodName, 
+                       symbolName, notes, params, argc, streaming, 0 );
+}
+
+int _osrfAppRegisterMethod( char* appName, char* methodName, 
+               char* symbolName, char* notes, char* params, int argc, int streaming, int system ) {
+
+       if( !appName || ! methodName  ) return -1;
 
        osrfApplication* app = _osrfAppFindApplication(appName);
        if(!app) return warning_handler("Unable to locate application %s", appName );
@@ -67,80 +76,80 @@ int osrfAppRegisterMethod( char* appName,
        debug_handler("Registering method %s for app %s", methodName, appName );
 
        osrfMethod* method = _osrfAppBuildMethod(
-               methodName, symbolName, notes, params, argc, 0 );               
+               methodName, symbolName, notes, params, argc, system, 0 );               
+       method->streaming = streaming;
 
        /* plug the method into the list of methods */
-       method->next = app->methods;
-       app->methods = method;
+       osrfHashSet( app->methods, method, method->name );
+
+       if( streaming ) { /* build the atomic counterpart */
+               osrfMethod* atomicMethod = _osrfAppBuildMethod(
+                       methodName, symbolName, notes, params, argc, system, 1 );               
+               osrfHashSet( app->methods, atomicMethod, atomicMethod->name );
+       }
+
        return 0;
 }
 
 
+
 osrfMethod* _osrfAppBuildMethod( char* methodName, 
-       char* symbolName, char* notes, char* params, int argc, int sysmethod ) {
+       char* symbolName, char* notes, char* params, int argc, int sysmethod, int atomic ) {
 
        osrfMethod* method                                      = safe_malloc(sizeof(osrfMethod));
+
        if(methodName) method->name             = strdup(methodName);
        if(symbolName) method->symbol           = strdup(symbolName);
        if(notes) method->notes                         = strdup(notes);
        if(params) method->paramNotes           = strdup(params);
+
        method->argc                                                    = argc;
        method->sysmethod                                               = sysmethod;
-       return method;
-}
+       method->atomic                                                  = atomic;
+       method->cachable                                                = 0;
+
+       if(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->streaming = 1;
+       }
 
+       debug_handler("Built method %s", method->name );
 
-int _osrfAppRegisterSystemMethod( char* appName, char* methodName, 
-               char* notes, char* params, int argc ) {
-       if(!(appName && methodName)) return -1;
-       osrfApplication* app = _osrfAppFindApplication(appName);
-       if(!app) return warning_handler("Unable to locate application %s", appName );
-       debug_handler("Registering system method %s for app %s", methodName, appName );
-       osrfMethod* method = _osrfAppBuildMethod(
-               methodName, NULL, notes, params, argc, 1 );             
-
-       /* plug the method into the list of methods */
-       method->next = app->methods;
-       app->methods = method;
-       return 0;
-
+       return method;
 }
 
+
 int __osrfAppRegisterSysMethods( char* app ) {
 
-       _osrfAppRegisterSystemMethod( 
-                       app, OSRF_SYSMETHOD_INTROSPECT, 
+       _osrfAppRegisterMethod( 
+                       app, OSRF_SYSMETHOD_INTROSPECT, NULL, 
                        "Return a list of methods whose names have the same initial "
                        "substring as that of the provided method name",
-                       "( methodNameSubstring )", 1 );
+                       "( methodNameSubstring )", 1, 1 , 1);
 
-       _osrfAppRegisterSystemMethod( 
-                       app, OSRF_SYSMETHOD_INTROSPECT_ALL, 
-                       "Returns a complete list of methods", "()", 0 ); 
+       _osrfAppRegisterMethod( 
+                       app, OSRF_SYSMETHOD_INTROSPECT_ALL, NULL, 
+                       "Returns a complete list of methods", "()", 0, 1, 1 ); 
+
+       _osrfAppRegisterMethod( 
+                       app, OSRF_SYSMETHOD_ECHO, NULL, 
+                       "Echos all data sent to the server back to the client", 
+                       "([a, b, ...])", 0, 1, 1);
 
        return 0;
 }
 
 osrfApplication* _osrfAppFindApplication( char* name ) {
        if(!name) return NULL;
-       osrfApplication* app = __osrfAppList;
-       while(app) {
-               if(!strcmp(app->name, name))
-                       return app;
-               app = app->next;
-       }
-       return NULL;
+       return (osrfApplication*) osrfHashGet(__osrfAppHash, name);
 }
 
 osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName ) {
        if(!app || ! methodName) return NULL;
-       osrfMethod* method = app->methods;
-       while(method) {
-               if(!strcmp(method->name, methodName))
-                       return method;
-               method = method->next;
-       }
-       return NULL;
+       return (osrfMethod*) osrfHashGet( app->methods, methodName );
 }
 
 osrfMethod* _osrfAppFindMethod( char* appName, char* methodName ) {
@@ -162,6 +171,7 @@ int osrfAppRunMethod( char* appName, char* methodName,
        context.session = ses;
        context.params = params;
        context.request = reqId;
+       context.responses = NULL;
 
        /* this is the method we're gonna run */
        int (*meth) (osrfMethodContext*);       
@@ -187,42 +197,91 @@ int osrfAppRunMethod( char* appName, char* methodName,
        }
        #endif
 
+       int retcode = 0;
+
        if( method->sysmethod ) {
+               retcode = __osrfAppRunSystemMethod(&context);
 
-               int sysres = __osrfAppRunSystemMethod(&context);
-               if(sysres == 0) return 0;
+       } else {
 
-               if(sysres > 0) 
-                       return osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  
-                                       "osrfConnectStatus", reqId, "Request Complete" );
+               /* open and now run the method */
+               *(void **) (&meth) = dlsym(app->handle, method->symbol);
 
-               if(sysres < 0) 
-                       return osrfAppRequestRespondException( 
-                               ses, reqId, "An unknown server error occurred" );
+               if( (error = dlerror()) != NULL ) {
+                       return osrfAppRequestRespondException( ses, reqId, 
+                               "Unable to execute method [%s]  for service %s", methodName, appName );
+               }
+
+               retcode = (*meth) (&context);
        }
 
+       if(retcode < 0) 
+               return osrfAppRequestRespondException( 
+                               ses, reqId, "An unknown server error occurred" );
 
-       /* open the method */
-       *(void **) (&meth) = dlsym(app->handle, method->symbol);
+       return __osrfAppPostProcess( &context, retcode );
 
-       if( (error = dlerror()) != NULL ) {
-               return osrfAppRequestRespondException( ses, reqId, 
-                               "Unable to execute method [%s]  for service %s", methodName, appName );
+}
+
+
+int osrfAppRespond( osrfMethodContext* ctx, jsonObject* data ) {
+       return _osrfAppRespond( ctx, data, 0 );
+}
+
+int osrfAppRespondComplete( osrfMethodContext* context, jsonObject* data ) {
+       return _osrfAppRespond( context, data, 1 );
+}
+
+int _osrfAppRespond( osrfMethodContext* ctx, jsonObject* data, int complete ) {
+       if(!(ctx && ctx->method)) return -1;
+
+       if( ctx->method->atomic ) {
+               osrfLog( OSRF_DEBUG, 
+                       "Adding responses to stash for atomic method %s", ctx->method );
+
+               if( ctx->responses == NULL )                                                                                            
+                       ctx->responses = jsonParseString("[]");                                                 
+               jsonObjectPush( ctx->responses, jsonObjectClone(data) );        
        }
 
-       /* run the method */
-       int ret;
-       if( (ret = (*meth) (&context)) < 0 )
-               return osrfAppRequestRespondException( 
-                               ses, reqId, "An unknown server error occurred" );
 
-       if( ret > 0 ) 
-               osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  
-                               "osrfConnectStatus", reqId, "Request Complete" );
+       if( !ctx->method->atomic && ! ctx->method->cachable ) {
+               if(complete) 
+                       osrfAppRequestRespondComplete( ctx->session, ctx->request, data );
+               else
+                       osrfAppRequestRespond( ctx->session, ctx->request, data );
+               return 0;
+       }
 
        return 0;
 }
 
+
+
+
+int __osrfAppPostProcess( osrfMethodContext* ctx, int retcode ) {
+       if(!(ctx && ctx->method)) return -1;
+
+       osrfLog( OSRF_DEBUG, "Postprocessing method %s with retcode %d",
+                       ctx->method->name, retcode );
+
+       if(ctx->responses) { /* we have cached responses to return */
+
+               osrfAppRequestRespondComplete( ctx->session, ctx->request, ctx->responses );
+               jsonObjectFree(ctx->responses);
+               ctx->responses = NULL;
+
+       } else {
+
+               if( retcode > 0 ) 
+                       osrfAppSessionStatus( ctx->session, OSRF_STATUS_COMPLETE,  
+                                       "osrfConnectStatus", ctx->request, "Request Complete" );
+       }
+
+       return 0;
+
+}
+
 int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... ) {
        if(!ses) return -1;
        if(!msg) msg = "";
@@ -235,13 +294,15 @@ int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg,
 
 static void __osrfAppSetIntrospectMethod( osrfMethodContext* ctx, osrfMethod* method, jsonObject* resp ) {
        if(!(ctx && resp)) return;
-       jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
-       jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
-       jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
-       jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
-       jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
-       jsonObjectSetKey(resp, "params", jsonNewObject(method->paramNotes) );
+       jsonObjectSetKey(resp, "api_name",      jsonNewObject(method->name));
+       jsonObjectSetKey(resp, "method",                jsonNewObject(method->symbol));
+       jsonObjectSetKey(resp, "service",       jsonNewObject(ctx->session->remote_service));
+       jsonObjectSetKey(resp, "notes",         jsonNewObject(method->notes));
+       jsonObjectSetKey(resp, "argc",          jsonNewNumberObject(method->argc));
+       jsonObjectSetKey(resp, "params",                jsonNewObject(method->paramNotes) );
        jsonObjectSetKey(resp, "sysmethod", jsonNewNumberObject(method->sysmethod) );
+       jsonObjectSetKey(resp, "atomic",                jsonNewNumberObject(method->atomic) );
+       jsonObjectSetKey(resp, "cachable",      jsonNewNumberObject(method->cachable) );
        jsonObjectSetClass(resp, "method");
 }
 
@@ -250,57 +311,77 @@ static void __osrfAppSetIntrospectMethod( osrfMethodContext* ctx, osrfMethod* me
 int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
        OSRF_METHOD_VERIFY_CONTEXT(ctx);
 
-       if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL )) {
-
-               jsonObject* resp = NULL;
-               osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
-               if(app) {
-                       osrfMethod* method = app->methods;
-                       while(method) {
-                               resp = jsonNewObject(NULL);
-                               __osrfAppSetIntrospectMethod( ctx, method, resp );
-                               osrfAppRequestRespond(ctx->session, ctx->request, resp);
-                               jsonObjectFree(resp);
-                               method = method->next;
-                       }
-                       return 1;
-               }
+       if(     !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL ) || 
+                       !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC )) {
 
-               return -1;
+               return osrfAppIntrospectAll(ctx);
        }
 
 
-       if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT )) {
+       if(     !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT ) ||
+                       !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ATOMIC )) {
+
+               return osrfAppIntrospect(ctx);
+       }
+
+       osrfAppRequestRespondException( ctx->session, 
+                       ctx->request, "System method implementation not found");
+
+       return 0;
+}
+
+
+int osrfAppIntrospect( osrfMethodContext* ctx ) {
 
-               jsonObject* resp = NULL;
-               char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
-               osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
-               int len = 0;
+       jsonObject* resp = NULL;
+       char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
+       osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
+       int len = 0;
 
-               if(!methodSubstring) return 1; /* respond with no methods */
+       if(!methodSubstring) return 1; /* respond with no methods */
 
-               if(app) {
-                       osrfMethod* method = app->methods;
-                       while(method) {
-                               if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
-                                       if( !strncmp( method->name, methodSubstring, len) ) {
-                                               resp = jsonNewObject(NULL);
-                                               __osrfAppSetIntrospectMethod( ctx, method, resp );
-                                               osrfAppRequestRespond(ctx->session, ctx->request, resp);
-                                               jsonObjectFree(resp);
-                                       }
+       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);
                                }
-                               method = method->next;
                        }
-                       return 1;
                }
-
-               return -1;
+               osrfHashIteratorFree(itr);
+               return 1;
        }
 
        return -1;
+
 }
 
 
+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);
+                       __osrfAppSetIntrospectMethod( ctx, method, resp );
+                       osrfAppRespond(ctx, resp);
+                       jsonObjectFree(resp);
+               }
+               osrfHashIteratorFree(itr);
+               return 1;
+       }
+
+       return -1;
+}
 
 
index 451450b..4dea5a2 100644 (file)
@@ -4,6 +4,7 @@
 #include "opensrf/logging.h"
 #include "objson/object.h"
 #include "osrf_app_session.h"
+#include "osrf_hash.h"
 
 
 /**
@@ -36,7 +37,7 @@
        _OSRF_METHOD_VERIFY_CONTEXT(d); \
        char* __j = jsonObjectToJSON(d->params);\
        if(__j) { \
-               osrfLog( OSRF_INFO, "[%s:%s] params: %s", d->session->remote_service, d->method->name, __j);\
+               osrfLog( OSRF_INFO, "%s %s - %s", d->session->remote_service, d->method->name, __j);\
                free(__j); \
        } 
 #else
@@ -45,7 +46,6 @@
 
 
 
-
 /* used internally to make sure the method description provided is OK */
 #define OSRF_METHOD_VERIFY_DESCRIPTION(app, d) \
        if(!app) return -1; \
 
 
 
+
 /* Some well known parameters */
-#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
+#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_ATOMIC 1
+//#define OSRF_METHOD_CACHABLE 2
 
        
 
 struct _osrfApplicationStruct {
-       char* name;                                                                             /* the name of our application */
+       //char* name;                                                                           /* the name of our application */
        void* handle;                                                                   /* the lib handle */
-       struct _osrfMethodStruct* methods;              /* list of methods */
-       struct _osrfApplicationStruct* next;    /* next application */
+       osrfHash* methods;
+       //struct _osrfMethodStruct* methods;            /* list of methods */
+//     struct _osrfApplicationStruct* next;    /* next application */
 };
 typedef struct _osrfApplicationStruct osrfApplication;
 
@@ -79,8 +88,11 @@ struct _osrfMethodStruct {
        char* notes;                            /* public method documentation */
        int argc;                                       /* how many args this method expects */
        char* paramNotes;                       /* Description of the params expected for this method */
-       struct _osrfMethodStruct* next; /* nest method in the list */
+//     struct _osrfMethodStruct* next; /* nest method in the list */
        int sysmethod;                          /* true if this is a system method */
+       int streaming;                          /* true if this is a streamable method */
+       int atomic;                                     /* true if the method is an atomic method */
+       int cachable;                           /* true if the method is cachable */
 }; 
 typedef struct _osrfMethodStruct osrfMethod;
 
@@ -89,6 +101,7 @@ struct _osrfMethodContextStruct {
        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;
 
@@ -110,16 +123,17 @@ int osrfAppRegisterApplication( char* appName, char* soFile );
   @param notes Public documentation for this method.
   @params params String description description of the params expected
   @params argc The number of arguments this method expects 
+  @param streaming True if this is a streaming method that requires an atomic version
   @return 0 on success, -1 on error
   */
-int osrfAppRegisterMethod( char* appName, 
-               char* methodName, char* symbolName, char* notes, char* params, int argc );
+int osrfAppRegisterMethod( char* appName, char* methodName, 
+               char* symbolName, char* notes, char* params, int argc, int streaming );
 
-int _osrfAppRegisterSystemMethod( char* appName, char* methodName, 
-               char* notes, char* params, int argc );
+int _osrfAppRegisterMethod( char* appName, char* methodName, 
+               char* symbolName, char* notes, char* params, int argc, int streaming, int system );
 
 osrfMethod* _osrfAppBuildMethod( char* methodName, 
-               char* symbolName, char* notes, char* params, int argc, int sysmethod );
+               char* symbolName, char* notes, char* params, int argc, int sysmethod, int streaming );
 
 /**
   Registher a method
@@ -197,4 +211,17 @@ int __osrfAppRegisterSysMethods( char* app );
   */
 int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... );
 
+int __osrfAppPostProcess( osrfMethodContext* context, int retcode );
+
+
+int osrfAppRespond( osrfMethodContext* context, jsonObject* data );
+int _osrfAppRespond( osrfMethodContext* context, jsonObject* data, int complete );
+int osrfAppRespondComplete( osrfMethodContext* context, jsonObject* data );
+
+/* OSRF_METHOD_ATOMIC and/or OSRF_METHOD_CACHABLE and/or 0 for no special options */
+//int osrfAppProcessMethodOptions( char* method );
+
+int osrfAppIntrospect( osrfMethodContext* ctx );
+int osrfAppIntrospectAll( osrfMethodContext* ctx );
+