[m-dev.] diff: assorted changes to extras/aditi

Simon TAYLOR stayl at cs.mu.OZ.AU
Fri May 26 18:38:35 AEST 2000



Estimated hours taken: 4

Assorted changes to extras/aditi. This stuff is really being
maintained as part of the Aditi repository (it's needed for
their nightly tests), but I'll leave it here for now.

extras/aditi/Mmakefile:
	Don't attempt to install `hlc.*' grades.

	Pass `--no-ansi' to mgnuc to avoid errors in the RPC
	headers on Linux.

extras/aditi/aditi.m:
	Be careful not to clean up the output relation and
	cursor for a call twice when using trailing.

	Use the compiler-generated procedure to bulk insert tuples
	into a base relation, rather than using the slow Aditi API
	function.

	Make sure the correct status is returned for transactions
	which fail.

extras/aditi/LIMITATIONS:
	Add some more comments about what isn't allowed.	


Index: LIMITATIONS
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/aditi/LIMITATIONS,v
retrieving revision 1.2
diff -u -u -r1.2 LIMITATIONS
--- LIMITATIONS	2000/05/05 06:08:04	1.2
+++ LIMITATIONS	2000/05/26 08:18:33
@@ -1,13 +1,18 @@
 The Aditi interface and Aditi itself are still in development.
-The Aditi system is not yet publicly available.
 
 * aditi__state arguments must currently be ground, not unique. This will
-  be fixed when the alias branch is merged in. Use the mode aditi_mui
-  defined in aditi.m instead for now.
+  be fixed when the alias tracking mode analyser is released. Use the
+  mode aditi_mui defined in aditi.m instead for now.
 
 * Only calls to local, non-recursive Mercury predicates are allowed
   from Aditi procedures (they are generated inline). The code
   generator aborts if recursive predicates are called. Stick
   to builtins in join conditions for now.
+  Non-deterministic predicates will probably not work.
 
-* Update predicates for base relations are not yet implemented.
+* Abstract data types are not supported.
+
+* Existential types are not supported.
+
+* Types with user-defined equality predicates are not supported.
+
Index: Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/aditi/Mmakefile,v
retrieving revision 1.3
diff -u -u -r1.3 Mmakefile
--- Mmakefile	2000/04/14 08:39:11	1.3
+++ Mmakefile	2000/05/26 08:18:33
@@ -6,34 +6,37 @@
 # Mmakefile for the Mercury->Aditi interface.
 # 
 # Environment variables (must be set externally):
-# MADITI_INSTALL_PREFIX - directory where the interface should be installed.
 # MAKEFILE_ADITI - makefile containing variables used when compiling
 # 		a program for Aditi.
 #				
 #-----------------------------------------------------------------------------#
 #
-# Defines ADITI_API_EXTRA_CFLAGS, ADITI_API_EXTRA_LIBS and
-# ADITI_API_EXTRA_LDFLAGS
+# Defines $(ADITI_API_EXTRA_CFLAGS), $(ADITI_API_EXTRA_LIBS) and
+# $(ADITI_API_EXTRA_LDFLAGS).
 include $(MAKEFILE_ADITI)
 
-INSTALL_PREFIX = $(MADITI_INSTALL_PREFIX)
-
 # The Aditi interface only works with conservative garbage collection.
+# It doesn't yet work with the new high level C code grade.
 # This is equivalent to
 # LIBGRADES-aditi = $(filter %.gc%,$(LIBGRADES))
 # but gmake patterns can't include multiple wildcards.
-LIBGRADES-aditi = $(shell echo $(LIBGRADES) | tr ' ' '\n' | grep '.gc')
+LIBGRADES-aditi = \
+	$(shell echo $(LIBGRADES) | tr ' ' '\n' | grep '.gc' | grep -v 'hlc')
 
 #----------------------------------------------------------------------------#
 
 # The --Wno-strict-prototypes is to shut up warnings about prototypes
 # without argument types in a header file generated by rpcgen.
+# To get more debugging messages, add "-DDEBUG_ON" to CFLAGS.
 CFLAGS = $(ADITI_API_EXTRA_CFLAGS) -Wno-strict-prototypes
+
+# The RPC headers on Linux don't like it when `-ansi' is passed to gcc.
+MGNUCFLAGS = --no-ansi
 
-MLFLAGS = --use-thread-libs $(ADITI_API_EXTRA_LDFLAGS) $(EXTRA_MLFLAGS)
+MLFLAGS = --use-thread-libs $(ADITI_API_EXTRA_LDFLAGS)
 MLLIBS = $(ADITI_API_EXTRA_LIBS)
 
-MCFLAGS = --no-infer-all --aditi
+MCFLAGS = --no-infer-all --aditi --aditi-user guest
 
 C2INITFLAGS = --aditi
 
@@ -43,19 +46,19 @@
 
 .PHONY: depend
 depend: aditi.depend
-	cd tests && mmake $(MMAKEFLAGS) depend
+	cd tests && $(MMAKE) depend
 
 .PHONY: clean
 clean:
-	cd tests && mmake $(MMAKEFLAGS) clean
+	cd tests && $(MMAKE) clean
 
 .PHONY: realclean
 realclean:
-	cd tests && mmake $(MMAKEFLAGS) realclean
+	cd tests && $(MMAKE) realclean
 
 .PHONY: tests
 tests:
-	cd tests && mmake $(MMAKEFLAGS)
+	cd tests && $(MMAKE)
 
 .PHONY: install
 install: libaditi.install
Index: aditi.m
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/aditi/aditi.m,v
retrieving revision 1.9
diff -u -u -r1.9 aditi.m
--- aditi.m	2000/05/08 13:48:18	1.9
+++ aditi.m	2000/05/26 08:18:33
@@ -11,10 +11,11 @@
 % "Aditi deductive database interface" section of the Mercury
 % Language Reference Manual (listed under "Implementation defined pragmas"
 % in the "Pragmas" chapter) for details on how to compile database queries.
-% (XXX this section in the manual is commented out, since Aditi is not yet
-% publicly available.)
 %
+% For information on how to build programs which use this interface,
+% see the example Mmakefile in $ADITI_HOME/demos/transactions. 
 %
+%
 % Compilation grade notes (see the section "Compilation model options"
 % in the Mercury User's Guide for more information):
 %
@@ -32,6 +33,9 @@
 %	It is up to the programmer to decide whether imposing the overhead
 %	of trailing on the rest of the program is worthwhile.
 %
+%	Compilation of this module in a high level C code grade (e.g. `hlc.gc')
+%	is not yet supported.
+%
 %
 % The transaction interface used here is described in
 %	Kemp, Conway, Harris, Henderson, Ramamohanarao and Somogyi,
@@ -154,9 +158,10 @@
 		pred(in, in, out) is det, out, out) is multi.
 
 /*
-	This should be translated into the equivalent aggregate_compute_initial
-   	by magic.m, but that hasn't been done yet. The main problem is
-	collecting the initial value - it may not be constant.
+	This should be translated into the equivalent
+	aggregate_compute_initial , but that hasn't been
+	done yet. The main problem is collecting the initial
+	value - it may not be constant.
 
 	Also, it would be nice to provide versions of aditi__aggregate
 	which work over one attribute relations, as in std_util__aggregate. 
@@ -202,8 +207,6 @@
 typedef enum { MADITI_INSERT_TUPLE, MADITI_DELETE_TUPLE } MADITI_insert_delete;
 typedef enum { MADITI_INSERT, MADITI_DELETE, MADITI_MODIFY } MADITI_bulk_op;
 
-#ifdef MR_USE_TRAIL
-
 /*
 ** Information used to clean up a call result if there is a commit
 ** or an exception across a database call.
@@ -211,11 +214,10 @@
 typedef struct {
 	ticket *output_rel;
 	ticket *output_cursor;
+	int num_output_args;
 	bool cleaned_up;
-} MADITI_trail_cleanup_data;
+} MADITI_output_info;
 
-#endif /* MR_USE_TRAIL */
-
 static ticket MADITI_ticket;		/* Current connection ticket. */
 static MR_jmp_buf MADITI_jmp_buf;	/* jmp_buf to longjmp() to when
 					** aborting the transaction.
@@ -233,7 +235,7 @@
 		String rel_name, ticket *call_result_ticket);
 static bool MADITI_get_output_tuple(int);
 static void MADITI_post_call_cleanup(void);
-static void MADITI_cleanup_call_output(ticket *output_rel, ticket *cursor);
+static void MADITI_cleanup_call_output(MADITI_output_info *);
 
 #ifdef MR_USE_TRAIL
 static void MADITI_trail_cleanup_call_output(void *cleanup_data,
@@ -435,8 +437,11 @@
 #ifndef CONSERVATIVE_GC
 #error ""The Aditi interface requires conservative garbage collection. \\
                 Use a compilation grade containing .gc.""
-#endif /* ! CONSERVATIVE_GC */
+#endif
 
+#ifdef MR_HIGHLEVEL_CODE
+#error ""The Aditi interface does not yet work in `hlc' grades""
+#endif
 
 ").
 
@@ -496,11 +501,9 @@
 */
 
 	/* Slots in frame apart from the typeinfos for the outputs */
-#define MADITI_NUM_FRAME_VARS 3
+#define MADITI_NUM_FRAME_VARS 1
 
-#define MADITI_saved_num_output_args		MR_framevar(1)
-#define MADITI_saved_output_rel			MR_framevar(2)
-#define MADITI_saved_cursor			MR_framevar(3)
+#define MADITI_saved_output_info		MR_framevar(1)
 #define MADITI_ADITI_FIRST_TYPEINFO		MADITI_NUM_FRAME_VARS + 1
 #define MADITI_OUTPUT_TYPEINFO(i) \
 			MR_framevar(MADITI_ADITI_FIRST_TYPEINFO + (i))
@@ -569,6 +572,7 @@
 		LABEL(do_nondet_aditi_call_i1));
 
 	save_transient_registers();
+	DEBUG(printf(""do_nondet_aditi_call\\n""));
 	MADITI_do_nondet_call();
 	restore_transient_registers();
 	GOTO(LABEL(do_nondet_aditi_call_i1));
@@ -595,6 +599,8 @@
 		ENTRY(do_not_reached));
 
 	save_transient_registers();
+
+	DEBUG(printf(""do_semidet_aditi_call\\n""));
 	MADITI_do_nondet_call();
 
 	/* Unpack the output tuple into r2 and upwards for semidet code. */
@@ -623,11 +629,13 @@
 		ENTRY(do_not_reached));
 
 	save_transient_registers();
+
+	DEBUG(printf(""do_det_aditi_call\\n""));
 	MADITI_do_nondet_call();
 
 	/* Unpack the output tuple into r1 and upwards. */
 	if (!MADITI_get_output_tuple(1)) {
-		MR_fatal_error(""no solution for det Aditi call"");
+		fatal_error(""no solution for det Aditi call"");
 	}
 
 	/*
@@ -659,16 +667,16 @@
 */
 Define_entry(do_aditi_insert);
 {
-	save_transient_registers();
 	DEBUG(printf(""do_aditi_insert\\n""));
+	save_transient_registers();
 	MADITI_do_insert_delete_tuple(MADITI_INSERT_TUPLE);
 	restore_transient_registers();
 	proceed();	
 }
 Define_entry(do_aditi_delete);
 {
-	save_transient_registers();
 	DEBUG(printf(""do_aditi_delete\\n""));
+	save_transient_registers();
 	MADITI_do_insert_delete_tuple(MADITI_DELETE_TUPLE);
 	restore_transient_registers();
 	proceed();	
@@ -685,24 +693,24 @@
 */
 Define_entry(do_aditi_bulk_insert);
 {
-	save_transient_registers();
 	DEBUG(printf(""do_aditi_bulk_insert\\n""));
+	save_transient_registers();
 	MADITI_do_bulk_operation(MADITI_INSERT);
 	restore_transient_registers();
 	proceed();	
 }
 Define_entry(do_aditi_bulk_delete);
 {
-	save_transient_registers();
 	DEBUG(printf(""do_aditi_bulk_delete\\n""));
+	save_transient_registers();
 	MADITI_do_bulk_operation(MADITI_DELETE);
 	restore_transient_registers();
 	proceed();	
 }
 Define_entry(do_aditi_bulk_modify);
 {
-	save_transient_registers();
 	DEBUG(printf(""do_aditi_bulk_modify\\n""));
+	save_transient_registers();
 	MADITI_do_bulk_operation(MADITI_MODIFY);
 	restore_transient_registers();
 	proceed();	
@@ -746,6 +754,7 @@
 					** type-infos for the output arguments
 					*/
 	int i;
+	MADITI_output_info *output_info;
 
 	restore_transient_registers();
 
@@ -755,10 +764,6 @@
 
 	num_output_args = (int) MADITI_num_output_args;
 
-	/* save the number of output arguments */
-	MADITI_saved_num_output_args = num_output_args;
-
-
 	DEBUG(printf(""Handling call to %s\\n"", proc_name));
 	DEBUG(printf(""%d input args; %d output args\\n"",
 		num_input_args, num_output_args));
@@ -796,79 +801,21 @@
 	MADITI_check(ADITI_NAME(rel_cursor_create)(output_ticket, cursor));
 	MADITI_check(ADITI_NAME(cursor_open)(cursor, CUR_FORWARD));
 	DEBUG(printf(""done\\n""));
-
-	MADITI_saved_output_rel = (Word) output_ticket;
-	MADITI_saved_cursor = (Word) cursor;
 
+	output_info = MR_GC_NEW(MADITI_output_info);
+	output_info->output_rel = output_ticket;
+	output_info->output_cursor = cursor;
+	output_info->num_output_args = num_output_args;
+	output_info->cleaned_up = FALSE;
+	MADITI_saved_output_info = (Word) output_info;
 #ifdef MR_USE_TRAIL
-	{
-		MADITI_trail_cleanup_data *cleanup_data;
-		cleanup_data = MR_GC_NEW(MADITI_trail_cleanup_data);
-		cleanup_data->output_rel = output_ticket;
-		cleanup_data->output_cursor = cursor;
-		cleanup_data->cleaned_up = FALSE;
-		MR_trail_function(MADITI_trail_cleanup_call_output,
-			(void *) cleanup_data);
-	}
-#endif /* MR_USE_TRAIL */
+	MR_trail_function(MADITI_trail_cleanup_call_output,
+		(void *) output_info);
+#endif
 
 	save_transient_registers();
 }
 
-#ifdef MR_USE_TRAIL
-static void
-MADITI_trail_cleanup_call_output(void *data, MR_untrail_reason reason)
-{
-	MADITI_trail_cleanup_data *cleanup_data;
-	switch (reason) {
-	    case MR_commit:
-	    case MR_exception:
-	    case MR_retry:
-		/*
-		** Cleanup the output relation.
-		*/
-		cleanup_data = (MADITI_trail_cleanup_data *) data;
-
-		if (cleanup_data->cleaned_up) {
-
-			/*
-			** This can happen if there is a commit followed
-			** by an exception -- the commit will not reset
-			** the trail.
-			*/
-			DEBUG(printf(
-	""MADITI_trail_cleanup_call_output: already cleaned up (%d)\n"",
-				reason));
-
-		} else {
-
-			DEBUG(printf(
-	""MADITI_trail_cleanup_call_output: cleaning up (%d)\n"",
-				reason));
-
-			MADITI_cleanup_call_output(cleanup_data->output_rel,
-				cleanup_data->output_cursor);
-			cleanup_data->cleaned_up = TRUE;
-		}
-		break;
-
-	    case MR_solve:
-	    case MR_undo:
-		/*
-		** Undo on backtracking will be handled by
-		** MADITI_post_call_cleanup, so that the 
-		** cleanup will happen even if trailing
-		** is not being used.
-		*/
-		break;
-
-	    case MR_gc:
-	    default:
-		MR_fatal_error(""MADITI_trail_cleanup_call_output"");
-	}
-}
-#endif /* MR_USE_TRAIL */
-
 /* 
 ** Given an RL procedure name, the schema of the input relation and a tuple
 ** to insert into the input relation, run the procedure, returning a ticket
@@ -905,7 +852,7 @@
 	DEBUG(printf(""running procedure... ""));
 	/* XXX MR_GC_NEW_ATOMIC */
 	output_ticket = (ticket *) MR_GC_NEW(ticket);
-	MADITI_check(ADITI_NAME(run2_s)(proc_name, 100000, &MADITI_ticket,
+	MADITI_check(ADITI_NAME(run2_s)(proc_name, 0, &MADITI_ticket,
 		&input_ticket, output_ticket));
 	DEBUG(printf(""done\\n""));
 
@@ -923,6 +870,28 @@
 	return output_ticket;
 }
 
+static void 
+MADITI_list_rel(ticket* rel)
+{
+	size_t len;
+	char* ptr;
+	ticket cur;
+
+	MADITI_check(ADITI_NAME(tmp_cursor_create)(rel,&cur));
+	MADITI_check(ADITI_NAME(cursor_open)(&cur,CUR_FORWARD));
+	len = 0;
+	ptr = NULL;
+	fflush(stdout);
+	while (ADITI_NAME(cursor_next)(&cur,&len,&ptr) == ADITI_OK) {
+		fprintf(stdout,""tuple: [%.*s]\n"",(int)len,ptr);
+		free(ptr);
+		len = 0;
+		ptr = NULL;
+	}
+	MADITI_check(ADITI_NAME(cursor_close)(&cur));
+	MADITI_check(ADITI_NAME(cursor_destroy)(&cur));
+}
+
 /*---------------------------------------------------------------------------*/
 
 static void
@@ -967,7 +936,9 @@
 		input_args[i] = virtual_reg(first_input_reg + rel_arity + i);
 	}
 
+	save_transient_registers();
 	tuple = MADITI_construct_tuple(rel_arity, input_typeinfos, input_args);
+	restore_transient_registers();
 
 	MR_GC_free(input_args);
 	MR_GC_free(input_typeinfos);
@@ -976,6 +947,7 @@
 		case MADITI_INSERT_TUPLE:
 			DEBUG(printf(""inserting tuple %s\\n"", tuple));
 			MADITI_check(ADITI_NAME(addtup)(rel_name, tuple));
+			DEBUG(printf(""finished insertion\\n""));
 			break;
 		case MADITI_DELETE_TUPLE:
 			DEBUG(printf(""deleting tuple %s\\n"", tuple));
@@ -985,8 +957,11 @@
 			MADITI_check(ADITI_NAME(rel_close)(
 				delete_output_rel));
 			MR_GC_free(delete_output_rel);
+			DEBUG(printf(""finished deletion\\n""));
 			break;
 	}
+
+	save_transient_registers();
 }
 
 /*---------------------------------------------------------------------------*/
@@ -1047,69 +1022,37 @@
 	input_typeinfos =
 		(Word *) closure->MR_closure_layout->arg_pseudo_type_info;
 
+	/*
+	** Call the query to compute the tuples to insert/delete/modify.
+	*/
+	save_transient_registers();
 	input_tuple = MADITI_construct_tuple(num_input_args,
 				input_typeinfos, input_args);
+	restore_transient_registers();
 
 	call_result_ticket = MADITI_run_procedure(called_proc_name,
 				input_schema, input_tuple);
 
-	switch (operation) {
-		case MADITI_INSERT:
-			DEBUG(printf(""Inserting tuples into %s\\n"",
-				rel_name));	
-
-			MADITI_check(ADITI_NAME(perm_open)(&MADITI_ticket,
-					rel_name, &modified_rel_ticket));
-			MADITI_check(ADITI_NAME(add_tups_to)(
-					call_result_ticket,
-					&modified_rel_ticket));
-			MADITI_check(ADITI_NAME(perm_close)(
-					&modified_rel_ticket));
-			break;
-
-		case MADITI_DELETE:
-		case MADITI_MODIFY:
-			DEBUG(printf(""Doing delete/modify of %s\n"",
-				rel_name));
-			MADITI_check(ADITI_NAME(run2_s)(update_proc_name,
-				100000, &MADITI_ticket,
-				call_result_ticket, &dummy_output_ticket)
-			);
-			MADITI_check(
-				ADITI_NAME(rel_close)(&dummy_output_ticket)
-			);
-			break;
-	}
-
+	/*
+	** Call the procedure generated by the compiler to apply the update.
+	*/
+	DEBUG(printf(""Query finished -- calling update procedure %s\\n"",
+		update_proc_name));
+	MADITI_check(ADITI_NAME(run2_s)(update_proc_name,
+		0, &MADITI_ticket, call_result_ticket,
+		&dummy_output_ticket)
+	);
 
+	/*
+	** Clean up.
+	*/
+	MADITI_check(ADITI_NAME(rel_close)(&dummy_output_ticket));
 	MADITI_check(ADITI_NAME(rel_close)(call_result_ticket));
 	MR_GC_free(call_result_ticket);
 
 	save_transient_registers();
 }
 
-static void 
-MADITI_list_rel(ticket* rel)
-{
-	size_t len;
-	char* ptr;
-	ticket cur;
-
-	MADITI_check(ADITI_NAME(tmp_cursor_create)(rel,&cur));
-	MADITI_check(ADITI_NAME(cursor_open)(&cur,CUR_FORWARD));
-	len = 0;
-	ptr = NULL;
-	fflush(stdout);
-	while (ADITI_NAME(cursor_next)(&cur,&len,&ptr) == ADITI_OK) {
-		fprintf(stdout,""tuple: [%.*s]\n"",(int)len,ptr);
-		free(ptr);
-		len = 0;
-		ptr = NULL;
-	}
-	MADITI_check(ADITI_NAME(cursor_close)(&cur));
-	MADITI_check(ADITI_NAME(cursor_destroy)(&cur));
-}
-
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -1128,6 +1071,7 @@
 		*/
 	Word tuple_list; 
 	Word new_tuple_list;
+	Code *saved_succip;
 
 	String tuple;
 	int i;
@@ -1138,8 +1082,12 @@
 	** This part calls back into Mercury to construct the tuple.
 	** The wrapper functions expect the registers to be saved,
 	** so do that here.
+	** MR_succip may be clobbered by the called code, so
+	** it must be saved and restored here.
 	*/
+	saved_succip = MR_succip;
 	save_registers();
+
 	tuple_list = MR_list_empty();
 	DEBUG(printf(""building input tuple...""));
 	for (i = 0; i < num_input_args; i++) {
@@ -1151,6 +1099,13 @@
 	MADITI__reverse_append_string_list(tuple_list, &tuple);
 	DEBUG(printf(""done: tuple = %s\\n"", tuple));
 
+	/*
+	** Get back the updated Mercury registers after the calls into Mercury.
+	*/
+	restore_registers();
+	MR_succip = saved_succip;
+	save_transient_registers();
+	
 	return tuple;
 }
 
@@ -1174,28 +1129,29 @@
 	String tuple_str_copy;
 	Word arg;
 	int found_result;
-	ticket *output_cursor;
-	int num_output_args;
+	MADITI_output_info *output_info;
 	int rc;
 		/* Somewhere to put the output arguments before copying them
 		** into the registers.
 		*/
 	Word *output_save_area;
+	Code *saved_succip;
 
 	restore_transient_registers();
-	num_output_args = MADITI_saved_num_output_args;
-	output_cursor = (ticket *)MADITI_saved_cursor;
+	
+	output_info = (MADITI_output_info *) MADITI_saved_output_info;
 
 	/* advance cursor, get tuple string */
 	DEBUG(printf(""getting output tuple\\n""));
-	rc = ADITI_NAME(cursor_next)(output_cursor,
+	rc = ADITI_NAME(cursor_next)(output_info->output_cursor,
 		&tuple_str_len, &tuple_str);
 	if (rc != ADITI_OK) {
 		DEBUG(printf(""no more output tuples\\n""));
 		found_result = FALSE;
 	} else {
 		DEBUG(printf(""handling tuple %s %ld %d\\n"",
-			tuple_str, tuple_str_len, num_output_args));
+			tuple_str, tuple_str_len,
+			output_info->num_output_args));
 
 		/*
 		** Found another output tuple.
@@ -1210,18 +1166,22 @@
 		** Allocate some space to hold the output arguments
 		** before we put them in registers. 
 		*/
-		output_save_area = MR_GC_NEW_ARRAY(Word, num_output_args);
+		output_save_area = MR_GC_NEW_ARRAY(Word,
+					output_info->num_output_args);
 	
 		/*
 		** This part calls back into Mercury to parse the
 		** tuple terms from the string returned from Aditi.
 		** The wrapper functions generated expect the registers
 		** to be saved, so do that here.
+		** MR_succip may be clobbered by the called code, so
+		** it must be saved and restored here.
 		*/
+		saved_succip = MR_succip;
 		save_registers();
 		/* convert tuple, put output args in stack slots */
 		MADITI__init_posn(&pos);
-		for (i = 0; i < num_output_args; i++) {
+		for (i = 0; i < output_info->num_output_args; i++) {
 			Word status;
 
 			MADITI__read_attr_from_string(
@@ -1235,10 +1195,11 @@
 		}
 
 		/* Move the output arguments to their registers. */
-		for (i = 0; i < num_output_args; i++) {
+		for (i = 0; i < output_info->num_output_args; i++) {
 			virtual_reg(first_reg + i) = output_save_area[i];
 		}
 		restore_registers();
+		MR_succip = saved_succip;
 		MR_GC_free(output_save_area);
 
 		found_result = TRUE;
@@ -1256,24 +1217,86 @@
 MADITI_post_call_cleanup(void)
 { 
 	restore_transient_registers();
-	MADITI_cleanup_call_output((ticket *) MADITI_saved_output_rel,
-		(ticket *) MADITI_saved_cursor);
+	MADITI_cleanup_call_output(
+		(MADITI_output_info *) MADITI_saved_output_info);
 	save_transient_registers();
 }
 
+#ifdef MR_USE_TRAIL
 static void
-MADITI_cleanup_call_output(ticket *output_rel, ticket *cursor)
+MADITI_trail_cleanup_call_output(void *data, MR_untrail_reason reason)
 {
-	/* close cursor */
-	MADITI_check(ADITI_NAME(cursor_close)(cursor));
+	switch (reason) {
+	    case MR_commit:
+	    case MR_exception:
+	    case MR_retry:
+		/*
+		** Clean up the output relation.
+		*/
+		DEBUG(printf(
+		    ""MADITI_trail_cleanup_call_output: cleaning up %d\\n"",
+		    reason));
+		MADITI_cleanup_call_output((MADITI_output_info *)data);
+		break;
 
-	/* destroy cursor */
-	MADITI_check(ADITI_NAME(cursor_destroy)(cursor));
-	MR_GC_free(cursor);
-
-	/* close output temporary */
-	MADITI_check(ADITI_NAME(rel_close)(output_rel));
-	MR_GC_free(output_rel);
+	    case MR_solve:
+	    case MR_undo:
+		/*
+		** Undo on backtracking will be handled by
+		** MADITI_post_call_cleanup, so that the 
+		** cleanup will happen even if trailing
+		** is not being used.
+		*/
+		break;
+
+	    case MR_gc:
+	    default:
+		fatal_error(""MADITI_trail_cleanup_call_output"");
+	}
+}
+#endif /* MR_USE_TRAIL */
+
+static void
+MADITI_cleanup_call_output(MADITI_output_info *output_info)
+{
+	if (output_info->cleaned_up) {
+
+		/*
+		** This can happen if there is a commit followed
+		** by an exception -- the commit will not reset
+		** the trail.
+		*/
+		DEBUG(printf(
+			""MADITI_cleanup_call_output: already cleaned up\n""
+		));
+
+	} else {
+
+		DEBUG(printf(
+			""MADITI_cleanup_call_output: cleaning up\n""
+		));
+
+		/* close cursor */
+		DEBUG(printf(""closing cursor\\n""));
+		MADITI_check(
+			ADITI_NAME(cursor_close)(output_info->output_cursor)
+		);
+
+		/* destroy cursor */
+		DEBUG(printf(""destroying cursor\\n""));
+		MADITI_check(
+			ADITI_NAME(cursor_destroy)(output_info->output_cursor)
+		);
+		MR_GC_free(output_info->output_cursor);
+
+		/* close output temporary */
+		DEBUG(printf(""closing output temporary relation\\n""));
+		MADITI_check(ADITI_NAME(rel_close)(output_info->output_rel));
+		MR_GC_free(output_info->output_rel);
+
+		/* Make sure we don't do this again. */
+		output_info->cleaned_up = TRUE;
+	}
 }
 
 /*---------------------------------------------------------------------------*/
@@ -1287,6 +1310,7 @@
 	if (status != ADITI_OK) {
 		DEBUG(printf(""aditi.m:%d MADITI_check_failed, status %d\\n"",
 				line, status));
+		MADITI_status = status;
 		MR_longjmp(&MADITI_jmp_buf);
 	}
 }
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list