]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_voicemail.c: Completely resequence mailbox folders.
authorSean Bright <sean@seanbright.com>
Mon, 27 Nov 2023 15:20:02 +0000 (10:20 -0500)
committerAsterisk Development Team <asteriskteam@digium.com>
Fri, 12 Jan 2024 18:32:13 +0000 (18:32 +0000)
Resequencing is a process that occurs when we open a voicemail folder
and discover that there are gaps between messages (e.g. `msg0000.txt`
is missing but `msg0001.txt` exists). Resequencing involves shifting
the existing messages down so we end up with a sequential list of
messages.

Currently, this process stops after reaching a threshold based on the
message limit (`maxmsg`) configured on the current folder. However, if
`maxmsg` is lowered when a voicemail folder contains more than
`maxmsg + 10` messages, resequencing will not run completely leaving
the mailbox in an inconsistent state.

We now resequence up to the maximum number of messages permitted by
`app_voicemail` (currently hard-coded at 9999 messages).

Fixes #86

(cherry picked from commit fbe92dce2b10ceca70ca12a5b901c40f308b9393)

apps/app_voicemail.c

index f37b73e17900e1a2ce49ef637a1d99b6a3908f45..e4067abd0632a9c8bd665d25ef6df17621783c4a 100644 (file)
@@ -4112,16 +4112,14 @@ bail:
 
 /*!
  * \brief Determines the highest message number in use for a given user and mailbox folder.
- * \param vmu
  * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
  *
  * This method is used when mailboxes are stored in an ODBC back end.
  * Typical use to set the msgnum would be to take the value returned from this method and add one to it.
  *
  * \return the value of zero or greater to indicate the last message index in use, -1 to indicate none.
-
  */
-static int last_message_index(struct ast_vm_user *vmu, char *dir)
+static int last_message_index(char *dir)
 {
        int x = -1;
        int res;
@@ -4684,7 +4682,6 @@ static void rename_file(char *sfn, char *dfn)
 
 /*!
  * \brief Determines the highest message number in use for a given user and mailbox folder.
- * \param vmu
  * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
  *
  * This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP).
@@ -4693,7 +4690,7 @@ static void rename_file(char *sfn, char *dfn)
  * \note Should always be called with a lock already set on dir.
  * \return the value of zero or greaterto indicate the last message index in use, -1 to indicate none.
  */
-static int last_message_index(struct ast_vm_user *vmu, char *dir)
+static int last_message_index(char *dir)
 {
        int x;
        unsigned char map[MAXMSGLIMIT] = "";
@@ -4720,12 +4717,8 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
        }
        closedir(msgdir);
 
-       for (x = 0; x < vmu->maxmsg; x++) {
-               if (map[x] == 1) {
-                       stopcount--;
-               } else if (map[x] == 0 && !stopcount) {
-                       break;
-               }
+       for (x = 0; x < MAXMSGLIMIT && stopcount; x++) {
+               stopcount -= map[x];
        }
 
        return x - 1;
@@ -5998,7 +5991,7 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i
        if (vm_lock_path(todir))
                return ERROR_LOCK_PATH;
 
-       recipmsgnum = last_message_index(recip, todir) + 1;
+       recipmsgnum = last_message_index(todir) + 1;
        if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
                make_file(topath, sizeof(topath), todir, recipmsgnum);
 #ifndef ODBC_STORAGE
@@ -6493,7 +6486,7 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata)
                return -1;
        }
 
-       msgnum = last_message_index(recipient, dir) + 1;
+       msgnum = last_message_index(dir) + 1;
 #endif
 
        /* Lock the directory receiving the voicemail since we want it to still exist when we attempt to copy the voicemail.
@@ -7061,7 +7054,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                        }
                                } else {
 #ifndef IMAP_STORAGE
-                                       msgnum = last_message_index(vmu, dir) + 1;
+                                       msgnum = last_message_index(dir) + 1;
 #endif
                                        make_file(fn, sizeof(fn), dir, msgnum);
 
@@ -7183,7 +7176,7 @@ static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
                return ERROR_LOCK_PATH;
        }
 
-       for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
+       for (x = 0, dest = 0; dest != stopcount && x < MAXMSGLIMIT; x++) {
                make_file(sfn, sizeof(sfn), dir, x);
                if (EXISTS(dir, x, sfn, NULL)) {
 
@@ -7272,7 +7265,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
        if (vm_lock_path(ddir))
                return ERROR_LOCK_PATH;
 
-       x = last_message_index(vmu, ddir) + 1;
+       x = last_message_index(ddir) + 1;
 
        if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
                x--;
@@ -9132,8 +9125,8 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
                return ERROR_LOCK_PATH;
        }
 
-       /* for local storage, checks directory for messages up to maxmsg limit */
-       last_msg = last_message_index(vmu, vms->curdir);
+       /* for local storage, checks directory for messages up to MAXMSGLIMIT */
+       last_msg = last_message_index(vms->curdir);
        ast_unlock_path(vms->curdir);
 
        if (last_msg < -1) {
@@ -9169,7 +9162,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
        }
 
        /* update count as message may have arrived while we've got mailbox open */
-       last_msg_idx = last_message_index(vmu, vms->curdir);
+       last_msg_idx = last_message_index(vms->curdir);
        if (last_msg_idx != vms->lastmsg) {
                ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
        }