154 #ifdef TEST_FRAMEWORK 171 struct timeval created;
216 .
name =
"memory_cache",
232 #define CACHES_CONTAINER_BUCKET_SIZE 53 235 #define CACHE_CONTAINER_BUCKET_SIZE 53 238 #define CACHE_HEAP_INIT_HEIGHT 5 246 #define PASSTHRU_UPDATE_THREAD_ID 0x5EED1E55 251 uint32_t *passthru_update_thread_id;
254 sizeof(*passthru_update_thread_id));
255 if (!passthru_update_thread_id) {
264 uint32_t *passthru_update_thread_id;
267 sizeof(*passthru_update_thread_id));
268 if (!passthru_update_thread_id) {
269 ast_log(
LOG_ERROR,
"Could not set passthru update ID for sorcery memory cache thread\n");
273 *passthru_update_thread_id =
value;
298 const char *
name = obj;
333 const char *right_name = arg;
339 right_name = right->
name;
342 cmp = strcmp(left->
name, right_name);
345 cmp = strncmp(left->
name, right_name, strlen(right_name));
363 const char *
name = obj;
398 const char *right_name = arg;
485 if (reschedule && (oldest_object == heap_object)) {
528 if (expiration > 0) {
663 #ifdef TEST_FRAMEWORK 701 if (!heap_old_object) {
707 ast_assert(heap_old_object == hash_old_object);
825 ast_log(
LOG_ERROR,
"Unable to make room in cache for sorcery object '%s'.\n",
900 if (!task_data->
type) {
918 if (!backend_objects) {
925 ast_log(
LOG_ERROR,
"The backend contains %d objects while the sorcery memory cache '%s' is explicitly configured to only allow %d\n",
942 ast_log(
LOG_WARNING,
"The backend contains %d objects while only %d could be added to sorcery memory cache '%s'\n",
1000 ast_debug(1,
"Backend no longer has object type '%s' ID '%s'. Removing from cache\n",
1006 ast_debug(1,
"Refreshing stale cache object type '%s' ID '%s'\n",
1042 if (!backend_objects) {
1048 ast_log(
LOG_ERROR,
"The backend contains %d objects while the sorcery memory cache '%s' is explicitly configured to only allow %d\n",
1061 ast_log(
LOG_WARNING,
"The backend contains %d objects while only %d could be added to sorcery memory cache '%s'\n",
1136 ast_debug(1,
"Cached sorcery object type '%s' ID '%s' is stale. Refreshing\n",
1143 ast_log(
LOG_ERROR,
"Unable to update stale cached object type '%s', ID '%s'.\n",
1161 struct timeval elapsed;
1260 if (params->
regex) {
1266 }
else if (params->
prefix) {
1271 }
else if (params->
fields &&
1309 void *
object =
NULL;
1378 .regex = &expression,
1387 regfree(&expression);
1446 ast_debug(1,
"Memory cache '%s' associated with sorcery instance '%p' of module '%s' with object type '%s'\n",
1490 return sscanf(value,
"%30u", result);
1527 if (!strcasecmp(name,
"name")) {
1534 }
else if (!strcasecmp(name,
"maximum_objects")) {
1536 ast_log(
LOG_ERROR,
"Unsupported maximum objects value of '%s' used for memory cache\n",
1540 }
else if (!strcasecmp(name,
"object_lifetime_maximum")) {
1542 ast_log(
LOG_ERROR,
"Unsupported object maximum lifetime value of '%s' used for memory cache\n",
1546 }
else if (!strcasecmp(name,
"object_lifetime_stale")) {
1548 ast_log(
LOG_ERROR,
"Unsupported object stale lifetime value of '%s' used for memory cache\n",
1552 }
else if (!strcasecmp(name,
"expire_on_reload")) {
1554 }
else if (!strcasecmp(name,
"full_backend_cache")) {
1557 ast_log(
LOG_ERROR,
"Unsupported option '%s' used for memory cache\n", name);
1566 ast_log(
LOG_ERROR,
"Could not create a container to hold cached objects for memory cache\n");
1656 int wordlen = strlen(word);
1662 if (!strncasecmp(word, cache->
name, wordlen)
1663 && ++which > state) {
1685 e->
command =
"sorcery memory cache show";
1687 "Usage: sorcery memory cache show <name>\n" 1688 " Show sorcery memory cache configuration and statistics.\n";
1704 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not exist\n", a->
argv[4]);
1713 ast_cli(a->
fd,
"There is no limit on the maximum number of objects in the cache\n");
1718 ast_cli(a->
fd,
"Object expiration is not enabled - cached objects will not expire\n");
1723 ast_cli(a->
fd,
"Object staleness is not enabled - cached objects will not go stale\n");
1746 #define FORMAT "%-25.25s %-15u %-15u \n" 1749 int seconds_until_expire = 0, seconds_until_stale = 0;
1770 #define FORMAT "%-25.25s %-15.15s %-15.15s \n" 1776 e->
command =
"sorcery memory cache dump";
1778 "Usage: sorcery memory cache dump <name>\n" 1779 " Dump a list of the objects within the cache, listed by object identifier.\n";
1795 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not exist\n", a->
argv[4]);
1802 ast_cli(a->
fd,
"Dumping sorcery memory cache '%s':\n", cache->
name);
1804 ast_cli(a->
fd,
" * Staleness is not enabled - objects will not go stale\n");
1807 ast_cli(a->
fd,
" * Object lifetime is not enabled - objects will not expire\n");
1810 ast_cli(a->
fd,
FORMAT,
"-------------------------",
"---------------",
"---------------");
1812 ast_cli(a->
fd,
FORMAT,
"-------------------------",
"---------------",
"---------------");
1830 int wordlen = strlen(word);
1842 && ++which > state) {
1867 e->
command =
"sorcery memory cache expire";
1869 "Usage: sorcery memory cache expire <cache name> [object name]\n" 1870 " Expire a specific object or ALL objects within a sorcery memory cache.\n";
1875 }
else if (a->
pos == 5) {
1888 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not exist\n", a->
argv[4]);
1895 ast_cli(a->
fd,
"All objects have been removed from cache '%s'\n", a->
argv[4]);
1898 ast_cli(a->
fd,
"Due to full backend caching per-object expiration is not available on cache '%s'\n", a->
argv[4]);
1900 ast_cli(a->
fd,
"Successfully expired object '%s' from cache '%s'\n", a->
argv[5], a->
argv[4]);
1902 ast_cli(a->
fd,
"Object '%s' was not expired from cache '%s' as it was not found\n", a->
argv[5],
1924 e->
command =
"sorcery memory cache stale";
1926 "Usage: sorcery memory cache stale <cache name> [object name [reload]]\n" 1927 " Mark a specific object or ALL objects as stale in a sorcery memory cache.\n" 1928 " If \"reload\" is specified, then the object is marked stale and immediately\n" 1929 " retrieved from backend storage to repopulate the cache\n";
1934 }
else if (a->
pos == 5) {
1936 }
else if (a->
pos == 6) {
1937 static const char *
const completions[] = {
"reload",
NULL };
1949 if (!strcasecmp(a->
argv[6],
"reload")) {
1958 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not exist\n", a->
argv[4]);
1963 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not have staleness enabled\n", a->
argv[4]);
1971 ast_cli(a->
fd,
"Marked all objects in sorcery memory cache '%s' as stale\n", a->
argv[4]);
1974 ast_cli(a->
fd,
"Successfully marked object '%s' in memory cache '%s' as stale\n",
1986 ast_cli(a->
fd,
"Object '%s' in sorcery memory cache '%s' could not be marked as stale as it was not found\n",
2007 e->
command =
"sorcery memory cache populate";
2009 "Usage: sorcery memory cache populate <cache name>\n" 2010 " Expire all objects in the cache and populate it with ALL objects from backend.\n";
2026 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not exist\n", a->
argv[4]);
2031 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' does not have full backend caching enabled\n", a->
argv[4]);
2038 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' is no longer active\n", a->
argv[4]);
2047 ast_cli(a->
fd,
"Specified sorcery memory cache '%s' has been populated with '%d' objects from the backend\n",
2077 astman_send_error(s, m,
"SorceryMemoryCacheExpireObject requires that a cache name be provided.\n");
2080 astman_send_error(s, m,
"SorceryMemoryCacheExpireObject requires that an object name be provided\n");
2101 astman_send_error(s, m,
"Due to full backend caching per-object expiration is not available, consider using SorceryMemoryCachePopulate or SorceryMemoryCacheExpire instead\n");
2103 astman_send_ack(s, m,
"The provided object was expired from the cache\n");
2105 astman_send_error(s, m,
"The provided object could not be expired from the cache\n");
2121 astman_send_error(s, m,
"SorceryMemoryCacheExpire requires that a cache name be provided.\n");
2155 astman_send_error(s, m,
"SorceryMemoryCacheStaleObject requires that a cache name be provided.\n");
2158 astman_send_error(s, m,
"SorceryMemoryCacheStaleObject requires that an object name be provided\n");
2187 astman_send_ack(s, m,
"The provided object was marked as stale in the cache\n");
2189 astman_send_error(s, m,
"The provided object could not be marked as stale in the cache\n");
2205 astman_send_error(s, m,
"SorceryMemoryCacheStale requires that a cache name be provided.\n");
2221 astman_send_ack(s, m,
"All objects were marked as stale in the cache\n");
2236 astman_send_error(s, m,
"SorceryMemoryCachePopulate requires that a cache name be provided.\n");
2247 astman_send_error(s, m,
"The provided cache does not have full backend caching enabled\n");
2272 #ifdef TEST_FRAMEWORK 2324 info->name =
"open_with_valid_options";
2325 info->category =
"/res/res_sorcery_memory_cache/";
2326 info->summary =
"Attempt to create sorcery memory caches using valid options";
2327 info->description =
"This test performs the following:\n" 2328 "\t* Creates a memory cache with default configuration\n" 2329 "\t* Creates a memory cache with a maximum object count of 10 and verifies it\n" 2330 "\t* Creates a memory cache with a maximum object lifetime of 60 and verifies it\n" 2331 "\t* Creates a memory cache with a stale object lifetime of 90 and verifies it";
2392 info->name =
"open_with_invalid_options";
2393 info->category =
"/res/res_sorcery_memory_cache/";
2394 info->summary =
"Attempt to create sorcery memory caches using invalid options";
2395 info->description =
"This test attempts to perform the following:\n" 2396 "\t* Create a memory cache with an empty name\n" 2397 "\t* Create a memory cache with a maximum object count of -1\n" 2398 "\t* Create a memory cache with a maximum object count of toast\n" 2399 "\t* Create a memory cache with a maximum object lifetime of -1\n" 2400 "\t* Create a memory cache with a maximum object lifetime of toast\n" 2401 "\t* Create a memory cache with a stale object lifetime of -1\n" 2402 "\t* Create a memory cache with a stale object lifetime of toast";
2477 info->name =
"create";
2478 info->category =
"/res/res_sorcery_memory_cache/";
2479 info->summary =
"Attempt to create an object in the cache";
2480 info->description =
"This test performs the following:\n" 2481 "\t* Creates a memory cache with default options\n" 2482 "\t* Creates a sorcery instance with a test object\n" 2483 "\t* Creates a test object with an id of test\n" 2484 "\t* Pushes the test object into the memory cache\n" 2485 "\t* Confirms that the test object is in the cache";
2522 if (!cached_object) {
2527 if (cached_object !=
object) {
2556 info->name =
"create";
2557 info->category =
"/res/res_sorcery_memory_cache/";
2558 info->summary =
"Attempt to create and then update an object in the cache";
2559 info->description =
"This test performs the following:\n" 2560 "\t* Creates a memory cache with default options\n" 2561 "\t* Creates a sorcery instance with a test object\n" 2562 "\t* Creates a test object with an id of test\n" 2563 "\t* Pushes the test object into the memory cache\n" 2564 "\t* Confirms that the test object is in the cache\n" 2565 "\t* Creates a new test object with the same id of test\n" 2566 "\t* Pushes the new test object into the memory cache\n" 2567 "\t* Confirms that the new test object has replaced the old one";
2591 if (!original_object) {
2599 if (!updated_object) {
2613 if (!cached_object) {
2618 if (cached_object == original_object) {
2621 }
else if (cached_object != updated_object) {
2649 info->name =
"delete";
2650 info->category =
"/res/res_sorcery_memory_cache/";
2651 info->summary =
"Attempt to create and then delete an object in the cache";
2652 info->description =
"This test performs the following:\n" 2653 "\t* Creates a memory cache with default options\n" 2654 "\t* Creates a sorcery instance with a test object\n" 2655 "\t* Creates a test object with an id of test\n" 2656 "\t* Pushes the test object into the memory cache\n" 2657 "\t* Confirms that the test object is in the cache\n" 2658 "\t* Deletes the test object from the cache\n" 2659 "\t* Confirms that the test object is no longer in the cache";
2696 if (!cached_object) {
2702 cached_object =
NULL;
2707 if (cached_object) {
2726 const char **in_cache,
size_t num_in_cache,
const char **not_in_cache,
size_t num_not_in_cache)
2732 for (i = 0; i < num_in_cache; ++i) {
2734 if (!cached_object) {
2742 for (i = 0; i < num_not_in_cache; ++i) {
2744 if (cached_object) {
2764 const char *in_cache[2];
2765 const char *not_in_cache[2];
2769 info->name =
"maximum_objects";
2770 info->category =
"/res/res_sorcery_memory_cache/";
2771 info->summary =
"Ensure that the 'maximum_objects' option works as expected";
2772 info->description =
"This test performs the following:\n" 2773 "\t* Creates a memory cache with maximum_objects=2\n" 2774 "\t* Creates a sorcery instance\n" 2775 "\t* Creates a three test objects: alice, bob, charlie, and david\n" 2776 "\t* Pushes alice and bob into the memory cache\n" 2777 "\t* Confirms that alice and bob are in the memory cache\n" 2778 "\t* Pushes charlie into the memory cache\n" 2779 "\t* Confirms that bob and charlie are in the memory cache\n" 2780 "\t* Deletes charlie from the memory cache\n" 2781 "\t* Confirms that only bob is in the memory cache\n" 2782 "\t* Pushes alice into the memory cache\n" 2783 "\t* Confirms that bob and alice are in the memory cache";
2810 if (!alice || !bob || !charlie) {
2816 in_cache[0] =
"alice";
2818 not_in_cache[0] =
"bob";
2819 not_in_cache[1] =
"charlie";
2830 in_cache[0] =
"alice";
2831 in_cache[1] =
"bob";
2832 not_in_cache[0] =
"charlie";
2833 not_in_cache[1] =
NULL;
2841 in_cache[0] =
"bob";
2842 in_cache[1] =
"charlie";
2843 not_in_cache[0] =
"alice";
2844 not_in_cache[1] =
NULL;
2851 in_cache[0] =
"bob";
2853 not_in_cache[0] =
"alice";
2854 not_in_cache[1] =
"charlie";
2861 in_cache[0] =
"bob";
2862 in_cache[1] =
"alice";
2863 not_in_cache[0] =
"charlie";
2864 not_in_cache[1] =
NULL;
2891 info->name =
"expiration";
2892 info->category =
"/res/res_sorcery_memory_cache/";
2893 info->summary =
"Add objects to a cache configured with maximum lifetime, confirm they are removed";
2894 info->description =
"This test performs the following:\n" 2895 "\t* Creates a memory cache with a maximum object lifetime of 5 seconds\n" 2896 "\t* Pushes 10 objects into the memory cache\n" 2897 "\t* Waits (up to) 10 seconds for expiration to occur\n" 2898 "\t* Confirms that the objects have been removed from the cache";
2920 for (i = 0; i < 5; ++i) {
2938 struct timespec end = {
2939 .tv_sec = start.tv_sec + 10,
2940 .tv_nsec = start.tv_usec * 1000,
3018 const char *
type,
const char *
id)
3100 void *previous_object,
struct test_data **new_object)
3108 if (
object != previous_object) {
3109 *new_object = object;
3124 { .
salt = 1, .pepper = 2, .exists = 1 },
3125 { .salt = 568729, .pepper = -234123, .exists = 1 },
3126 { .salt = 0, .pepper = 0, .exists = 0 },
3137 info->name =
"stale";
3138 info->category =
"/res/res_sorcery_memory_cache/";
3139 info->summary =
"Ensure that stale objects are replaced with updated objects";
3140 info->description =
"This test performs the following:\n" 3141 "\t* Create a sorcery instance with two wizards" 3142 "\t\t* The first is a memory cache that marks items stale after 3 seconds\n" 3143 "\t\t* The second is a mock of a back-end\n" 3144 "\t* Pre-populates the cache by retrieving some initial data from the backend.\n" 3145 "\t* Performs iterations of the following:\n" 3146 "\t\t* Update backend data with new values\n" 3147 "\t\t* Retrieve item from the cache\n" 3148 "\t\t* Ensure the retrieved item does not have the new backend values\n" 3149 "\t\t* Wait for cached object to become stale\n" 3150 "\t\t* Retrieve the stale cached object\n" 3151 "\t\t* Ensure that the stale object retrieved is the same as the fresh one from earlier\n" 3152 "\t\t* Wait for the cache to update with new data\n" 3153 "\t\t* Ensure that new data in the cache matches backend data";
3168 "object_lifetime_stale=3", 1);
3176 if (!backend_object) {
3182 for (i = 0; i <
ARRAY_LEN(iterations); ++i) {
3197 if (cache_fresh->salt == iterations[i].
salt || cache_fresh->pepper == iterations[i].
pepper) {
3210 if (cache_stale != cache_fresh) {
3220 if (iterations[i].
exists) {
3224 }
else if (cache_new->salt != iterations[i].
salt ||
3225 cache_new->pepper != iterations[i].
pepper) {
3229 }
else if (cache_new) {
3257 struct timeval start;
3258 struct timespec end;
3262 info->name =
"full_backend_cache_expiration";
3263 info->category =
"/res/res_sorcery_memory_cache/";
3264 info->summary =
"Ensure that the full backend cache actually caches the backend";
3265 info->description =
"This test performs the following:\n" 3266 "\t* Create a sorcery instance with two wizards" 3267 "\t\t* The first is a memory cache that expires objects after 3 seconds and does full backend caching\n" 3268 "\t\t* The second is a mock of a back-end\n" 3269 "\t* Populates the cache by requesting all objects which returns 4.\n" 3270 "\t* Updates the backend to contain a different number of objects, 8.\n" 3271 "\t* Requests all objects and confirms the number returned is only 4.\n" 3272 "\t* Wait for cached objects to expire.\n" 3273 "\t* Requests all objects and confirms the number returned is 8.";
3288 "object_lifetime_maximum=3,full_backend_cache=yes", 1);
3327 end.tv_sec = start.tv_sec + 5;
3328 end.tv_nsec = start.tv_usec * 1000;
3375 struct timeval start;
3376 struct timespec end;
3380 info->name =
"full_backend_cache_stale";
3381 info->category =
"/res/res_sorcery_memory_cache/";
3382 info->summary =
"Ensure that the full backend cache works with staleness";
3383 info->description =
"This test performs the following:\n" 3384 "\t* Create a sorcery instance with two wizards" 3385 "\t\t* The first is a memory cache that stales objects after 1 second and does full backend caching\n" 3386 "\t\t* The second is a mock of a back-end\n" 3387 "\t* Populates the cache by requesting all objects which returns 4.\n" 3388 "\t* Wait for objects to go stale.\n" 3389 "\t* Updates the backend to contain a different number of objects, 8.\"" 3390 "\t* Requests all objects and confirms the number returned is only 4.\n" 3391 "\t* Wait for objects to be refreshed from backend.\n" 3392 "\t* Requests all objects and confirms the number returned is 8.";
3410 "object_lifetime_stale=1,full_backend_cache=yes", 1);
3428 end.tv_sec = start.tv_sec + 5;
3429 end.tv_nsec = start.tv_usec * 1000;
3454 end.tv_sec = start.tv_sec + 5;
3455 end.tv_nsec = start.tv_usec * 1000;
3478 end.tv_sec = start.tv_sec + 5;
3479 end.tv_nsec = start.tv_usec * 1000;
3559 ast_log(
LOG_ERROR,
"Failed to create scheduler thread for cache management\n");
static int schedule_cache_expiration(struct sorcery_memory_cache *cache)
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
static int object_stale_callback(void *obj, void *arg, int flags)
static void * sorcery_memory_cache_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
static int sorcery_memory_cache_delete(const struct ast_sorcery *sorcery, void *data, void *object)
#define CACHE_CONTAINER_BUCKET_SIZE
The default bucket size for the container of objects in the cache.
const struct ast_variable * fields
Pointer to the fields to check.
static int sorcery_memory_cached_object_hash(const void *obj, int flags)
#define AST_CLI_DEFINE(fn, txt,...)
static int is_passthru_update(void)
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
unsigned int maximum_objects
The maximum number of objects permitted in the cache, 0 if no limit.
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static struct stale_cache_update_task_data * stale_cache_update_task_data_alloc(struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, const char *type)
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static int sorcery_memory_cache_ami_expire_object(struct mansession *s, const struct message *m)
static void start_passthru_update(void)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define ast_sorcery_apply_wizard_mapping(sorcery, type, name, data, caching)
Apply additional object wizard mappings.
static void sorcery_memory_cache_load(void *data, const struct ast_sorcery *sorcery, const char *type)
static char * sorcery_memory_cache_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
The arg parameter is a search key, but is not an object.
static int stale_cache_update(const void *data)
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
ssize_t __heap_index
index required by heap
static void sorcery_memory_cache_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
const struct ast_sorcery * sorcery
An unreffed pointer to the sorcery instance, accessible only with lock held.
static char * sorcery_memory_cache_complete_object_name(const char *cache_name, const char *word, int state)
descriptor for a cli entry.
static struct ast_sorcery_wizard memory_cache_object_wizard
#define ao2_callback(c, flags, cb_fn, arg)
struct ao2_container * container
Optional container to put object into.
static int sorcery_memory_cached_object_cmp(void *obj, void *arg, int flags)
Structure for variables, used for configurations and for channel variables.
Perform no matching, return all objects.
#define AST_TEST_REGISTER(cb)
Assume that the ao2_container is already locked.
Full structure for sorcery.
struct ast_heap * ast_heap_destroy(struct ast_heap *h)
Destroy a max heap.
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
struct ast_sorcery * sorcery
#define ast_cond_init(cond, attr)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Return all matching objects.
struct timeval created
The time at which the object was created.
#define ao2_alloc_options(data_size, destructor_fn, options)
static int sorcery_memory_cache_print_object(void *obj, void *arg, int flags)
#define ao2_link_flags(container, obj, flags)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
static char * sorcery_memory_cache_populate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
unsigned int object_lifetime_maximum
The maximum time (in seconds) an object will stay in the cache, 0 if no limit.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
static void * test_sorcery_object_alloc(const char *id)
#define ast_strdup(str)
A wrapper for strdup()
ast_mutex_t lock
Mutex lock used for signaling when the cache has reached empty.
void * ast_heap_pop(struct ast_heap *h)
Pop the max element off of the heap.
void ast_cli(int fd, const char *fmt,...)
static void sorcery_memory_cache_close(void *data)
static void * mock_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
Callback for retrieving sorcery object by ID.
const char * name
Name of the wizard.
static int sorcery_memory_cache_create(const struct ast_sorcery *sorcery, void *data, void *object)
#define ast_cond_signal(cond)
struct ast_heap * object_heap
Heap of cached objects. Oldest object is at the top.
#define AST_CLI_ONOFF(x)
return On or Off depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point).
static int load_module(void)
#define PASSTHRU_UPDATE_THREAD_ID
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
const char * prefix
Prefix for matching object id.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
const char * ast_sorcery_get_module(const struct ast_sorcery *sorcery)
Get the module that has opened the provided sorcery instance.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
static int sorcery_memory_cache_hash(const void *obj, int flags)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
static int unload_module(void)
static void sorcery_memory_cache_reload(void *data, const struct ast_sorcery *sorcery, const char *type)
static void set_passthru_update(uint32_t value)
static int sorcery_memory_cache_cmp(void *obj, void *arg, int flags)
static void memory_cache_stale_update_object(const struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, struct sorcery_memory_cached_object *cached)
static int sorcery_memory_cache_ami_populate(struct mansession *s, const struct message *m)
#define EVENT_FLAG_SYSTEM
#define ast_debug(level,...)
Log a DEBUG message.
static void sorcery_memory_cache_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex)
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
#define ast_heap_push(h, elm)
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
Structure for storing a memory cache.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Type for default option handler for unsigned integers.
#define ast_test_status_update(a, b, c...)
regex_t * regex
Regular expression for checking object id.
static char * sorcery_memory_cache_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void mock_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
Callback for retrieving multiple sorcery objects.
unsigned int full_backend_cache
Whether this is a cache of the entire backend, 0 if disabled.
const size_t prefix_len
Prefix length in bytes for matching object id.
Scheduler Routines (derived from cheops)
struct sorcery_memory_cache * cache
The sorcery memory cache.
const struct ast_sorcery * sorcery
Pointer to the sorcery structure.
static int check_cache_content(struct ast_test *test, struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, const char **in_cache, size_t num_in_cache, const char **not_in_cache, size_t num_not_in_cache)
#define ao2_ref(o, delta)
In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Structure for stored a cached object.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
static char * sorcery_memory_cache_expire(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
int stale_update_sched_id
scheduler id of stale update task
unsigned int expire_on_reload
Whether all objects are expired when the object type is reloaded, 0 if disabled.
static int sorcery_memory_cache_ami_expire(struct mansession *s, const struct message *m)
static void sorcery_memory_cache_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
static int remove_from_cache(struct sorcery_memory_cache *cache, const char *id, int reschedule)
static void sorcery_memory_cached_object_destructor(void *obj)
static void memory_cache_populate(const struct ast_sorcery *sorcery, const char *type, struct sorcery_memory_cache *cache)
int expire_id
Scheduler item for expiring oldest object.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
#define ast_test_suite_event_notify(s, f,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
static struct ast_sched_context * sched
Scheduler for cache management.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define ast_sorcery_wizard_register(interface)
See __ast_sorcery_wizard_register()
static void memory_cache_stale_check_object(const struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, struct sorcery_memory_cached_object *cached)
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
#define ast_sorcery_internal_object_register(sorcery, type, alloc, transform, apply)
Register an internal, hidden object type.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static void remove_all_from_cache(struct sorcery_memory_cache *cache)
Structure used to pass data for printing cached object information.
#define SORCERY_OBJECT(details)
Macro which must be used at the beginning of each sorcery capable object.
static void * test_data_alloc(const char *id)
Allocation callback for test_data sorcery object.
static int remove_oldest_from_cache(struct sorcery_memory_cache *cache)
#define ao2_unlink(container, obj)
static struct ao2_container * caches
Container of created caches.
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
Unregister a sorcery wizard.
static void stale_cache_update_task_data_destructor(void *obj)
#define AST_TEST_UNREGISTER(cb)
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
#define ast_sorcery_apply_default(sorcery, type, name, data)
#define ao2_callback_data(container, flags, cb_fn, arg, data)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Sorcery object created based on backend data.
static int sorcery_memory_cache_fields_cmp(void *obj, void *arg, int flags)
userdata associated with baseline taskprocessor test
struct sorcery_memory_cache * cache
#define ao2_iterator_next(iter)
#define ast_cond_destroy(cond)
#define ao2_alloc(data_size, destructor_fn)
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Backend data that the mock sorcery wizard uses to create objects.
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
static int expire_objects_from_cache(const void *data)
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
void * object
The cached object.
static void memory_cache_stale_update_full(const struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, const char *type)
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
static void memory_cache_full_update(const struct ast_sorcery *sorcery, const char *type, struct sorcery_memory_cache *cache)
Module has failed to load, may be in an inconsistent state.
static int wait_for_cache_update(const struct ast_sorcery *sorcery, void *previous_object, struct test_data **new_object)
Wait for the cache to be updated after a stale object is retrieved.
#define ao2_find(container, arg, flags)
struct sorcery_memory_cache * cache
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
static void * cleanup(void *unused)
#define ast_heap_create(init_height, cmp_fn, index_offset)
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct ao2_container * cache
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
static struct ast_cli_entry cli_memory_cache[]
Interface for a sorcery wizard.
static struct stale_update_task_data * stale_update_task_data_alloc(struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache, const char *type, void *object)
The arg parameter is an object of the same type.
void * ast_heap_remove(struct ast_heap *h, void *elm)
Remove a specific element from a heap.
char * strsep(char **str, const char *delims)
static void sorcery_memory_cache_destructor(void *obj)
int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
Tests 2 variable lists to see if they match.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
char * object_type
The type of object we are caching.
#define CACHES_CONTAINER_BUCKET_SIZE
The bucket size for the container of caches.
static struct ast_sorcery * alloc_and_initialize_sorcery(void)
static char * sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ao2_container * objects
Objects in the cache.
struct ast_variable * objectset
Cached objectset for field and regex retrieval.
static struct backend_data * real_backend_data
static struct ast_sorcery_wizard mock_wizard
A mock sorcery wizard used for the stale test.
void * ast_heap_peek(struct ast_heap *h, unsigned int index)
Peek at an element on a heap.
#define ast_sorcery_open()
#define CACHE_HEAP_INIT_HEIGHT
Height of heap for cache object heap. Allows 31 initial objects.
static void stale_update_task_data_destructor(void *obj)
AST_TEST_DEFINE(open_with_valid_options)
static int object_add_to_cache_callback(void *obj, void *arg, void *data, int flags)
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
unsigned int cache_notify
Variable used to indicate we should notify a test when we reach empty.
struct ast_sorcery * sorcery
static int sorcery_memory_cache_ami_stale(struct mansession *s, const struct message *m)
static int add_to_cache(struct sorcery_memory_cache *cache, struct sorcery_memory_cached_object *cached_object)
static int mark_object_as_stale_in_cache(struct sorcery_memory_cache *cache, const char *id)
#define ast_mutex_init(pmutex)
Search option field mask.
#define ast_mutex_destroy(a)
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
static int sorcery_memory_cache_ami_stale_object(struct mansession *s, const struct message *m)
Structure used for fields comparison.
static void * sorcery_memory_cache_open(const char *data)
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
#define ASTERISK_GPL_KEY
The text the key() function should return.
static void mark_all_as_stale_in_cache(struct sorcery_memory_cache *cache)
static int configuration_parse_unsigned_integer(const char *value, unsigned int *result)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
static void end_passthru_update(void)
Asterisk module definitions.
ast_cond_t cond
Condition used for signaling when the cache has reached empty.
struct ast_cli_args * a
The CLI arguments.
unsigned int object_lifetime_stale
The amount of time (in seconds) before an object is marked as stale, 0 if disabled.
static struct sorcery_memory_cached_object * sorcery_memory_cached_object_alloc(const struct ast_sorcery *sorcery, const struct sorcery_memory_cache *cache, void *object)
static int stale_item_update(const void *data)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_cond_timedwait(cond, mutex, time)
char * name
The name of the memory cache.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
static int age_cmp(void *a, void *b)
Structure for mutex and tracking information.
static void * sorcery_memory_cache_retrieve_fields(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields)
static char * sorcery_memory_cache_complete_name(const char *word, int state)
static struct ast_threadstorage passthru_update_id_storage
static void memory_cache_stale_check(const struct ast_sorcery *sorcery, struct sorcery_memory_cache *cache)
Sorcery Data Access Layer API.
#define ast_mutex_unlock(a)
static char prefix[MAX_PREFIX]
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
unsigned int cache_completed
Variable that is set when the cache has reached empty.
struct sorcery_memory_cache * cache
The sorcery memory cache.
#define ao2_link(container, obj)
int stale_update_sched_id
scheduler id of stale update task