From 317b1d33ffa3c088856b4e39d80f6feb82f101e2 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Wed, 28 Nov 2007 20:28:21 +0100
Subject: [PATCH] Added untested support for side effects to result object.

---
 src/lib-sieve/sieve-actions.h | 22 +++++++++
 src/lib-sieve/sieve-common.h  |  1 +
 src/lib-sieve/sieve-result.c  | 93 +++++++++++++++++++++++++++++++++--
 src/lib-sieve/sieve-result.h  |  5 ++
 4 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index f7dd0cde9..8371e8009 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -41,6 +41,28 @@ struct sieve_action {
 			const struct sieve_action_exec_env *aenv, void *tr_context, bool success);
 };
 
+struct sieve_side_effect {
+	const char *name;
+	const struct sieve_action *to_action;
+	
+	bool (*pre_execute)
+		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void **se_context, 
+			void *tr_context);
+	bool (*post_execute)
+		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void *se_context, 
+			void *tr_context);
+	bool (*post_commit)
+		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void *se_context,
+			void *tr_context);
+	void (*rollback)
+		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void *se_context,
+			void *tr_context, bool success);
+};
+
 /* Actions common to multiple commands */
 
 const struct sieve_action act_store;
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index cd664b43c..92bba80e7 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -77,5 +77,6 @@ struct sieve_result;
 /* sieve-actions.h */
 struct sieve_action_exec_env;
 struct sieve_action;
+struct sieve_side_effect;
 
 #endif /* __SIEVE_COMMON_H */
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 369cdc356..2e1dabadc 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -9,11 +9,21 @@
 #include <stdio.h>
 
 struct sieve_result_action {
+	struct sieve_result *result;
 	const struct sieve_action *action;
 	void *context;
 	void *tr_context;
 	bool success;
 	struct sieve_result_action *prev, *next; 
+
+	struct sieve_result_side_effect *first_effect;
+	struct sieve_result_side_effect *last_effect;
+};
+
+struct sieve_result_side_effect {
+	const struct sieve_side_effect *seffect;
+	void *context;
+	struct sieve_result_side_effect *prev, *next; 
 };
 
 struct sieve_result {
@@ -104,6 +114,7 @@ bool sieve_result_add_action
 		
 	/* Create new action object */
 	raction = p_new(result->pool, struct sieve_result_action, 1);
+	raction->result = result;
 	raction->action = action;
 	raction->context = context;
 	raction->tr_context = NULL;
@@ -125,6 +136,33 @@ bool sieve_result_add_action
 	return TRUE;
 }	
 
+bool sieve_result_add_side_effect
+(struct sieve_result_action *raction, const struct sieve_side_effect *seffect, 
+	void *context)		
+{
+	struct sieve_result_side_effect *reffect;
+	
+	/* Create new action object */
+	reffect = p_new(raction->result->pool, struct sieve_result_side_effect, 1);
+	reffect->seffect = seffect;
+	reffect->context = context;
+	
+	/* Add */
+	if ( raction->first_effect == NULL ) {
+		raction->first_effect = reffect;
+		raction->last_effect = reffect;
+		reffect->prev = NULL;
+		reffect->next = NULL;
+	} else {
+		raction->last_effect->next = reffect;
+		reffect->prev = raction->last_effect;
+		raction->last_effect = reffect;
+		reffect->next = NULL;
+	}	
+	
+	return TRUE;
+}	
+
 bool sieve_result_print(struct sieve_result *result)
 {
 	struct sieve_result_action *rac = result->first_action;
@@ -154,7 +192,6 @@ bool sieve_result_execute
 	struct sieve_result_action *rac;
 	struct sieve_result_action *last_attempted;
 
-	
 	result->action_env.msgdata = msgdata;
 	result->action_env.mailenv = menv;
 	
@@ -182,14 +219,37 @@ bool sieve_result_execute
 	rac = result->first_action;
 	while ( success && rac != NULL ) {
 		const struct sieve_action *act = rac->action;
+		struct sieve_result_side_effect *rsef;
+		const struct sieve_side_effect *sef;
+		void *context = rac->tr_context == NULL ? 
+				rac->context : rac->tr_context;
+		
+		/* Execute pre-execute event of side effects */
+		rsef = rac->first_effect;
+		while ( rsef != NULL ) {
+			sef = rsef->seffect;
+			if ( sef->pre_execute != NULL ) 
+				sef->pre_execute
+					(sef, act, &result->action_env, &rsef->context, context);
+			rsef = rsef->next;
+		}
 	
+		/* Execute the action itself */
 		if ( act->execute != NULL ) {
-			void *context = rac->tr_context == NULL ? 
-				rac->context : rac->tr_context;
-				
 			rac->success = act->execute(act, &result->action_env, context);
 			success = success && rac->success;
-		} 
+		}
+		
+		/* Execute pre-execute event of side effects */
+		rsef = rac->first_effect;
+		while ( rsef != NULL ) {
+			sef = rsef->seffect;
+			if ( sef->post_execute != NULL ) 
+				sef->post_execute
+					(sef, act, &result->action_env, rsef->context, context);
+			rsef = rsef->next;
+		}
+		 
 		rac = rac->next;	
 	}
 	
@@ -203,15 +263,38 @@ bool sieve_result_execute
 	rac = result->first_action;
 	while ( rac != NULL && rac != last_attempted ) {
 		const struct sieve_action *act = rac->action;
+		struct sieve_result_side_effect *rsef;
+		const struct sieve_side_effect *sef;
 		void *context = rac->tr_context == NULL ? 
 				rac->context : rac->tr_context;
 		
 		if ( success ) {
 			if ( act->commit != NULL ) 
 				commit_ok = act->commit(act, &result->action_env, context) && commit_ok;
+	
+			/* Execute post_commit event of side effects */
+			rsef = rac->first_effect;
+			while ( rsef != NULL ) {
+				sef = rsef->seffect;
+				if ( sef->post_commit != NULL ) 
+					sef->post_commit
+						(sef, act, &result->action_env, rsef->context, context);
+				rsef = rsef->next;
+			}
 		} else {
 			if ( act->rollback != NULL ) 
 				act->rollback(act, &result->action_env, context, rac->success);
+				
+			/* Rollback side effects */
+			rsef = rac->first_effect;
+			while ( rsef != NULL ) {
+				sef = rsef->seffect;
+				if ( sef->rollback != NULL ) 
+					sef->rollback
+						(sef, act, &result->action_env, rsef->context, context, 
+						rac->success);
+				rsef = rsef->next;
+			}
 		}
 		rac = rac->next;	
 	}
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 46c01a04c..f32266846 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -5,6 +5,8 @@
 
 struct sieve_result;
 
+struct sieve_result_action;
+
 struct sieve_result *sieve_result_create(void);
 void sieve_result_ref(struct sieve_result *result); 
 void sieve_result_unref(struct sieve_result **result); 
@@ -13,6 +15,9 @@ inline pool_t sieve_result_pool(struct sieve_result *result);
 bool sieve_result_add_action
 (const struct sieve_runtime_env *renv, const struct sieve_action *action, 
 	void *context);	
+bool sieve_result_add_side_effect
+(struct sieve_result_action *raction, const struct sieve_side_effect *seffect, 
+	void *context);
 
 bool sieve_result_print(struct sieve_result *result);
 
-- 
GitLab