summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2013-10-03 14:58:16 +0000
committerMark Michelson <mmichelson@digium.com>2013-10-03 14:58:16 +0000
commitee21eee7e067573ad83bd0df492036094b4dbaca (patch)
tree024e25a92079bc7e5348bd55cc29eff2f3c38dec /main
parentc977f73e136eca1f2aaccd0ea0fe45c350906374 (diff)
Cache string values of formats on ast_format_cap() to save processing.
Channel snapshots have string representations of the channel's native formats. Prior to this change, the format strings were re-created on ever channel snapshot creation. Since channel native formats rarely change, this was very wasteful. Now, string representations of formats may optionally be stored on the ast_format_cap for cases where string representations may be requested frequently. When formats are altered, the string cache is marked as invalid. When strings are requested, the cache validity is checked. If the cache is valid, then the cached strings are copied. If the cache is invalid, then the string cache is rebuilt and copied, and the cache is marked as being valid again. Review: https://reviewboard.asterisk.org/r/2879 ........ Merged revisions 400356 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400363 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/bridge_basic.c4
-rw-r--r--main/ccss.c2
-rw-r--r--main/channel.c10
-rw-r--r--main/core_local.c2
-rw-r--r--main/dial.c2
-rw-r--r--main/file.c4
-rw-r--r--main/format_cap.c111
-rw-r--r--main/manager.c2
-rw-r--r--main/media_index.c2
-rw-r--r--main/rtp_engine.c8
10 files changed, 93 insertions, 54 deletions
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 942a3ce25..76dfb2893 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -2218,7 +2218,7 @@ static void recall_callback(struct ast_dial *dial)
static int recalling_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc_nolock(), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
struct ast_format fmt;
if (!cap) {
@@ -2346,7 +2346,7 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
static int retransfer_enter(struct attended_transfer_properties *props)
{
- RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc_nolock(), ast_format_cap_destroy);
+ RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
struct ast_format fmt;
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
int cause;
diff --git a/main/ccss.c b/main/ccss.c
index 3068c6ffa..fadc6e36f 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -2815,7 +2815,7 @@ static void *generic_recall(void *data)
const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
struct ast_format tmp_fmt;
- struct ast_format_cap *tmp_cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
if (!tmp_cap) {
return NULL;
diff --git a/main/channel.c b/main/channel.c
index 36528f5df..e6025c062 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -879,7 +879,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_stage_snapshot(tmp);
- if (!(nativeformats = ast_format_cap_alloc())) {
+ if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_CACHE_STRINGS))) {
ao2_ref(tmp, -1);
/* format capabilities structure allocation failure */
return NULL;
@@ -5401,7 +5401,7 @@ static int set_format(struct ast_channel *chan,
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
int res;
if (!cap) {
@@ -5422,7 +5422,7 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
int ast_set_read_format_by_id(struct ast_channel *chan, enum ast_format_id id)
{
- struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
struct ast_format tmp_format;
int res;
@@ -5454,7 +5454,7 @@ int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
{
- struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
int res;
if (!cap) {
@@ -5475,7 +5475,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
int ast_set_write_format_by_id(struct ast_channel *chan, enum ast_format_id id)
{
- struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
struct ast_format tmp_format;
int res;
diff --git a/main/core_local.c b/main/core_local.c
index d4ec06d9f..4a047032c 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -1018,7 +1018,7 @@ int ast_local_init(void)
return -1;
}
- if (!(local_tech.capabilities = ast_format_cap_alloc())) {
+ if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
return -1;
}
ast_format_cap_add_all(local_tech.capabilities);
diff --git a/main/dial.c b/main/dial.c
index 6d796e2b9..8cc6f9c89 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -273,7 +273,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
} else if (chan) {
cap_request = ast_channel_nativeformats(chan);
} else {
- cap_all_audio = ast_format_cap_alloc_nolock();
+ cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
ast_format_cap_add_all_by_type(cap_all_audio, AST_FORMAT_TYPE_AUDIO);
cap_request = cap_all_audio;
}
diff --git a/main/file.c b/main/file.c
index b24cdeeb3..ffdbf1821 100644
--- a/main/file.c
+++ b/main/file.c
@@ -749,7 +749,7 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char
buflen = strlen(preflang) + strlen(filename) + 4;
buf = ast_alloca(buflen);
- if (!(file_fmt_cap = ast_format_cap_alloc_nolock())) {
+ if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
return NULL;
}
if (!fileexists_core(filename, NULL, preflang, buf, buflen, file_fmt_cap) ||
@@ -797,7 +797,7 @@ struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *fil
if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO)) {
return NULL;
}
- if (!(tmp_cap = ast_format_cap_alloc_nolock())) {
+ if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
return NULL;
}
/* Video is supported, so see what video formats exist for this file */
diff --git a/main/format_cap.c b/main/format_cap.c
index 5fc110812..96c2fa3aa 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -38,13 +38,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
+#define FORMAT_STR_BUFSIZE 256
struct ast_format_cap {
/* The capabilities structure is just an ao2 container of ast_formats */
struct ao2_container *formats;
struct ao2_iterator it;
/*! TRUE if the formats container created without a lock. */
- int nolock;
+ struct ast_flags flags;
+ unsigned int string_cache_valid;
+ char format_strs[0];
};
/*! format exists within capabilities structure if it is identical to
@@ -67,17 +70,27 @@ static int hash_cb(const void *obj, const int flags)
return format->id;
}
-static struct ast_format_cap *cap_alloc_helper(int nolock)
+struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags)
{
- struct ast_format_cap *cap = ast_calloc(1, sizeof(*cap));
+ struct ast_format_cap *cap;
+ unsigned int alloc_size;
+
+ alloc_size = sizeof(*cap);
+ if (flags & AST_FORMAT_CAP_FLAG_CACHE_STRINGS) {
+ alloc_size += FORMAT_STR_BUFSIZE;
+ }
+ cap = ast_calloc(1, alloc_size);
if (!cap) {
return NULL;
}
- cap->nolock = nolock;
+
+ ast_set_flag(&cap->flags, flags);
cap->formats = ao2_container_alloc_options(
- nolock ? AO2_ALLOC_OPT_LOCK_NOLOCK : AO2_ALLOC_OPT_LOCK_MUTEX,
- 283, hash_cb, cmp_cb);
+ (flags & AST_FORMAT_CAP_FLAG_NOLOCK) ?
+ AO2_ALLOC_OPT_LOCK_NOLOCK :
+ AO2_ALLOC_OPT_LOCK_MUTEX,
+ 11, hash_cb, cmp_cb);
if (!cap->formats) {
ast_free(cap);
return NULL;
@@ -86,16 +99,6 @@ static struct ast_format_cap *cap_alloc_helper(int nolock)
return cap;
}
-struct ast_format_cap *ast_format_cap_alloc_nolock(void)
-{
- return cap_alloc_helper(1);
-}
-
-struct ast_format_cap *ast_format_cap_alloc(void)
-{
- return cap_alloc_helper(0);
-}
-
void *ast_format_cap_destroy(struct ast_format_cap *cap)
{
if (!cap) {
@@ -106,7 +109,7 @@ void *ast_format_cap_destroy(struct ast_format_cap *cap)
return NULL;
}
-void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
+static void format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
{
struct ast_format *fnew;
@@ -118,9 +121,16 @@ void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *for
}
ast_format_copy(fnew, format);
ao2_link(cap->formats, fnew);
+
ao2_ref(fnew, -1);
}
+void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format)
+{
+ format_cap_add(cap, format);
+ cap->string_cache_valid = 0;
+}
+
void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type)
{
int x;
@@ -129,9 +139,10 @@ void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_
for (x = 0; x < f_len; x++) {
if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == type) {
- ast_format_cap_add(cap, &f_list[x].format);
+ format_cap_add(cap, &f_list[x].format);
}
}
+ cap->string_cache_valid = 0;
ast_format_list_destroy(f_list);
}
@@ -142,8 +153,9 @@ void ast_format_cap_add_all(struct ast_format_cap *cap)
const struct ast_format_list *f_list = ast_format_list_get(&f_len);
for (x = 0; x < f_len; x++) {
- ast_format_cap_add(cap, &f_list[x].format);
+ format_cap_add(cap, &f_list[x].format);
}
+ cap->string_cache_valid = 0;
ast_format_list_destroy(f_list);
}
@@ -153,7 +165,7 @@ static int append_cb(void *obj, void *arg, int flag)
struct ast_format *format = (struct ast_format *) obj;
if (!ast_format_cap_iscompatible(result, format)) {
- ast_format_cap_add(result, format);
+ format_cap_add(result, format);
}
return 0;
@@ -162,6 +174,7 @@ static int append_cb(void *obj, void *arg, int flag)
void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src)
{
ao2_callback(src->formats, OBJ_NODATA, append_cb, dst);
+ dst->string_cache_valid = 0;
}
static int copy_cb(void *obj, void *arg, int flag)
@@ -169,28 +182,32 @@ static int copy_cb(void *obj, void *arg, int flag)
struct ast_format_cap *result = (struct ast_format_cap *) arg;
struct ast_format *format = (struct ast_format *) obj;
- ast_format_cap_add(result, format);
+ format_cap_add(result, format);
return 0;
}
+static void format_cap_remove_all(struct ast_format_cap *cap)
+{
+ ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL);
+}
+
void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src)
{
- ast_format_cap_remove_all(dst);
+ format_cap_remove_all(dst);
ao2_callback(src->formats, OBJ_NODATA, copy_cb, dst);
+ dst->string_cache_valid = 0;
}
struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap)
{
struct ast_format_cap *dst;
- if (cap->nolock) {
- dst = ast_format_cap_alloc_nolock();
- } else {
- dst = ast_format_cap_alloc();
- }
+
+ dst = ast_format_cap_alloc(ast_test_flag(&cap->flags, AST_FLAGS_ALL));
if (!dst) {
return NULL;
}
ao2_callback(cap->formats, OBJ_NODATA, copy_cb, dst);
+ dst->string_cache_valid = 0;
return dst;
}
@@ -217,6 +234,7 @@ int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
fremove = ao2_callback(cap->formats, OBJ_POINTER | OBJ_UNLINK, find_exact_cb, format);
if (fremove) {
ao2_ref(fremove, -1);
+ cap->string_cache_valid = 0;
return 0;
}
@@ -259,6 +277,7 @@ int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id
/* match_found will be set if at least one item was removed */
if (data.match_found) {
+ cap->string_cache_valid = 0;
return 0;
}
@@ -278,17 +297,20 @@ void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_ty
OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
multiple_by_type_cb,
&type);
+ cap->string_cache_valid = 0;
}
void ast_format_cap_remove_all(struct ast_format_cap *cap)
{
- ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL);
+ format_cap_remove_all(cap);
+ cap->string_cache_valid = 0;
}
void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format)
{
- ast_format_cap_remove_all(cap);
- ast_format_cap_add(cap, format);
+ format_cap_remove_all(cap);
+ format_cap_add(cap, format);
+ cap->string_cache_valid = 0;
}
int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result)
@@ -434,7 +456,7 @@ int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast
struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
struct ao2_iterator it;
- struct ast_format_cap *result = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
struct ast_format *tmp;
struct find_joint_data data = {
.joint_found = 0,
@@ -472,7 +494,7 @@ static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast
.joint_found = 0,
};
if (!append) {
- ast_format_cap_remove_all(result);
+ format_cap_remove_all(result);
}
it = ao2_iterator_init(cap1->formats, 0);
while ((tmp = ao2_iterator_next(&it))) {
@@ -485,6 +507,8 @@ static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast
}
ao2_iterator_destroy(&it);
+ result->string_cache_valid = 0;
+
return ao2_container_count(result->formats) ? 1 : 0;
}
@@ -501,7 +525,7 @@ int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct as
struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype)
{
struct ao2_iterator it;
- struct ast_format_cap *result = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
struct ast_format *tmp;
if (!result) {
@@ -575,7 +599,7 @@ int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *form
return 0;
}
-char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+static char *getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
{
int x;
unsigned len;
@@ -611,6 +635,20 @@ char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *
return buf;
}
+char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
+{
+ if (ast_test_flag(&cap->flags, AST_FORMAT_CAP_FLAG_CACHE_STRINGS)) {
+ if (!cap->string_cache_valid) {
+ getformatname_multiple(cap->format_strs, FORMAT_STR_BUFSIZE, cap);
+ cap->string_cache_valid = 1;
+ }
+ ast_copy_string(buf, cap->format_strs, size);
+ return buf;
+ }
+
+ return getformatname_multiple(buf, size, cap);
+}
+
uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap)
{
uint64_t res = 0;
@@ -632,11 +670,12 @@ void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src)
int x;
struct ast_format tmp_format = { 0, };
- ast_format_cap_remove_all(dst);
+ format_cap_remove_all(dst);
for (x = 0; x < 64; x++) {
tmp = (1ULL << x);
if (tmp & src) {
- ast_format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp));
+ format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp));
}
}
+ dst->string_cache_valid = 0;
}
diff --git a/main/manager.c b/main/manager.c
index f06b7dbca..f3e883407 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -4683,7 +4683,7 @@ static int action_originate(struct mansession *s, const struct message *m)
int reason = 0;
char tmp[256];
char tmp2[256];
- struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
struct ast_format tmp_fmt;
pthread_t th;
int bridge_early = 0;
diff --git a/main/media_index.c b/main/media_index.c
index 605cee927..64fbbbddb 100644
--- a/main/media_index.c
+++ b/main/media_index.c
@@ -67,7 +67,7 @@ static struct media_variant *media_variant_alloc(const char *variant_str)
return NULL;
}
- variant->formats = ast_format_cap_alloc();
+ variant->formats = ast_format_cap_alloc(0);
if (!variant->formats) {
return NULL;
}
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index c7e359795..54e1e45e3 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -1081,8 +1081,8 @@ void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struc
struct ast_rtp_glue *glue0, *glue1;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock();
- struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
/* Lock both channels so we can look for the glue that binds them together */
ast_channel_lock_both(c0, c1);
@@ -1167,8 +1167,8 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
struct ast_rtp_glue *glue0, *glue1;
enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
- struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock();
- struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+ struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
/* If there is no second channel just immediately bail out, we are of no use in that scenario */
if (!c1 || !cap1 || !cap0) {