diff --git a/main/channel.c b/main/channel.c index 987ea40a3d..787bdb8886 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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); @@ -1342,7 +1342,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) @@ -1406,7 +1406,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); } /* @@ -1423,7 +1423,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) @@ -1435,7 +1435,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) @@ -1447,7 +1447,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) diff --git a/main/channelstorage.c b/main/channelstorage.c index eee82069a2..63b551443e 100644 --- a/main/channelstorage.c +++ b/main/channelstorage.c @@ -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); diff --git a/main/channelstorage.h b/main/channelstorage.h index c986fbd1dc..3636962388 100644 --- a/main/channelstorage.h +++ b/main/channelstorage.h @@ -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) } diff --git a/main/channelstorage_ao2_legacy.c b/main/channelstorage_ao2_legacy.c index b44b4bf3c4..513a5f4eef 100644 --- a/main/channelstorage_ao2_legacy.c +++ b/main/channelstorage_ao2_legacy.c @@ -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) diff --git a/main/channelstorage_cpp_map_name_id.cc b/main/channelstorage_cpp_map_name_id.cc index cb9e00311a..d4b42f3bf5 100644 --- a/main/channelstorage_cpp_map_name_id.cc +++ b/main/channelstorage_cpp_map_name_id.cc @@ -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; }