[open-ils-commits] r16270 - trunk/Open-ILS/src/c-apps (scottmk)

svn at svn.open-ils.org svn at svn.open-ils.org
Mon Apr 19 08:48:02 EDT 2010


Author: scottmk
Date: 2010-04-19 08:48:01 -0400 (Mon, 19 Apr 2010)
New Revision: 16270

Added:
   trunk/Open-ILS/src/c-apps/oils_qstore.c
Modified:
   trunk/Open-ILS/src/c-apps/Makefile.am
Log:
Add a new service, open-ils.qstore.  It is not yet useful except for testing
connectivity, because the methods are stubbed out.  It will require changes to
opensrf.core before a client can access it.

A    Open-ILS/src/c-apps/oils_qstore.c
M    Open-ILS/src/c-apps/Makefile.am


Modified: trunk/Open-ILS/src/c-apps/Makefile.am
===================================================================
--- trunk/Open-ILS/src/c-apps/Makefile.am	2010-04-19 12:47:12 UTC (rev 16269)
+++ trunk/Open-ILS/src/c-apps/Makefile.am	2010-04-19 12:48:01 UTC (rev 16270)
@@ -21,7 +21,7 @@
 test_json_query_LDFLAGS = $(AM_LDFLAGS) -loils_idl -loils_utils
 test_json_query_DEPENDENCIES = liboils_idl.la liboils_utils.la
 
-lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_rstore.la oils_pcrud.la oils_auth.la
+lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_qstore.la oils_rstore.la oils_pcrud.la oils_auth.la
 
 liboils_idl_la_SOURCES = oils_idl-core.c
 
@@ -31,6 +31,10 @@
 oils_cstore_la_LDFLAGS = $(AM_LDFLAGS) -loils_idl -ldbi -ldbdpgsql -loils_utils -module
 oils_cstore_la_DEPENDENCIES = liboils_idl.la liboils_idl.la
 
+oils_qstore_la_SOURCES = oils_qstore.c oils_sql.c
+oils_qstore_la_LDFLAGS = $(AM_LDFLAGS) -loils_idl -ldbi -ldbdpgsql -loils_utils -module
+oils_qstore_la_DEPENDENCIES = liboils_idl.la liboils_idl.la
+
 oils_rstore_la_SOURCES = oils_rstore.c oils_sql.c
 oils_rstore_la_LDFLAGS = $(AM_LDFLAGS) -loils_idl -ldbi -ldbdpgsql -loils_utils -module
 oils_rstore_la_DEPENDENCIES = liboils_idl.la liboils_idl.la

Added: trunk/Open-ILS/src/c-apps/oils_qstore.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_qstore.c	                        (rev 0)
+++ trunk/Open-ILS/src/c-apps/oils_qstore.c	2010-04-19 12:48:01 UTC (rev 16270)
@@ -0,0 +1,233 @@
+/**
+	@file oils_qstore.c
+	@brief As a server, perform database queries as defined in the database itself.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <dbi/dbi.h>
+#include "opensrf/utils.h"
+#include "opensrf/log.h"
+#include "opensrf/osrf_json.h"
+#include "opensrf/osrf_application.h"
+#include "openils/oils_utils.h"
+#include "openils/oils_sql.h"
+
+static dbi_conn dbhandle; /* our db connection */
+
+static const char modulename[] = "open-ils.qstore";
+
+int doPrepare( osrfMethodContext* ctx );
+int doExecute( osrfMethodContext* ctx );
+int doSql( osrfMethodContext* ctx );
+
+/**
+	@brief Disconnect from the database.
+
+	This function is called when the server drone is about to terminate.
+*/
+void osrfAppChildExit() {
+	osrfLogDebug( OSRF_LOG_MARK, "Child is exiting, disconnecting from database..." );
+
+	if ( dbhandle ) {
+		dbi_conn_query( dbhandle, "ROLLBACK;" );
+		dbi_conn_close( dbhandle );
+		dbhandle = NULL;
+	}
+}
+
+/**
+	@brief Initialize the application.
+	@return Zero if successful, or non-zero if not.
+
+	Load the IDL file into an internal data structure for future reference.  Each non-virtual
+	class in the IDL corresponds to a table or view in the database, or to a subquery defined
+	in the IDL.  Ignore all virtual tables and virtual fields.
+
+	Register the functions for remote procedure calls.
+
+	This function is called when the registering the application, and is executed by the
+	listener before spawning the drones.
+*/
+int osrfAppInitialize() {
+
+	osrfLogInfo( OSRF_LOG_MARK, "Initializing the QStore Server..." );
+	osrfLogInfo( OSRF_LOG_MARK, "Finding XML file..." );
+
+	if ( !oilsIDLInit( osrf_settings_host_value( "/IDL" )))
+		return 1; /* return non-zero to indicate error */
+
+	growing_buffer* method_name = buffer_init( 64 );
+
+	OSRF_BUFFER_ADD( method_name, modulename );
+	OSRF_BUFFER_ADD( method_name, ".prepare" );
+	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
+			"doBuild", "", 1, 0 );
+
+	buffer_reset( method_name );
+	OSRF_BUFFER_ADD( method_name, modulename );
+	OSRF_BUFFER_ADD( method_name, ".execute" );
+	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
+			"doExecute", "", 1, OSRF_METHOD_STREAMING );
+
+	buffer_reset( method_name );
+	OSRF_BUFFER_ADD( method_name, modulename );
+	OSRF_BUFFER_ADD( method_name, ".sql" );
+	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
+			"doSql", "", 1, OSRF_METHOD_STREAMING );
+
+	return 0;
+}
+
+/**
+	@brief Initialize a server drone.
+	@return Zero if successful, -1 if not.
+
+	Connect to the database.  For each non-virtual class in the IDL, execute a dummy "SELECT * "
+	query to get the datatype of each column.  Record the datatypes in the loaded IDL.
+
+	This function is called by a server drone shortly after it is spawned by the listener.
+*/
+int osrfAppChildInit() {
+
+	osrfLogDebug( OSRF_LOG_MARK, "Attempting to initialize libdbi..." );
+	dbi_initialize( NULL );
+	osrfLogDebug( OSRF_LOG_MARK, "... libdbi initialized." );
+
+	char* driver = osrf_settings_host_value( "/apps/%s/app_settings/driver", modulename );
+	char* user   = osrf_settings_host_value( "/apps/%s/app_settings/database/user", modulename );
+	char* host   = osrf_settings_host_value( "/apps/%s/app_settings/database/host", modulename );
+	char* port   = osrf_settings_host_value( "/apps/%s/app_settings/database/port", modulename );
+	char* db     = osrf_settings_host_value( "/apps/%s/app_settings/database/db", modulename );
+	char* pw     = osrf_settings_host_value( "/apps/%s/app_settings/database/pw", modulename );
+
+	osrfLogDebug( OSRF_LOG_MARK, "Attempting to load the database driver [%s]...", driver );
+	dbhandle = dbi_conn_new( driver );
+
+	if( !dbhandle ) {
+		osrfLogError( OSRF_LOG_MARK, "Error loading database driver [%s]", driver );
+		return -1;
+	}
+	osrfLogDebug( OSRF_LOG_MARK, "Database driver [%s] seems OK", driver );
+
+	osrfLogInfo(OSRF_LOG_MARK, "%s connecting to database.  host=%s, "
+			"port=%s, user=%s, db=%s", modulename, host, port, user, db );
+
+	if( host ) dbi_conn_set_option( dbhandle, "host", host );
+	if( port ) dbi_conn_set_option_numeric( dbhandle, "port", atoi( port ) );
+	if( user ) dbi_conn_set_option( dbhandle, "username", user );
+	if( pw )   dbi_conn_set_option( dbhandle, "password", pw );
+	if( db )   dbi_conn_set_option( dbhandle, "dbname", db );
+
+	free( user );
+	free( host );
+	free( port );
+	free( db );
+	free( pw );
+
+	const char* err;
+	if( dbi_conn_connect( dbhandle ) < 0 ) {
+		sleep( 1 );
+		if( dbi_conn_connect( dbhandle ) < 0 ) {
+			dbi_conn_error( dbhandle, &err );
+			osrfLogError( OSRF_LOG_MARK, "Error connecting to database: %s", err );
+			return -1;
+		}
+	}
+
+	oilsSetDBConnection( dbhandle );
+	osrfLogInfo( OSRF_LOG_MARK, "%s successfully connected to the database", modulename );
+
+	// Add datatypes from database to the fields in the IDL
+	if( oilsExtendIDL() ) {
+		osrfLogError( OSRF_LOG_MARK, "Error extending the IDL" );
+		return -1;
+	}
+	else
+		return 0;
+}
+
+int doPrepare( osrfMethodContext* ctx ) {
+	if(osrfMethodVerifyContext( ctx )) {
+		osrfLogError( OSRF_LOG_MARK,  "Invalid method context" );
+		return -1;
+	}
+
+	// Get the query id from a method parameter
+	const jsonObject* query_id_obj = jsonObjectGetIndex( ctx->params, 0 );
+	if( query_id_obj->type != JSON_NUMBER ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; query id must be a number" );
+		return -1;
+	}
+	int query_id = atoi( jsonObjectGetString( query_id_obj ));
+	if( query_id <= 0 ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter: query id must be greater than zero" );
+		return -1;
+	}
+
+	osrfLogInfo( OSRF_LOG_MARK, "Building query for id # %d", query_id );
+
+	osrfAppRespondComplete( ctx, jsonNewObject( "build method not yet implemented" ));
+	return 0;
+}
+
+int doExecute( osrfMethodContext* ctx ) {
+	if(osrfMethodVerifyContext( ctx )) {
+		osrfLogError( OSRF_LOG_MARK,  "Invalid method context" );
+		return -1;
+	}
+
+	// Get the query token
+	const jsonObject* token_obj = jsonObjectGetIndex( ctx->params, 0 );
+	if( token_obj->type != JSON_STRING ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; query id must be a string" );
+		return -1;
+	}
+	const char* token = jsonObjectGetString( token_obj );
+
+	// Get the list of bind variables, if there is one
+	jsonObject* bind_map = jsonObjectGetIndex( ctx->params, 1 );
+	if( bind_map && bind_map->type != JSON_HASH ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; bind map must be a JSON object" );
+		return -1;
+	}
+
+	osrfLogInfo( OSRF_LOG_MARK, "Executing query for token \"%s\"", token );
+
+	osrfAppRespondComplete( ctx, jsonNewObject( "execute method not yet implemented" ));
+	return 0;
+}
+
+int doSql( osrfMethodContext* ctx ) {
+	if(osrfMethodVerifyContext( ctx )) {
+		osrfLogError( OSRF_LOG_MARK,  "Invalid method context" );
+		return -1;
+	}
+
+	// Get the query token
+	const jsonObject* token_obj = jsonObjectGetIndex( ctx->params, 0 );
+	if( token_obj->type != JSON_STRING ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; query id must be a string" );
+		return -1;
+	}
+	const char* token = jsonObjectGetString( token_obj );
+
+	// Get the list of bind variables, if there is one
+	jsonObject* bind_map = jsonObjectGetIndex( ctx->params, 1 );
+	if( bind_map && bind_map->type != JSON_HASH ) {
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException",
+			ctx->request, "Invalid parameter; bind map must be a JSON object" );
+		return -1;
+	}
+
+	osrfLogInfo( OSRF_LOG_MARK, "Returning SQL for token \"%s\"", token );
+
+	osrfAppRespondComplete( ctx, jsonNewObject( "sql method not yet implemented" ));
+	return 0;
+}



More information about the open-ils-commits mailing list