mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-30 18:21:52 +00:00
channelstorage: Allow storage driver read locking to be skipped.
After PR #1498 added read locking to channelstorage_cpp_map_name_id, if ARI channels/externalMedia was called with a custom channel id AND the cpp_map_name_id channel storage backend is in use, a deadlock can occur when hanging up the channel. It's actually triggered in channel.c:__ast_channel_alloc_ap() when it gets a write lock on the channelstorage driver then subsequently does a lookup for channel uniqueid which now does a read lock. This is an invalid operation and causes the lock state to get "bad". When the channels try to hang up, a write lock is attempted again which hangs and causes the deadlock. Now instead of the cpp_map_name_id channelstorage driver "get" APIs automatically performing a read lock, they take a "lock" parameter which allows a caller who already has a write lock to indicate that the "get" API must not attempt its own lock. This prevents the state from getting mesed up. The ao2_legacy driver uses the ao2 container's recursive mutex so doesn't have this issue but since it also implements the common channelstorage API, it needed its "get" implementations updated to take the lock parameter. They just don't use it. Resolves: #1578
This commit is contained in:
@@ -498,7 +498,7 @@ void ast_softhangup_all(void)
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
int ast_active_channels(void)
|
||||
{
|
||||
return current_channel_storage_instance ? CHANNELSTORAGE_API(current_channel_storage_instance, active_channels) : 0;
|
||||
return current_channel_storage_instance ? CHANNELSTORAGE_API(current_channel_storage_instance, active_channels, 1) : 0;
|
||||
}
|
||||
|
||||
int ast_undestroyed_channels(void)
|
||||
@@ -707,7 +707,7 @@ static const struct ast_channel_tech null_tech = {
|
||||
static void ast_channel_destructor(void *obj);
|
||||
static void ast_dummy_channel_destructor(void *obj);
|
||||
|
||||
static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
static int do_ids_conflict(const struct ast_assigned_ids *assignedids, int rdlock)
|
||||
{
|
||||
struct ast_channel *conflict;
|
||||
|
||||
@@ -717,7 +717,7 @@ static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
|
||||
if (!ast_strlen_zero(assignedids->uniqueid)) {
|
||||
conflict = CHANNELSTORAGE_API(current_channel_storage_instance,
|
||||
get_by_uniqueid, assignedids->uniqueid);
|
||||
get_by_uniqueid, assignedids->uniqueid, rdlock);
|
||||
if (conflict) {
|
||||
ast_log(LOG_ERROR, "Channel Unique ID '%s' already in use by channel %s(%p)\n",
|
||||
assignedids->uniqueid, ast_channel_name(conflict), conflict);
|
||||
@@ -728,7 +728,7 @@ static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
|
||||
if (!ast_strlen_zero(assignedids->uniqueid2)) {
|
||||
conflict = CHANNELSTORAGE_API(current_channel_storage_instance,
|
||||
get_by_uniqueid, assignedids->uniqueid2);
|
||||
get_by_uniqueid, assignedids->uniqueid2, rdlock);
|
||||
if (conflict) {
|
||||
ast_log(LOG_ERROR, "Channel Unique ID2 '%s' already in use by channel %s(%p)\n",
|
||||
assignedids->uniqueid2, ast_channel_name(conflict), conflict);
|
||||
@@ -933,7 +933,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
|
||||
|
||||
CHANNELSTORAGE_API(current_channel_storage_instance, wrlock);
|
||||
|
||||
if (do_ids_conflict(assignedids)) {
|
||||
if (do_ids_conflict(assignedids, 0)) {
|
||||
ast_channel_internal_errno_set(AST_CHANNEL_ERROR_ID_EXISTS);
|
||||
ast_channel_unlock(tmp);
|
||||
CHANNELSTORAGE_API(current_channel_storage_instance, unlock);
|
||||
@@ -1324,7 +1324,7 @@ struct ast_channel *ast_channel_callback(
|
||||
ast_log(LOG_ERROR, "callback function must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, callback, cb_fn, arg, data, ao2_flags);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, callback, cb_fn, arg, data, ao2_flags, 1);
|
||||
}
|
||||
|
||||
struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i)
|
||||
@@ -1388,7 +1388,7 @@ struct ast_channel *ast_channel_get_by_name_prefix(const char *name, size_t name
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, name_len);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, name_len, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1405,7 +1405,7 @@ struct ast_channel *ast_channel_get_by_name(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, 0);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, 0, 1);
|
||||
}
|
||||
|
||||
struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *context)
|
||||
@@ -1417,7 +1417,7 @@ struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *cont
|
||||
ast_log(LOG_ERROR, "exten and context must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_exten, exten, context);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_exten, exten, context, 1);
|
||||
}
|
||||
|
||||
struct ast_channel *ast_channel_get_by_uniqueid(const char *uniqueid)
|
||||
@@ -1429,7 +1429,7 @@ struct ast_channel *ast_channel_get_by_uniqueid(const char *uniqueid)
|
||||
ast_log(LOG_ERROR, "uniqueid must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_uniqueid, uniqueid);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_uniqueid, uniqueid, 1);
|
||||
}
|
||||
|
||||
int ast_is_deferrable_frame(const struct ast_frame *frame)
|
||||
|
||||
@@ -85,12 +85,12 @@ int channelstorage_exten_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context)
|
||||
const char *exten, const char *context, int rdlock)
|
||||
{
|
||||
char *l_exten = (char *) exten;
|
||||
char *l_context = (char *) context;
|
||||
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_exten_cb, l_context, l_exten, 0);
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_exten_cb, l_context, l_exten, 0, rdlock);
|
||||
}
|
||||
|
||||
int channelstorage_name_cb(void *obj, void *arg, void *data, int flags)
|
||||
@@ -114,23 +114,23 @@ int channelstorage_name_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_name_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name)
|
||||
const char *name, int rdlock)
|
||||
{
|
||||
return CHANNELSTORAGE_API(driver, get_by_name_prefix_or_uniqueid, name, 0);
|
||||
return CHANNELSTORAGE_API(driver, get_by_name_prefix_or_uniqueid, name, 0, rdlock);
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_name_prefix_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int rdlock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_name_prefix, name, name_len);
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_name_prefix, name, name_len, rdlock);
|
||||
if (chan) {
|
||||
return chan;
|
||||
}
|
||||
|
||||
if (name_len == 0) {
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_uniqueid, name);
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_uniqueid, name, rdlock);
|
||||
}
|
||||
|
||||
return chan;
|
||||
@@ -150,9 +150,9 @@ int channelstorage_uniqueid_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int rdlock)
|
||||
{
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_uniqueid_cb, (char *)uniqueid, NULL, 0);
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_uniqueid_cb, (char *)uniqueid, NULL, 0, rdlock);
|
||||
}
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
@@ -214,14 +214,14 @@ static void *test_storage_thread(void *data)
|
||||
}
|
||||
end = ast_tvnow();
|
||||
elapsed = ast_tvdiff_us(end, start);
|
||||
i = CHANNELSTORAGE_API(storage_instance, active_channels);
|
||||
i = CHANNELSTORAGE_API(storage_instance, active_channels, 1);
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "create channels", elapsed);
|
||||
ast_test_validate_cleanup(test, i == CHANNEL_COUNT, res, done);
|
||||
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "testchannel-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_test_validate_cleanup(test, mock_channel == test_channels[i], res, done);
|
||||
ast_test_validate_cleanup(test,
|
||||
@@ -235,7 +235,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestUniqueid-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_uniqueid, search1);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_uniqueid, search1, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -246,7 +246,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestUniqueid-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestChannel-%ld-%04d", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, strlen(search1));
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, strlen(search1), 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -269,7 +269,7 @@ static void *test_storage_thread(void *data)
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestContext-%ld-%04d", rand, i % 100);
|
||||
sprintf(search2, "TestExten-%ld-%04d", rand, i % 10);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_exten, search2, search1);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_exten, search2, search1, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -290,7 +290,7 @@ static void *test_storage_thread(void *data)
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "iter all chan", elapsed);
|
||||
ast_test_validate_cleanup_custom(test, i == CHANNEL_COUNT, res, done,
|
||||
"Expected %d channels, got %d, in container: %d\n", CHANNEL_COUNT, i,
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels));
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels, 1));
|
||||
|
||||
i = 0;
|
||||
start = ast_tvnow();
|
||||
@@ -310,7 +310,7 @@ static void *test_storage_thread(void *data)
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "iter 10 partial name", elapsed);
|
||||
ast_test_validate_cleanup_custom(test, i == 10, res, done,
|
||||
"Expected %d channels, got %d, in container: %d\n", 10, i,
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels));
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels, 1));
|
||||
|
||||
i = 0;
|
||||
start = ast_tvnow();
|
||||
@@ -349,7 +349,7 @@ done:
|
||||
elapsed = ast_tvdiff_us(end, start);
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "del all channels", elapsed);
|
||||
ast_test_validate_cleanup(test, i == CHANNEL_COUNT, res, done);
|
||||
rc = CHANNELSTORAGE_API(storage_instance, active_channels);
|
||||
rc = CHANNELSTORAGE_API(storage_instance, active_channels, 1);
|
||||
ast_test_validate_cleanup_custom(test, rc == 0, res, final,
|
||||
"There are still %d channels in the container\n", rc);
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ struct ast_channelstorage_instance {
|
||||
void (*rdlock)(struct ast_channelstorage_instance *driver);
|
||||
void (*wrlock)(struct ast_channelstorage_instance *driver);
|
||||
void (*unlock)(struct ast_channelstorage_instance *driver);
|
||||
int (*active_channels)(struct ast_channelstorage_instance *driver);
|
||||
int (*active_channels)(struct ast_channelstorage_instance *driver, int rdlock);
|
||||
struct ast_channel *(*callback)(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn,
|
||||
void *arg, void *data, int ao2_flags);
|
||||
struct ast_channel *(*get_by_name_prefix)(struct ast_channelstorage_instance *driver, const char *name, size_t len);
|
||||
struct ast_channel *(*get_by_name_prefix_or_uniqueid)(struct ast_channelstorage_instance *driver, const char *name, size_t len);
|
||||
struct ast_channel *(*get_by_exten)(struct ast_channelstorage_instance *driver, const char *exten, const char *context);
|
||||
struct ast_channel *(*get_by_uniqueid)(struct ast_channelstorage_instance *driver, const char *uniqueid);
|
||||
void *arg, void *data, int ao2_flags, int rdlock);
|
||||
struct ast_channel *(*get_by_name_prefix)(struct ast_channelstorage_instance *driver, const char *name, size_t len, int rdlock);
|
||||
struct ast_channel *(*get_by_name_prefix_or_uniqueid)(struct ast_channelstorage_instance *driver, const char *name, size_t len, int rdlock);
|
||||
struct ast_channel *(*get_by_exten)(struct ast_channelstorage_instance *driver, const char *exten, const char *context, int rdlock);
|
||||
struct ast_channel *(*get_by_uniqueid)(struct ast_channelstorage_instance *driver, const char *uniqueid, int rdlock);
|
||||
struct ast_channel_iterator *(*iterator_all_new)(struct ast_channelstorage_instance *driver);
|
||||
struct ast_channel_iterator *(*iterator_by_exten_new)
|
||||
(struct ast_channelstorage_instance *driver, const char *exten, const char *context);
|
||||
@@ -81,15 +81,15 @@ void ast_channelstorage_close(struct ast_channelstorage_instance *storage_instan
|
||||
|
||||
int channelstorage_exten_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context);
|
||||
const char *exten, const char *context, int rdlock);
|
||||
int channelstorage_name_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_name_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name);
|
||||
const char *name, int rdlock);
|
||||
struct ast_channel *channelstorage_by_name_prefix_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len);
|
||||
const char *name, size_t name_len, int rdlock);
|
||||
int channelstorage_uniqueid_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid);
|
||||
const char *uniqueid, int rdlock);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ static int delete_channel(struct ast_channelstorage_instance *driver,
|
||||
}
|
||||
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
static int active_channels(struct ast_channelstorage_instance *driver, int rdlock)
|
||||
{
|
||||
return getdb(driver) ? ao2_container_count(getdb(driver)) : 0;
|
||||
}
|
||||
|
||||
static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
|
||||
{
|
||||
return ao2_callback_data(getdb(driver), ao2_flags, cb_fn, arg, data);
|
||||
}
|
||||
@@ -161,7 +161,7 @@ static struct ast_channel_iterator *iterator_by_exten_new(struct ast_channelstor
|
||||
}
|
||||
|
||||
i->active_iterator = (void *) callback(driver, by_exten_cb,
|
||||
l_context, l_exten, OBJ_MULTIPLE);
|
||||
l_context, l_exten, OBJ_MULTIPLE, 1);
|
||||
if (!i->active_iterator) {
|
||||
ast_free(i);
|
||||
return NULL;
|
||||
@@ -182,7 +182,7 @@ static struct ast_channel_iterator *iterator_by_name_new(struct ast_channelstora
|
||||
|
||||
i->active_iterator = (void *) callback(driver, by_name_cb,
|
||||
l_name, &name_len,
|
||||
OBJ_MULTIPLE | (name_len == 0 /* match the whole word, so optimize */ ? OBJ_KEY : 0));
|
||||
OBJ_MULTIPLE | (name_len == 0 /* match the whole word, so optimize */ ? OBJ_KEY : 0), 1);
|
||||
if (!i->active_iterator) {
|
||||
ast_free(i);
|
||||
return NULL;
|
||||
@@ -212,17 +212,17 @@ static struct ast_channel *iterator_next(struct ast_channelstorage_instance *dri
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int lock)
|
||||
{
|
||||
char *l_name = (char *) uniqueid;
|
||||
size_t name_len = strlen(uniqueid);
|
||||
|
||||
struct ast_channel *chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0);
|
||||
struct ast_channel *chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int lock)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
char *l_name = (char *) name;
|
||||
@@ -233,23 +233,23 @@ static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance
|
||||
}
|
||||
|
||||
chan = callback(driver, by_name_cb, l_name, &name_len,
|
||||
(name_len == 0) /* optimize if it is a complete name match */ ? OBJ_KEY : 0);
|
||||
(name_len == 0) /* optimize if it is a complete name match */ ? OBJ_KEY : 0, lock);
|
||||
if (chan) {
|
||||
return chan;
|
||||
}
|
||||
|
||||
/* Now try a search for uniqueid. */
|
||||
chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0);
|
||||
chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context)
|
||||
const char *exten, const char *context, int rdlock)
|
||||
{
|
||||
char *l_exten = (char *) exten;
|
||||
char *l_context = (char *) context;
|
||||
|
||||
return callback(driver, by_exten_cb, l_context, l_exten, 0);
|
||||
return callback(driver, by_exten_cb, l_context, l_exten, 0, rdlock);
|
||||
}
|
||||
|
||||
static int hash_cb(const void *obj, const int flags)
|
||||
|
||||
@@ -139,7 +139,7 @@ static int delete_channel(struct ast_channelstorage_instance *driver,
|
||||
}
|
||||
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
static int active_channels(struct ast_channelstorage_instance *driver, int lock)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
@@ -147,15 +147,19 @@ static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
count = getdb(driver).size();
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
ChannelMap::const_iterator it;
|
||||
@@ -164,18 +168,21 @@ static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
for (it = getdb(driver).begin(); it != getdb(driver).end(); it++) {
|
||||
chan = it->second;
|
||||
if (cb_fn(chan, arg, data, ao2_flags) == (CMP_MATCH | CMP_STOP)) {
|
||||
ao2_bump(chan);
|
||||
unlock(driver);
|
||||
return chan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return chan;
|
||||
}
|
||||
|
||||
enum cpp_map_iterator_type {
|
||||
@@ -460,7 +467,7 @@ static struct ast_channel_iterator *iterator_by_exten_new(struct ast_channelstor
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *search = uniqueid ? ast_str_to_lower(ast_strdupa(uniqueid)) : NULL;
|
||||
@@ -469,18 +476,22 @@ static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *d
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = map_by_id(driver).find(search);
|
||||
if (rtn != map_by_id(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_exact(struct ast_channelstorage_instance *driver,
|
||||
const char *name)
|
||||
const char *name, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *search = name ? ast_str_to_lower(ast_strdupa(name)) : NULL;
|
||||
@@ -489,35 +500,43 @@ static struct ast_channel *get_by_name_exact(struct ast_channelstorage_instance
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = getdb(driver).find(search);
|
||||
if (rtn != getdb(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *l_name = NULL;
|
||||
|
||||
if (name_len == 0) {
|
||||
chan = get_by_name_exact(driver, name);
|
||||
chan = get_by_name_exact(driver, name, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
l_name = ast_str_to_lower(ast_strdupa(name));
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = getdb(driver).lower_bound(l_name);
|
||||
if (rtn != getdb(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user