2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Asterisk  - -  An  open  source  telephony  toolkit . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  ( C )  2015 ,  Digium ,  Inc . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Joshua  Colp  < jcolp @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  See  http : //www.asterisk.org for more information about
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  Asterisk  project .  Please  do  not  directly  contact 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  any  of  the  maintainers  of  this  project  for  assistance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  project  provides  a  web  site ,  mailing  lists  and  IRC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channels  for  your  use . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  program  is  free  software ,  distributed  under  the  terms  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  GNU  General  Public  License  Version  2.  See  the  LICENSE  file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  at  the  top  of  the  source  tree . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Sorcery  Memory  Cache  Object  Wizard 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ author  Joshua  Colp  < jcolp @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*** MODULEINFO
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< support_level > core < / support_level > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/module.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/sorcery.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/astobj2.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/sched.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/test.h" 
  
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/heap.h" 
  
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/cli.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/manager.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*** DOCUMENTATION
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " SorceryMemoryCacheExpireObject "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 13.5 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Expire  ( remove )  an  object  from  a  sorcery  memory  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Cache "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  cache  to  expire  the  object  from . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Object "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  object  to  expire . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 06:35:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< para > Expires  ( removes )  an  object  from  a  sorcery  memory  cache .  If  full  backend  caching  is  enabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  action  is  not  available  and  will  fail .  In  this  case  the  SorceryMemoryCachePopulate  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											SorceryMemoryCacheExpire  AMI  actions  must  be  used  instead . < / para > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " SorceryMemoryCacheExpire "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 13.5 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Expire  ( remove )  ALL  objects  from  a  sorcery  memory  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Cache "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  cache  to  expire  all  objects  from . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Expires  ( removes )  ALL  objects  from  a  sorcery  memory  cache . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " SorceryMemoryCacheStaleObject "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 13.5 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Mark  an  object  in  a  sorcery  memory  cache  as  stale . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Cache "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  cache  to  mark  the  object  as  stale  in . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Object "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  object  to  mark  as  stale . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											< parameter  name = " Reload "  required = " false " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > If  true ,  then  immediately  reload  the  object  from  the  backend  cache  instead  of  waiting  for  the  next  retrieval < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Marks  an  object  as  stale  within  a  sorcery  memory  cache . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " SorceryMemoryCacheStale "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 13.5 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Marks  ALL  objects  in  a  sorcery  memory  cache  as  stale . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Cache "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  cache  to  mark  all  object  as  stale  in . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Marks  ALL  objects  in  a  sorcery  memory  cache  as  stale . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< manager  name = " SorceryMemoryCachePopulate "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 13.7 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Expire  all  objects  from  a  memory  cache  and  populate  it  with  all  objects  from  the  backend . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " Cache "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  cache  to  populate . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Expires  all  objects  from  a  memory  cache  and  populate  it  with  all  objects  from  the  backend . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Structure for storing a memory cache */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  sorcery_memory_cache  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The name of the memory cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Objects in the cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The maximum number of objects permitted in the cache, 0 if no limit */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  maximum_objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The maximum time (in seconds) an object will stay in the cache, 0 if no limit */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  object_lifetime_maximum ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The amount of time (in seconds) before an object is marked as stale, 0 if disabled */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  object_lifetime_stale ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Whether all objects are expired when the object type is reloaded, 0 if disabled */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									unsigned  int  expire_on_reload ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Whether this is a cache of the entire backend, 0 if disabled */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  full_backend_cache ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Heap of cached objects. Oldest object is at the top. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_heap  * object_heap ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Scheduler item for expiring oldest object. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  expire_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief scheduler id of stale update task */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  stale_update_sched_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief An unreffed pointer to the sorcery instance, accessible only with lock held */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_sorcery  * sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The type of object we are caching */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * object_type ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:28:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! TRUE if trying to stop the oldest object expiration scheduler item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  del_expire : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef TEST_FRAMEWORK 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Variable used to indicate we should notify a test when we reach empty */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  cache_notify ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Mutex lock used for signaling when the cache has reached empty */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_t  lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Condition used for signaling when the cache has reached empty */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_t  cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Variable that is set when the cache has reached empty */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  cache_completed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Structure for stored a cached object */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  sorcery_memory_cached_object  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The cached object */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The time at which the object was created */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  created ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief index required by heap */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ssize_t  __heap_index ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief scheduler id of stale update task */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  stale_update_sched_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Cached objectset for field and regex retrieval */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_variable  * objectset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Structure used for fields comparison */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  sorcery_memory_cache_fields_cmp_params  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Pointer to the sorcery structure */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_sorcery  * sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The sorcery memory cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Pointer to the fields to check */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_variable  * fields ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Regular expression for checking object id */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									regex_t  * regex ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Prefix for matching object id */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * prefix ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Prefix length in bytes for matching object id */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  size_t  prefix_len ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*! \brief Optional container to put object into */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * container ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_open ( const  char  * data ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_create ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  void  * object ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_load ( void  * data ,  const  struct  ast_sorcery  * sorcery ,  const  char  * type ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_reload ( void  * data ,  const  struct  ast_sorcery  * sorcery ,  const  char  * type ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_retrieve_id ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_retrieve_fields ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_variable  * fields ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_retrieve_regex ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * objects ,  const  char  * regex ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_delete ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  void  * object ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_close ( void  * data ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_sorcery_wizard  memory_cache_object_wizard  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " memory_cache " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. open  =  sorcery_memory_cache_open , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. create  =  sorcery_memory_cache_create , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. update  =  sorcery_memory_cache_create , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. delete  =  sorcery_memory_cache_delete , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. load  =  sorcery_memory_cache_load , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. reload  =  sorcery_memory_cache_reload , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. retrieve_id  =  sorcery_memory_cache_retrieve_id , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. retrieve_fields  =  sorcery_memory_cache_retrieve_fields , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. retrieve_multiple  =  sorcery_memory_cache_retrieve_multiple , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. retrieve_regex  =  sorcery_memory_cache_retrieve_regex , 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. retrieve_prefix  =  sorcery_memory_cache_retrieve_prefix , 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									. close  =  sorcery_memory_cache_close , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The bucket size for the container of caches */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define CACHES_CONTAINER_BUCKET_SIZE 53 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The default bucket size for the container of objects in the cache */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define CACHE_CONTAINER_BUCKET_SIZE 53 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Height of heap for cache object heap. Allows 31 initial objects */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define CACHE_HEAP_INIT_HEIGHT 5 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*! \brief Container of created caches */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ao2_container  * caches ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Scheduler for cache management */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_sched_context  * sched ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define PASSTHRU_UPDATE_THREAD_ID 0x5EED1E55 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_THREADSTORAGE ( passthru_update_id_storage ) ;  
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  is_passthru_update ( void )  
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  * passthru_update_thread_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									passthru_update_thread_id  =  ast_threadstorage_get ( & passthru_update_id_storage , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sizeof ( * passthru_update_thread_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! passthru_update_thread_id )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  * passthru_update_thread_id  = =  PASSTHRU_UPDATE_THREAD_ID ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_passthru_update ( uint32_t  value )  
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  * passthru_update_thread_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									passthru_update_thread_id  =  ast_threadstorage_get ( & passthru_update_id_storage , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sizeof ( * passthru_update_thread_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! passthru_update_thread_id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Could not set passthru update ID for sorcery memory cache thread \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* passthru_update_thread_id  =  value ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  start_passthru_update ( void )  
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									set_passthru_update ( PASSTHRU_UPDATE_THREAD_ID ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  end_passthru_update ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_passthru_update ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Hashing  function  for  the  container  holding  caches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  sorcery  memory  cache  or  name  of  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Hashing  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  The  hash  of  the  memory  cache  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_hash ( const  void  * obj ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cache  * cache  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  hash ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( flags  &  OBJ_SEARCH_MASK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_OBJECT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  cache - > name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  =  ast_str_hash ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Should never happen in hash callback. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  hash ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Comparison  function  for  the  container  holding  caches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  arg  A  sorcery  memory  cache ,  or  name  of  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Comparison  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  CMP_MATCH  if  the  name  is  the  same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  the  name  does  not  match 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_cmp ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cache  * left  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cache  * right  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * right_name  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( flags  &  OBJ_SEARCH_MASK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_OBJECT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										right_name  =  right - > name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strcmp ( left - > name ,  right_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strncmp ( left - > name ,  right_name ,  strlen ( right_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cmp  ?  0  :  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Hashing  function  for  the  container  holding  cached  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  cached  object  or  id  of  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Hashing  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  The  hash  of  the  cached  object  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cached_object_hash ( const  void  * obj ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cached_object  * cached  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  hash ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( flags  &  OBJ_SEARCH_MASK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_OBJECT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  ast_sorcery_object_get_id ( cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  =  ast_str_hash ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Should never happen in hash callback. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  hash ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Comparison  function  for  the  container  holding  cached  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  arg  A  cached  object ,  or  id  of  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Comparison  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  CMP_MATCH  if  the  id  is  the  same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  the  id  does  not  match 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cached_object_cmp ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * left  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * right  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * right_name  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( flags  &  OBJ_SEARCH_MASK )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_OBJECT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										right_name  =  ast_sorcery_object_get_id ( right - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strcmp ( ast_sorcery_object_get_id ( left - > object ) ,  right_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_SEARCH_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strncmp ( ast_sorcery_object_get_id ( left - > object ) ,  right_name ,  strlen ( right_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cmp  ?  0  :  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Destructor  function  for  a  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_destructor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( cache - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > object_heap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_heap_destroy ( cache - > object_heap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_cleanup ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_free ( cache - > object_type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Destructor  function  for  sorcery  memory  cached  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  A  sorcery  memory  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cached_object_destructor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( cached - > object ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_variables_destroy ( cached - > objectset ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  schedule_cache_expiration ( struct  sorcery_memory_cache  * cache ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Remove  an  object  from  the  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  removes  the  item  from  both  the  hashtable  and  the  heap . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  from  which  the  object  is  being  removed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  id  The  sorcery  object  id  of  the  object  to  remove . 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  reschedule  Reschedule  cache  expiration  if  this  was  the  oldest  object . 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - zero  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  remove_from_cache ( struct  sorcery_memory_cache  * cache ,  const  char  * id ,  int  reschedule )  
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * hash_object ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * oldest_object ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * heap_object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hash_object  =  ao2_find ( cache - > objects ,  id ,  OBJ_SEARCH_KEY  |  OBJ_UNLINK  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! hash_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-02 12:20:00 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( ! strcmp ( ast_sorcery_object_get_id ( hash_object - > object ) ,  id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									oldest_object  =  ast_heap_peek ( cache - > object_heap ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									heap_object  =  ast_heap_remove ( cache - > object_heap ,  hash_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( heap_object  = =  hash_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( hash_object ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( reschedule  & &  ( oldest_object  = =  heap_object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										schedule_cache_expiration ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Scheduler  callback  invoked  to  expire  old  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  opaque  callback  data  ( in  our  case ,  the  memory  cache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  expire_objects_from_cache ( const  void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  ( struct  sorcery_memory_cache  * ) data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:28:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  We  need  to  do  deadlock  avoidance  between  a  non - scheduler  thread 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  blocking  when  trying  to  delete  the  scheduled  entry  for  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  callback  because  the  scheduler  thread  is  running  this  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  and  this  callback  waiting  for  the  cache - > objects  container  lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  that  the  blocked  non - scheduler  thread  already  holds . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ao2_trywrlock ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > del_expire )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache - > expire_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sched_yield ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache - > expire_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* This is an optimization for objects which have been cached close to each other */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( ( cached  =  ast_heap_peek ( cache - > object_heap ,  1 ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  expiration ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										expiration  =  ast_tvdiff_ms ( ast_tvadd ( cached - > created ,  ast_samp2tv ( cache - > object_lifetime_maximum ,  1 ) ) ,  ast_tvnow ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If the current oldest object has not yet expired stop and reschedule for it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( expiration  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										remove_from_cache ( cache ,  ast_sorcery_object_get_id ( cached - > object ) ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									schedule_cache_expiration ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Remove  all  objects  from  the  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  removes  ALL  objects  from  both  the  hash  table  and  heap . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  to  empty . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  remove_all_from_cache ( struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( ast_heap_pop ( cache - > object_heap ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  OBJ_UNLINK  |  OBJ_NOLOCK  |  OBJ_NODATA  |  OBJ_MULTIPLE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:28:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > del_expire  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_SCHED_DEL_UNREF ( sched ,  cache - > expire_id ,  ao2_ref ( cache ,  - 1 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:28:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > del_expire  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AO2  callback  function  for  making  an  object  stale  immediately 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  changes  the  creation  time  of  an  object  so  it  appears  as  though  it  is  stale  immediately . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  The  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  arg  The  cache  itself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Unused  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  object_stale_callback ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Since our granularity is seconds it's possible for something to retrieve us within a window
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  where  we  wouldn ' t  be  treated  as  stale .  To  ensure  that  doesn ' t  happen  we  use  the  configured  stale 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  time  plus  a  second . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached - > created  =  ast_tvsub ( cached - > created ,  ast_samp2tv ( cache - > object_lifetime_stale  +  1 ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Mark  an  object  as  stale  explicitly . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  changes  the  creation  time  of  an  object  so  it  appears  as  though  it  is  stale  immediately . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  read - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  the  object  is  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  id  The  unique  identifier  of  the  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  mark_object_as_stale_in_cache ( struct  sorcery_memory_cache  * cache ,  const  char  * id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  ao2_find ( cache - > objects ,  id ,  OBJ_SEARCH_KEY  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-02 12:20:00 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ! strcmp ( ast_sorcery_object_get_id ( cached - > object ) ,  id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									object_stale_callback ( cached ,  cache ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Mark  all  objects  as  stale  within  a  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  changes  the  creation  time  of  ALL  objects  so  they  appear  as  though  they  are  stale . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  read - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mark_all_as_stale_in_cache ( struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  OBJ_NOLOCK  |  OBJ_NODATA  |  OBJ_MULTIPLE ,  object_stale_callback ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Schedule  a  callback  for  cached  object  expiration . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  that  is  having  its  callback  scheduled . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  schedule_cache_expiration ( struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  expiration  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_lifetime_maximum )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:28:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > del_expire  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_SCHED_DEL_UNREF ( sched ,  cache - > expire_id ,  ao2_ref ( cache ,  - 1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache - > del_expire  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  ast_heap_peek ( cache - > object_heap ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef TEST_FRAMEWORK 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_mutex_lock ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cache - > cache_completed  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cond_signal ( & cache - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_mutex_unlock ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									expiration  =  MAX ( ast_tvdiff_ms ( ast_tvadd ( cached - > created ,  ast_samp2tv ( cache - > object_lifetime_maximum ,  1 ) ) ,  ast_tvnow ( ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache - > expire_id  =  ast_sched_add ( sched ,  expiration ,  expire_objects_from_cache ,  ao2_bump ( cache ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > expire_id  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Remove  the  oldest  item  from  the  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  from  which  to  remove  the  oldest  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - zero  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  remove_oldest_from_cache ( struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * heap_old_object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * hash_old_object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									heap_old_object  =  ast_heap_pop ( cache - > object_heap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! heap_old_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_old_object  =  ao2_find ( cache - > objects ,  heap_old_object , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										OBJ_SEARCH_OBJECT  |  OBJ_UNLINK  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( heap_old_object  = =  hash_old_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( hash_old_object ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									schedule_cache_expiration ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Add  a  new  object  to  the  cache . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  cache  in  which  to  add  the  new  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cached_object  The  object  to  add  to  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - zero  Failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  add_to_cache ( struct  sorcery_memory_cache  * cache ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sorcery_memory_cached_object  * cached_object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * front ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ao2_link_flags ( cache - > objects ,  cached_object ,  OBJ_NOLOCK ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > full_backend_cache  & &  ( front  =  ast_heap_peek ( cache - > object_heap ,  1 ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* For a full backend cache all objects share the same lifetime */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cached_object - > created  =  front - > created ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_heap_push ( cache - > object_heap ,  cached_object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_find ( cache - > objects ,  cached_object , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											OBJ_SEARCH_OBJECT  |  OBJ_UNLINK  |  OBJ_NODATA  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > expire_id  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										schedule_cache_expiration ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Allocate  a  cached  object  for  caching  an  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  object  The  object  to  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  sorcery_memory_cached_object  * sorcery_memory_cached_object_alloc ( const  struct  ast_sorcery  * sorcery ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cache  * cache ,  void  * object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  ao2_alloc ( sizeof ( * cached ) ,  sorcery_memory_cached_object_destructor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached - > object  =  ao2_bump ( object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached - > created  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached - > stale_update_sched_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* A cached objectset allows us to easily perform all retrieval operations in a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  minimal  of  time . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cached - > objectset  =  ast_sorcery_objectset_create ( sorcery ,  object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cached - > objectset )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  cache  an  object  in  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  object  The  object  to  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_create ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  void  * object )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cached  =  sorcery_memory_cached_object_alloc ( sorcery ,  cache ,  object ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* As there is no guarantee that this won't be called by multiple threads wanting to cache
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  the  same  object  we  remove  any  old  ones ,  which  turns  this  into  a  create / update  function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  in  reality .  As  well  since  there ' s  no  guarantee  that  the  object  in  the  cache  is  the  same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  one  here  we  remove  any  old  objects  using  the  object  identifier . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									remove_from_cache ( cache ,  ast_sorcery_object_get_id ( object ) ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > maximum_objects  & &  ao2_container_count ( cache - > objects )  > =  cache - > maximum_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( remove_oldest_from_cache ( cache ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unable to make room in cache for sorcery object '%s'. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_sorcery_object_get_id ( object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-02 12:20:00 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( ao2_container_count ( cache - > objects )  ! =  cache - > maximum_objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( add_to_cache ( cache ,  cached ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Unable to add object '%s' to the cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_sorcery_object_get_id ( object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-30 17:27:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AO2  callback  function  for  adding  an  object  to  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  The  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  arg  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  cache  itself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Unused  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  object_add_to_cache_callback ( void  * obj ,  void  * arg ,  void  * data ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  sorcery_memory_cached_object_alloc ( arg ,  cache ,  obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CMP_STOP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									add_to_cache ( cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  stale_cache_update_task_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  stale_cache_update_task_data_destructor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_cache_update_task_data  * task_data  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( task_data - > cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_unref ( task_data - > sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( task_data - > type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_cache_update_task_data  * task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data  =  ao2_alloc_options ( sizeof ( * task_data ) ,  stale_cache_update_task_data_destructor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AO2_ALLOC_OPT_LOCK_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! task_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > sorcery  =  ao2_bump ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > cache  =  ao2_bump ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > type  =  ast_strdup ( type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! task_data - > type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( task_data ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  stale_cache_update ( const  void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_cache_update_task_data  * task_data  =  ( struct  stale_cache_update_task_data  * )  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * backend_objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start_passthru_update ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									backend_objects  =  ast_sorcery_retrieve_by_fields ( task_data - > sorcery ,  task_data - > type , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end_passthru_update ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! backend_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data - > cache - > stale_update_sched_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( task_data ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( task_data - > cache - > maximum_objects  & &  ao2_container_count ( backend_objects )  > =  task_data - > cache - > maximum_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " The backend contains %d objects while the sorcery memory cache '%s' is explicitly configured to only allow %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_container_count ( backend_objects ) ,  task_data - > cache - > name ,  task_data - > cache - > maximum_objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data - > cache - > stale_update_sched_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( task_data ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( task_data - > cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									remove_all_from_cache ( task_data - > cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback_data ( backend_objects ,  OBJ_NOLOCK  |  OBJ_NODATA  |  OBJ_MULTIPLE ,  object_add_to_cache_callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data - > sorcery ,  task_data - > cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If the number of cached objects does not match the number of backend objects we encountered a memory allocation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  failure  and  the  cache  is  incomplete ,  so  drop  everything  and  fall  back  to  querying  the  backend  directly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  as  it  may  be  able  to  provide  what  is  wanted . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( task_data - > cache - > objects )  ! =  ao2_container_count ( backend_objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " The backend contains %d objects while only %d could be added to sorcery memory cache '%s' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_container_count ( backend_objects ) ,  ao2_container_count ( task_data - > cache - > objects ) ,  task_data - > cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										remove_all_from_cache ( task_data - > cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( task_data - > cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( backend_objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > cache - > stale_update_sched_id  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( task_data ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  stale_update_task_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  stale_update_task_data_destructor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_update_task_data  * task_data  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( task_data - > cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( task_data - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_unref ( task_data - > sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_update_task_data  * task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data  =  ao2_alloc_options ( sizeof ( * task_data ) ,  stale_update_task_data_destructor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AO2_ALLOC_OPT_LOCK_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! task_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > sorcery  =  ao2_bump ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > cache  =  ao2_bump ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									task_data - > object  =  ao2_bump ( object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  stale_item_update ( const  void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stale_update_task_data  * task_data  =  ( struct  stale_update_task_data  * )  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									start_passthru_update ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									object  =  ast_sorcery_retrieve_by_id ( task_data - > sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_object_get_type ( task_data - > object ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_object_get_id ( task_data - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Backend no longer has object type '%s' ID '%s'. Removing from cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_sorcery_object_get_type ( task_data - > object ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_sorcery_object_get_id ( task_data - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_delete ( task_data - > sorcery ,  task_data - > cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											task_data - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Refreshing stale cache object type '%s' ID '%s' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_sorcery_object_get_type ( task_data - > object ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_sorcery_object_get_id ( task_data - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_create ( task_data - > sorcery ,  task_data - > cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											object ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-23 11:01:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_ref ( object ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-04 07:33:30 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_test_suite_event_notify ( " SORCERY_MEMORY_CACHE_REFRESHED " ,  " Cache: %s \r \n Type: %s \r \n Name: %s \r \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data - > cache - > name ,  ast_sorcery_object_get_type ( task_data - > object ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_object_get_id ( task_data - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( task_data ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									end_passthru_update ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Populate  the  cache  with  all  objects  from  the  backend 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ pre  cache - > objects  is  write - locked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_populate ( const  struct  ast_sorcery  * sorcery ,  const  char  * type ,  struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * backend_objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start_passthru_update ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									backend_objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  type ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end_passthru_update ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! backend_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* This will occur in off-nominal memory allocation failure scenarios */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > maximum_objects  & &  ao2_container_count ( backend_objects )  > =  cache - > maximum_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " The backend contains %d objects while the sorcery memory cache '%s' is explicitly configured to only allow %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_container_count ( backend_objects ) ,  cache - > name ,  cache - > maximum_objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback_data ( backend_objects ,  OBJ_NOLOCK  |  OBJ_NODATA  |  OBJ_MULTIPLE ,  object_add_to_cache_callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										( struct  ast_sorcery * ) sorcery ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If the number of cached objects does not match the number of backend objects we encountered a memory allocation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  failure  and  the  cache  is  incomplete ,  so  drop  everything  and  fall  back  to  querying  the  backend  directly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  as  it  may  be  able  to  provide  what  is  wanted . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects )  ! =  ao2_container_count ( backend_objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " The backend contains %d objects while only %d could be added to sorcery memory cache '%s' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_container_count ( backend_objects ) ,  ao2_container_count ( cache - > objects ) ,  cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( backend_objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Determine  if  a  full  backend  cache  update  is  needed  and  do  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_full_update ( const  struct  ast_sorcery  * sorcery ,  const  char  * type ,  struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_populate ( sorcery ,  type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Queue  a  full  cache  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_stale_update_full ( const  struct  ast_sorcery  * sorcery ,  struct  sorcery_memory_cache  * cache ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > stale_update_sched_id  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  stale_cache_update_task_data  * task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data  =  stale_cache_update_task_data_alloc ( ( struct  ast_sorcery  * )  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache ,  type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( task_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache - > stale_update_sched_id  =  ast_sched_add ( sched ,  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												stale_cache_update ,  task_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > stale_update_sched_id  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ( task_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Queue  a  stale  object  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cached  The  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_stale_update_object ( const  struct  ast_sorcery  * sorcery ,  struct  sorcery_memory_cache  * cache ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cached - > stale_update_sched_id  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  stale_update_task_data  * task_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										task_data  =  stale_update_task_data_alloc ( ( struct  ast_sorcery  * )  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache ,  ast_sorcery_object_get_type ( cached - > object ) ,  cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( task_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Cached sorcery object type '%s' ID '%s' is stale. Refreshing \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_sorcery_object_get_type ( cached - > object ) ,  ast_sorcery_object_get_id ( cached - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cached - > stale_update_sched_id  =  ast_sched_add ( sched ,  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												stale_item_update ,  task_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cached - > stale_update_sched_id  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ( task_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unable to update stale cached object type '%s', ID '%s'. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_sorcery_object_get_type ( cached - > object ) ,  ast_sorcery_object_get_id ( cached - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  whether  an  object  ( or  cache )  is  stale  and  queue  an  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cached  The  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_stale_check_object ( const  struct  ast_sorcery  * sorcery ,  struct  sorcery_memory_cache  * cache ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  elapsed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* For a full cache as every object has the same expiration/staleness we can do the same check */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									elapsed  =  ast_tvsub ( ast_tvnow ( ) ,  cached - > created ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( elapsed . tv_sec  <  cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_update_full ( sorcery ,  cache ,  ast_sorcery_object_get_type ( cached - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_update_object ( sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  whether  the  entire  cache  is  stale  or  not  and  queue  an  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cache  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  Unlike  \ ref  memory_cache_stale_check  this  does  not  require   an  explicit  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  memory_cache_stale_check ( const  struct  ast_sorcery  * sorcery ,  struct  sorcery_memory_cache  * cache )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_rdlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  ao2_bump ( ast_heap_peek ( cache - > object_heap ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_stale_check_object ( sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  retrieve  an  object  from  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  id  The  id  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_retrieve_id ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  const  char  * id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( is_passthru_update ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memory_cache_full_update ( sorcery ,  type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									cached  =  ao2_find ( cache - > objects ,  id ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-02 12:20:00 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ! strcmp ( ast_sorcery_object_get_id ( cached - > object ) ,  id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memory_cache_stale_check_object ( sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									object  =  ao2_bump ( cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AO2  callback  function  for  comparing  a  retrieval  request  and  finding  applicable  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  The  cached  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  arg  The  comparison  parameters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  Unused  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_fields_cmp ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  sorcery_memory_cache_fields_cmp_params  * params  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_variable  * ,  diff ,  NULL ,  ast_variables_destroy ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( params - > regex )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If a regular expression has been provided see if it matches, otherwise move on */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! regexec ( params - > regex ,  ast_sorcery_object_get_id ( cached - > object ) ,  0 ,  NULL ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_link ( params - > container ,  cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( params - > prefix )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncmp ( params - > prefix ,  ast_sorcery_object_get_id ( cached - > object ) ,  params - > prefix_len ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_link ( params - > container ,  cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( params - > fields  & & 
							 
						 
					
						
							
								
									
										
											 
										
											
												sorcery/res_pjsip:  Refactor for realtime performance
There were a number of places in the res_pjsip stack that were getting
all endpoints or all aors, and then filtering them locally.
A good example is pjsip_options which, on startup, retrieves all
endpoints, then the aors for those endpoints, then tests the aors to see
if the qualify_frequency is > 0.  One issue was that it never did
anything with the endpoints other than retrieve the aors so we probably
could have skipped a step and just retrieved all aors. But nevermind.
This worked reasonably well with local config files but with a realtime
backend and thousands of objects, this was a nightmare.  The issue
really boiled down to the fact that while realtime supports predicates
that are passed to the database engine, the non-realtime sorcery
backends didn't.
They do now.
The realtime engines have a scheme for doing simple comparisons. They
take in an ast_variable (or list) for matching, and the name of each
variable can contain an operator.  For instance, a name of
"qualify_frequency >" and a value of "0" would create a SQL predicate
that looks like "where qualify_frequency > '0'".  If there's no operator
after the name, the engines add an '=' so a simple name of
"qualify_frequency" and a value of "10" would return exact matches.
The non-realtime backends decide whether to include an object in a
result set by calling ast_sorcery_changeset_create on every object in
the internal container.  However, ast_sorcery_changeset_create only does
exact string matches though so a name of "qualify_frequency >" and a
value of "0" returns nothing because the literal "qualify_frequency >"
doesn't match any name in the objset set.
So, the real task was to create a generic string matcher that can take a
left value, operator and a right value and perform the match. To that
end, strings.c has a new ast_strings_match(left, operator, right)
function.  Left and right are the strings to operate on and the operator
can be a string containing any of the following: = (or NULL or ""), !=,
>, >=, <, <=, like or regex.  If the operator is like or regex, the
right string should be a %-pattern or a regex expression.  If both left
and right can be converted to float, then a numeric comparison is
performed, otherwise a string comparison is performed.
To use this new function on ast_variables, 2 new functions were added to
config.c.  One that compares 2 ast_variables, and one that compares 2
ast_variable lists.  The former is useful when you want to compare 2
ast_variables that happen to be in a list but don't want to traverse the
list.  The latter will traverse the right list and return true if all
the variables in it match the left list.
Now, the backends' fields_cmp functions call ast_variable_lists_match
instead of ast_sorcery_changeset_create and they can now process the
same syntax as the realtime engines.  The realtime backend just passes
the variable list unaltered to the engine.  The only gotcha is that
there's no common realtime engine support for regex so that's been noted
in the api docs for ast_sorcery_retrieve_by_fields.
Only one more change to sorcery was done...  A new config flag
"allow_unqualified_fetch" was added to reg_sorcery_realtime.
"no": ignore fetches if no predicate fields were supplied.
"error": same as no but emit an error. (good for testing)
"yes": allow (the default);
"warn": allow but emit a warning. (good for testing)
Now on to res_pjsip...
pjsip_options was modified to retrieve aors with qualify_frequency > 0
rather than all endpoints then all aors.  Not only was this a big
improvement in realtime retrieval but even for config files there's an
improvement because we're not going through endpoints anymore.
res_pjsip_mwi was modified to retieve only endpoints with something in
the mailboxes field instead of all endpoints then testing mailboxes.
res_pjsip_registrar_expire was completely refactored.  It was retrieving
all contacts then setting up scheduler entries to check for expiration.
Now, it's a single thread (like keepalive) that periodically retrieves
only contacts whose expiration time is < now and deletes them.  A new
contact_expiration_check_interval was added to global with a default of
30 seconds.
Ross Beer reports that with this patch, his Asterisk startup time dropped
from around an hour to under 30 seconds.
There are still objects that can't be filtered at the database like
identifies, transports, and registrations.  These are not going to be
anywhere near as numerous as endpoints, aors, auths, contacts however.
Back to allow_unqualified_fetch.  If this is set to yes and you have a
very large number of objects in the database, the pjsip CLI commands
will attempt to retrive ALL of them if not qualified with a LIKE.
Worse, if you type "pjsip show endpoint <tab>" guess what's going to
happen? :)  Having a cache helps but all the objects will have to be
retrieved at least once to fill the cache.  Setting
allow_unqualified_fetch=no prevents the mass retrieve and should be used
on endpoints, auths, aors, and contacts.  It should NOT be used for
identifies, registrations and transports since these MUST be
retrieved in bulk.
Example sorcery.conf:
[res_pjsip]
endpoint=config,pjsip.conf,criteria=type=endpoint
endpoint=realtime,ps_endpoints,allow_unqualified_fetch=error
ASTERISK-25826 #close
Reported-by: Ross Beer
Tested-by: Ross Beer
Change-Id: Id2691e447db90892890036e663aaf907b2dc1c67
											 
										 
										
											2016-03-08 14:55:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									     ( ! ast_variable_lists_match ( cached - > objectset ,  params - > fields ,  0 ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* If we can't turn the object into an object set OR if differences exist between the fields
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  passed  in  and  what  are  present  on  the  object  they  are  not  a  match . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( params - > container )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_link ( params - > container ,  cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* As multiple objects are being returned keep going */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Immediately stop and return, we only want a single object */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CMP_MATCH  |  CMP_STOP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  retrieve  a  single  object  based  on  fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  fields  Any  explicit  fields  to  search  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_retrieve_fields ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_variable  * fields ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache_fields_cmp_params  params  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. sorcery  =  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. cache  =  cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. fields  =  fields , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * object  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_passthru_update ( )  | |  ! cache - > full_backend_cache  | |  ! fields )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached  =  ao2_callback ( cache - > objects ,  0 ,  sorcery_memory_cache_fields_cmp ,  & params ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_check_object ( sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										object  =  ao2_bump ( cached - > object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  retrieve  multiple  objects  from  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  objects  Container  to  place  the  objects  into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  fields  Any  explicit  fields  to  search  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache_fields_cmp_params  params  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. sorcery  =  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. cache  =  cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. fields  =  fields , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. container  =  objects , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_passthru_update ( )  | |  ! cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_full_update ( sorcery ,  type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  0 ,  sorcery_memory_cache_fields_cmp ,  & params ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_check ( sorcery ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  retrieve  multiple  objects  using  a  regex  on  the  object  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  objects  Container  to  place  the  objects  into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  regex  Regular  expression  to  apply  to  the  object  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_retrieve_regex ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  const  char  * type ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * objects ,  const  char  * regex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									regex_t  expression ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache_fields_cmp_params  params  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. sorcery  =  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. cache  =  cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. container  =  objects , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. regex  =  & expression , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_passthru_update ( )  | |  ! cache - > full_backend_cache  | |  regcomp ( & expression ,  regex ,  REG_EXTENDED  |  REG_NOSUB ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_full_update ( sorcery ,  type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  0 ,  sorcery_memory_cache_fields_cmp ,  & params ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									regfree ( & expression ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_check ( sorcery ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  retrieve  multiple  objects  whose  id  matches  a  prefix 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  the  object  to  retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  objects  Container  to  place  the  objects  into 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  prefix ,  prefix_len  Prefix  to  match  against  the  object  id 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 09:21:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache_fields_cmp_params  params  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. sorcery  =  sorcery , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. cache  =  cache , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. container  =  objects , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. prefix  =  prefix , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. prefix_len  =  prefix_len , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_passthru_update ( )  | |  ! cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_full_update ( sorcery ,  type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  0 ,  sorcery_memory_cache_fields_cmp ,  & params ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memory_cache_stale_check ( sorcery ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-17 09:00:21 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  finish  configuring  the  memory  cache 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  object  being  loaded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_load ( void  * data ,  const  struct  ast_sorcery  * sorcery ,  const  char  * type )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If no name was explicitly specified generate one given the sorcery instance and object type */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_asprintf ( & cache - > name ,  " %s/%s " ,  ast_sorcery_get_module ( sorcery ) ,  type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_link ( caches ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Memory cache '%s' associated with sorcery instance '%p' of module '%s' with object type '%s' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cache - > name ,  sorcery ,  ast_sorcery_get_module ( sorcery ) ,  type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > sorcery  =  sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache - > object_type  =  ast_strdup ( type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  expire  objects  from  the  memory  cache  on  reload  ( if  configured ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  type  of  object  being  reloaded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_reload ( void  * data ,  const  struct  ast_sorcery  * sorcery ,  const  char  * type )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-06-04 15:11:44 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > expire_on_reload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Function  used  to  take  an  unsigned  integer  based  configuration  option  and  parse  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  value  The  string  value  of  the  configuration  option 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  result  The  unsigned  integer  to  place  the  result  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  1  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  configuration_parse_unsigned_integer ( const  char  * value ,  unsigned  int  * result )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( value )  | |  ! strncmp ( value ,  " - " ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sscanf ( value ,  " %30u " ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  age_cmp ( void  * a ,  void  * b )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_tvcmp ( ( ( struct  sorcery_memory_cached_object  * )  b ) - > created , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( ( struct  sorcery_memory_cached_object  * )  a ) - > created ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  create  a  new  sorcery  memory  cache  using  provided  configuration 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  A  stringified  configuration  for  the  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * sorcery_memory_cache_open ( const  char  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-05-12 04:21:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  * options  =  ast_strdupa ( data ) ,  * option ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  sorcery_memory_cache  * ,  cache ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_alloc_options ( sizeof ( * cache ) ,  sorcery_memory_cache_destructor ,  AO2_ALLOC_OPT_LOCK_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > expire_id  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > stale_update_sched_id  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* If no configuration options have been provided this memory cache will operate in a default
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  configuration . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ! ast_strlen_zero ( options )  & &  ( option  =  strsep ( & options ,  " , " ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  * name  =  strsep ( & option ,  " = " ) ,  * value  =  option ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  " name " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_strlen_zero ( value ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " A name must be specified for the memory cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache - > name  =  ast_strdup ( value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( name ,  " maximum_objects " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( configuration_parse_unsigned_integer ( value ,  & cache - > maximum_objects )  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Unsupported maximum objects value of '%s' used for memory cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( name ,  " object_lifetime_maximum " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( configuration_parse_unsigned_integer ( value ,  & cache - > object_lifetime_maximum )  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Unsupported object maximum lifetime value of '%s' used for memory cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( name ,  " object_lifetime_stale " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( configuration_parse_unsigned_integer ( value ,  & cache - > object_lifetime_stale )  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Unsupported object stale lifetime value of '%s' used for memory cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( name ,  " expire_on_reload " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache - > expire_on_reload  =  ast_true ( value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( ! strcasecmp ( name ,  " full_backend_cache " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cache - > full_backend_cache  =  ast_true ( value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unsupported option '%s' used for memory cache \n " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-16 15:11:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > objects  =  ao2_container_alloc_hash ( AO2_ALLOC_OPT_LOCK_RWLOCK ,  0 , 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										cache - > maximum_objects  ?  cache - > maximum_objects  :  CACHE_CONTAINER_BUCKET_SIZE , 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-16 15:11:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sorcery_memory_cached_object_hash ,  NULL ,  sorcery_memory_cached_object_cmp ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Could not create a container to hold cached objects for memory cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache - > object_heap  =  ast_heap_create ( CACHE_HEAP_INIT_HEIGHT ,  age_cmp , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										offsetof ( struct  sorcery_memory_cached_object ,  __heap_index ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_heap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Could not create heap to hold cached objects \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* The memory cache is not linked to the caches container until the load callback is invoked.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Linking  occurs  there  so  an  intelligent  cache  name  can  be  constructed  using  the  module  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  the  sorcery  instance  and  the  specific  object  type  if  no  cache  name  was  specified  as  part 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  of  the  configuration . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* This is done as RAII_VAR will drop the reference */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ao2_bump ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  delete  an  object  from  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  object  The  object  to  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_delete ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  void  * object )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  remove_from_cache ( cache ,  ast_sorcery_object_get_id ( object ) ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-13 13:06:34 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Unable to delete object '%s' from sorcery cache \n " ,  ast_sorcery_object_get_id ( object ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  to  terminate  a  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  The  sorcery  memory  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  sorcery_memory_cache_close ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* This can occur if a cache is created but never loaded */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( cache - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlink ( caches ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > object_lifetime_maximum )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If object lifetime support is enabled we need to explicitly drop all cached objects here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  and  stop  the  scheduled  task .  Failure  to  do  so  could  potentially  keep  the  cache  around  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  a  prolonged  period  of  time . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-01 14:30:06 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cache - > sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  tab  completion  for  cache  names 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_complete_name ( const  char  * word ,  int  state )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  it_caches ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen  =  strlen ( word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  which  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * result  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_caches  =  ao2_iterator_init ( caches ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( cache  =  ao2_iterator_next ( & it_caches ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( word ,  cache - > name ,  wordlen ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  + + which  >  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											result  =  ast_strdup ( cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_caches ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  command  implementation  for  ' sorcery  memory  cache  show ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_show ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " sorcery memory cache show " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    " Usage: sorcery memory cache show <name> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        Show sorcery memory cache configuration and statistics. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_name ( a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  a - > argv [ 4 ] ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not exist \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Sorcery memory cache: %s \n " ,  cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Number of objects within cache: %d \n " ,  ao2_container_count ( cache - > objects ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > maximum_objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Maximum allowed objects: %d \n " ,  cache - > maximum_objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " There is no limit on the maximum number of objects in the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > object_lifetime_maximum )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Number of seconds before object expires: %d \n " ,  cache - > object_lifetime_maximum ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Object expiration is not enabled - cached objects will not expire \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Number of seconds before object becomes stale: %d \n " ,  cache - > object_lifetime_stale ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Object staleness is not enabled - cached objects will not go stale \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Expire all objects on reload: %s \n " ,  AST_CLI_ONOFF ( cache - > expire_on_reload ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Structure used to pass data for printing cached object information */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  print_object_details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The sorcery memory cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief The CLI arguments */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cli_args  * a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  function  for  displaying  object  within  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_print_object ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FORMAT "%-25.25s %-15u %-15u \n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  print_object_details  * details  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  seconds_until_expire  =  0 ,  seconds_until_stale  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( details - > cache - > object_lifetime_maximum )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										seconds_until_expire  =  ast_tvdiff_ms ( ast_tvadd ( cached - > created ,  ast_samp2tv ( details - > cache - > object_lifetime_maximum ,  1 ) ) ,  ast_tvnow ( ) )  /  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( details - > cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										seconds_until_stale  =  ast_tvdiff_ms ( ast_tvadd ( cached - > created ,  ast_samp2tv ( details - > cache - > object_lifetime_stale ,  1 ) ) ,  ast_tvnow ( ) )  /  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( details - > a - > fd ,  FORMAT ,  ast_sorcery_object_get_id ( cached - > object ) ,  MAX ( seconds_until_stale ,  0 ) ,  MAX ( seconds_until_expire ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  command  implementation  for  ' sorcery  memory  cache  dump ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_dump ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FORMAT "%-25.25s %-15.15s %-15.15s \n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  print_object_details  details ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " sorcery memory cache dump " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    " Usage: sorcery memory cache dump <name> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        Dump a list of the objects within the cache, listed by object identifier. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_name ( a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  a - > argv [ 4 ] ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not exist \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									details . cache  =  cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									details . a  =  a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Dumping sorcery memory cache '%s': \n " ,  cache - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  "  * Staleness is not enabled - objects will not go stale \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_lifetime_maximum )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  "  * Object lifetime is not enabled - objects will not expire \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  FORMAT ,  " Object Name " ,  " Stale In " ,  " Expires In " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  FORMAT ,  " ------------------------- " ,  " --------------- " ,  " --------------- " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( cache - > objects ,  OBJ_NODATA  |  OBJ_MULTIPLE ,  sorcery_memory_cache_print_object ,  & details ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  FORMAT ,  " ------------------------- " ,  " --------------- " ,  " --------------- " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Total number of objects cached: %d \n " ,  ao2_container_count ( cache - > objects ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  tab  completion  for  cached  object  names 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_complete_object_name ( const  char  * cache_name ,  const  char  * word ,  int  state )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  it_cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen  =  strlen ( word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  which  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * result  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_cached  =  ao2_iterator_init ( cache - > objects ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( cached  =  ao2_iterator_next ( & it_cached ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( word ,  ast_sorcery_object_get_id ( cached - > object ) ,  wordlen ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  + + which  >  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											result  =  ast_strdup ( ast_sorcery_object_get_id ( cached - > object ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  command  implementation  for  ' sorcery  memory  cache  expire ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_expire ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " sorcery memory cache expire " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    " Usage: sorcery memory cache expire <cache name> [object name] \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        Expire a specific object or ALL objects within a sorcery memory cache. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_name ( a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( a - > pos  = =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_object_name ( a - > argv [ 4 ] ,  a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-25 13:17:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  <  5  | |  a - > argc  >  6 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  a - > argv [ 4 ] ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not exist \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  = =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " All objects have been removed from cache '%s' \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 06:35:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Due to full backend caching per-object expiration is not available on cache '%s' \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( ! remove_from_cache ( cache ,  a - > argv [ 5 ] ,  1 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Successfully expired object '%s' from cache '%s' \n " ,  a - > argv [ 5 ] ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Object '%s' was not expired from cache '%s' as it was not found \n " ,  a - > argv [ 5 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  command  implementation  for  ' sorcery  memory  cache  stale ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_stale ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 10:57:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  reload  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " sorcery memory cache stale " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										    " Usage: sorcery memory cache stale <cache name> [object name [reload]] \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        Mark a specific object or ALL objects as stale in a sorcery memory cache. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        If  \" reload \"  is specified, then the object is marked stale and immediately \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        retrieved from backend storage to repopulate the cache \n " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_name ( a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( a - > pos  = =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_object_name ( a - > argv [ 4 ] ,  a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 10:57:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( a - > pos  = =  6 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											static  const  char  *  const  completions [ ]  =  {  " reload " ,  NULL  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ast_cli_complete ( a - > word ,  completions ,  a - > n ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  <  5  | |  a - > argc  >  7 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 10:57:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  = =  7 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( a - > argv [ 6 ] ,  " reload " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reload  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  a - > argv [ 4 ] ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not exist \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > object_lifetime_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not have staleness enabled \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_rdlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  = =  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mark_all_as_stale_in_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Marked all objects in sorcery memory cache '%s' as stale \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! mark_object_as_stale_in_cache ( cache ,  a - > argv [ 5 ] ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Successfully marked object '%s' in memory cache '%s' as stale \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												a - > argv [ 5 ] ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 10:57:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( reload )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cached  =  ao2_find ( cache - > objects ,  a - > argv [ 5 ] ,  OBJ_SEARCH_KEY  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													memory_cache_stale_update_object ( cache - > sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Object '%s' in sorcery memory cache '%s' could not be marked as stale as it was not found \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												a - > argv [ 5 ] ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  CLI  command  implementation  for  ' sorcery  memory  cache  populate ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * sorcery_memory_cache_populate ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " sorcery memory cache populate " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    " Usage: sorcery memory cache populate <cache name> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    "        Expire all objects in the cache and populate it with ALL objects from backend. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sorcery_memory_cache_complete_name ( a - > word ,  a - > n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-25 13:17:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  5 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  a - > argv [ 4 ] ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not exist \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' does not have full backend caching enabled \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' is no longer active \n " ,  a - > argv [ 4 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_FAILURE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_populate ( cache - > sorcery ,  cache - > object_type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Specified sorcery memory cache '%s' has been populated with '%d' objects from the backend \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										a - > argv [ 4 ] ,  ao2_container_count ( cache - > objects ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_cli_entry  cli_memory_cache [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( sorcery_memory_cache_show ,  " Show sorcery memory cache information " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( sorcery_memory_cache_dump ,  " Dump all objects within a sorcery memory cache " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( sorcery_memory_cache_expire ,  " Expire a specific object or ALL objects within a sorcery memory cache " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( sorcery_memory_cache_stale ,  " Mark a specific object or ALL objects as stale within a sorcery memory cache " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( sorcery_memory_cache_populate ,  " Clear and populate the sorcery memory cache with objects from the backend " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AMI  command  implementation  for  ' SorceryMemoryCacheExpireObject ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_ami_expire_object ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * cache_name  =  astman_get_header ( m ,  " Cache " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * object_name  =  astman_get_header ( m ,  " Object " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheExpireObject requires that a cache name be provided. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ast_strlen_zero ( object_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheExpireObject requires that an object name be provided \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not exist \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 06:35:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  remove_from_cache ( cache ,  object_name ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 06:35:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " Due to full backend caching per-object expiration is not available, consider using SorceryMemoryCachePopulate or SorceryMemoryCacheExpire instead \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										astman_send_ack ( s ,  m ,  " The provided object was expired from the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided object could not be expired from the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AMI  command  implementation  for  ' SorceryMemoryCacheExpire ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_ami_expire ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * cache_name  =  astman_get_header ( m ,  " Cache " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheExpire requires that a cache name be provided. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not exist \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									astman_send_ack ( s ,  m ,  " All objects were expired from the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AMI  command  implementation  for  ' SorceryMemoryCacheStaleObject ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_ami_stale_object ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * cache_name  =  astman_get_header ( m ,  " Cache " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * object_name  =  astman_get_header ( m ,  " Object " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * reload  =  astman_get_header ( m ,  " Reload " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheStaleObject requires that a cache name be provided. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ast_strlen_zero ( object_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheStaleObject requires that an object name be provided \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not exist \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_rdlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  mark_object_as_stale_in_cache ( cache ,  object_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-25 15:26:53 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_true ( reload ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sorcery_memory_cached_object  * cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cached  =  ao2_find ( cache - > objects ,  object_name ,  OBJ_SEARCH_KEY  |  OBJ_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cached )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memory_cache_stale_update_object ( cache - > sorcery ,  cache ,  cached ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( cached ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_ack ( s ,  m ,  " The provided object was marked as stale in the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided object could not be marked as stale in the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AMI  command  implementation  for  ' SorceryMemoryCacheStale ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_ami_stale ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * cache_name  =  astman_get_header ( m ,  " Cache " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCacheStale requires that a cache name be provided. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not exist \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_rdlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mark_all_as_stale_in_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									astman_send_ack ( s ,  m ,  " All objects were marked as stale in the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  AMI  command  implementation  for  ' SorceryMemoryCachePopulate ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  sorcery_memory_cache_ami_populate ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * cache_name  =  astman_get_header ( m ,  " Cache " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( cache_name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " SorceryMemoryCachePopulate requires that a cache name be provided. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  ao2_find ( caches ,  cache_name ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not exist \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > full_backend_cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache does not have full backend caching enabled \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_wrlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache - > sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " The provided cache is no longer active \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									remove_all_from_cache ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memory_cache_populate ( cache - > sorcery ,  cache - > object_type ,  cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cache - > objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cache ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									astman_send_ack ( s ,  m ,  " Cache has been expired and populated \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef TEST_FRAMEWORK 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Dummy sorcery object */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  test_sorcery_object  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SORCERY_OBJECT ( details ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Allocator  for  test  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  id  The  identifier  for  the  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * test_sorcery_object_alloc ( const  char  * id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_sorcery_generic_alloc ( sizeof ( struct  test_sorcery_object ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Allocator  for  test  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_sorcery  * alloc_and_initialize_sorcery ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ( sorcery  =  ast_sorcery_open ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( ast_sorcery_apply_default ( sorcery ,  " test " ,  " memory " ,  NULL )  ! =  AST_SORCERY_APPLY_SUCCESS )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_internal_object_register ( sorcery ,  " test " ,  test_sorcery_object_alloc ,  NULL ,  NULL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sorcery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( open_with_valid_options )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " open_with_valid_options " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Attempt to create sorcery memory caches using valid options " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with default configuration \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with a maximum object count of 10 and verifies it \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with a maximum object lifetime of 60 and verifies it \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Creates a memory cache with a stale object lifetime of 90 and verifies it " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache using default configuration \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " maximum_objects=10 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache with a maximum object count of 10 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > maximum_objects  ! =  10 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Created a sorcery memory cache with a maximum object count of 10 but it has '%u' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cache - > maximum_objects ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_maximum=60 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache with a maximum object lifetime of 60 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > object_lifetime_maximum  ! =  60 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Created a sorcery memory cache with a maximum object lifetime of 60 but it has '%u' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cache - > object_lifetime_maximum ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_stale=90 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache with a stale object lifetime of 90 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > object_lifetime_stale  ! =  90 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Created a sorcery memory cache with a stale object lifetime of 90 but it has '%u' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cache - > object_lifetime_stale ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( open_with_invalid_options )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " open_with_invalid_options " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Attempt to create sorcery memory caches using invalid options " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test attempts to perform the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with an empty name \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with a maximum object count of -1 \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with a maximum object count of toast \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with a maximum object lifetime of -1 \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with a maximum object lifetime of toast \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a memory cache with a stale object lifetime of -1 \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Create a memory cache with a stale object lifetime of toast " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " name= " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with an empty name \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " maximum_objects=-1 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with a maximum object count of -1 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " maximum_objects=toast " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with a maximum object count of toast \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_maximum=-1 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with an object lifetime maximum of -1 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_maximum=toast " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with an object lifetime maximum of toast \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_stale=-1 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with a stale object lifetime of -1 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_stale=toast " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with a stale object lifetime of toast \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " tacos " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Created a sorcery memory cache with an invalid configuration option 'tacos' \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( create_and_retrieve )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  cached_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " create " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Attempt to create an object in the cache " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with default options \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a sorcery instance with a test object \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a test object with an id of test \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes the test object into the memory cache \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Confirms that the test object is in the cache " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache using default options \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Memory cache contains cached objects before we added one \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  alloc_and_initialize_sorcery ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a test sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									object  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to allocate a test object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Added test object to memory cache but cache remains empty \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Object placed into memory cache could not be retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cached_object  ! =  object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Object retrieved from memory cached is not the one we cached \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( update )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  original_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  updated_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  cached_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " create " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Attempt to create and then update an object in the cache " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with default options \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a sorcery instance with a test object \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a test object with an id of test \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes the test object into the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Confirms that the test object is in the cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a new test object with the same id of test \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes the new test object into the memory cache \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Confirms that the new test object has replaced the old one " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache using default options \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Memory cache contains cached objects before we added one \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  alloc_and_initialize_sorcery ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a test sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									original_object  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! original_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to allocate a test object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  original_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									updated_object  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! updated_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to allocate an updated test object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  updated_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects )  ! =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Added updated test object to memory cache but cache now contains %d objects instead of 1 \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_container_count ( cache - > objects ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Updated object placed into memory cache could not be retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cached_object  = =  original_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Updated object placed into memory cache but old one is being retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( cached_object  ! =  updated_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Updated object placed into memory cache but different one is being retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( delete )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  cached_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " delete " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Attempt to create and then delete an object in the cache " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with default options \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a sorcery instance with a test object \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a test object with an id of test \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes the test object into the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Confirms that the test object is in the cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Deletes the test object from the cache \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Confirms that the test object is no longer in the cache " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache using default options \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Memory cache contains cached objects before we added one \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  alloc_and_initialize_sorcery ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a test sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									object  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to allocate a test object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Added test object to memory cache but cache contains no objects \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Test object placed into memory cache could not be retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cached_object ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached_object  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_delete ( sorcery ,  cache ,  object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Test object deleted from memory cache can still be retrieved \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  cached_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  num_in_cache ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  in_cache [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Failed to retrieve '%s' object from the cache \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													in_cache [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cached_object ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  num_not_in_cache ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cached_object  =  sorcery_memory_cache_retrieve_id ( sorcery ,  cache ,  " test " ,  not_in_cache [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cached_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Retrieved '%s' object from the cache unexpectedly \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													not_in_cache [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( cached_object ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( maximum_objects )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  alice ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  bob ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  charlie ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  cached_object ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * in_cache [ 2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * not_in_cache [ 2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " maximum_objects " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Ensure that the 'maximum_objects' option works as expected " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with maximum_objects=2 \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a sorcery instance \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a three test objects: alice, bob, charlie, and david \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes alice and bob into the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Confirms that alice and bob are in the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes charlie into the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Confirms that bob and charlie are in the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Deletes charlie from the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Confirms that only bob is in the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes alice into the memory cache \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Confirms that bob and alice are in the memory cache " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " maximum_objects=2 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache with maximum_objects=2 \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Memory cache contains cached objects before we added one \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  alloc_and_initialize_sorcery ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a test sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									alice  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " alice " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bob  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " bob " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									charlie  =  ast_sorcery_alloc ( sorcery ,  " test " ,  " charlie " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! alice  | |  ! bob  | |  ! charlie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to allocate sorcery object(s) \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  alice ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 0 ]  =  " alice " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 1 ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 0 ]  =  " bob " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 1 ]  =  " charlie " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( check_cache_content ( test ,  sorcery ,  cache ,  in_cache ,  1 ,  not_in_cache ,  2 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Delays are added to ensure that we are not adding cache entries within the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  same  microsecond 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usleep ( 1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  bob ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 0 ]  =  " alice " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 1 ]  =  " bob " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 0 ]  =  " charlie " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 1 ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( check_cache_content ( test ,  sorcery ,  cache ,  in_cache ,  2 ,  not_in_cache ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usleep ( 1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  charlie ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 0 ]  =  " bob " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 1 ]  =  " charlie " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 0 ]  =  " alice " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 1 ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( check_cache_content ( test ,  sorcery ,  cache ,  in_cache ,  2 ,  not_in_cache ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usleep ( 1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_delete ( sorcery ,  cache ,  charlie ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 0 ]  =  " bob " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 1 ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 0 ]  =  " alice " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 1 ]  =  " charlie " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( check_cache_content ( test ,  sorcery ,  cache ,  in_cache ,  1 ,  not_in_cache ,  2 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usleep ( 1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery_memory_cache_create ( sorcery ,  cache ,  alice ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 0 ]  =  " bob " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									in_cache [ 1 ]  =  " alice " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 0 ]  =  " charlie " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									not_in_cache [ 1 ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( check_cache_content ( test ,  sorcery ,  cache ,  in_cache ,  2 ,  not_in_cache ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( expiration )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sorcery_memory_cache  * cache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " expiration " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Add objects to a cache configured with maximum lifetime, confirm they are removed " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Creates a memory cache with a maximum object lifetime of 5 seconds \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pushes 10 objects into the memory cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Waits (up to) 10 seconds for expiration to occur \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t * Confirms that the objects have been removed from the cache " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache  =  sorcery_memory_cache_open ( " object_lifetime_maximum=5 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a sorcery memory cache using default options \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  alloc_and_initialize_sorcery ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create a test sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cache - > cache_notify  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_init ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_init ( & cache - > cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  5 ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  uuid [ AST_UUID_STR_LEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										object  =  ast_sorcery_alloc ( sorcery ,  " test " ,  ast_uuid_generate_str ( uuid ,  sizeof ( uuid ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Failed to allocate test object for expiration \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_create ( sorcery ,  cache ,  object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( object ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ! cache - > cache_completed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timeval  start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timespec  end  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. tv_sec  =  start . tv_sec  +  10 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. tv_nsec  =  start . tv_usec  *  1000 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_cond_timedwait ( & cache - > cond ,  & cache - > lock ,  & end )  = =  ETIMEDOUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( cache - > objects ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Objects placed into the memory cache did not expire and get removed \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache - > cache_notify )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cond_destroy ( & cache - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_mutex_destroy ( & cache - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sorcery_memory_cache_close ( cache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Backend  data  that  the  mock  sorcery  wizard  uses  to  create  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  backend_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! An arbitrary data field */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  salt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Another arbitrary data field */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  pepper ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Indicates whether the backend has data */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  exists ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  * real_backend_data ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Sorcery  object  created  based  on  backend  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  test_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SORCERY_OBJECT ( details ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Mirrors the backend data's salt field */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  salt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Mirrors the backend data's pepper field */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  pepper ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Allocation  callback  for  test_data  sorcery  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * test_data_alloc ( const  char  * id )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_sorcery_generic_alloc ( sizeof ( struct  test_data ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  for  retrieving  sorcery  object  by  ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  mock  wizard  uses  the  \ ref  real_backend_data  in  order  to  construct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  objects .  If  the  backend  data  is  " nonexisent "  then  no  object  is  returned . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Otherwise ,  an  object  is  created  that  has  the  backend  data ' s  salt  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  pepper  values  copied . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Unused 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  object  type .  Will  always  be  " test " . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  id  The  object  id .  Will  always  be  " test " . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  Backend  data  does  not  exist 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - NULL  An  object  representing  the  backend  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * mock_retrieve_id ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * type ,  const  char  * id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  test_data  * b_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! real_backend_data - > exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b_data  =  ast_sorcery_alloc ( sorcery ,  type ,  id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! b_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b_data - > salt  =  real_backend_data - > salt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b_data - > pepper  =  real_backend_data - > pepper ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  b_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  for  retrieving  multiple  sorcery  objects 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  mock  wizard  uses  the  \ ref  real_backend_data  in  order  to  construct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  objects .  If  the  backend  data  is  " nonexisent "  then  no  object  is  returned . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Otherwise ,  the  number  of  objects  matching  the  exists  value  will  be  returned . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Unused 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  The  object  type .  Will  always  be  " test " . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  objects  Container  to  place  objects  into . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  fields  Fields  to  search  for . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  mock_retrieve_multiple ( const  struct  ast_sorcery  * sorcery ,  void  * data ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * type ,  struct  ao2_container  * objects ,  const  struct  ast_variable  * fields ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( fields )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  real_backend_data - > exists ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  uuid [ AST_UUID_STR_LEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  test_data  * b_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b_data  =  ast_sorcery_alloc ( sorcery ,  type ,  ast_uuid_generate_str ( uuid ,  sizeof ( uuid ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! b_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b_data - > salt  =  real_backend_data - > salt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										b_data - > pepper  =  real_backend_data - > pepper ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_link ( objects ,  b_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( b_data ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  A  mock  sorcery  wizard  used  for  the  stale  test 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_sorcery_wizard  mock_wizard  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " mock " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. retrieve_id  =  mock_retrieve_id , 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. retrieve_multiple  =  mock_retrieve_multiple , 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Wait  for  the  cache  to  be  updated  after  a  stale  object  is  retrieved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Since  the  cache  does  not  know  what  type  of  objects  it  is  dealing  with ,  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  since  we  do  not  have  the  internals  of  the  cache ,  the  only  way  to  make  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  determination  is  to  continuously  retrieve  an  object  from  the  cache  until 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  we  retrieve  a  different  object  than  we  had  previously  retrieved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sorcery  The  sorcery  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  previous_object  The  object  we  had  previously  retrieved  from  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param [ out ]  new_object  The  new  object  we  retrieve  from  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  Successfully  retrieved  a  new  object  from  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  non - zero  Failed  to  retrieve  a  new  object  from  the  cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  wait_for_cache_update ( const  struct  ast_sorcery  * sorcery ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										void  * previous_object ,  struct  test_data  * * new_object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ast_remaining_ms ( start ,  5000 )  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										void  * object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										object  =  ast_sorcery_retrieve_by_id ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( object  ! =  previous_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* new_object  =  object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_cleanup ( object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( stale )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  test_data  * backend_object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  backend_data  iterations [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{  . salt  =  1 ,       . pepper  =  2 ,        . exists  =  1  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{  . salt  =  568729 ,  . pepper  =  - 234123 ,  . exists  =  1  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{  . salt  =  0 ,       . pepper  =  0 ,        . exists  =  0  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  backend_data  initial  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. salt  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. pepper  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. exists  =  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " stale " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Ensure that stale objects are replaced with updated objects " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a sorcery instance with two wizards " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The first is a memory cache that marks items stale after 3 seconds \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The second is a mock of a back-end \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Pre-populates the cache by retrieving some initial data from the backend. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Performs iterations of the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Update backend data with new values \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Retrieve item from the cache \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Ensure the retrieved item does not have the new backend values \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Wait for cached object to become stale \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Retrieve the stale cached object \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Ensure that the stale object retrieved is the same as the fresh one from earlier \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * Wait for the cache to update with new data \n " 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-24 16:39:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" \t \t * Ensure that new data in the cache matches backend data " ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_register ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  ast_sorcery_open ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " memory_cache " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" object_lifetime_stale=3 " ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " mock " ,  NULL ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_internal_object_register ( sorcery ,  " test " ,  test_data_alloc ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Prepopulate the cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									real_backend_data  =  & initial ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									backend_object  =  ast_sorcery_retrieve_by_id ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! backend_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve backend data and populate the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( backend_object ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  ARRAY_LEN ( iterations ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  test_data  * ,  cache_fresh ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  test_data  * ,  cache_stale ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  test_data  * ,  cache_new ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										real_backend_data  =  & iterations [ i ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Begininning iteration %d \n " ,  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cache_fresh  =  ast_sorcery_retrieve_by_id ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cache_fresh )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Unable to retrieve fresh cached object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache_fresh - > salt  = =  iterations [ i ] . salt  | |  cache_fresh - > pepper  = =  iterations [ i ] . pepper )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Fresh cached object has unexpected values. Did we hit the backend? \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sleep ( 5 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cache_stale  =  ast_sorcery_retrieve_by_id ( sorcery ,  " test " ,  " test " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cache_stale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Unable to retrieve stale cached object \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cache_stale  ! =  cache_fresh )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Stale cache hit retrieved different object than fresh cache hit \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( wait_for_cache_update ( sorcery ,  cache_stale ,  & cache_new ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Cache was not updated \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( iterations [ i ] . exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! cache_new )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_test_status_update ( test ,  " Failed to retrieve item from cache when there should be one present \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  ( cache_new - > salt  ! =  iterations [ i ] . salt  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													cache_new - > pepper  ! =  iterations [ i ] . pepper )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_test_status_update ( test ,  " New cached item has unexpected values \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( cache_new )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_test_status_update ( test ,  " Retrieved a cached item when there should not have been one present \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_unregister ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( full_backend_cache_expiration )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  backend_data  initial  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. salt  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. pepper  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. exists  =  4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_t  lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_t  cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timespec  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " full_backend_cache_expiration " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Ensure that the full backend cache actually caches the backend " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a sorcery instance with two wizards " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The first is a memory cache that expires objects after 3 seconds and does full backend caching \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The second is a mock of a back-end \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Populates the cache by requesting all objects which returns 4. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Updates the backend to contain a different number of objects, 8. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Requests all objects and confirms the number returned is only 4. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Wait for cached objects to expire. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Requests all objects and confirms the number returned is 8. " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_register ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  ast_sorcery_open ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " memory_cache " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" object_lifetime_maximum=3,full_backend_cache=yes " ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " mock " ,  NULL ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_internal_object_register ( sorcery ,  " test " ,  test_data_alloc ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_object_field_register_nodoc ( sorcery ,  " test " ,  " salt " ,  " 0 " ,  OPT_UINT_T ,  0 ,  FLDSET ( struct  test_data ,  salt ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_object_field_register_nodoc ( sorcery ,  " test " ,  " pepper " ,  " 0 " ,  OPT_UINT_T ,  0 ,  FLDSET ( struct  test_data ,  pepper ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Prepopulate the cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									real_backend_data  =  & initial ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Update the backend to have a different number of objects */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									initial . exists  =  8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects )  = =  initial . exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Number of objects returned is of the current backend and not the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_init ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_init ( & cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_sec  =  start . tv_sec  +  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_nsec  =  start . tv_usec  *  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ast_cond_timedwait ( & cond ,  & lock ,  & end )  ! =  ETIMEDOUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_destroy ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_destroy ( & cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects )  ! =  initial . exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Number of objects returned is NOT of the current backend when it should be \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_unregister ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_TEST_DEFINE ( full_backend_cache_stale )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  AST_TEST_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_sorcery  * sorcery  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  backend_data  initial  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. salt  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. pepper  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. exists  =  4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * objects ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_t  lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_t  cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timespec  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > name  =  " full_backend_cache_stale " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > category  =  " /res/res_sorcery_memory_cache/ " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > summary  =  " Ensure that the full backend cache works with staleness " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										info - > description  =  " This test performs the following: \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Create a sorcery instance with two wizards " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The first is a memory cache that stales objects after 1 second and does full backend caching \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t \t * The second is a mock of a back-end \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Populates the cache by requesting all objects which returns 4. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Wait for objects to go stale. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Updates the backend to contain a different number of objects, 8. \" " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Requests all objects and confirms the number returned is only 4. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Wait for objects to be refreshed from backend. \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \t * Requests all objects and confirms the number returned is 8. " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_TEST_NOT_RUN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  TEST_EXECUTE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_register ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_init ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_init ( & cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sorcery  =  ast_sorcery_open ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Failed to create sorcery instance \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " memory_cache " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" object_lifetime_stale=1,full_backend_cache=yes " ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_apply_wizard_mapping ( sorcery ,  " test " ,  " mock " ,  NULL ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_internal_object_register ( sorcery ,  " test " ,  test_data_alloc ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_object_field_register_nodoc ( sorcery ,  " test " ,  " salt " ,  " 0 " ,  OPT_UINT_T ,  0 ,  FLDSET ( struct  test_data ,  salt ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_object_field_register_nodoc ( sorcery ,  " test " ,  " pepper " ,  " 0 " ,  OPT_UINT_T ,  0 ,  FLDSET ( struct  test_data ,  pepper ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Prepopulate the cache */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									real_backend_data  =  & initial ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_sec  =  start . tv_sec  +  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_nsec  =  start . tv_usec  *  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ast_cond_timedwait ( & cond ,  & lock ,  & end )  ! =  ETIMEDOUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									initial . exists  =  8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects )  = =  initial . exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Number of objects returned is of the backend and not the cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_sec  =  start . tv_sec  +  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_nsec  =  start . tv_usec  *  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ast_cond_timedwait ( & cond ,  & lock ,  & end )  ! =  ETIMEDOUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get all current objects in the backend */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objects  =  ast_sorcery_retrieve_by_fields ( sorcery ,  " test " ,  AST_RETRIEVE_FLAG_MULTIPLE  |  AST_RETRIEVE_FLAG_ALL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! objects )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Unable to retrieve all objects in backend and populate cache \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ao2_container_count ( objects )  ! =  initial . exists )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_status_update ( test ,  " Number of objects returned is not of backend \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  cleanup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( objects ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_sec  =  start . tv_sec  +  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									end . tv_nsec  =  start . tv_usec  *  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ast_cond_timedwait ( & cond ,  & lock ,  & end )  ! =  ETIMEDOUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  AST_TEST_PASS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cleanup :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sorcery )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sorcery_unref ( sorcery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_unregister ( & mock_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_destroy ( & lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_destroy ( & cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  unload_module ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( open_with_valid_options ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( open_with_invalid_options ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( create_and_retrieve ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( update ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( delete ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( maximum_objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( expiration ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 13:01:24 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( stale ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( full_backend_cache_expiration ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_UNREGISTER ( full_backend_cache_stale ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-01 14:27:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_manager_unregister ( " SorceryMemoryCacheExpireObject " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_unregister ( " SorceryMemoryCacheExpire " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_unregister ( " SorceryMemoryCacheStaleObject " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_unregister ( " SorceryMemoryCacheStale " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_manager_unregister ( " SorceryMemoryCachePopulate " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-01 14:27:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli_unregister_multiple ( cli_memory_cache ,  ARRAY_LEN ( cli_memory_cache ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_sorcery_wizard_unregister ( & memory_cache_object_wizard ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  XXX  There  is  the  potential  to  leak  memory  if  there  are  pending 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  next - cache - expiration  and  stale - cache - update  tasks  in  the  scheduler . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sched )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_sched_context_destroy ( sched ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sched  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( caches ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									caches  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  load_module ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-19 15:10:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									caches  =  ao2_container_alloc_hash ( AO2_ALLOC_OPT_LOCK_MUTEX ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CACHES_CONTAINER_BUCKET_SIZE ,  sorcery_memory_cache_hash ,  NULL , 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-01 14:27:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sorcery_memory_cache_cmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! caches )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Failed to create container for configured caches \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_module ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									sched  =  ast_sched_context_create ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! sched )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Failed to create scheduler for cache management \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_module ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_sched_start_thread ( sched ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Failed to create scheduler thread for cache management \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_module ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_sorcery_wizard_register ( & memory_cache_object_wizard ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_module ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  ast_cli_register_multiple ( cli_memory_cache ,  ARRAY_LEN ( cli_memory_cache ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_manager_register_xml ( " SorceryMemoryCacheExpireObject " ,  EVENT_FLAG_SYSTEM ,  sorcery_memory_cache_ami_expire_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_manager_register_xml ( " SorceryMemoryCacheExpire " ,  EVENT_FLAG_SYSTEM ,  sorcery_memory_cache_ami_expire ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_manager_register_xml ( " SorceryMemoryCacheStaleObject " ,  EVENT_FLAG_SYSTEM ,  sorcery_memory_cache_ami_stale_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  | =  ast_manager_register_xml ( " SorceryMemoryCacheStale " ,  EVENT_FLAG_SYSTEM ,  sorcery_memory_cache_ami_stale ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  | =  ast_manager_register_xml ( " SorceryMemoryCachePopulate " ,  EVENT_FLAG_SYSTEM ,  sorcery_memory_cache_ami_populate ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-26 09:34:47 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unload_module ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_MODULE_LOAD_DECLINE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-06 11:24:43 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* This causes the stale unit test to execute last, so if a sorcery instance persists
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  longer  than  expected  subsequent  unit  tests  don ' t  fail  when  setting  it  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( stale ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( open_with_valid_options ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( open_with_invalid_options ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( create_and_retrieve ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( update ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( delete ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 15:19:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( maximum_objects ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-20 19:35:54 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( expiration ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-05 12:01:55 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( full_backend_cache_expiration ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_TEST_REGISTER ( full_backend_cache_stale ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-16 19:02:50 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  AST_MODULE_LOAD_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_MODULE_INFO ( ASTERISK_GPL_KEY ,  AST_MODFLAG_GLOBAL_SYMBOLS  |  AST_MODFLAG_LOAD_ORDER ,  " Sorcery Memory Cache Object Wizard " ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. support_level  =  AST_MODULE_SUPPORT_CORE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. load  =  load_module , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. unload  =  unload_module , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. load_pri  =  AST_MODPRI_REALTIME_DRIVER , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								) ;