From 6cf3d1d3fcfeb59527a12803d72728a7ec57fcf3 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Tue, 27 Nov 2007 01:12:29 +0100 Subject: [PATCH] Turned action execution into a transaction. --- src/lib-sieve/cmd-keep.c | 1 + src/lib-sieve/cmd-redirect.c | 19 ++++---- src/lib-sieve/sieve-actions.c | 82 +++++++++++++++++++++++++---------- src/lib-sieve/sieve-actions.h | 15 ++++++- src/lib-sieve/sieve-result.c | 61 +++++++++++++++++++++++--- 5 files changed, 138 insertions(+), 40 deletions(-) diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 13f871757..7a59bc212 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -2,6 +2,7 @@ #include "sieve-commands.h" #include "sieve-commands-private.h" +#include "sieve-actions.h" #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 1dbee6daf..e6c802fae 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -56,9 +56,9 @@ static bool act_redirect_check_duplicate const struct sieve_action *action1, void *context1, void *context2); static void act_redirect_print (const struct sieve_action *action, void *context); -static int act_redirect_execute - (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, - void *context); +static bool act_redirect_commit +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context); struct act_redirect_context { const char *to_address; @@ -69,7 +69,9 @@ const struct sieve_action act_redirect = { act_redirect_check_duplicate, NULL, act_redirect_print, - act_redirect_execute + NULL, NULL, + act_redirect_commit, + NULL }; /* Validation */ @@ -178,12 +180,12 @@ static void act_redirect_print printf("* redirect message to: %s\n", ctx->to_address); } -static int act_redirect_execute +static bool act_redirect_commit (const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv, void *context) + const struct sieve_action_exec_env *aenv, void *tr_context) { const struct sieve_message_data *msgdata = aenv->msgdata; - struct act_redirect_context *ctx = (struct act_redirect_context *) context; + struct act_redirect_context *ctx = (struct act_redirect_context *) tr_context; int res; if ((res = aenv->mailenv-> @@ -191,9 +193,10 @@ static int act_redirect_execute i_info("msgid=%s: forwarded to <%s>", msgdata->id == NULL ? "" : str_sanitize(msgdata->id, 80), str_sanitize(ctx->to_address, 80)); + return TRUE; } - return res; + return FALSE; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index fc11fd911..a62ce74b6 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -14,18 +14,47 @@ static bool act_store_check_duplicate void *context1, void *context2); static void act_store_print (const struct sieve_action *action ATTR_UNUSED, void *context); -static int act_store_execute - (const struct sieve_action *action, const struct sieve_action_exec_env *aenv, - void *context); + +static bool act_store_start + (const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *context, void **tr_context); +static bool act_store_execute + (const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context); +static bool act_store_commit + (const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context); +static void act_store_rollback + (const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context); const struct sieve_action act_store = { "store", act_store_check_duplicate, NULL, act_store_print, - act_store_execute + act_store_start, + act_store_execute, + act_store_commit, + act_store_rollback, }; +bool sieve_act_store_add_to_result +(const struct sieve_runtime_env *renv, const char *folder) +{ + pool_t pool; + struct act_store_context *act; + + /* Add redirect action to the result */ + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_store_context, 1); + act->folder = p_strdup(pool, folder); + + return sieve_result_add_action(renv, &act_store, (void *) act); +} + +/* Store action implementation */ + static bool act_store_check_duplicate (const struct sieve_runtime_env *renv ATTR_UNUSED, const struct sieve_action *action1 ATTR_UNUSED, @@ -48,28 +77,35 @@ static void act_store_print printf("* store message in folder: %s\n", ctx->folder); } -static int act_store_execute +/* Store transaction */ + +static bool act_store_start (const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv, void *context) -{ - const struct sieve_message_data *msgdata = aenv->msgdata; - struct act_store_context *ctx = (struct act_store_context *) context; - int res = 0; - - return res; + const struct sieve_action_exec_env *aenv, void *context, void **tr_context) +{ + return TRUE; } -bool sieve_act_store_add_to_result -(const struct sieve_runtime_env *renv, const char *folder) -{ - pool_t pool; - struct act_store_context *act; - - /* Add redirect action to the result */ - pool = sieve_result_pool(renv->result); - act = p_new(pool, struct act_store_context, 1); - act->folder = p_strdup(pool, folder); +static bool act_store_execute +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context) +{ + return TRUE; +} - return sieve_result_add_action(renv, &act_store, (void *) act); +static bool act_store_commit +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context) +{ + return TRUE; } +static void act_store_rollback +(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context) +{ +} + + + + diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index c76d9cc91..64b298fea 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -21,9 +21,20 @@ struct sieve_action { void (*print) (const struct sieve_action *action, void *context); - int (*execute) + + bool (*start) + (const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *context, + void **tr_context); + bool (*execute) + (const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *tr_context); + bool (*commit) + (const struct sieve_action *action, + const struct sieve_action_exec_env *aenv, void *tr_context); + void (*rollback) (const struct sieve_action *action, - const struct sieve_action_exec_env *aenv, void *context); + const struct sieve_action_exec_env *aenv, void *tr_context); }; /* Actions common to multiple commands */ diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index 07e7efc34..e2b4f71bf 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -11,7 +11,7 @@ struct sieve_result_action { const struct sieve_action *action; void *context; - + void *tr_context; struct sieve_result_action *prev, *next; }; @@ -104,6 +104,7 @@ bool sieve_result_add_action raction = p_new(result->pool, struct sieve_result_action, 1); raction->action = action; raction->context = context; + raction->tr_context = NULL; /* Add */ if ( result->first_action == NULL ) { @@ -146,22 +147,68 @@ bool sieve_result_execute (struct sieve_result *result, const struct sieve_message_data *msgdata, const struct sieve_mail_environment *menv) { - struct sieve_result_action *rac = result->first_action; + bool success = TRUE, commit_ok; + struct sieve_result_action *rac; result->action_env.msgdata = msgdata; result->action_env.mailenv = menv; - printf("\n"); - while ( rac != NULL ) { + /* Transaction start */ + + printf("\nTransaction start:\n"); + + rac = result->first_action; + while ( success && rac != NULL ) { + const struct sieve_action *act = rac->action; + + if ( act->start != NULL ) { + success = success && act->start(act, &result->action_env, rac->context, + &rac->tr_context); + } + rac = rac->next; + } + + /* Transaction execute */ + + printf("\nTransaction execute:\n"); + + rac = result->first_action; + while ( success && rac != NULL ) { const struct sieve_action *act = rac->action; if ( act->execute != NULL ) { - (void) act->execute(act, &result->action_env, rac->context); + void *context = rac->tr_context == NULL ? + rac->context : rac->tr_context; + + success = success && act->execute(act, &result->action_env, context); + } + rac = rac->next; + } + + /* Transaction commit/rollback */ + if ( success ) + printf("\nTransaction commit:\n"); + else + printf("\nTransaction rollback:\n"); + + commit_ok = success; + rac = result->first_action; + while ( rac != NULL ) { + const struct sieve_action *act = rac->action; + 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; } else { - i_warning("Action %s performs absolutely nothing.", act->name); + if ( act->rollback != NULL ) + act->rollback(act, &result->action_env, context); } rac = rac->next; } - return TRUE; + printf("\nTransaction result: %s\n", commit_ok ? "success" : "failed"); + + return commit_ok; } -- GitLab