From 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf Mon Sep 17 00:00:00 2001 From: zautrix Date: Fri, 18 Mar 2005 20:17:03 +0000 Subject: Initial revision --- (limited to 'libetpan/src/driver/implementation/nntp/nntpdriver_cached.c') diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c new file mode 100644 index 0000000..5c29b7b --- a/dev/null +++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c @@ -0,0 +1,1059 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mail_cache_db.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver_tools.h" +#include "nntpdriver.h" +#include "maildriver.h" +#include "newsnntp.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maillock.h" +#include "nntpdriver_cached_message.h" +#include "nntpdriver_tools.h" + +static int nntpdriver_cached_initialize(mailsession * session); + +static void nntpdriver_cached_uninitialize(mailsession * session); + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int nntpdriver_cached_login(mailsession * session, + char * userid, char * password); + +static int nntpdriver_cached_logout(mailsession * session); + +static int nntpdriver_cached_check_folder(mailsession * session); + +static int nntpdriver_cached_select_folder(mailsession * session, char * mb); + +static int nntpdriver_cached_status_folder(mailsession * session, + char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_append_message(mailsession * session, + char * message, size_t size); + +static int nntpdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags); + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + char * mb); + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + char * mb); + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_cached_noop(mailsession * session); + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_nntp_cached_session_driver = { + .sess_name = "nntp-cached", + + .sess_initialize = nntpdriver_cached_initialize, + .sess_uninitialize = nntpdriver_cached_uninitialize, + + .sess_parameters = nntpdriver_cached_parameters, + + .sess_connect_stream = nntpdriver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = NULL, + .sess_login = nntpdriver_cached_login, + .sess_logout = nntpdriver_cached_logout, + .sess_noop = nntpdriver_cached_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = nntpdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = nntpdriver_cached_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = nntpdriver_cached_status_folder, + .sess_messages_number = nntpdriver_cached_messages_number, + .sess_recent_number = nntpdriver_cached_recent_number, + .sess_unseen_number = nntpdriver_cached_unseen_number, + .sess_list_folders = nntpdriver_cached_list_folders, + .sess_lsub_folders = nntpdriver_cached_lsub_folders, + .sess_subscribe_folder = nntpdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder, + + .sess_append_message = nntpdriver_cached_append_message, + .sess_append_message_flags = nntpdriver_cached_append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = nntpdriver_cached_get_messages_list, + .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = nntpdriver_cached_get_message, + .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid, +}; + + +mailsession_driver * nntp_cached_session_driver = +&local_nntp_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast); + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last); + + +static inline struct nntp_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_ancestor_data(session)->nntp_session; +} + +static int nntpdriver_cached_initialize(mailsession * session) +{ + struct nntp_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->nntp_flags_store = mail_flags_store_new(); + if (data->nntp_flags_store == NULL) + goto free; + + data->nntp_ancestor = mailsession_new(nntp_session_driver); + if (data->nntp_ancestor == NULL) + goto free_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->nntp_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntp_flags_store_process(char * flags_directory, char * group_name, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (group_name == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void nntpdriver_cached_uninitialize(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + mail_flags_store_free(cached_data->nntp_flags_store); + + mailsession_free(cached_data->nntp_ancestor); + free(cached_data); + + session->sess_data = NULL; +} + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->nntp_cache_directory, value, PATH_MAX); + cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->nntp_flags_directory, value, PATH_MAX); + cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(get_ancestor(session), id, value); + } +} + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + return mailsession_connect_stream(get_ancestor(session), s); +} + +static int nntpdriver_cached_login(mailsession * session, + char * userid, char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int nntpdriver_cached_logout(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int nntpdriver_cached_select_folder(mailsession * session, char * mb) +{ + int r; + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + int res; + char key[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + if (ancestor_data->nntp_group_name == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int nntpdriver_cached_check_folder(mailsession * session) +{ + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return MAIL_NO_ERROR; +} + + +static int nntpdriver_cached_status_folder(mailsession * session, + char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + uint32_t i; + int r; + uint32_t recent; + uint32_t unseen; + uint32_t first; + uint32_t last; + uint32_t count; + uint32_t additionnal; + + r = nntpdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + read_article_seq(session, &first, &last); + + count = 0; + recent = 0; + unseen = 0; + + ancestor_data = get_ancestor_data(session); + cached_data = get_cached_data(session); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + if (ancestor_data->nntp_group_info->grp_first > first) + first = ancestor_data->nntp_group_info->grp_first; + if (last < first) + last = ancestor_data->nntp_group_info->grp_last; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = first ; i <= last ; i++) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + i, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) { + mail_flags_free(flags); + continue; + } + + count ++; + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + if ((count == 0) && (first != last)) { + count = last - first + 1; + recent = count; + unseen = count; + } + + additionnal = ancestor_data->nntp_group_info->grp_last - last; + recent += additionnal; + unseen += additionnal; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int nntpdriver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_recent_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_unseen_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + + + +/* messages operations */ + +static int nntpdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + +static int nntpdriver_cached_append_message_flags(mailsession * session, + char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_cached_append_message(session, message, size); +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + char keyname[PATH_MAX]; + int r; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + int res; + char keyname[PATH_MAX]; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +#define SEQ_FILENAME "articles-seq" + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + uint32_t first; + uint32_t last; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + + first = 0; + last = 0; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + f = fopen(seq_filename, "r"); + + if (f != NULL) { + int fd; + + fd = fileno(f); + + r = maillock_read_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t) * 2]; + size_t read_size; + + read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr != NULL) { + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &first); + r = mailimf_cache_int_read(mmapstr, &cur_token, &last); + + mmap_string_free(mmapstr); + } + + maillock_read_unlock(seq_filename, fd); + } + fclose(f); + } + + * pfirst = first; + * plast = last; +} + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + int fd; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + + fd = creat(seq_filename, S_IRUSR | S_IWUSR); + if (fd < 0) + return; + + f = fdopen(fd, "w"); + if (f != NULL) { + r = maillock_write_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr != NULL) { + r = mail_serialize_clear(mmapstr, &cur_token); + if (r == MAIL_NO_ERROR) { + r = mailimf_cache_int_write(mmapstr, &cur_token, first); + r = mailimf_cache_int_write(mmapstr, &cur_token, last); + + fwrite(mmapstr->str, 1, mmapstr->len, f); + } + + mmap_string_free(mmapstr); + } + + maillock_write_unlock(seq_filename, fd); + } + fclose(f); + } + else + close(fd); +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + if (strcmp(filename, SEQ_FILENAME) == 0) + * filename = 0; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct nntp_cached_session_state_data * cached_data; + uint32_t first; + uint32_t last; + struct nntp_session_state_data * ancestor_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + char cache_dir[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* read articles sequence */ + + read_article_seq(session, &first, &last); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if ((msg->msg_index < first) || (msg->msg_index > last)) + continue; + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + msg->msg_cached = TRUE; + } + } + } + + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + else { + msg->msg_flags = mail_flags_new_empty(); + if (msg->msg_fields == NULL) { + msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(msg); + } + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + } + + first = 0; + last = 0; + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + first = msg->msg_index; + + msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1); + last = msg->msg_index; + } + + /* write articles sequence */ + + write_article_seq(session, first, last); + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + /* remove cache files */ + + snprintf(cache_dir, PATH_MAX, "%s/%s", + cached_data->nntp_cache_directory, ancestor_data->nntp_group_name); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + maildriver_message_cache_clean_up(cache_dir, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(get_ancestor(session), session, + nntp_cached_message_driver, result); +} + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_cached_get_message(session, num, result); +} -- cgit v0.9.0.2