mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 19:16:15 +00:00
app_voicemail_odbc: Allow audio to be kept on disk
This commit adds a new voicemail.conf option 'odbc_audio_on_disk' which when set causes the ODBC variant of app_voicemail to leave the message and greeting audio files on disk and only store the message metadata in the database. This option came from a concern that the database could grow to large and cause remote access and/or replication to become slow. In a clustering situation with this option, all asterisk instances would share the same database for the metadata and either use a shared filesystem or other filesystem replication service much more suitable for synchronizing files. The changes to app_voicemail to implement this feature were actually quite small but due to the complexity of the module, the actual source code changes were greater. They fall into the following categories: * Tracing. The module is so complex that it was impossible to figure out the path taken for various scenarios without the addition of many SCOPE_ENTER, SCOPE_EXIT and ast_trace statements, even in code that's not related to the functional change. Making this worse was the fact that many "if" statements in this module didn't use braces. Since the tracing macros add multiple statements, many "if" statements had to be converted to use braces. * Excessive use of PATH_MAX. Previous maintainers of this module used PATH_MAX to allocate character arrays for filesystem paths and SQL statements as though they cost nothing. In fact, PATH_MAX is defined as 4096 bytes! Some functions had (and still have) multiples of these. One function has 7. Given that the vast majority of installations use the default spool directory path `/var/spool/asterisk/voicemail`, the actual path length is usually less than 80 bytes. That's over 4000 bytes wasted. It was the same for SQL statement buffers. A 4K buffer for statement that only needed 60 bytes. All of these PATH_MAX allocations in the ODBC related code were changed to dynamically allocated buffers. The rest will have to be addressed separately. * Bug fixes. During the development of this feature, several pre-existing ODBC related bugs were discovered and fixed. They had to do with leaving orphaned files on disk, not preserving original message ids when moving messages between folders, not honoring the "formats" config parameter in certain circumstances, etc. UserNote: This commit adds a new voicemail.conf option 'odbc_audio_on_disk' which when set causes the ODBC variant of app_voicemail_odbc to leave the message and greeting audio files on disk and only store the message metadata in the database. Much more information can be found in the voicemail.conf.sample file.
This commit is contained in:
20
main/app.c
20
main/app.c
@@ -1794,7 +1794,11 @@ static int global_maxsilence = 0;
|
||||
* \retval 't' Recording ended from the message exceeding the maximum duration, or via DTMF in prepend mode
|
||||
* \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
|
||||
*/
|
||||
static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
|
||||
static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
const char *recordfile, int maxtime, const char *fmt, int *duration,
|
||||
int *sound_duration, int beep, int silencethreshold, int maxsilence,
|
||||
const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf,
|
||||
int skip_confirmation_sound, enum ast_record_if_exists if_exists)
|
||||
{
|
||||
int d = 0;
|
||||
char *fmts;
|
||||
@@ -1812,6 +1816,8 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
struct ast_silence_generator *silgen = NULL;
|
||||
char prependfile[PATH_MAX];
|
||||
int ioflags; /* IO flags for writing output file */
|
||||
SCOPE_ENTER(3, "%s: play: '%s' record: '%s' path: '%s' prepend: %d\n",
|
||||
ast_channel_name(chan), playfile, recordfile, path, prepend);
|
||||
|
||||
ioflags = O_CREAT|O_WRONLY;
|
||||
|
||||
@@ -1849,19 +1855,22 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
|
||||
if (playfile || beep) {
|
||||
if (!beep) {
|
||||
ast_trace(-1, "Playing '%s' to '%s'\n", playfile, ast_channel_name(chan));
|
||||
d = ast_play_and_wait(chan, playfile);
|
||||
}
|
||||
if (d > -1) {
|
||||
ast_trace(-1, "Playing 'beep' to '%s'\n", ast_channel_name(chan));
|
||||
d = ast_stream_and_wait(chan, "beep", "");
|
||||
}
|
||||
if (d < 0) {
|
||||
return -1;
|
||||
SCOPE_EXIT_RTN_VALUE(-1, "Failed to play. RC: %d\n", d);
|
||||
}
|
||||
}
|
||||
|
||||
if (prepend) {
|
||||
ast_copy_string(prependfile, recordfile, sizeof(prependfile));
|
||||
strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
|
||||
ast_trace(-1, "Prepending to '%s'\n", prependfile);
|
||||
}
|
||||
|
||||
fmts = ast_strdupa(fmt);
|
||||
@@ -1887,7 +1896,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */
|
||||
for (x = 0; x < fmtcnt; x++) {
|
||||
others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, ioflags, 0, AST_FILE_MODE);
|
||||
ast_verb(3, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
|
||||
ast_trace(-1, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
|
||||
|
||||
if (!others[x]) {
|
||||
break;
|
||||
@@ -2178,7 +2187,8 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
ast_closestream(others[x]);
|
||||
ast_closestream(realfiles[x]);
|
||||
ast_filerename(prependfile, recordfile, sfmt[x]);
|
||||
ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
|
||||
ast_trace(-1, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
|
||||
ast_trace(-1, "Deleting the prepend file %s.%s\n", recordfile, sfmt[x]);
|
||||
ast_filedelete(prependfile, sfmt[x]);
|
||||
}
|
||||
} else {
|
||||
@@ -2200,7 +2210,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
|
||||
if (sildet) {
|
||||
ast_dsp_free(sildet);
|
||||
}
|
||||
return res;
|
||||
SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res);
|
||||
}
|
||||
|
||||
static const char default_acceptdtmf[] = "#";
|
||||
|
Reference in New Issue
Block a user