static int cmd_deduplicate_box(struct doveadm_mail_cmd_context *_ctx, const struct mailbox_info *info, struct mail_search_args *search_args) { struct deduplicate_cmd_context *ctx = (struct deduplicate_cmd_context *)_ctx; struct doveadm_mail_iter *iter; struct mailbox *box; struct mail *mail; enum mail_error error; pool_t pool; HASH_TABLE(const char *, struct uidlist *) hash; const char *key, *errstr; struct uidlist *value; int ret = 0; if (doveadm_mail_iter_init(_ctx, info, search_args, 0, NULL, &iter) < 0) return -1; pool = pool_alloconly_create("deduplicate", 10240); hash_table_create(&hash, pool, 0, str_hash, strcmp); while (doveadm_mail_iter_next(iter, &mail)) { if (ctx->by_msgid) { if (mail_get_first_header(mail, "Message-ID", &key) < 0) { errstr = mailbox_get_last_error(mail->box, &error); if (error == MAIL_ERROR_NOTFOUND) continue; i_error("Couldn't lookup Message-ID: for UID=%u: %s", mail->uid, errstr); doveadm_mail_failed_error(_ctx, error); ret = -1; break; } } else { if (mail_get_special(mail, MAIL_FETCH_GUID, &key) < 0) { errstr = mailbox_get_last_error(mail->box, &error); if (error == MAIL_ERROR_NOTFOUND) continue; i_error("Couldn't lookup GUID: for UID=%u: %s", mail->uid, errstr); doveadm_mail_failed_error(_ctx, error); ret = -1; break; } } if (key != NULL && *key != '\0') { value = p_new(pool, struct uidlist, 1); value->uid = mail->uid; value->next = hash_table_lookup(hash, key); if (value->next == NULL) { key = p_strdup(pool, key); hash_table_insert(hash, key, value); } else { hash_table_update(hash, key, value); } } }
const char *str_table_ref(struct str_table *table, const char *str) { char *key; void *value; unsigned int ref; if (!hash_table_lookup_full(table->hash, str, &key, &value)) { key = i_strdup(str); ref = 1; } else { ref = POINTER_CAST_TO(value, unsigned int); i_assert(ref > 0); ref++; } hash_table_update(table->hash, key, POINTER_CAST(ref)); return key; }
void str_table_unref(struct str_table *table, const char **str) { char *key; void *value; unsigned int ref; if (!hash_table_lookup_full(table->hash, *str, &key, &value)) i_unreached(); ref = POINTER_CAST_TO(value, unsigned int); i_assert(ref > 0); if (--ref > 0) hash_table_update(table->hash, key, POINTER_CAST(ref)); else { hash_table_remove(table->hash, key); i_free(key); } *str = NULL; }
static void stats_read(struct top_context *ctx) { struct top_line *old_line, *line; unsigned int i; char **args; /* read lines */ while ((args = p_read_next_line(ctx->cur_pool, ctx->input)) != NULL) { if (args[0] == NULL) { /* end of stats */ return; } if (str_array_length((void *)args) != ctx->headers_count) i_fatal("read(%s): invalid stats line", ctx->path); line = p_new(ctx->cur_pool, struct top_line, 1); line->id = args[0]; line->flip = ctx->flip; line->cur_values = p_new(ctx->cur_pool, const char *, ctx->headers_count); for (i = 0; i < ctx->headers_count; i++) line->cur_values[i] = args[i]; old_line = hash_table_lookup(ctx->sessions, line->id); if (old_line != NULL) { stats_line_set_prev_values(ctx, old_line, line); array_append(&ctx->lines, &line, 1); } hash_table_update(ctx->sessions, line->id, line); } if (ctx->input->stream_errno != 0) { i_fatal("read(%s) failed: %s", ctx->path, i_stream_get_error(ctx->input)); } i_fatal("read(%s): unexpected EOF", ctx->path); }