X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fmigrate%2Fserv_migrate.c;h=7cc8fc041fde63275598c34fd4c85e202cd5bd09;hb=79d6eafd2a8bb379b3e13ff071a000d9bf36771b;hp=7c62d34652754747a03a03ab6e433f6e67965d1e;hpb=9ffea7c3315046ddcea2589656c13da5f5e0c076;p=citadel.git diff --git a/citadel/modules/migrate/serv_migrate.c b/citadel/modules/migrate/serv_migrate.c index 7c62d3465..7cc8fc041 100644 --- a/citadel/modules/migrate/serv_migrate.c +++ b/citadel/modules/migrate/serv_migrate.c @@ -1,7 +1,7 @@ /* * This module dumps and/or loads the Citadel database in XML format. * - * Copyright (c) 1987-2019 by the citadel.org team + * Copyright (c) 1987-2021 by the citadel.org team * * This program is open source software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3. @@ -15,14 +15,17 @@ /* * Explanation of tags: * - * 0% nothing - * 2% finished exporting configuration - * 7% finished exporting users - * 12% finished exporting openids - * 17% finished exporting rooms - * 18% finished exporting floors - * 25% finished exporting visits - * 100% finished exporting messages + * 0% started + * 2% finished exporting configuration + * 7% finished exporting users + * 12% finished exporting openids + * 17% finished exporting rooms + * 18% finished exporting floors + * 25% finished exporting visits + * 26-99% exporting messages + * 100% finished exporting messages + * + * These tags are inserted into the XML stream to give the reader an approximation of its progress. */ #include "sysdep.h" @@ -34,18 +37,7 @@ #include #include #include - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - +#include #include #include #include @@ -63,15 +55,12 @@ #include "euidindex.h" #include "ctdl_module.h" -#define END_OF_MESSAGE "---eom---dbd---" - char migr_tempfilename1[PATH_MAX]; char migr_tempfilename2[PATH_MAX]; FILE *migr_global_message_list; int total_msgs = 0; char *ikey = NULL; // If we're importing a config key we store it here. - /****************************************************************************** * Code which implements the export appears in this section * ******************************************************************************/ @@ -135,6 +124,9 @@ void migr_export_users_backend(char *username, void *data) { client_write(HKEY("")); xml_strout(u.fullname); client_write(HKEY("\n")); cprintf("%ld\n", u.msgnum_bio); cprintf("%ld\n", u.msgnum_pic); + cprintf("%s\n", u.emailaddrs); + cprintf("%ld\n", u.msgnum_inboxrules); + cprintf("%ld\n", u.lastproc_inboxrules); client_write(HKEY("\n")); } @@ -145,15 +137,24 @@ void migr_export_users(void) { void migr_export_room_msg(long msgnum, void *userdata) { - cprintf("%ld\n", msgnum); + static int count = 0; + + cprintf("%ld,", msgnum); + if (++count%10==0) { + cprintf("\n"); + } fprintf(migr_global_message_list, "%ld\n", msgnum); } void migr_export_rooms_backend(struct ctdlroom *buf, void *data) { client_write(HKEY("\n")); - client_write(HKEY("")); xml_strout(buf->QRname); client_write(HKEY("\n")); - client_write(HKEY("")); xml_strout(buf->QRpasswd); client_write(HKEY("\n")); + client_write(HKEY("")); + xml_strout(buf->QRname); + client_write(HKEY("\n")); + client_write(HKEY("")); + xml_strout(buf->QRpasswd); + client_write(HKEY("\n")); cprintf("%ld\n", buf->QRroomaide); cprintf("%ld\n", buf->QRhighest); cprintf("%ld\n", (long)buf->QRgen); @@ -176,16 +177,15 @@ void migr_export_rooms_backend(struct ctdlroom *buf, void *data) { client_write(HKEY("\n")); /* message list goes inside this tag */ - CtdlGetRoom(&CC->room, buf->QRname); client_write(HKEY("")); - client_write(HKEY("")); xml_strout(CC->room.QRname); client_write(HKEY("\n")); - client_write(HKEY("")); + client_write(HKEY("")); + xml_strout(buf->QRname); // buf->QRname rather than CC->room.QRname to guarantee consistency + client_write(HKEY("\n")); + client_write(HKEY("\n")); CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, migr_export_room_msg, NULL); client_write(HKEY("\n")); client_write(HKEY("\n")); - - } @@ -204,10 +204,13 @@ void migr_export_rooms(void) { * exporting the message multiple times.) */ snprintf(cmd, sizeof cmd, "sort -n <%s >%s", migr_tempfilename1, migr_tempfilename2); - if (system(cmd) != 0) syslog(LOG_ALERT, "Error %d", errno); + if (system(cmd) != 0) { + syslog(LOG_ERR, "migrate: error %d", errno); + } snprintf(cmd, sizeof cmd, "uniq <%s >%s", migr_tempfilename2, migr_tempfilename1); - if (system(cmd) != 0) syslog(LOG_ALERT, "Error %d", errno); - + if (system(cmd) != 0) { + syslog(LOG_ERR, "migrate: error %d", errno); + } snprintf(cmd, sizeof cmd, "wc -l %s", migr_tempfilename1); FILE *fp = popen(cmd, "r"); @@ -219,7 +222,7 @@ void migr_export_rooms(void) { else { total_msgs = 1; // any nonzero just to keep it from barfing } - syslog(LOG_DEBUG, "Total messages to be exported: %d", total_msgs); + syslog(LOG_DEBUG, "migrate: total messages to be exported: %d", total_msgs); } @@ -306,12 +309,14 @@ void migr_export_message(long msgnum) { struct MetaData smi; struct CtdlMessage *msg; struct ser_ret smr; + long bytes_written = 0; + long this_block = 0; + + // We can use a static buffer here because there will never be more than + // one of this operation happening at any given time, and it's really best + // to just keep it allocated once instead of torturing malloc/free. + // Call this function with msgnum "-1" to free the buffer when finished. - /* We can use a static buffer here because there will never be more than - * one of this operation happening at any given time, and it's really best - * to just keep it allocated once instead of torturing malloc/free. - * Call this function with msgnum "-1" to free the buffer when finished. - */ static int encoded_alloc = 0; static char *encoded_msg = NULL; @@ -324,10 +329,10 @@ void migr_export_message(long msgnum) { return; } - /* Ok, here we go ... */ + // Ok, here we go ... - msg = CtdlFetchMessage(msgnum, 1, 0); - if (msg == NULL) return; /* fail silently */ + msg = CtdlFetchMessage(msgnum, 1); + if (msg == NULL) return; // fail silently client_write(HKEY("\n")); GetMetaData(&smi, msgnum); @@ -340,7 +345,7 @@ void migr_export_message(long msgnum) { CtdlSerializeMessage(&smr, msg); CM_Free(msg); - /* Predict the buffer size we need. Expand the buffer if necessary. */ + // Predict the buffer size we need. Expand the buffer if necessary. int encoded_len = smr.len * 15 / 10 ; if (encoded_len > encoded_alloc) { encoded_alloc = encoded_len; @@ -348,13 +353,24 @@ void migr_export_message(long msgnum) { } if (encoded_msg == NULL) { - /* Questionable hack that hopes it'll work next time and we only lose one message */ + // Questionable hack that hopes it'll work next time and we only lose one message encoded_alloc = 0; } else { - /* Once we do the encoding we know the exact size */ + // Once we do the encoding we know the exact size encoded_len = CtdlEncodeBase64(encoded_msg, (char *)smr.ser, smr.len, 1); - client_write(encoded_msg, encoded_len); + + // Careful now. If the message is gargantuan, trying to write multiple gigamegs in one + // big write operation can make our transport unhappy. So we'll chunk it up 10 KB at a time. + bytes_written = 0; + while ( (bytes_written < encoded_len) && (!server_shutting_down) ) { + this_block = encoded_len - bytes_written; + if (this_block > 10240) { + this_block = 10240; + } + client_write(&encoded_msg[bytes_written], this_block); + bytes_written += this_block; + } } free(smr.ser); @@ -420,7 +436,7 @@ void migr_export_messages(void) { Ctx = CC; migr_global_message_list = fopen(migr_tempfilename1, "r"); if (migr_global_message_list != NULL) { - syslog(LOG_INFO, "Opened %s", migr_tempfilename1); + syslog(LOG_INFO, "migrate: opened %s", migr_tempfilename1); while ((Ctx->kill_me == 0) && (fgets(buf, sizeof(buf), migr_global_message_list) != NULL)) { msgnum = atol(buf); @@ -437,10 +453,10 @@ void migr_export_messages(void) { fclose(migr_global_message_list); } if (Ctx->kill_me == 0) { - syslog(LOG_INFO, "Exported %d messages.", count); + syslog(LOG_INFO, "migrate: exported %d messages.", count); } else { - syslog(LOG_ERR, "Export aborted due to client disconnect!"); + syslog(LOG_ERR, "migrate: export aborted due to client disconnect!"); } migr_export_message(-1L); /* This frees the encoding buffer */ @@ -474,8 +490,8 @@ void migr_do_export(void) { if (Ctx->kill_me == 0) migr_export_visits(); cprintf("%d\n", 25); if (Ctx->kill_me == 0) migr_export_messages(); - client_write(HKEY("\n")); cprintf("%d\n", 100); + client_write(HKEY("\n")); client_write(HKEY("000\n")); Ctx->dont_term = 0; } @@ -507,8 +523,7 @@ long import_msgnum = 0; /* * This callback stores up the data which appears in between tags. */ -void migr_xml_chardata(void *data, const XML_Char *s, int len) -{ +void migr_xml_chardata(void *data, const XML_Char *s, int len) { StrBufAppendBufPlain(migr_chardata, s, len, 0); } @@ -537,7 +552,7 @@ void migr_xml_start(void *data, const char *el, const char **attr) { } if (citadel_migrate_data != 1) { - syslog(LOG_ALERT, "Out-of-sequence tag <%s> detected. Warning: ODD-DATA!", el); + syslog(LOG_ERR, "migrate: out-of-sequence tag <%s> detected. Warning: ODD-DATA!", el); return; } @@ -571,8 +586,7 @@ void migr_xml_start(void *data, const char *el, const char **attr) { } -int migr_userrecord(void *data, const char *el) -{ +int migr_userrecord(void *data, const char *el) { if (!strcasecmp(el, "u_version")) usbuf.version = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "u_uid")) usbuf.uid = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "u_password")) safestrncpy(usbuf.password, ChrPtr(migr_chardata), sizeof usbuf.password); @@ -586,13 +600,15 @@ int migr_userrecord(void *data, const char *el) else if (!strcasecmp(el, "u_fullname")) safestrncpy(usbuf.fullname, ChrPtr(migr_chardata), sizeof usbuf.fullname); else if (!strcasecmp(el, "u_msgnum_bio")) usbuf.msgnum_bio = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "u_msgnum_pic")) usbuf.msgnum_pic = atol(ChrPtr(migr_chardata)); + else if (!strcasecmp(el, "u_emailaddrs")) safestrncpy(usbuf.emailaddrs, ChrPtr(migr_chardata), sizeof usbuf.emailaddrs); + else if (!strcasecmp(el, "u_msgnum_inboxrules")) usbuf.msgnum_inboxrules = atol(ChrPtr(migr_chardata)); + else if (!strcasecmp(el, "u_lastproc_inboxrules")) usbuf.lastproc_inboxrules = atol(ChrPtr(migr_chardata)); else return 0; return 1; } -int migr_roomrecord(void *data, const char *el) -{ +int migr_roomrecord(void *data, const char *el) { if (!strcasecmp(el, "QRname")) safestrncpy(qrbuf.QRname, ChrPtr(migr_chardata), sizeof qrbuf.QRname); else if (!strcasecmp(el, "QRpasswd")) safestrncpy(qrbuf.QRpasswd, ChrPtr(migr_chardata), sizeof qrbuf.QRpasswd); else if (!strcasecmp(el, "QRroomaide")) qrbuf.QRroomaide = atol(ChrPtr(migr_chardata)); @@ -615,8 +631,7 @@ int migr_roomrecord(void *data, const char *el) } -int migr_floorrecord(void *data, const char *el) -{ +int migr_floorrecord(void *data, const char *el) { if (!strcasecmp(el, "f_num")) floornum = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "f_flags")) flbuf.f_flags = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "f_name")) safestrncpy(flbuf.f_name, ChrPtr(migr_chardata), sizeof flbuf.f_name); @@ -628,8 +643,7 @@ int migr_floorrecord(void *data, const char *el) } -int migr_visitrecord(void *data, const char *el) -{ +int migr_visitrecord(void *data, const char *el) { if (!strcasecmp(el, "v_roomnum")) vbuf.v_roomnum = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "v_roomgen")) vbuf.v_roomgen = atol(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "v_usernum")) vbuf.v_usernum = atol(ChrPtr(migr_chardata)); @@ -656,8 +670,7 @@ int migr_visitrecord(void *data, const char *el) } -void migr_xml_end(void *data, const char *el) -{ +void migr_xml_end(void *data, const char *el) { const char *ptr; int msgcount = 0; long msgnum = 0L; @@ -671,7 +684,7 @@ void migr_xml_end(void *data, const char *el) } if (citadel_migrate_data != 1) { - syslog(LOG_ALERT, "Out-of-sequence tag <%s> detected. Warning: ODD-DATA!", el); + syslog(LOG_ERR, "migrate: out-of-sequence tag <%s> detected. Warning: ODD-DATA!", el); return; } @@ -679,9 +692,8 @@ void migr_xml_end(void *data, const char *el) /*** CONFIG ***/ - if (!strcasecmp(el, "config")) - { - syslog(LOG_DEBUG, "Imported config key=%s", ikey); + if (!strcasecmp(el, "config")) { + syslog(LOG_DEBUG, "migrate: imported config key=%s", ikey); if (ikey != NULL) { CtdlSetConfigStr(ikey, (char *)ChrPtr(migr_chardata)); @@ -689,7 +701,7 @@ void migr_xml_end(void *data, const char *el) ikey = NULL; } else { - syslog(LOG_INFO, "Closed a tag but no key name was supplied."); + syslog(LOG_INFO, "migrate: closed a tag but no key name was supplied."); } } @@ -699,7 +711,7 @@ void migr_xml_end(void *data, const char *el) ; /* Nothing to do anymore */ else if (!strcasecmp(el, "user")) { CtdlPutUser(&usbuf); - syslog(LOG_INFO, "Imported user: %s", usbuf.fullname); + syslog(LOG_INFO, "migrate: imported user: %s", usbuf.fullname); } /*** OPENID ***/ @@ -716,7 +728,7 @@ void migr_xml_end(void *data, const char *el) memcpy(&oid_data[sizeof(long)], openid_url, strlen(openid_url) + 1); cdb_store(CDB_EXTAUTH, openid_url, strlen(openid_url), oid_data, oid_data_len); free(oid_data); - syslog(LOG_INFO, "Imported OpenID: %s (%ld)", openid_url, openid_usernum); + syslog(LOG_INFO, "migrate: imported OpenID: %s (%ld)", openid_url, openid_usernum); } /*** ROOM ***/ @@ -725,12 +737,14 @@ void migr_xml_end(void *data, const char *el) ; /* Nothing to do anymore */ else if (!strcasecmp(el, "room")) { CtdlPutRoom(&qrbuf); - syslog(LOG_INFO, "Imported room: %s", qrbuf.QRname); + syslog(LOG_INFO, "migrate: imported room: %s", qrbuf.QRname); } /*** ROOM MESSAGE POINTERS ***/ - else if (!strcasecmp(el, "FRname")) safestrncpy(FRname, ChrPtr(migr_chardata), sizeof FRname); + else if (!strcasecmp(el, "FRname")) { + safestrncpy(FRname, ChrPtr(migr_chardata), sizeof FRname); + } else if (!strcasecmp(el, "FRmsglist")) { if (!IsEmptyStr(FRname)) { @@ -738,7 +752,7 @@ void migr_xml_end(void *data, const char *el) msglist_alloc = 1000; msglist = malloc(sizeof(long) * msglist_alloc); - syslog(LOG_DEBUG, "Message list for: %s", FRname); + syslog(LOG_DEBUG, "migrate: message list for: %s", FRname); ptr = ChrPtr(migr_chardata); while (*ptr != 0) { @@ -766,7 +780,7 @@ void migr_xml_end(void *data, const char *el) free(msglist); msglist = NULL; msglist_alloc = 0; - syslog(LOG_DEBUG, "Imported %d messages.", msgcount); + syslog(LOG_DEBUG, "migrate: imported %d messages.", msgcount); if (server_shutting_down) { return; } @@ -779,7 +793,7 @@ void migr_xml_end(void *data, const char *el) else if (!strcasecmp(el, "floor")) { CtdlPutFloor(&flbuf, floornum); - syslog(LOG_INFO, "Imported floor #%d (%s)", floornum, flbuf.f_name); + syslog(LOG_INFO, "migrate: imported floor #%d (%s)", floornum, flbuf.f_name); } /*** VISITS ***/ @@ -788,7 +802,7 @@ void migr_xml_end(void *data, const char *el) } else if (!strcasecmp(el, "visit")) { put_visit(&vbuf); - syslog(LOG_INFO, "Imported visit: %ld/%ld/%ld", vbuf.v_roomnum, vbuf.v_roomgen, vbuf.v_usernum); + syslog(LOG_INFO, "migrate: imported visit: %ld/%ld/%ld", vbuf.v_roomnum, vbuf.v_roomgen, vbuf.v_usernum); } /*** MESSAGES ***/ @@ -798,8 +812,7 @@ void migr_xml_end(void *data, const char *el) else if (!strcasecmp(el, "msg_meta_rfc822_length")) smi.meta_rfc822_length = atoi(ChrPtr(migr_chardata)); else if (!strcasecmp(el, "msg_meta_content_type")) safestrncpy(smi.meta_content_type, ChrPtr(migr_chardata), sizeof smi.meta_content_type); - else if (!strcasecmp(el, "msg_text")) - { + else if (!strcasecmp(el, "msg_text")) { long rc; struct CtdlMessage *msg; @@ -821,7 +834,7 @@ void migr_xml_end(void *data, const char *el) } syslog(LOG_INFO, - "%s message #%ld, size=%d, refcount=%d, bodylength=%ld, content-type: %s", + "migrate: %s message #%ld, size=%d, refcount=%d, bodylength=%ld, content-type: %s", (rc!= 0)?"failed to import ":"Imported ", import_msgnum, StrLength(migr_MsgData), @@ -842,14 +855,12 @@ void migr_xml_end(void *data, const char *el) * Import begins here */ void migr_do_import(void) { - StrBuf *Buf; XML_Parser xp; - int Finished = 0; + char buf[SIZ]; unbuffer_output(); migr_chardata = NewStrBufPlain(NULL, SIZ * 20); migr_MsgData = NewStrBufPlain(NULL, SIZ * 20); - Buf = NewStrBufPlain(NULL, SIZ); xp = XML_ParserCreate(NULL); if (!xp) { cprintf("%d Failed to create XML parser instance\n", ERROR+INTERNAL_ERROR); @@ -865,24 +876,14 @@ void migr_do_import(void) { client_set_inbound_buf(SIZ * 10); - while (!Finished && client_read_random_blob(Buf, -1) >= 0) { - if ((StrLength(Buf) > 4) && !strcmp(ChrPtr(Buf) + StrLength(Buf) - 4, "000\n")) { - Finished = 1; - StrBufCutAt(Buf, StrLength(Buf) - 4, NULL); - } + while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) { + XML_Parse(xp, buf, strlen(buf), 0); if (server_shutting_down) break; // Should we break or return? - - if (StrLength(Buf) == 0) - continue; - - XML_Parse(xp, ChrPtr(Buf), StrLength(Buf), 0); - FlushStrBuf(Buf); } XML_Parse(xp, "", 0, 1); XML_ParserFree(xp); - FreeStrBuf(&Buf); FreeStrBuf(&migr_chardata); FreeStrBuf(&migr_MsgData); rebuild_euid_index(); @@ -914,9 +915,7 @@ void migr_do_listdirs(void) { StrBuf *PlainMessageBuf = NULL; HashList *UsedMessageIDS = NULL; -int migr_restore_message_metadata(long msgnum, int refcount) -{ - CitContext *CCC = MyContext(); +int migr_restore_message_metadata(long msgnum, int refcount) { struct MetaData smi; struct CtdlMessage *msg; char *mptr = NULL; @@ -945,7 +944,7 @@ int migr_restore_message_metadata(long msgnum, int refcount) /* Ok, here we go ... */ - msg = CtdlFetchMessage(msgnum, 1, 0); + msg = CtdlFetchMessage(msgnum, 1); if (msg == NULL) { return 1; } @@ -972,13 +971,13 @@ int migr_restore_message_metadata(long msgnum, int refcount) } } - CCC->redirect_buffer = PlainMessageBuf; + CC->redirect_buffer = PlainMessageBuf; CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, QP_EADDR); - smi.meta_rfc822_length = StrLength(CCC->redirect_buffer); - CCC->redirect_buffer = NULL; + smi.meta_rfc822_length = StrLength(CC->redirect_buffer); + CC->redirect_buffer = NULL; syslog(LOG_INFO, - "Setting message #%ld meta data to: refcount=%d, bodylength=%ld, content-type: %s", + "migrate: setting message #%ld meta data to: refcount=%d, bodylength=%ld, content-type: %s", smi.meta_msgnum, smi.meta_refcount, smi.meta_rfc822_length, @@ -986,9 +985,7 @@ int migr_restore_message_metadata(long msgnum, int refcount) ); PutMetaData(&smi); - CM_Free(msg); - return 0; } @@ -999,9 +996,7 @@ void migr_check_room_msg(long msgnum, void *userdata) { void migr_check_rooms_backend(struct ctdlroom *buf, void *data) { - /* message list goes inside this tag */ - CtdlGetRoom(&CC->room, buf->QRname); CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, migr_check_room_msg, NULL); } @@ -1012,7 +1007,7 @@ void RemoveMessagesFromRooms(StrBuf *RoomNameVec, long msgnum) { const char *Pos = NULL; StrBuf *oneRoom = NewStrBuf(); - syslog(LOG_INFO, "removing message pointer %ld from these rooms: %s", msgnum, ChrPtr(RoomNameVec)); + syslog(LOG_INFO, "migrate: removing message pointer %ld from these rooms: %s", msgnum, ChrPtr(RoomNameVec)); while (Pos != StrBufNOTNULL){ StrBufExtract_NextToken(oneRoom, RoomNameVec, &Pos, '|'); @@ -1047,13 +1042,15 @@ void migr_do_restore_meta(void) { * exporting the message multiple times.) */ snprintf(cmd, sizeof cmd, "sort -n <%s >%s", migr_tempfilename1, migr_tempfilename2); - if (system(cmd) != 0) syslog(LOG_ALERT, "Error %d", errno); + if (system(cmd) != 0) { + syslog(LOG_ERR, "migrate: error %d", errno); + } RoomNames = NewStrBuf(); Ctx = CC; migr_global_message_list = fopen(migr_tempfilename2, "r"); if (migr_global_message_list != NULL) { - syslog(LOG_INFO, "Opened %s", migr_tempfilename1); + syslog(LOG_INFO, "migrate: opened %s", migr_tempfilename1); while ((Ctx->kill_me == 0) && (fgets(buf, sizeof(buf), migr_global_message_list) != NULL)) { msgnum = atol(buf);