From 5830bf5ef753fb1d78914a93d1e130b352b27abe Mon Sep 17 00:00:00 2001 From: Janos SUTO Date: Tue, 23 Jan 2018 20:02:50 +0100 Subject: [PATCH] improved error handling for sql insert failures Signed-off-by: Janos SUTO --- src/import.c | 11 +++-- src/message.c | 123 +++++++++++++++++++++++++++----------------------- src/piler.c | 1 + src/piler.h | 1 + 4 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/import.c b/src/import.c index 254a884a..1927301b 100644 --- a/src/import.c +++ b/src/import.c @@ -89,15 +89,18 @@ int import_message(struct session_data *sdata, struct data *data, struct config if(sdata->hdr_len < 10){ printf("%s: invalid message, hdr_len: %d\n", data->import->filename, sdata->hdr_len); - return ERR; + rc = ERR; + } + else { + rc = process_message(sdata, &state, data, cfg); + unlink(state.message_id_hash); } - - rc = process_message(sdata, &state, data, cfg); - unlink(state.message_id_hash); } unlink(sdata->tmpframe); + remove_stripped_attachments(&state); + if(strcmp(data->import->filename, "-") == 0) unlink(sdata->ttmpfile); diff --git a/src/message.c b/src/message.c index cde57ae5..5d0b4563 100644 --- a/src/message.c +++ b/src/message.c @@ -57,10 +57,10 @@ int store_index_data(struct session_data *sdata, struct parser_state *state, str sql.sql[sql.pos] = sdata->attachments; sql.type[sql.pos] = TYPE_STRING; sql.pos++; if(p_exec_stmt(sdata, &sql) == OK) rc = OK; + else syslog(LOG_PRIORITY, "ERROR: %s failed to store index data for id=%llu, sql_errno=%d", sdata->ttmpfile, id, sdata->sql_errno); close_prepared_statement(&sql); - return rc; } @@ -95,11 +95,11 @@ uint64 get_metaid_by_messageid(struct session_data *sdata, struct data *data, ch int store_recipients(struct session_data *sdata, struct data *data, char *to, uint64 id, struct config *cfg){ - int ret=OK, n=0; + int rc=OK, n=0; char *p, *q, puf[SMALLBUFSIZE]; struct sql sql; - if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_INSERT_INTO_RCPT_TABLE) == ERR) return ret; + if(prepare_sql_statement(sdata, &sql, SQL_PREPARED_STMT_INSERT_INTO_RCPT_TABLE) == ERR) return ERR; p = to; do { @@ -117,7 +117,10 @@ int store_recipients(struct session_data *sdata, struct data *data, char *to, ui sql.sql[sql.pos] = q; sql.type[sql.pos] = TYPE_STRING; sql.pos++; if(p_exec_stmt(sdata, &sql) == ERR){ - if(sdata->sql_errno != ER_DUP_ENTRY) ret = ERR; + if(sdata->sql_errno != ER_DUP_ENTRY){ + syslog(LOG_PRIORITY, "ERROR: %s: failed to add '%s' for id=%llu to rcpt table, sql_errno=%d", sdata->ttmpfile, puf, id, sdata->sql_errno); + rc = ERR; + } } else n++; } @@ -126,9 +129,9 @@ int store_recipients(struct session_data *sdata, struct data *data, char *to, ui close_prepared_statement(&sql); - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: added %d recipients", sdata->ttmpfile, n); + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored %d recipients, rc=%d", sdata->ttmpfile, n, rc); - return ret; + return rc; } @@ -141,8 +144,8 @@ void remove_recipients(struct session_data *sdata, uint64 id){ } -int store_folder_id(struct session_data *sdata, struct data *data, uint64 id){ - int rc = ERR; +int store_folder_id(struct session_data *sdata, struct data *data, uint64 id, struct config *cfg){ + int rc=ERR; struct sql sql; if(data->folder == ERR_FOLDER) return rc; @@ -157,19 +160,12 @@ int store_folder_id(struct session_data *sdata, struct data *data, uint64 id){ if(p_exec_stmt(sdata, &sql) == OK) rc = OK; close_prepared_statement(&sql); + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored folderdata, rc=%d", sdata->ttmpfile, rc); + return rc; } -void remove_folder_id(struct session_data *sdata, uint64 id){ - char s[SMALLBUFSIZE]; - - snprintf(s, sizeof(s)-1, "DELETE FROM " SQL_FOLDER_MESSAGE_TABLE " WHERE id=%llu", id); - - p_query(sdata, s); -} - - int update_metadata_reference(struct session_data *sdata, struct parser_state *state, struct data *data, char *ref, struct config *cfg){ int ret = ERR; struct sql sql; @@ -192,7 +188,7 @@ int update_metadata_reference(struct session_data *sdata, struct parser_state *s int store_meta_data(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg){ - int rc, ret=ERR, result; + int rc=ERR, result; char *subj, *p, s[MAXBUFSIZE], s2[SMALLBUFSIZE], vcode[2*DIGEST_LENGTH+1], ref[2*DIGEST_LENGTH+1]; uint64 id=0; struct sql sql; @@ -251,30 +247,62 @@ int store_meta_data(struct session_data *sdata, struct parser_state *state, stru sql.sql[sql.pos] = sdata->bodydigest; sql.type[sql.pos] = TYPE_STRING; sql.pos++; sql.sql[sql.pos] = &vcode[0]; sql.type[sql.pos] = TYPE_STRING; sql.pos++; - if(p_exec_stmt(sdata, &sql) == ERR){ - ret = ERR_EXISTS; - } - else { + if(p_exec_stmt(sdata, &sql) == OK){ id = p_get_insert_id(&sql); - rc = store_recipients(sdata, data, state->b_to, id, cfg); - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored recipients, rc=%d", sdata->ttmpfile, rc); + if(store_recipients(sdata, data, state->b_to, id, cfg) == OK){ - rc = store_index_data(sdata, state, data, id, cfg); + if(store_index_data(sdata, state, data, id, cfg) == OK) rc = OK; - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored indexdata, rc=%d", sdata->ttmpfile, rc); - - if(cfg->enable_folders == 1){ - rc = store_folder_id(sdata, data, id); - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored folderdata, rc=%d", sdata->ttmpfile, rc); + if(cfg->enable_folders == 1){ + rc = store_folder_id(sdata, data, id, cfg); + } } - ret = OK; + // There were some sql errors, so we should rollback everything + if(rc == ERR){ + rollback(sdata, state, id, cfg); + } + + } + else { + syslog(LOG_PRIORITY, "ERROR: %s storing metadata, sql_errno=%d", sdata->ttmpfile, sdata->sql_errno); } close_prepared_statement(&sql); - return ret; + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored metadata, rc=%d", sdata->ttmpfile, rc); + + return rc; +} + + +void rollback(struct session_data *sdata, struct parser_state *state, uint64 id, struct config *cfg){ + char buf[SMALLBUFSIZE]; + + snprintf(buf, sizeof(buf)-2, "DELETE FROM %s WHERE id=%llu", SQL_SPHINX_TABLE, id); + p_query(sdata, buf); + syslog(LOG_PRIORITY, "ERROR: %s: rollback sql stmt=%s", sdata->ttmpfile, buf); + + snprintf(buf, sizeof(buf)-2, "DELETE FROM %s WHERE id=%llu", SQL_RECIPIENT_TABLE, id); + p_query(sdata, buf); + syslog(LOG_PRIORITY, "ERROR: %s: rollback sql stmt=%s", sdata->ttmpfile, buf); + + snprintf(buf, sizeof(buf)-2, "DELETE FROM %s WHERE id=%llu", SQL_METADATA_TABLE, id); + p_query(sdata, buf); + syslog(LOG_PRIORITY, "ERROR: %s: rollback sql stmt=%s", sdata->ttmpfile, buf); + + snprintf(buf, sizeof(buf)-2, "DELETE FROM %s WHERE piler_id='%s'", SQL_ATTACHMENT_TABLE, sdata->ttmpfile); + p_query(sdata, buf); + syslog(LOG_PRIORITY, "ERROR: %s: rollback sql stmt=%s", sdata->ttmpfile, buf); + + if(cfg->enable_folders == 1){ + snprintf(buf, sizeof(buf)-1, "DELETE FROM " SQL_FOLDER_MESSAGE_TABLE " WHERE id=%llu", id); + p_query(sdata, buf); + syslog(LOG_PRIORITY, "ERROR: %s: rollback sql stmt=%s", sdata->ttmpfile, buf); + } + + remove_stored_message_files(sdata, state, cfg); } @@ -286,7 +314,7 @@ void remove_stripped_attachments(struct parser_state *state){ int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg){ - int rc, fd; + int fd; char piler_id[SMALLBUFSIZE]; /* discard if existing message_id */ @@ -330,36 +358,17 @@ int process_message(struct session_data *sdata, struct parser_state *state, stru } + sdata->retained += query_retain_period(data, state, sdata->tot_len, sdata->spam_message, cfg); - /* store base64 encoded file attachments */ - - if(state->n_attachments > 0){ - rc = store_attachments(sdata, state, data, cfg); - - remove_stripped_attachments(state); - - if(rc) return ERR; - } + if(state->n_attachments > 0 && store_attachments(sdata, state, data, cfg) == ERR) return ERR; - rc = store_file(sdata, sdata->tmpframe, 0, cfg); - if(rc == 0){ - syslog(LOG_PRIORITY, "%s: error storing message: %s", sdata->ttmpfile, sdata->tmpframe); + if(store_file(sdata, sdata->tmpframe, 0, cfg) == 0){ + syslog(LOG_PRIORITY, "ERROR: %s: failed to store message: %s", sdata->ttmpfile, sdata->tmpframe); return ERR; } - sdata->retained += query_retain_period(data, state, sdata->tot_len, sdata->spam_message, cfg); - - rc = store_meta_data(sdata, state, data, cfg); - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: stored metadata, rc=%d", sdata->ttmpfile, rc); - if(rc == ERR_EXISTS){ - - remove_stored_message_files(sdata, state, cfg); - - return ERR_EXISTS; - } - - return OK; + return store_meta_data(sdata, state, data, cfg); } diff --git a/src/piler.c b/src/piler.c index 534403a3..99b92b38 100644 --- a/src/piler.c +++ b/src/piler.c @@ -163,6 +163,7 @@ int process_email(char *filename, struct session_data *sdata, struct data *data, unlink(sdata->tmpframe); + remove_stripped_attachments(&parser_state); if(rc == OK){ status = S_STATUS_STORED; diff --git a/src/piler.h b/src/piler.h index cd29103d..3a4b94a5 100644 --- a/src/piler.h +++ b/src/piler.h @@ -40,6 +40,7 @@ void digest_string(char *s, char *digest); void remove_stripped_attachments(struct parser_state *state); int process_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg); +void rollback(struct session_data *sdata, struct parser_state *state, uint64 id, struct config *cfg); int reimport_message(struct session_data *sdata, struct parser_state *state, struct data *data, struct config *cfg); int store_file(struct session_data *sdata, char *filename, int len, struct config *cfg); int remove_stored_message_files(struct session_data *sdata, struct parser_state *state, struct config *cfg);