コード例 #1
0
/**
	@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_STREAMING     method may return more than one response
	- OSRF_METHOD_CACHABLE      cache results in memcache

	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 ) {

	return osrfAppRegisterExtendedMethod(
			appName,
			methodName,
			symbolName,
			notes,
			argc,
			options,
			NULL
	);
}
コード例 #2
0
/**
	@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 a number of methods, some of them general-purpose and others specific for
	particular classes.

	The name of the application is given by the MODULENAME macro, whose value depends on
	conditional compilation.  The method names also incorporate MODULENAME, followed by a
	dot, as a prefix.

	The general-purpose methods are as follows (minus their MODULENAME prefixes):

	- json_query
	- transaction.begin
	- transaction.commit
	- transaction.rollback
	- savepoint.set
	- savepoint.release
	- savepoint.rollback

	For each non-virtual class, create up to eight class-specific methods:

	- create    (not for readonly classes)
	- retrieve
	- update    (not for readonly classes)
	- delete    (not for readonly classes
	- search    (atomic and non-atomic versions)
	- id_list   (atomic and non-atomic versions)

	The full method names follow the pattern "MODULENAME.direct.XXX.method_type", where XXX
	is the fieldmapper name from the IDL, with every run of one or more consecutive colons
	replaced by a period.  In addition, the names of atomic methods have a suffix of ".atomic".

	This function is called when the registering the application, and is executed by the
	listener before spawning the drones.
*/
int osrfAppInitialize( void ) {

	osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
	osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");

	// Load the IDL into memory
	if ( !oilsIDLInit( osrf_settings_host_value( "/IDL" )))
		return 1; /* return non-zero to indicate error */

	// Open the database temporarily.  Look up the datatypes of all
	// the non-virtual fields and record them with the IDL data.
	dbi_conn handle = oilsConnectDB( modulename );
	if( !handle )
		return -1;
	else if( oilsExtendIDL( handle )) {
		osrfLogError( OSRF_LOG_MARK, "Error extending the IDL" );
		return -1;
	}
	dbi_conn_close( handle );

	// Get the maximum flesh depth from the settings
	char* md = osrf_settings_host_value(
		"/apps/%s/app_settings/max_query_recursion", modulename );
	int max_flesh_depth = 100;
	if( md )
		max_flesh_depth = atoi( md );
	if( max_flesh_depth < 0 )
		max_flesh_depth = 1;
	else if( max_flesh_depth > 1000 )
		max_flesh_depth = 1000;

	oilsSetSQLOptions( modulename, enforce_pcrud, max_flesh_depth );

	// Now register all the methods
	growing_buffer* method_name = buffer_init(64);

	// Generic search thingy
	buffer_add( method_name, modulename );
	buffer_add( method_name, ".json_query" );
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
		"doJSONSearch", "", 1, OSRF_METHOD_STREAMING );

	// Next we register all the transaction and savepoint methods
	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".transaction.begin");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ),
			"beginTransaction", "", 0, 0 );

	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".transaction.commit");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name),
			"commitTransaction", "", 0, 0 );

	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".transaction.rollback");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name),
			"rollbackTransaction", "", 0, 0 );

	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".savepoint.set");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name),
			"setSavepoint", "", 1, 0 );

	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".savepoint.release");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name),
			"releaseSavepoint", "", 1, 0 );

	buffer_reset(method_name);
	OSRF_BUFFER_ADD(method_name, modulename );
	OSRF_BUFFER_ADD(method_name, ".savepoint.rollback");
	osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name),
			"rollbackSavepoint", "", 1, 0 );

	static const char* global_method[] = {
		"create",
		"retrieve",
		"update",
		"delete",
		"search",
		"id_list"
	};
	const int global_method_count
		= sizeof( global_method ) / sizeof ( global_method[0] );

	unsigned long class_count = osrfHashGetCount( oilsIDL() );
	osrfLogDebug(OSRF_LOG_MARK, "%lu classes loaded", class_count );
	osrfLogDebug(OSRF_LOG_MARK,
		"At most %lu methods will be generated",
		(unsigned long) (class_count * global_method_count) );

	osrfHashIterator* class_itr = osrfNewHashIterator( oilsIDL() );
	osrfHash* idlClass = NULL;

	// For each class in the IDL...
	while( (idlClass = osrfHashIteratorNext( class_itr ) ) ) {

		const char* classname = osrfHashIteratorKey( class_itr );
		osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", classname);

		if (!osrfStringArrayContains( osrfHashGet(idlClass, "controller"), modulename )) {
			osrfLogInfo(OSRF_LOG_MARK, "%s is not listed as a controller for %s, moving on",
					modulename, classname);
			continue;
		}

		if ( str_is_true( osrfHashGet(idlClass, "virtual") ) ) {
			osrfLogDebug(OSRF_LOG_MARK, "Class %s is virtual, skipping", classname );
			continue;
		}

		// Look up some other attributes of the current class
		const char* idlClass_fieldmapper = osrfHashGet(idlClass, "fieldmapper");
		if( !idlClass_fieldmapper ) {
			osrfLogDebug( OSRF_LOG_MARK, "Skipping class \"%s\"; no fieldmapper in IDL",
					classname );
			continue;
		}

		const char* readonly = osrfHashGet(idlClass, "readonly");

		int i;
		for( i = 0; i < global_method_count; ++i ) {  // for each global method
			const char* method_type = global_method[ i ];
			osrfLogDebug(OSRF_LOG_MARK,
				"Using files to build %s class methods for %s", method_type, classname);

			// No create, update, or delete methods for a readonly class
			if ( str_is_true( readonly )
				&& ( *method_type == 'c' || *method_type == 'u' || *method_type == 'd') )
				continue;

			buffer_reset( method_name );

			// Build the method name: MODULENAME.MODULENAME.direct.XXX.method_type
			// where XXX is the fieldmapper name from the IDL, with every run of
			// one or more consecutive colons replaced by a period.
			char* st_tmp = NULL;
			char* part = NULL;
			char* _fm = strdup( idlClass_fieldmapper );
			part = strtok_r(_fm, ":", &st_tmp);

			buffer_fadd(method_name, "%s.direct.%s", modulename, part);

			while ((part = strtok_r(NULL, ":", &st_tmp))) {
				OSRF_BUFFER_ADD_CHAR(method_name, '.');
				OSRF_BUFFER_ADD(method_name, part);
			}
			OSRF_BUFFER_ADD_CHAR(method_name, '.');
			OSRF_BUFFER_ADD(method_name, method_type);
			free(_fm);

			// For an id_list or search method we specify the OSRF_METHOD_STREAMING option.
			// The consequence is that we implicitly create an atomic method in addition to
			// the usual non-atomic method.
			int flags = 0;
			if (*method_type == 'i' || *method_type == 's') {  // id_list or search
				flags = flags | OSRF_METHOD_STREAMING;
			}

			osrfHash* method_meta = osrfNewHash();
			osrfHashSet( method_meta, idlClass, "class");
			osrfHashSet( method_meta, buffer_data( method_name ), "methodname" );
			osrfHashSet( method_meta, strdup(method_type), "methodtype" );

			// Register the method, with a pointer to an osrfHash to tell the method
			// its name, type, and class.
			osrfAppRegisterExtendedMethod(
				modulename,
				OSRF_BUFFER_C_STR( method_name ),
				"dispatchCRUDMethod",
				"",
				1,
				flags,
				(void*)method_meta
			);

		} // end for each global method
	} // end for each class in IDL

	buffer_free( method_name );
	osrfHashIteratorFree( class_itr );

	return 0;
}