Skip to content

Commit 2c519ff

Browse files
committed
imap: replace direct disk I/O with imapfile_read/write EXRPCs
1 parent e38995b commit 2c519ff

File tree

1 file changed

+59
-56
lines changed

1 file changed

+59
-56
lines changed

mra/imap/cmd.cpp

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <gromox/mjson.hpp>
3939
#include <gromox/mysql_adaptor.hpp>
4040
#include <gromox/range_set.hpp>
41+
#include <gromox/scope.hpp>
4142
#include <gromox/simple_tree.hpp>
4243
#include <gromox/textmaps.hpp>
4344
#include <gromox/util.hpp>
@@ -674,10 +675,10 @@ static int pstruct_else(imap_context &ctx, MJSON *pjson,
674675
if (storage_path == nullptr) {
675676
eml_path = ctx.maildir + "/eml/"s + pjson->get_mail_filename();
676677
if (!ctx.io_actor.exists(eml_path)) {
677-
size_t z = 0;
678-
std::unique_ptr<char[], stdlib_delete> d(HX_slurp_file(eml_path.c_str(), &z));
679-
if (d != nullptr)
680-
ctx.io_actor.place(eml_path, std::string(d.get(), z));
678+
std::string content;
679+
if (exmdb_client::imapfile_read(ctx.maildir, "eml",
680+
pjson->get_mail_filename(), &content))
681+
ctx.io_actor.place(eml_path, std::move(content));
681682
}
682683
} else {
683684
eml_path = ctx.maildir + "/tmp/imap.rfc822/"s + storage_path + "/" + pjson->get_mail_filename();
@@ -734,10 +735,9 @@ static int icp_process_fetch_item(imap_context &ctx,
734735
mjson.path = eml_path;
735736
auto eml_file = eml_path + "/"s + pitem->mid;
736737
if (!ctx.io_actor.exists(eml_file)) {
737-
size_t z = 0;
738-
std::unique_ptr<char[], stdlib_delete> d(HX_slurp_file(eml_file.c_str(), &z));
739-
if (d != nullptr)
740-
ctx.io_actor.place(eml_file, std::string(d.get(), z));
738+
std::string content;
739+
if (exmdb_client::imapfile_read(ctx.maildir, "eml", pitem->mid, &content))
740+
ctx.io_actor.place(eml_file, std::move(content));
741741
}
742742
}
743743

@@ -2034,21 +2034,11 @@ int icp_append(int argc, char **argv, imap_context &ctx) try
20342034
}
20352035
mid_string += "."s + znul(g_config_file->get_value("host_id"));
20362036
auto pcontext = &ctx;
2037-
auto eml_path = fmt::format("{}/eml/{}", pcontext->maildir, mid_string);
2038-
wrapfd fd = open(eml_path.c_str(), O_CREAT | O_RDWR | O_TRUNC, FMODE_PRIVATE);
2039-
if (fd.get() < 0) {
2040-
mlog(LV_ERR, "E-1763: write to %s failed: %s",
2041-
eml_path.c_str(), strerror(errno));
2042-
if (remove(eml_path.c_str()) < 0 && errno != ENOENT)
2043-
mlog(LV_WARN, "W-1370: remove %s: %s",
2044-
eml_path.c_str(), strerror(errno));
2045-
return 1909;
2046-
}
2047-
auto eml_size = strlen(argv[argc-1]);
2048-
auto wrret = HXio_fullwrite(fd.get(), argv[argc-1], eml_size);
2049-
if (wrret < 0 || static_cast<size_t>(wrret) != eml_size ||
2050-
fd.close_wr() < 0) {
2051-
mlog(LV_WARN, "E-2395: write %s: %s", eml_path.c_str(), strerror(errno));
2037+
imrpc_build_env();
2038+
auto cl_0 = make_scope_exit(imrpc_free_env);
2039+
if (!exmdb_client::imapfile_write(ctx.maildir, "eml",
2040+
mid_string, argv[argc-1])) {
2041+
mlog(LV_ERR, "E-1763: write %s/eml/%s failed", ctx.maildir, mid_string.c_str());
20522042
return 1909;
20532043
}
20542044

@@ -2057,7 +2047,7 @@ int icp_append(int argc, char **argv, imap_context &ctx) try
20572047
auto ret = m2icode(ssr, errnum);
20582048
if (ret != 0)
20592049
return ret;
2060-
imap_parser_log_info(pcontext, LV_DEBUG, "message %s is appended OK", eml_path.c_str());
2050+
imap_parser_log_info(pcontext, LV_DEBUG, "message %s is appended OK", mid_string.c_str());
20612051
imap_parser_bcast_touch(nullptr, pcontext->username, pcontext->selected_folder);
20622052
if (pcontext->proto_stat == iproto_stat::select)
20632053
imap_parser_echo_modify(pcontext, NULL);
@@ -2163,23 +2153,22 @@ int icp_append_begin(int argc, char **argv, imap_context &ctx)
21632153
static int icp_append_end2(int argc, char **argv, imap_context &ctx) try
21642154
{
21652155
auto pcontext = &ctx;
2166-
auto eml_path = fmt::format("{}/eml/{}", pcontext->maildir, pcontext->mid);
2167-
wrapfd fd = open(eml_path.c_str(), O_CREAT | O_RDWR | O_TRUNC, FMODE_PRIVATE);
2168-
if (fd.get() < 0) {
2169-
mlog(LV_ERR, "E-1764: write to %s failed: %s",
2170-
eml_path.c_str(), strerror(errno));
2171-
ctx.append_stream.clear();
2172-
return 1909 | DISPATCH_TAG;
2173-
} else if (ctx.append_stream.dump(fd.get()) != STREAM_DUMP_OK) {
2174-
mlog(LV_WARN, "E-1346: write %s: %s", eml_path.c_str(), strerror(errno));
2175-
ctx.append_stream.clear();
2176-
return 1909 | DISPATCH_TAG;
2177-
} else if (fd.close_wr() < 0) {
2178-
mlog(LV_WARN, "E-2016: write %s: %s", eml_path.c_str(), strerror(errno));
2179-
ctx.append_stream.clear();
2156+
std::string content;
2157+
void *strb;
2158+
unsigned int strb_size = STREAM_BLOCK_SIZE;
2159+
ctx.append_stream.reset_reading();
2160+
while ((strb = ctx.append_stream.get_read_buf(&strb_size)) != nullptr) {
2161+
content.append(static_cast<char *>(strb), strb_size);
2162+
strb_size = STREAM_BLOCK_SIZE;
2163+
}
2164+
imrpc_build_env();
2165+
auto cl_0 = make_scope_exit(imrpc_free_env);
2166+
if (!exmdb_client::imapfile_write(ctx.maildir, "eml",
2167+
ctx.mid, content)) {
2168+
mlog(LV_ERR, "E-1764: write to %s/eml/%s failed",
2169+
pcontext->maildir, pcontext->mid.c_str());
21802170
return 1909 | DISPATCH_TAG;
21812171
}
2182-
ctx.append_stream.clear();
21832172

21842173
int errnum;
21852174
auto sys_name = ctx.append_folder.c_str();
@@ -2191,7 +2180,7 @@ static int icp_append_end2(int argc, char **argv, imap_context &ctx) try
21912180
auto ret = m2icode(ssr, errnum);
21922181
if (ret != 0)
21932182
return ret | DISPATCH_TAG;
2194-
imap_parser_log_info(pcontext, LV_DEBUG, "message %s is appended OK", eml_path.c_str());
2183+
imap_parser_log_info(pcontext, LV_DEBUG, "message %s is appended OK", cmid.c_str());
21952184
imap_parser_bcast_touch(nullptr, pcontext->username, pcontext->selected_folder);
21962185
if (pcontext->proto_stat == iproto_stat::select)
21972186
imap_parser_echo_modify(pcontext, NULL);
@@ -2272,6 +2261,8 @@ int icp_expunge(int argc, char **argv, imap_context &ctx) try
22722261
return 1726;
22732262
}
22742263
std::vector<MITEM *> exp_list;
2264+
imrpc_build_env();
2265+
auto cl_0 = make_scope_exit(imrpc_free_env);
22752266
for (size_t i = 0; i < num; ++i) {
22762267
auto pitem = xarray.get_item(i);
22772268
if (zero_uid_bit(*pitem))
@@ -2295,11 +2286,12 @@ int icp_expunge(int argc, char **argv, imap_context &ctx) try
22952286
auto ct_item = pcontext->contents.get_itemx(pitem->uid);
22962287
if (ct_item == nullptr)
22972288
continue;
2298-
auto eml_path = std::string(pcontext->maildir) + "/eml/" + pitem->mid;
2299-
if (remove(eml_path.c_str()) < 0 && errno != ENOENT)
2300-
mlog(LV_WARN, "W-2030: remove %s: %s",
2301-
eml_path.c_str(), strerror(errno));
2302-
imap_parser_log_info(pcontext, LV_DEBUG, "message %s has been deleted", eml_path.c_str());
2289+
if (!exmdb_client::imapfile_delete(ctx.maildir, "eml", pitem->mid))
2290+
mlog(LV_WARN, "W-2030: remove %s/eml/%s failed",
2291+
ctx.maildir, pitem->mid.c_str());
2292+
else
2293+
imap_parser_log_info(pcontext, LV_DEBUG, "message %s has been deleted",
2294+
pitem->mid.c_str());
23032295
}
23042296
if (!exp_list.empty())
23052297
imap_parser_bcast_expunge(*pcontext, exp_list);
@@ -2439,6 +2431,8 @@ int icp_fetch(int argc, char **argv, imap_context &ctx)
24392431
return result;
24402432
pcontext->stream.clear();
24412433
num = xarray.get_capacity();
2434+
imrpc_build_env();
2435+
auto cl_0 = make_scope_exit(imrpc_free_env);
24422436
for (i=0; i<num; i++) {
24432437
auto pitem = xarray.get_item(i);
24442438
/*
@@ -2712,6 +2706,8 @@ int icp_uid_fetch(int argc, char **argv, imap_context &ctx) try
27122706
return ret;
27132707
pcontext->stream.clear();
27142708
num = xarray.get_capacity();
2709+
imrpc_build_env();
2710+
auto cl_0 = make_scope_exit(imrpc_free_env);
27152711
for (i=0; i<num; i++) {
27162712
auto pitem = xarray.get_item(i);
27172713
auto ct_item = pcontext->contents.get_itemx(pitem->uid);
@@ -2925,6 +2921,8 @@ int icp_uid_expunge(int argc, char **argv, imap_context &ctx) try
29252921
auto pitem = xarray.get_item(num - 1);
29262922
max_uid = pitem->uid;
29272923
std::vector<MITEM *> exp_list;
2924+
imrpc_build_env();
2925+
auto cl_0 = make_scope_exit(imrpc_free_env);
29282926
for (size_t i = 0; i < num; ++i) {
29292927
pitem = xarray.get_item(i);
29302928
if (zero_uid_bit(*pitem) ||
@@ -2947,11 +2945,12 @@ int icp_uid_expunge(int argc, char **argv, imap_context &ctx) try
29472945
auto ct_item = pcontext->contents.get_itemx(pitem->uid);
29482946
if (ct_item == nullptr)
29492947
continue;
2950-
auto eml_path = std::string(pcontext->maildir) + "/eml/" + pitem->mid;
2951-
if (remove(eml_path.c_str()) < 0 && errno != ENOENT)
2952-
mlog(LV_WARN, "W-2086: remove %s: %s",
2953-
eml_path.c_str(), strerror(errno));
2954-
imap_parser_log_info(pcontext, LV_DEBUG, "message %s has been deleted", eml_path.c_str());
2948+
if (!exmdb_client::imapfile_delete(ctx.maildir, "eml", pitem->mid))
2949+
mlog(LV_WARN, "W-2086: remove %s/eml/%s failed",
2950+
ctx.maildir, pitem->mid.c_str());
2951+
else
2952+
imap_parser_log_info(pcontext, LV_DEBUG, "message %s has been deleted",
2953+
pitem->mid.c_str());
29552954
}
29562955
if (!exp_list.empty())
29572956
imap_parser_bcast_expunge(*pcontext, exp_list);
@@ -3025,19 +3024,23 @@ void icp_clsfld(imap_context &ctx) try
30253024
result = midb_agent::remove_mail(pcontext->maildir,
30263025
prev_selected, exp_list, &errnum);
30273026
switch(result) {
3028-
case MIDB_RESULT_OK:
3027+
case MIDB_RESULT_OK: {
3028+
imrpc_build_env();
3029+
auto cl_0 = make_scope_exit(imrpc_free_env);
30293030
for (i = 0; i < num; ++i) {
30303031
auto pitem = xarray.get_item(i);
30313032
if (zero_uid_bit(*pitem))
30323033
continue;
3033-
auto eml_path = fmt::format("{}/eml/{}", pcontext->maildir, pitem->mid);
3034-
if (remove(eml_path.c_str()) < 0 && errno != ENOENT)
3035-
mlog(LV_WARN, "W-2087: remove %s: %s",
3036-
eml_path.c_str(), strerror(errno));
3037-
imap_parser_log_info(pcontext, LV_DEBUG, "message %s has been deleted", eml_path.c_str());
3034+
if (!exmdb_client::imapfile_delete(ctx.maildir, "eml", pitem->mid))
3035+
mlog(LV_WARN, "W-2087: remove %s/eml/%s failed",
3036+
ctx.maildir, pitem->mid.c_str());
3037+
else
3038+
imap_parser_log_info(pcontext, LV_DEBUG,
3039+
"message %s has been deleted", pitem->mid.c_str());
30383040
b_deleted = TRUE;
30393041
}
30403042
break;
3043+
}
30413044
case MIDB_NO_SERVER:
30423045
/* IMAP_CODE_2190005: NO server internal
30433046
error, missing MIDB connection */

0 commit comments

Comments
 (0)