Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
test_sorcery_memory_cache_thrash.c File Reference

Sorcery Unit Tests. More...

#include "asterisk.h"
#include "asterisk/test.h"
#include "asterisk/module.h"
#include "asterisk/sorcery.h"
#include "asterisk/logger.h"
#include "asterisk/vector.h"
#include "asterisk/cli.h"
Include dependency graph for test_sorcery_memory_cache_thrash.c:

Go to the source code of this file.

Data Structures

struct  sorcery_memory_cache_thrash
 Structure for memory cache thrashing. More...
 
struct  sorcery_memory_cache_thrash_thread
 Structure for a memory cache thras thread. More...
 
struct  test_data
 Sorcery object created based on backend data. More...
 

Macros

#define TEST_THRASH_RETRIEVERS   25
 The number of threads to use for retrieving for applicable tests. More...
 
#define TEST_THRASH_TIME   3
 The default amount of time (in seconds) that thrash unit tests execute for. More...
 
#define TEST_THRASH_UPDATERS   25
 The number of threads to use for updating for applicable tests. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (conflicting_expire_and_stale)
 
 AST_TEST_DEFINE (high_object_count_without_expiration)
 
 AST_TEST_DEFINE (low_unique_object_count_high_concurrent_updates)
 
 AST_TEST_DEFINE (low_unique_object_count_immediately_expire)
 
 AST_TEST_DEFINE (low_unique_object_count_immediately_stale)
 
 AST_TEST_DEFINE (unique_objects_exceeding_maximum)
 
 AST_TEST_DEFINE (unique_objects_exceeding_maximum_with_expire_and_stale)
 
static int load_module (void)
 
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. More...
 
static int mock_update (const struct ast_sorcery *sorcery, void *data, void *object)
 Callback for updating a sorcery object. More...
 
static enum ast_test_result_state nominal_thrash (struct ast_test *test, const char *cache_configuration, unsigned int thrash_time, unsigned int unique_objects, unsigned int retrieve_threads, unsigned int update_threads)
 
static char * sorcery_memory_cache_cli_thrash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct sorcery_memory_cache_thrashsorcery_memory_cache_thrash_create (const char *cache_configuration, unsigned int update_threads, unsigned int retrieve_threads, unsigned int unique_objects)
 
static void sorcery_memory_cache_thrash_destroy (void *obj)
 
static void * sorcery_memory_cache_thrash_retrieve (void *data)
 
static int sorcery_memory_cache_thrash_start (struct sorcery_memory_cache_thrash *thrash)
 
static void sorcery_memory_cache_thrash_stop (struct sorcery_memory_cache_thrash *thrash)
 
static void * sorcery_memory_cache_thrash_update (void *data)
 
static void * test_data_alloc (const char *id)
 Allocation callback for test_data sorcery object. More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Sorcery Cache Thrasing test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_memory_cache_thrash []
 
static struct ast_sorcery_wizard mock_wizard
 A mock sorcery wizard used for the stale test. More...
 

Detailed Description

Sorcery Unit Tests.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file test_sorcery_memory_cache_thrash.c.

Macro Definition Documentation

◆ TEST_THRASH_RETRIEVERS

#define TEST_THRASH_RETRIEVERS   25

The number of threads to use for retrieving for applicable tests.

Definition at line 45 of file test_sorcery_memory_cache_thrash.c.

◆ TEST_THRASH_TIME

#define TEST_THRASH_TIME   3

The default amount of time (in seconds) that thrash unit tests execute for.

Definition at line 42 of file test_sorcery_memory_cache_thrash.c.

◆ TEST_THRASH_UPDATERS

#define TEST_THRASH_UPDATERS   25

The number of threads to use for updating for applicable tests.

Definition at line 48 of file test_sorcery_memory_cache_thrash.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 631 of file test_sorcery_memory_cache_thrash.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 631 of file test_sorcery_memory_cache_thrash.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 631 of file test_sorcery_memory_cache_thrash.c.

◆ AST_TEST_DEFINE() [1/7]

AST_TEST_DEFINE ( conflicting_expire_and_stale  )

Definition at line 566 of file test_sorcery_memory_cache_thrash.c.

567{
568 switch (cmd) {
569 case TEST_INIT:
570 info->name = "conflicting_expire_and_stale";
571 info->category = "/res/res_sorcery_memory_cache/thrash/";
572 info->summary = "Thrash a cache with a large number of objects that expire and go stale";
573 info->description = "This test creates a cache with a large number of objects that expire\n"
574 "and go stale. As there is such a large number this ensures that both operations occur.\n"
575 "This test confirms that stale refreshing and expiration do not conflict.";
576 return AST_TEST_NOT_RUN;
577 case TEST_EXECUTE:
578 break;
579 }
580
581 return nominal_thrash(test, "object_lifetime_maximum=2,object_lifetime_stale=1", TEST_THRASH_TIME * 2, 5000,
583}
def info(msg)
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
@ AST_TEST_NOT_RUN
Definition: test.h:194
#define TEST_THRASH_TIME
The default amount of time (in seconds) that thrash unit tests execute for.
static enum ast_test_result_state nominal_thrash(struct ast_test *test, const char *cache_configuration, unsigned int thrash_time, unsigned int unique_objects, unsigned int retrieve_threads, unsigned int update_threads)
#define TEST_THRASH_RETRIEVERS
The number of threads to use for retrieving for applicable tests.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ AST_TEST_DEFINE() [2/7]

AST_TEST_DEFINE ( high_object_count_without_expiration  )

Definition at line 585 of file test_sorcery_memory_cache_thrash.c.

586{
587 switch (cmd) {
588 case TEST_INIT:
589 info->name = "high_object_count_without_expiration";
590 info->category = "/res/res_sorcery_memory_cache/thrash/";
591 info->summary = "Thrash a cache with a large number of objects";
592 info->description = "This test creates a cache with a large number of objects that persist.\n"
593 "A large number of threads are created which constantly retrieve from the cache.\n"
594 "This test confirms that the large number of retrieves do not cause a problem.";
595 return AST_TEST_NOT_RUN;
596 case TEST_EXECUTE:
597 break;
598 }
599
600 return nominal_thrash(test, "default", TEST_THRASH_TIME, 5000, TEST_THRASH_RETRIEVERS, 0);
601}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ AST_TEST_DEFINE() [3/7]

AST_TEST_DEFINE ( low_unique_object_count_high_concurrent_updates  )

Definition at line 506 of file test_sorcery_memory_cache_thrash.c.

507{
508 switch (cmd) {
509 case TEST_INIT:
510 info->name = "low_unique_object_count_high_concurrent_updates";
511 info->category = "/res/res_sorcery_memory_cache/thrash/";
512 info->summary = "Thrash a cache with low number of unique objects that are updated frequently";
513 info->description = "This test creates a cache with objects that are being constantly\n"
514 "updated and retrieved at the same time. This will create contention between all\n"
515 "of the threads as the write lock is held for the updates. This test confirms that\n"
516 "no problems occur in this situation.";
517 return AST_TEST_NOT_RUN;
518 case TEST_EXECUTE:
519 break;
520 }
521
523}
#define TEST_THRASH_UPDATERS
The number of threads to use for updating for applicable tests.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, TEST_THRASH_TIME, and TEST_THRASH_UPDATERS.

◆ AST_TEST_DEFINE() [4/7]

AST_TEST_DEFINE ( low_unique_object_count_immediately_expire  )

Definition at line 487 of file test_sorcery_memory_cache_thrash.c.

488{
489 switch (cmd) {
490 case TEST_INIT:
491 info->name = "low_unique_object_count_immediately_expire";
492 info->category = "/res/res_sorcery_memory_cache/thrash/";
493 info->summary = "Thrash a cache with low number of unique objects that are immediately expired";
494 info->description = "This test creates a cache with objects that are expired\n"
495 "after 1 second. It also creates 25 threads which are constantly attempting\n"
496 "to retrieve the objects. This test confirms that the expiration process does\n"
497 "not cause a problem as the retrieve threads execute.";
498 return AST_TEST_NOT_RUN;
499 case TEST_EXECUTE:
500 break;
501 }
502
503 return nominal_thrash(test, "object_lifetime_maximum=1", TEST_THRASH_TIME, 10, TEST_THRASH_RETRIEVERS, 0);
504}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ AST_TEST_DEFINE() [5/7]

AST_TEST_DEFINE ( low_unique_object_count_immediately_stale  )

Definition at line 467 of file test_sorcery_memory_cache_thrash.c.

468{
469 switch (cmd) {
470 case TEST_INIT:
471 info->name = "low_unique_object_count_immediately_stale";
472 info->category = "/res/res_sorcery_memory_cache/thrash/";
473 info->summary = "Thrash a cache with low number of unique objects that are immediately stale";
474 info->description = "This test creates a cache with objects that are stale\n"
475 "after 1 second. It also creates 25 threads which are constantly attempting\n"
476 "to retrieve the objects. This test confirms that the background refreshes\n"
477 "being done as a result of going stale do not conflict or cause problems with\n"
478 "the large number of retrieve threads.";
479 return AST_TEST_NOT_RUN;
480 case TEST_EXECUTE:
481 break;
482 }
483
484 return nominal_thrash(test, "object_lifetime_stale=1", TEST_THRASH_TIME, 10, TEST_THRASH_RETRIEVERS, 0);
485}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ AST_TEST_DEFINE() [6/7]

AST_TEST_DEFINE ( unique_objects_exceeding_maximum  )

Definition at line 525 of file test_sorcery_memory_cache_thrash.c.

526{
527 switch (cmd) {
528 case TEST_INIT:
529 info->name = "unique_objects_exceeding_maximum";
530 info->category = "/res/res_sorcery_memory_cache/thrash/";
531 info->summary = "Thrash a cache with a fixed maximum object count";
532 info->description = "This test creates a cache with a maximum number of objects\n"
533 "allowed in it. The maximum number of unique objects, however, far exceeds the\n"
534 "the maximum number allowed in the cache. This test confirms that the cache does\n"
535 "not exceed the maximum and that the removal of older objects does not cause\n"
536 "a problem.";
537 return AST_TEST_NOT_RUN;
538 case TEST_EXECUTE:
539 break;
540 }
541
542 return nominal_thrash(test, "maximum_objects=10", TEST_THRASH_TIME, 100, TEST_THRASH_RETRIEVERS, 0);
543}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ AST_TEST_DEFINE() [7/7]

AST_TEST_DEFINE ( unique_objects_exceeding_maximum_with_expire_and_stale  )

Definition at line 545 of file test_sorcery_memory_cache_thrash.c.

546{
547 switch (cmd) {
548 case TEST_INIT:
549 info->name = "unique_objects_exceeding_maximum_with_expire_and_stale";
550 info->category = "/res/res_sorcery_memory_cache/thrash/";
551 info->summary = "Thrash a cache with a fixed maximum object count with objects that expire and go stale";
552 info->description = "This test creates a cache with a maximum number of objects\n"
553 "allowed in it with objects that also go stale after a period of time and expire.\n"
554 "A number of threads are created that constantly retrieve from the cache, causing\n"
555 "both stale refresh and expiration to occur. This test confirms that the combination\n"
556 "of these do not present a problem.";
557 return AST_TEST_NOT_RUN;
558 case TEST_EXECUTE:
559 break;
560 }
561
562 return nominal_thrash(test, "maximum_objects=10,object_lifetime_maximum=2,object_lifetime_stale=1",
564}

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_thrash(), TEST_EXECUTE, TEST_INIT, TEST_THRASH_RETRIEVERS, and TEST_THRASH_TIME.

◆ load_module()

static int load_module ( void  )
static

Definition at line 617 of file test_sorcery_memory_cache_thrash.c.

618{
620 AST_TEST_REGISTER(low_unique_object_count_immediately_stale);
621 AST_TEST_REGISTER(low_unique_object_count_immediately_expire);
622 AST_TEST_REGISTER(low_unique_object_count_high_concurrent_updates);
623 AST_TEST_REGISTER(unique_objects_exceeding_maximum);
624 AST_TEST_REGISTER(unique_objects_exceeding_maximum_with_expire_and_stale);
625 AST_TEST_REGISTER(conflicting_expire_and_stale);
626 AST_TEST_REGISTER(high_object_count_without_expiration);
627
629}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static struct ast_cli_entry cli_memory_cache_thrash[]
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_SUCCESS, AST_TEST_REGISTER, and cli_memory_cache_thrash.

◆ mock_retrieve_id()

static void * mock_retrieve_id ( const struct ast_sorcery sorcery,
void *  data,
const char *  type,
const char *  id 
)
static

Callback for retrieving sorcery object by ID.

Parameters
sorceryThe sorcery instance
dataUnused
typeThe object type. Will always be "test".
idThe object id. Will always be "test".
Return values
NULLBackend data successfully allocated
non-NULLBackend data could not be successfully allocated

Definition at line 106 of file test_sorcery_memory_cache_thrash.c.

108{
109 return ast_sorcery_alloc(sorcery, type, id);
110}
static const char type[]
Definition: chan_ooh323.c:109
static struct ast_sorcery * sorcery
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744

References ast_sorcery_alloc(), sorcery, and type.

◆ mock_update()

static int mock_update ( const struct ast_sorcery sorcery,
void *  data,
void *  object 
)
static

Callback for updating a sorcery object.

Parameters
sorceryThe sorcery instance
dataUnused
objectThe object to update.

Definition at line 120 of file test_sorcery_memory_cache_thrash.c.

122{
123 return 0;
124}

◆ nominal_thrash()

static enum ast_test_result_state nominal_thrash ( struct ast_test *  test,
const char *  cache_configuration,
unsigned int  thrash_time,
unsigned int  unique_objects,
unsigned int  retrieve_threads,
unsigned int  update_threads 
)
static

Definition at line 447 of file test_sorcery_memory_cache_thrash.c.

450{
451 struct sorcery_memory_cache_thrash *thrash;
452
453 thrash = sorcery_memory_cache_thrash_create(cache_configuration, update_threads, retrieve_threads, unique_objects);
454 if (!thrash) {
455 return AST_TEST_FAIL;
456 }
457
459 while ((thrash_time = sleep(thrash_time)));
461
462 ao2_ref(thrash, -1);
463
464 return AST_TEST_PASS;
465}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Structure for memory cache thrashing.
unsigned int update_threads
The number of threads which are updating.
unsigned int retrieve_threads
The number of threads which are retrieving.
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
static void sorcery_memory_cache_thrash_stop(struct sorcery_memory_cache_thrash *thrash)
static int sorcery_memory_cache_thrash_start(struct sorcery_memory_cache_thrash *thrash)
static struct sorcery_memory_cache_thrash * sorcery_memory_cache_thrash_create(const char *cache_configuration, unsigned int update_threads, unsigned int retrieve_threads, unsigned int unique_objects)

References ao2_ref, AST_TEST_FAIL, AST_TEST_PASS, sorcery_memory_cache_thrash::retrieve_threads, sorcery_memory_cache_thrash_create(), sorcery_memory_cache_thrash_start(), sorcery_memory_cache_thrash_stop(), and sorcery_memory_cache_thrash::update_threads.

Referenced by AST_TEST_DEFINE().

◆ sorcery_memory_cache_cli_thrash()

static char * sorcery_memory_cache_cli_thrash ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 368 of file test_sorcery_memory_cache_thrash.c.

369{
370 struct sorcery_memory_cache_thrash *thrash;
371 unsigned int thrash_time, unique_objects, retrieve_threads, update_threads;
372
373 switch (cmd) {
374 case CLI_INIT:
375 e->command = "sorcery memory cache thrash";
376 e->usage =
377 "Usage: sorcery memory cache thrash <cache configuration> <amount of time to thrash the cache> <number of unique objects> <number of retrieve threads> <number of update threads>\n"
378 " Create a sorcery instance with a memory cache using the provided configuration and thrash it.\n";
379 return NULL;
380 case CLI_GENERATE:
381 return NULL;
382 }
383
384 if (a->argc != 9) {
385 return CLI_SHOWUSAGE;
386 }
387
388 if (sscanf(a->argv[5], "%30u", &thrash_time) != 1) {
389 ast_cli(a->fd, "An invalid value of '%s' has been provided for the thrashing time\n", a->argv[5]);
390 return CLI_FAILURE;
391 } else if (sscanf(a->argv[6], "%30u", &unique_objects) != 1) {
392 ast_cli(a->fd, "An invalid value of '%s' has been provided for number of unique objects\n", a->argv[6]);
393 return CLI_FAILURE;
394 } else if (sscanf(a->argv[7], "%30u", &retrieve_threads) != 1) {
395 ast_cli(a->fd, "An invalid value of '%s' has been provided for the number of retrieve threads\n", a->argv[7]);
396 return CLI_FAILURE;
397 } else if (sscanf(a->argv[8], "%30u", &update_threads) != 1) {
398 ast_cli(a->fd, "An invalid value of '%s' has been provided for the number of update threads\n", a->argv[8]);
399 return CLI_FAILURE;
400 }
401
402 thrash = sorcery_memory_cache_thrash_create(a->argv[4], update_threads, retrieve_threads, unique_objects);
403 if (!thrash) {
404 ast_cli(a->fd, "Could not create a sorcery memory cache thrash test using the provided arguments\n");
405 return CLI_FAILURE;
406 }
407
408 ast_cli(a->fd, "Starting cache thrash test.\n");
409 ast_cli(a->fd, "Memory cache configuration: %s\n", a->argv[4]);
410 ast_cli(a->fd, "Amount of time to perform test: %u seconds\n", thrash_time);
411 ast_cli(a->fd, "Number of unique objects: %u\n", unique_objects);
412 ast_cli(a->fd, "Number of retrieve threads: %u\n", retrieve_threads);
413 ast_cli(a->fd, "Number of update threads: %u\n", update_threads);
414
416 while ((thrash_time = sleep(thrash_time)));
418
419 ast_cli(a->fd, "Stopped cache thrash test\n");
420
421 ast_cli(a->fd, "Average retrieve execution time (in milliseconds): %u\n", thrash->average_retrieve_execution_time);
422 ast_cli(a->fd, "Average update execution time (in milliseconds): %u\n", thrash->average_update_execution_time);
423
424 ao2_ref(thrash, -1);
425
426 return CLI_SUCCESS;
427}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define NULL
Definition: resample.c:96
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
unsigned int average_update_execution_time
The average execution time of sorcery update operations.
unsigned int average_retrieve_execution_time
The average execution time of sorcery retrieve operations.
static struct test_val a

References a, ao2_ref, ast_cli(), sorcery_memory_cache_thrash::average_retrieve_execution_time, sorcery_memory_cache_thrash::average_update_execution_time, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, sorcery_memory_cache_thrash::retrieve_threads, sorcery_memory_cache_thrash_create(), sorcery_memory_cache_thrash_start(), sorcery_memory_cache_thrash_stop(), sorcery_memory_cache_thrash::update_threads, and ast_cli_entry::usage.

◆ sorcery_memory_cache_thrash_create()

static struct sorcery_memory_cache_thrash * sorcery_memory_cache_thrash_create ( const char *  cache_configuration,
unsigned int  update_threads,
unsigned int  retrieve_threads,
unsigned int  unique_objects 
)
static

Definition at line 173 of file test_sorcery_memory_cache_thrash.c.

175{
176 struct sorcery_memory_cache_thrash *thrash;
178 unsigned int total_threads = update_threads + retrieve_threads;
179
182 if (!thrash) {
183 return NULL;
184 }
185
186 thrash->update_threads = update_threads;
187 thrash->retrieve_threads = retrieve_threads;
188
190
191 thrash->sorcery = ast_sorcery_open();
192 if (!thrash->sorcery) {
193 ao2_ref(thrash, -1);
194 return NULL;
195 }
196
197 ast_sorcery_apply_wizard_mapping(thrash->sorcery, "test", "memory_cache",
198 !strcmp(cache_configuration, "default") ? "" : cache_configuration, 1);
199 ast_sorcery_apply_wizard_mapping(thrash->sorcery, "test", "mock", NULL, 0);
201
202 if (AST_VECTOR_INIT(&thrash->threads, update_threads + retrieve_threads)) {
203 ao2_ref(thrash, -1);
204 return NULL;
205 }
206
207 while (AST_VECTOR_SIZE(&thrash->threads) != total_threads) {
208 thread = ast_calloc(1, sizeof(*thread));
209
210 if (!thread) {
211 ao2_ref(thrash, -1);
212 return NULL;
213 }
214
215 thread->thread = AST_PTHREADT_NULL;
216 thread->unique_objects = unique_objects;
217
218 /* This purposely holds no ref as the main thrash structure does */
219 thread->sorcery = thrash->sorcery;
220
221 if (AST_VECTOR_APPEND(&thrash->threads, thread)) {
223 ao2_ref(thrash, -1);
224 return NULL;
225 }
226 }
227
228 return thrash;
229}
pthread_t thread
Definition: app_sla.c:329
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_sorcery_apply_wizard_mapping(sorcery, type, name, data, caching)
Apply additional object wizard mappings.
Definition: sorcery.h:510
#define ast_sorcery_internal_object_register(sorcery, type, alloc, transform, apply)
Register an internal, hidden object type.
Definition: sorcery.h:867
#define ast_sorcery_wizard_register(interface)
See __ast_sorcery_wizard_register()
Definition: sorcery.h:383
#define ast_sorcery_open()
Open a new sorcery structure.
Definition: sorcery.h:406
Structure for a memory cache thras thread.
unsigned int unique_objects
The number of unique objects we should restrict ourself to.
struct sorcery_memory_cache_thrash::@504 threads
Threads which are updating or reading from the cache.
struct ast_sorcery * sorcery
The sorcery instance being tested.
static void sorcery_memory_cache_thrash_destroy(void *obj)
static struct ast_sorcery_wizard mock_wizard
A mock sorcery wizard used for the stale test.
static void * test_data_alloc(const char *id)
Allocation callback for test_data sorcery object.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_calloc, ast_free, AST_PTHREADT_NULL, ast_sorcery_apply_wizard_mapping, ast_sorcery_internal_object_register, ast_sorcery_open, ast_sorcery_wizard_register, AST_VECTOR_APPEND, AST_VECTOR_INIT, AST_VECTOR_SIZE, mock_wizard, NULL, sorcery_memory_cache_thrash::retrieve_threads, sorcery_memory_cache_thrash::sorcery, sorcery_memory_cache_thrash_destroy(), test_data_alloc(), thread, sorcery_memory_cache_thrash::threads, sorcery_memory_cache_thrash_thread::unique_objects, and sorcery_memory_cache_thrash::update_threads.

Referenced by nominal_thrash(), and sorcery_memory_cache_cli_thrash().

◆ sorcery_memory_cache_thrash_destroy()

static void sorcery_memory_cache_thrash_destroy ( void *  obj)
static

Definition at line 141 of file test_sorcery_memory_cache_thrash.c.

142{
143 struct sorcery_memory_cache_thrash *thrash = obj;
144 int idx;
145
146 if (thrash->sorcery) {
147 ast_sorcery_unref(thrash->sorcery);
148 }
149
150 for (idx = 0; idx < AST_VECTOR_SIZE(&thrash->threads); ++idx) {
152
153 thread = AST_VECTOR_GET(&thrash->threads, idx);
155 }
156 AST_VECTOR_FREE(&thrash->threads);
157
159}
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
Unregister a sorcery wizard.
Definition: sorcery.c:474
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_free, ast_sorcery_unref, ast_sorcery_wizard_unregister(), AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_SIZE, mock_wizard, sorcery_memory_cache_thrash::sorcery, thread, and sorcery_memory_cache_thrash::threads.

Referenced by sorcery_memory_cache_thrash_create().

◆ sorcery_memory_cache_thrash_retrieve()

static void * sorcery_memory_cache_thrash_retrieve ( void *  data)
static

Definition at line 267 of file test_sorcery_memory_cache_thrash.c.

268{
270 struct timeval start;
271 unsigned int object_id;
272 char object_id_str[AST_UUID_STR_LEN];
273 void *object;
274
275 while (!thread->stop) {
276 object_id = ast_random() % thread->unique_objects;
277 snprintf(object_id_str, sizeof(object_id_str), "%u", object_id);
278
279 start = ast_tvnow();
280 object = ast_sorcery_retrieve_by_id(thread->sorcery, "test", object_id_str);
281 thread->average_execution_time = (thread->average_execution_time + ast_tvdiff_ms(ast_tvnow(), start)) / 2;
282 ast_assert(object != NULL);
283
284 ao2_ref(object, -1);
285 }
286
287 return NULL;
288}
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define ast_assert(a)
Definition: utils.h:739
long int ast_random(void)
Definition: utils.c:2312
#define AST_UUID_STR_LEN
Definition: uuid.h:27

References ao2_ref, ast_assert, ast_random(), ast_sorcery_retrieve_by_id(), ast_tvdiff_ms(), ast_tvnow(), AST_UUID_STR_LEN, NULL, and thread.

Referenced by sorcery_memory_cache_thrash_start().

◆ sorcery_memory_cache_thrash_start()

static int sorcery_memory_cache_thrash_start ( struct sorcery_memory_cache_thrash thrash)
static

Definition at line 345 of file test_sorcery_memory_cache_thrash.c.

346{
347 int idx;
348
349 for (idx = 0; idx < AST_VECTOR_SIZE(&thrash->threads); ++idx) {
351
352 thread = AST_VECTOR_GET(&thrash->threads, idx);
353
354 if (ast_pthread_create(&thread->thread, NULL, idx < thrash->update_threads ?
357 return -1;
358 }
359 }
360
361 return 0;
362}
static void * sorcery_memory_cache_thrash_retrieve(void *data)
static void * sorcery_memory_cache_thrash_update(void *data)
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584

References ast_pthread_create, AST_VECTOR_GET, AST_VECTOR_SIZE, NULL, sorcery_memory_cache_thrash_retrieve(), sorcery_memory_cache_thrash_stop(), sorcery_memory_cache_thrash_update(), thread, and sorcery_memory_cache_thrash::threads.

Referenced by nominal_thrash(), and sorcery_memory_cache_cli_thrash().

◆ sorcery_memory_cache_thrash_stop()

static void sorcery_memory_cache_thrash_stop ( struct sorcery_memory_cache_thrash thrash)
static

Definition at line 296 of file test_sorcery_memory_cache_thrash.c.

297{
298 int idx;
299
300 for (idx = 0; idx < AST_VECTOR_SIZE(&thrash->threads); ++idx) {
302
303 thread = AST_VECTOR_GET(&thrash->threads, idx);
304 if (thread->thread == AST_PTHREADT_NULL) {
305 continue;
306 }
307
308 thread->stop = 1;
309 }
310
311 for (idx = 0; idx < AST_VECTOR_SIZE(&thrash->threads); ++idx) {
313
314 thread = AST_VECTOR_GET(&thrash->threads, idx);
315 if (thread->thread == AST_PTHREADT_NULL) {
316 continue;
317 }
318
319 pthread_join(thread->thread, NULL);
320
321 if (idx < thrash->update_threads) {
322 thrash->average_update_execution_time += thread->average_execution_time;
323 } else {
324 thrash->average_retrieve_execution_time += thread->average_execution_time;
325 }
326 }
327
328 if (thrash->update_threads) {
330 }
331 if (thrash->retrieve_threads) {
333 }
334}

References AST_PTHREADT_NULL, AST_VECTOR_GET, AST_VECTOR_SIZE, sorcery_memory_cache_thrash::average_retrieve_execution_time, sorcery_memory_cache_thrash::average_update_execution_time, NULL, sorcery_memory_cache_thrash::retrieve_threads, thread, sorcery_memory_cache_thrash::threads, and sorcery_memory_cache_thrash::update_threads.

Referenced by nominal_thrash(), sorcery_memory_cache_cli_thrash(), and sorcery_memory_cache_thrash_start().

◆ sorcery_memory_cache_thrash_update()

static void * sorcery_memory_cache_thrash_update ( void *  data)
static

Definition at line 237 of file test_sorcery_memory_cache_thrash.c.

238{
240 struct timeval start;
241 unsigned int object_id;
242 char object_id_str[AST_UUID_STR_LEN];
243 void *object;
244
245 while (!thread->stop) {
246 object_id = ast_random() % thread->unique_objects;
247 snprintf(object_id_str, sizeof(object_id_str), "%u", object_id);
248
249 object = ast_sorcery_alloc(thread->sorcery, "test", object_id_str);
250 ast_assert(object != NULL);
251
252 start = ast_tvnow();
253 ast_sorcery_update(thread->sorcery, object);
254 thread->average_execution_time = (thread->average_execution_time + ast_tvdiff_ms(ast_tvnow(), start)) / 2;
255 ao2_ref(object, -1);
256 }
257
258 return NULL;
259}
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2145

References ao2_ref, ast_assert, ast_random(), ast_sorcery_alloc(), ast_sorcery_update(), ast_tvdiff_ms(), ast_tvnow(), AST_UUID_STR_LEN, NULL, and thread.

Referenced by sorcery_memory_cache_thrash_start().

◆ test_data_alloc()

static void * test_data_alloc ( const char *  id)
static

Allocation callback for test_data sorcery object.

Definition at line 90 of file test_sorcery_memory_cache_thrash.c.

91{
92 return ast_sorcery_generic_alloc(sizeof(struct test_data), NULL);
93}
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
Sorcery object created based on backend data.

References ast_sorcery_generic_alloc(), and NULL.

Referenced by sorcery_memory_cache_thrash_create().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 603 of file test_sorcery_memory_cache_thrash.c.

604{
606 AST_TEST_UNREGISTER(low_unique_object_count_immediately_stale);
607 AST_TEST_UNREGISTER(low_unique_object_count_immediately_expire);
608 AST_TEST_UNREGISTER(low_unique_object_count_high_concurrent_updates);
609 AST_TEST_UNREGISTER(unique_objects_exceeding_maximum);
610 AST_TEST_UNREGISTER(unique_objects_exceeding_maximum_with_expire_and_stale);
611 AST_TEST_UNREGISTER(conflicting_expire_and_stale);
612 AST_TEST_UNREGISTER(high_object_count_without_expiration);
613
614 return 0;
615}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References ARRAY_LEN, ast_cli_unregister_multiple(), AST_TEST_UNREGISTER, and cli_memory_cache_thrash.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Sorcery Cache Thrasing test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 631 of file test_sorcery_memory_cache_thrash.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 631 of file test_sorcery_memory_cache_thrash.c.

◆ cli_memory_cache_thrash

struct ast_cli_entry cli_memory_cache_thrash[]
static
Initial value:
= {
{ .handler = sorcery_memory_cache_cli_thrash , .summary = "Thrash a sorcery memory cache" ,},
}
static char * sorcery_memory_cache_cli_thrash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 429 of file test_sorcery_memory_cache_thrash.c.

Referenced by load_module(), and unload_module().

◆ mock_wizard

struct ast_sorcery_wizard mock_wizard
static
Initial value:
= {
.name = "mock",
.retrieve_id = mock_retrieve_id,
.update = mock_update,
}
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.
static int mock_update(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for updating a sorcery object.

A mock sorcery wizard used for the stale test.

Definition at line 129 of file test_sorcery_memory_cache_thrash.c.

Referenced by sorcery_memory_cache_thrash_create(), and sorcery_memory_cache_thrash_destroy().