@@ -2414,24 +2414,8 @@ static int mail_engine_mdele(int argc, char **argv, int sockd)
24142414 */
24152415static int mail_engine_mcopy (int argc, char **argv, int sockd) try
24162416{
2417- uint32_t tmp_flags;
2418- uint64_t change_num;
2419- uint64_t message_id;
2420- char sql_string[1024 ];
2421-
24222417 if (strlen (argv[4 ]) >= 1024 )
24232418 return MIDB_E_PARAMETER_ERROR;
2424- auto eml_src = argv[1 ] + " /eml/" s + argv[3 ];
2425- size_t slurp_size = 0 ;
2426- std::unique_ptr<char [], stdlib_delete> pbuff (HX_slurp_file (eml_src.c_str (), &slurp_size));
2427- if (pbuff == nullptr ) {
2428- mlog (LV_ERR, " E-2074: Opening %s for reading failed: %s" , eml_src.c_str (), strerror (errno));
2429- return errno == ENOMEM ? MIDB_E_NO_MEMORY : MIDB_E_DISK_ERROR;
2430- }
2431-
2432- MAIL imail;
2433- if (!imail.load_from_str_move (pbuff.get (), slurp_size))
2434- return MIDB_E_IMAIL_RETRIEVE;
24352419 auto pidb = mail_engine_get_idb (argv[1 ]);
24362420 if (pidb == nullptr )
24372421 return MIDB_E_HASHTABLE_FULL;
@@ -2452,103 +2436,42 @@ static int mail_engine_mcopy(int argc, char **argv, int sockd) try
24522436 if (pstmt.step () != SQLITE_ROW ||
24532437 pstmt.col_uint64 (CTM_FOLDERID) != src_fid)
24542438 return MIDB_E_NO_MESSAGE;
2455-
2456- std::string flags_buff = " (" ;
2457- if (pstmt.col_uint64 (CTM_REPLIED) != 0 )
2458- flags_buff += ' A' ;
2459- if (pstmt.col_uint64 (CTM_FLAGGED) != 0 )
2460- flags_buff += ' F' ;
2461- if (pstmt.col_uint64 (CTM_FWD) != 0 )
2462- flags_buff += ' W' ;
2463- flags_buff += ' )' ;
2464- auto b_unsent = pstmt.col_uint64 (CTM_UNSENT) != 0 ;
2465- uint8_t b_read = pstmt.col_uint64 (CTM_READ) != 0 ;
2466- uint64_t nt_time = pstmt.col_int64 (CTM_RCVDTIME);
2439+ uint64_t src_mid = pstmt.col_uint64 (CTM_MSGID), message_id = 0 ;
24672440 pstmt.finalize ();
2468- unsigned int user_id = 0 ;
2469- if (!system_services_get_user_ids (pidb->username .c_str (), &user_id, nullptr , nullptr ))
2470- return MIDB_E_SSGETID;
2471- sql_meta_result mres;
2472- auto mret = system_services_meta (pidb->username .c_str (),
2473- WANTPRIV_METAONLY, mres);
2474- auto charset = mret == 0 ? lang_to_charset (mres.lang .c_str ()) : nullptr ;
2475- if (*znul (charset) == ' \0 ' )
2476- charset = g_default_charset;
2477- auto tmzone = mret == 0 ? mres.timezone .c_str () : nullptr ;
2478- if (*znul (tmzone) == ' \0 ' )
2479- tmzone = GROMOX_FALLBACK_TIMEZONE;
2480- auto pmsgctnt = oxcmail_import (charset, tmzone, &imail,
2481- common_util_alloc, common_util_get_propids_create);
2482- imail.clear ();
2483- pbuff.reset ();
2484- if (pmsgctnt == nullptr )
2485- return MIDB_E_OXCMAIL_IMPORT;
2486- auto cl_msg = make_scope_exit ([&]() { message_content_free (pmsgctnt); });
2487- if (pmsgctnt->proplist .set (PR_MESSAGE_DELIVERY_TIME, &nt_time) != 0 )
2488- return MIDB_E_NO_MEMORY;
2489- static_assert (std::is_same_v<decltype (b_read), uint8_t >);
2490- if (b_read && pmsgctnt->proplist .set (PR_READ, &b_read) != 0 )
2491- return MIDB_E_NO_MEMORY;
2492- if (0 != b_unsent) {
2493- tmp_flags = MSGFLAG_UNSENT;
2494- if (pmsgctnt->proplist .set (PR_MESSAGE_FLAGS, &tmp_flags) != 0 )
2495- return MIDB_E_NO_MEMORY;
2496- }
24972441 if (!exmdb_client::allocate_message_id (argv[1 ],
2498- rop_util_make_eid_ex (1 , dst_fid), &message_id) ||
2499- !exmdb_client::allocate_cn (argv[1 ], &change_num))
2442+ rop_util_make_eid_ex (1 , dst_fid), &message_id))
25002443 return MIDB_E_MDB_ALLOCID;
25012444
2502- auto mid_string = std::to_string (time (nullptr )) + " ." +
2503- std::to_string (++g_sequence_id) + " .midb" ;
2504- eml_src = argv[1 ] + " /eml/" s + argv[3 ];
2505- auto eml_dst = argv[1 ] + " /eml/" s + mid_string;
2506- if (link (eml_src.c_str (), eml_dst.c_str ()) != 0 )
2507- mlog (LV_ERR, " E-2083: link %s %s: %s" ,
2508- eml_src.c_str (), eml_dst.c_str (),
2509- strerror (errno));
2510- eml_src = argv[1 ] + " /ext/" s + argv[3 ];
2511- eml_dst = argv[1 ] + " /ext/" s + mid_string;
2512- if (link (eml_src.c_str (), eml_dst.c_str ()) != 0 )
2513- mlog (LV_ERR, " E-2084: link %s %s: %s" ,
2514- eml_src.c_str (), eml_dst.c_str (),
2515- strerror (errno));
2516- snprintf (sql_string, std::size (sql_string), " INSERT INTO mapping"
2517- " (message_id, mid_string, flag_string) VALUES"
2518- " (%llu, ?, ?)" , LLU{rop_util_get_gc_value (message_id)});
2519- pstmt = gx_sql_prep (pidb->psqlite , sql_string);
2520- if (pstmt == nullptr )
2521- return MIDB_E_SQLPREP;
2522- sqlite3_bind_text (pstmt, 1 , mid_string.c_str (), -1 , SQLITE_STATIC);
2523- sqlite3_bind_text (pstmt, 2 , flags_buff.c_str (), -1 , SQLITE_STATIC);
2524- if (pstmt.step () != SQLITE_DONE)
2525- return MIDB_E_SQLUNEXP;
2526- pstmt.finalize ();
2527- std::string username = pidb->username ;
2528- pidb.reset ();
2529- if (pmsgctnt->proplist .set (PidTagMid, &message_id) != 0 ||
2530- pmsgctnt->proplist .set (PidTagChangeNumber, &change_num) != 0 )
2531- return MIDB_E_NO_MEMORY;
2532- auto pbin = cu_xid_to_bin ({rop_util_make_user_guid (user_id), change_num});
2533- if (pbin == nullptr ||
2534- pmsgctnt->proplist .set (PR_CHANGE_KEY, pbin) != 0 )
2535- return MIDB_E_NO_MEMORY;
2536- auto newval = common_util_pcl_append (NULL , pbin);
2537- if (newval == nullptr ||
2538- pmsgctnt->proplist .set (PR_PREDECESSOR_CHANGE_LIST, newval) != 0 )
2539- return MIDB_E_NO_MEMORY;
2540- auto cpid = cset_to_cpid (charset);
2541- if (cpid == CP_ACP)
2542- cpid = static_cast <cpid_t >(1252 );
2543- ec_error_t e_result = ecRpcFailed;
2544- if (!exmdb_client::write_message (argv[1 ], cpid,
2545- rop_util_make_eid_ex (1 , dst_fid), pmsgctnt, &e_result) ||
2546- e_result != ecSuccess)
2445+ /*
2446+ * exmdb-level copy: this triggers an event and some other midb threads
2447+ * will instantiate the midb message (and decide mid_string)
2448+ */
2449+ BOOL e_result = false ;
2450+ if (!exmdb_client::movecopy_message (argv[1 ], CP_UTF8, rop_util_make_eid_ex (1 , src_mid),
2451+ rop_util_make_eid_ex (1 , dst_fid), message_id,
2452+ false , &e_result) || !e_result)
25472453 return MIDB_E_MDB_WRITEMESSAGE;
2548- cl_msg.release ();
2549- message_content_free (pmsgctnt);
2550- mid_string.insert (0 , " TRUE " );
2551- mid_string.append (" \r\n " );
2454+
2455+ pidb.reset (); /* release giant lock, let event get processed */
2456+ std::string mid_string;
2457+ for (unsigned int i = 0 ; i < 10 ; ++i) {
2458+ pidb = mail_engine_get_idb (argv[1 ]);
2459+ if (pidb == nullptr )
2460+ return MIDB_E_HASHTABLE_FULL;
2461+ pstmt = gx_sql_prep (pidb->psqlite , " SELECT mid_string FROM messages WHERE message_id=?" );
2462+ if (pstmt == nullptr )
2463+ return MIDB_E_NO_MEMORY;
2464+ pstmt.bind_int64 (1 , rop_util_get_gc_value (message_id));
2465+ if (pstmt.step () == SQLITE_ROW) {
2466+ mid_string = " TRUE " s + pstmt.col_text (0 ) + " \r\n " ;
2467+ break ;
2468+ }
2469+ pstmt.reset ();
2470+ pidb.reset ();
2471+ usleep (100000 );
2472+ }
2473+ if (mid_string.empty ())
2474+ mid_string = " FALSE\r\n " ;
25522475 return cmd_write (sockd, mid_string.c_str (), mid_string.size ());
25532476} catch (const std::bad_alloc &) {
25542477 mlog (LV_ERR, " E-1486: ENOMEM" );
0 commit comments