changeset 20530:1d5136f4f27c

lib-dict: Added DICT_COMMIT_RET_WRITE_UNCERTAIN
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sat, 16 Jul 2016 11:30:39 -0500
parents 6450eb09e83c
children 048ff0f4651d
files src/dict/dict-commands.c src/lib-dict/dict-client.c src/lib-dict/dict-client.h src/lib-dict/dict-sql.c src/lib-dict/dict.h
diffstat 5 files changed, 46 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/dict/dict-commands.c	Sun Jul 17 12:37:06 2016 -0600
+++ b/src/dict/dict-commands.c	Sat Jul 16 11:30:39 2016 -0500
@@ -296,6 +296,10 @@
 	case 0:
 		chr = DICT_PROTOCOL_REPLY_NOTFOUND;
 		break;
+	case DICT_COMMIT_RET_WRITE_UNCERTAIN:
+		chr = DICT_PROTOCOL_REPLY_WRITE_UNCERTAIN;
+		break;
+	case DICT_COMMIT_RET_FAILED:
 	default:
 		chr = DICT_PROTOCOL_REPLY_FAIL;
 		break;
--- a/src/lib-dict/dict-client.c	Sun Jul 17 12:37:06 2016 -0600
+++ b/src/lib-dict/dict-client.c	Sat Jul 16 11:30:39 2016 -0500
@@ -40,7 +40,8 @@
 	bool background;
 
 	void (*callback)(struct client_dict_cmd *cmd,
-			 const char *line, const char *error);
+			 const char *line, const char *error,
+			 bool disconnected);
         struct client_dict_iterate_context *iter;
 
 	struct {
@@ -168,16 +169,17 @@
 dict_cmd_callback_line(struct client_dict_cmd *cmd, const char *line)
 {
 	cmd->unfinished = FALSE;
-	cmd->callback(cmd, line, NULL);
+	cmd->callback(cmd, line, NULL, FALSE);
 	return !cmd->unfinished;
 }
 
 static void
-dict_cmd_callback_error(struct client_dict_cmd *cmd, const char *error)
+dict_cmd_callback_error(struct client_dict_cmd *cmd, const char *error,
+			bool disconnected)
 {
 	cmd->unfinished = FALSE;
 	if (cmd->callback != NULL)
-		cmd->callback(cmd, NULL, error);
+		cmd->callback(cmd, NULL, error, disconnected);
 	i_assert(!cmd->unfinished);
 }
 
@@ -252,7 +254,8 @@
 		return TRUE;
 	} else if (ret < 0) {
 		i_assert(error != NULL);
-		dict_cmd_callback_error(cmd, error);
+		/* we didn't successfully send this command to dict */
+		dict_cmd_callback_error(cmd, error, FALSE);
 		client_dict_cmd_unref(cmd);
 		if (error_r != NULL)
 			*error_r = error;
@@ -443,7 +446,7 @@
 	array_clear(&dict->cmds);
 
 	array_foreach(&cmds_copy, cmdp) {
-		dict_cmd_callback_error(*cmdp, reason);
+		dict_cmd_callback_error(*cmdp, reason, TRUE);
 		client_dict_cmd_unref(*cmdp);
 	}
 }
@@ -609,7 +612,7 @@
 
 static void
 client_dict_lookup_async_callback(struct client_dict_cmd *cmd, const char *line,
-				  const char *error)
+				  const char *error, bool disconnected ATTR_UNUSED)
 {
 	struct client_dict *dict = cmd->dict;
 	struct dict_lookup_result result;
@@ -726,7 +729,7 @@
 
 static void
 client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line,
-				const char *error)
+				const char *error, bool disconnected ATTR_UNUSED)
 {
 	struct client_dict_iterate_context *ctx = cmd->iter;
 	struct client_dict *dict = cmd->dict;
@@ -888,7 +891,8 @@
 
 static void
 client_dict_transaction_commit_callback(struct client_dict_cmd *cmd,
-					const char *line, const char *error)
+					const char *line, const char *error,
+					bool disconnected)
 {
 	struct client_dict *dict = cmd->dict;
 	int ret = -1;
@@ -896,6 +900,8 @@
 	if (error != NULL) {
 		/* failed */
 		i_error("dict-client: Commit failed: %s", error);
+		if (disconnected)
+			ret = DICT_COMMIT_RET_WRITE_UNCERTAIN;
 	} else switch (*line) {
 	case DICT_PROTOCOL_REPLY_OK:
 		ret = 1;
@@ -903,6 +909,9 @@
 	case DICT_PROTOCOL_REPLY_NOTFOUND:
 		ret = 0;
 		break;
+	case DICT_PROTOCOL_REPLY_WRITE_UNCERTAIN:
+		ret = DICT_COMMIT_RET_WRITE_UNCERTAIN;
+		/* fallthrough */
 	case DICT_PROTOCOL_REPLY_FAIL: {
 		const char *error = strchr(line+1, '\t');
 
--- a/src/lib-dict/dict-client.h	Sun Jul 17 12:37:06 2016 -0600
+++ b/src/lib-dict/dict-client.h	Sat Jul 16 11:30:39 2016 -0500
@@ -32,6 +32,7 @@
 	DICT_PROTOCOL_REPLY_OK = 'O', /* <value> */
 	DICT_PROTOCOL_REPLY_NOTFOUND = 'N',
 	DICT_PROTOCOL_REPLY_FAIL = 'F',
+	DICT_PROTOCOL_REPLY_WRITE_UNCERTAIN = 'W',
 	DICT_PROTOCOL_REPLY_ASYNC_COMMIT = 'A'
 };
 
--- a/src/lib-dict/dict-sql.c	Sun Jul 17 12:37:06 2016 -0600
+++ b/src/lib-dict/dict-sql.c	Sat Jul 16 11:30:39 2016 -0500
@@ -807,16 +807,24 @@
 }
 
 static void
-sql_dict_transaction_commit_callback(const char *error,
+sql_dict_transaction_commit_callback(const struct sql_commit_result *sql_result,
 				     struct sql_dict_transaction_context *ctx)
 {
 	int ret;
 
-	if (error == NULL)
+	if (sql_result->error == NULL)
 		ret = sql_dict_transaction_has_nonexistent(ctx) ? 0 : 1;
 	else {
-		i_error("sql dict: commit failed: %s", error);
-		ret = -1;
+		i_error("sql dict: commit failed: %s", sql_result->error);
+		switch (sql_result->error_type) {
+		case SQL_RESULT_ERROR_TYPE_UNKNOWN:
+		default:
+			ret = DICT_COMMIT_RET_FAILED;
+			break;
+		case SQL_RESULT_ERROR_TYPE_WRITE_UNCERTAIN:
+			ret = DICT_COMMIT_RET_WRITE_UNCERTAIN;
+			break;
+		}
 	}
 
 	if (ctx->async_callback != NULL)
@@ -846,7 +854,7 @@
 	} else if (async) {
 		ctx->async_callback = callback;
 		ctx->async_context = context;
-		sql_transaction_commit(&ctx->sql_ctx,
+		sql_transaction_commit2(&ctx->sql_ctx,
 			sql_dict_transaction_commit_callback, ctx);
 		return 1;
 	} else {
--- a/src/lib-dict/dict.h	Sun Jul 17 12:37:06 2016 -0600
+++ b/src/lib-dict/dict.h	Sat Jul 16 11:30:39 2016 -0500
@@ -44,9 +44,19 @@
 	const char *error;
 };
 
+enum dict_commit_ret {
+	DICT_COMMIT_RET_OK = 1,
+	DICT_COMMIT_RET_NOTFOUND = 0,
+	DICT_COMMIT_RET_FAILED = -1,
+	/* write may or may not have succeeded (e.g. write timeout or
+	   disconnected from server) */
+	DICT_COMMIT_RET_WRITE_UNCERTAIN = -2,
+};
+
 typedef void dict_lookup_callback_t(const struct dict_lookup_result *result,
 				    void *context);
 typedef void dict_iterate_callback_t(void *context);
+/* ret = enum dict_commit_ret */
 typedef void dict_transaction_commit_callback_t(int ret, void *context);
 
 void dict_driver_register(struct dict *driver);