summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/mhdriver_cached.c
Side-by-side diff
Diffstat (limited to 'kmicromail/libetpan/generic/mhdriver_cached.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/mhdriver_cached.c93
1 files changed, 88 insertions, 5 deletions
diff --git a/kmicromail/libetpan/generic/mhdriver_cached.c b/kmicromail/libetpan/generic/mhdriver_cached.c
index 5c35089..04aa523 100644
--- a/kmicromail/libetpan/generic/mhdriver_cached.c
+++ b/kmicromail/libetpan/generic/mhdriver_cached.c
@@ -63,153 +63,156 @@ static int mhdriver_cached_initialize(mailsession * session);
static void mhdriver_cached_uninitialize(mailsession * session);
static int mhdriver_cached_parameters(mailsession * session,
int id, void * value);
static int mhdriver_cached_connect_path(mailsession * session, char * path);
static int mhdriver_cached_logout(mailsession * session);
static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
char * name, char ** result);
static int mhdriver_cached_create_folder(mailsession * session, char * mb);
static int mhdriver_cached_delete_folder(mailsession * session, char * mb);
static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
char * new_name);
static int mhdriver_cached_check_folder(mailsession * session);
static int mhdriver_cached_select_folder(mailsession * session, char * mb);
static int mhdriver_cached_expunge_folder(mailsession * session);
static int mhdriver_cached_status_folder(mailsession * session, char * mb,
uint32_t * result_messages, uint32_t * result_recent,
uint32_t * result_unseen);
static int mhdriver_cached_messages_number(mailsession * session, char * mb,
uint32_t * result);
static int mhdriver_cached_recent_number(mailsession * session, char * mb,
uint32_t * result);
static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
uint32_t * result);
static int mhdriver_cached_list_folders(mailsession * session, char * mb,
struct mail_list ** result);
static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
struct mail_list ** result);
static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb);
static int mhdriver_cached_unsubscribe_folder(mailsession * session,
char * mb);
static int mhdriver_cached_append_message(mailsession * session,
char * message, size_t size);
+static int mhdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags);
static int mhdriver_cached_copy_message(mailsession * session,
uint32_t num, char * mb);
static int mhdriver_cached_remove_message(mailsession * session,
uint32_t num);
static int mhdriver_cached_move_message(mailsession * session,
uint32_t num, char * mb);
static int
mhdriver_cached_get_messages_list(mailsession * session,
struct mailmessage_list ** result);
static int
mhdriver_cached_get_envelopes_list(mailsession * session,
struct mailmessage_list * env_list);
static int mhdriver_cached_get_message(mailsession * session,
uint32_t num, mailmessage ** result);
static int mhdriver_cached_get_message_by_uid(mailsession * session,
const char * uid,
mailmessage ** result);
static mailsession_driver local_mh_cached_session_driver = {
.sess_name = "mh-cached",
.sess_initialize = mhdriver_cached_initialize,
.sess_uninitialize = mhdriver_cached_uninitialize,
.sess_parameters = mhdriver_cached_parameters,
.sess_connect_stream = NULL,
.sess_connect_path = mhdriver_cached_connect_path,
.sess_starttls = NULL,
.sess_login = NULL,
.sess_logout = mhdriver_cached_logout,
.sess_noop = NULL,
.sess_build_folder_name = mhdriver_cached_build_folder_name,
.sess_create_folder = mhdriver_cached_create_folder,
.sess_delete_folder = mhdriver_cached_delete_folder,
.sess_rename_folder = mhdriver_cached_rename_folder,
.sess_check_folder = mhdriver_cached_check_folder,
.sess_examine_folder = NULL,
.sess_select_folder = mhdriver_cached_select_folder,
.sess_expunge_folder = mhdriver_cached_expunge_folder,
.sess_status_folder = mhdriver_cached_status_folder,
.sess_messages_number = mhdriver_cached_messages_number,
.sess_recent_number = mhdriver_cached_recent_number,
.sess_unseen_number = mhdriver_cached_unseen_number,
.sess_list_folders = mhdriver_cached_list_folders,
.sess_lsub_folders = mhdriver_cached_lsub_folders,
.sess_subscribe_folder = mhdriver_cached_subscribe_folder,
.sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder,
.sess_append_message = mhdriver_cached_append_message,
+ .sess_append_message_flags = mhdriver_cached_append_message_flags,
.sess_copy_message = mhdriver_cached_copy_message,
.sess_move_message = mhdriver_cached_move_message,
.sess_get_messages_list = mhdriver_cached_get_messages_list,
.sess_get_envelopes_list = mhdriver_cached_get_envelopes_list,
.sess_remove_message = mhdriver_cached_remove_message,
#if 0
.sess_search_messages = maildriver_generic_search_messages,
#endif
.sess_get_message = mhdriver_cached_get_message,
.sess_get_message_by_uid = mhdriver_cached_get_message_by_uid,
};
mailsession_driver * mh_cached_session_driver =
&local_mh_cached_session_driver;
#define ENV_NAME "env.db"
#define FLAGS_NAME "flags.db"
static inline struct mh_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)->mh_ancestor;
}
static inline struct mh_session_state_data *
get_ancestor_data(mailsession * session)
{
return get_ancestor(session)->sess_data;
}
static inline struct mailmh *
get_mh_session(mailsession * session)
{
return get_ancestor_data(session)->mh_session;
}
static inline struct mailmh_folder *
get_mh_cur_folder(mailsession * session)
{
return get_ancestor_data(session)->mh_cur_folder;
@@ -838,213 +841,293 @@ static int mhdriver_cached_recent_number(mailsession * session, char * mb,
static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
uint32_t * result)
{
uint32_t messages;
uint32_t recent;
uint32_t unseen;
int r;
r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
if (r != MAIL_NO_ERROR)
return r;
* result = recent;
return MAIL_NO_ERROR;
}
static int mhdriver_cached_list_folders(mailsession * session, char * mb,
struct mail_list ** result)
{
return mailsession_list_folders(get_ancestor(session), mb, result);
}
static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
struct mail_list ** result)
{
return mailsession_lsub_folders(get_ancestor(session), mb, result);
}
static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb)
{
return mailsession_subscribe_folder(get_ancestor(session), mb);
}
static int mhdriver_cached_unsubscribe_folder(mailsession * session,
char * mb)
{
return mailsession_unsubscribe_folder(get_ancestor(session), mb);
}
/* messages operations */
static int mhdriver_cached_append_message(mailsession * session,
char * message, size_t size)
{
- return mailsession_append_message(get_ancestor(session), message, size);
+ return mhdriver_cached_append_message_flags(session,
+ message, size, NULL);
+}
+
+static int mhdriver_cached_append_message_flags(mailsession * session,
+ char * message, size_t size, struct mail_flags * flags)
+{
+ int r;
+ struct mailmh_folder * folder;
+ struct mailmh_msg_info * msg_info;
+ chashdatum key;
+ chashdatum value;
+ uint32_t uid;
+ struct mh_cached_session_state_data * data;
+ char filename_flags[PATH_MAX];
+ struct mail_cache_db * cache_db_flags;
+ MMAPString * mmapstr;
+ char keyname[PATH_MAX];
+
+ folder = get_mh_cur_folder(session);
+ if (folder == NULL)
+ return MAIL_ERROR_BAD_STATE;
+
+ r = mailmh_folder_add_message_uid(folder,
+ message, size, &uid);
+
+ switch (r) {
+ case MAILMH_ERROR_FILE:
+ return MAIL_ERROR_DISKSPACE;
+
+ case MAILMH_NO_ERROR:
+ break;
+
+ default:
+ return mhdriver_mh_error_to_mail_error(r);
+ }
+
+ if (flags == NULL)
+ goto exit;
+
+ key.data = &uid;
+ key.len = sizeof(uid);
+ r = chash_get(folder->fl_msgs_hash, &key, &value);
+ if (r < 0)
+ return MAIL_ERROR_CACHE_MISS;
+
+ msg_info = value.data;
+
+ data = get_cached_data(session);
+
+ snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
+ data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME);
+
+ r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
+ if (r < 0)
+ goto exit;
+
+ mmapstr = mmap_string_new("");
+ if (mmapstr == NULL)
+ goto close_db_flags;
+
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
+ uid, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
+
+ r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
+
+ mmap_string_free(mmapstr);
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+
+ if (r != MAIL_NO_ERROR)
+ goto exit;
+
+ return MAIL_NO_ERROR;
+
+ close_db_flags:
+ mail_cache_db_close_unlock(filename_flags, cache_db_flags);
+ exit:
+ return MAIL_NO_ERROR;
}
static int mhdriver_cached_copy_message(mailsession * session,
uint32_t num, char * mb)
{
return mailsession_copy_message(get_ancestor(session), num, mb);
}
static int mhdriver_cached_remove_message(mailsession * session, uint32_t num)
{
return mailsession_remove_message(get_ancestor(session), num);
}
static int mhdriver_cached_move_message(mailsession * session,
uint32_t num, char * mb)
{
return mailsession_move_message(get_ancestor(session), num, mb);
}
static int
mhdriver_cached_get_messages_list(mailsession * session,
struct mailmessage_list ** result)
{
struct mailmh_folder * folder;
int res;
folder = get_mh_cur_folder(session);
if (folder == NULL) {
res = MAIL_ERROR_BAD_STATE;
goto err;
}
return mh_get_messages_list(folder, session,
mh_cached_message_driver, result);
err:
return res;
}
static int
get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
mailsession * session, uint32_t num,
struct mailimf_fields ** result)
{
int r;
char keyname[PATH_MAX];
struct mailimf_fields * fields;
int res;
struct mailmh_folder * folder;
struct mailmh_msg_info * msg_info;
chashdatum key;
chashdatum data;
folder = get_mh_cur_folder(session);
#if 0
msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
if (msg_info == NULL)
return MAIL_ERROR_CACHE_MISS;
#endif
key.data = &num;
key.len = sizeof(num);
r = chash_get(folder->fl_msgs_hash, &key, &data);
if (r < 0)
return MAIL_ERROR_CACHE_MISS;
msg_info = data.data;
- snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope",
- num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size);
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
+ num, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
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;
char keyname[PATH_MAX];
int res;
struct mailmh_folder * folder;
chashdatum key;
chashdatum data;
struct mailmh_msg_info * msg_info;
folder = get_mh_cur_folder(session);
#if 0
msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
if (msg_info == NULL) {
res = MAIL_ERROR_CACHE_MISS;
goto err;
}
#endif
key.data = &num;
key.len = sizeof(num);
r = chash_get(folder->fl_msgs_hash, &key, &data);
if (r < 0)
return MAIL_ERROR_CACHE_MISS;
msg_info = data.data;
- snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope",
- num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size);
+ snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
+ num, (unsigned long) msg_info->msg_mtime,
+ (unsigned long) msg_info->msg_size);
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;
}
static int
mhdriver_cached_get_envelopes_list(mailsession * session,
struct mailmessage_list * env_list)
{
int r;
unsigned int i;
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;
struct mh_cached_session_state_data * cached_data;
cached_data = get_cached_data(session);
if (cached_data->mh_quoted_mb == NULL) {
res = MAIL_ERROR_BAD_STATE;
goto err;
}
mh_flags_store_process(cached_data->mh_flags_directory,
cached_data->mh_quoted_mb,
cached_data->mh_flags_store);
mmapstr = mmap_string_new("");
if (mmapstr == NULL) {
res = MAIL_ERROR_MEMORY;
goto err;
}
snprintf(filename_env, PATH_MAX, "%s/%s/%s",
cached_data->mh_cache_directory,
cached_data->mh_quoted_mb, ENV_NAME);
r = mail_cache_db_open_lock(filename_env, &cache_db_env);