[asterisk-commits] russell: branch russell/sla_rewrite r51345 - in /team/russell/sla_rewrite: ap...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Jan 19 17:59:20 MST 2007


Author: russell
Date: Fri Jan 19 18:59:20 2007
New Revision: 51345

URL: http://svn.digium.com/view/asterisk?view=rev&rev=51345
Log:
- Add support for rwlock based linked lists
- Parse sla.conf and put the info in lists

Modified:
    team/russell/sla_rewrite/apps/app_meetme.c
    team/russell/sla_rewrite/include/asterisk/app.h
    team/russell/sla_rewrite/include/asterisk/linkedlists.h

Modified: team/russell/sla_rewrite/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/russell/sla_rewrite/apps/app_meetme.c?view=diff&rev=51345&r1=51344&r2=51345
==============================================================================
--- team/russell/sla_rewrite/apps/app_meetme.c (original)
+++ team/russell/sla_rewrite/apps/app_meetme.c Fri Jan 19 18:59:20 2007
@@ -65,6 +65,7 @@
 #include "leave.h"
 
 #define CONFIG_FILE_NAME "meetme.conf"
+#define SLA_CONFIG_FILE  "sla.conf"
 
 /*! each buffer is 20ms, so this is 640ms total */
 #define DEFAULT_AUDIO_BUFFERS  32
@@ -153,9 +154,9 @@
 enum {
 	OPT_ARG_WAITMARKED = 0,
 	OPT_ARG_ARRAY_SIZE = 1,
-} meetme_option_args;
-
-AST_APP_OPTIONS(meetme_opts, {
+};
+
+AST_APP_OPTIONS(meetme_opts, BEGIN_OPTIONS
 	AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
 	AST_APP_OPTION('a', CONFFLAG_ADMIN ),
 	AST_APP_OPTION('b', CONFFLAG_AGI ),
@@ -181,11 +182,8 @@
 	AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
 	AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
 	AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
-});
-
-AST_APP_OPTIONS(sla_opts, {
-	/* Just a placeholder for now */
-});
+END_OPTIONS);
+
 static const char *app = "MeetMe";
 static const char *app2 = "MeetMeCount";
 static const char *app3 = "MeetMeAdmin";
@@ -271,8 +269,6 @@
 "      'V' -- Raise entire conference listening volume\n"
 "";
 
-#define CONFIG_FILE_NAME "meetme.conf"
-
 /*! \brief The MeetMe Conference object */
 struct ast_conference {
 	ast_mutex_t playlock;                   /*!< Conference specific lock (players) */
@@ -324,9 +320,23 @@
 	AST_LIST_ENTRY(ast_conf_user) list;
 };
 
-static int audio_buffers;			/*!< The number of audio buffers to be allocated on pseudo channels
-						   when in a conference
-						*/
+struct sla_station {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(device);	
+	);
+	AST_RWLIST_ENTRY(sla_station) entry;
+};
+
+struct sla_trunk {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(device);
+	);
+	AST_RWLIST_ENTRY(sla_trunk) entry;
+};
+
+static AST_RWLIST_HEAD_STATIC(sla_stations, sla_station);
+static AST_RWLIST_HEAD_STATIC(sla_trunks, sla_trunk);
+
 /*! The number of audio buffers to be allocated on pseudo channels
  *  when in a conference */
 static int audio_buffers;
@@ -2608,9 +2618,108 @@
 	ast_config_destroy(cfg);
 }
 
-static void load_config(void)
+static int build_trunk(struct ast_config *cfg, const char *cat)
+{
+	struct sla_trunk *trunk;
+	const char *dev;
+
+	if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
+		ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat);
+		return -1;
+	}
+
+	if (!(trunk = ast_calloc(1, sizeof(*trunk))))
+		return -1;
+
+	ast_string_field_set(trunk, device, dev);
+
+	AST_RWLIST_WRLOCK(&sla_trunks);
+	AST_RWLIST_INSERT_HEAD(&sla_trunks, trunk, entry);
+	AST_RWLIST_UNLOCK(&sla_trunks);
+
+	return 0;
+}
+
+static int build_station(struct ast_config *cfg, const char *cat)
+{
+	struct sla_station *station;
+	const char *dev;
+
+	if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
+		ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat);
+		return -1;
+	}
+
+	if (!(station = ast_calloc(1, sizeof(*station))))
+		return -1;
+
+	ast_string_field_set(station, device, dev);
+
+	AST_RWLIST_WRLOCK(&sla_stations);
+	AST_RWLIST_INSERT_HEAD(&sla_stations, station, entry);
+	AST_RWLIST_UNLOCK(&sla_stations);
+
+	return 0;
+}
+
+static int load_config_sla(void)
+{
+	struct ast_config *cfg;
+	const char *cat = NULL;
+	int res = 0;
+
+	if (!(cfg = ast_config_load(SLA_CONFIG_FILE)))
+		return 0; /* Treat no config as normal */
+
+	while ((cat = ast_category_browse(cfg, cat)) && !res) {
+		const char *type;
+		/* Reserve "general" for ... general stuff! */
+		if (!strcasecmp(cat, "general"))
+			continue;
+		if (!(type = ast_variable_retrieve(cfg, cat, "type"))) {
+			ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n",
+				SLA_CONFIG_FILE);
+			continue;
+		}
+		if (!strcasecmp(type, "trunk"))
+			res = build_trunk(cfg, cat);
+		else if (!strcasecmp(type, "station"))
+			res = build_station(cfg, cat);
+		else {
+			ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n",
+				SLA_CONFIG_FILE, type);
+		}
+	}
+
+	ast_config_destroy(cfg);
+
+	return res;
+}
+
+static void destroy_sla(void)
+{
+	struct sla_trunk *trunk;
+	struct sla_station *station;
+
+	AST_RWLIST_WRLOCK(&sla_trunks);
+	while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) {
+		ast_string_field_free_all(trunk);
+		free(trunk);
+	}
+	AST_RWLIST_UNLOCK(&sla_trunks);
+
+	AST_RWLIST_WRLOCK(&sla_stations);
+	while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) {
+		ast_string_field_free_all(station);
+		free(station);
+	}
+	AST_RWLIST_UNLOCK(&sla_stations);
+}
+
+static int load_config(void)
 {
 	load_config_meetme();
+	return load_config_sla();
 }
 
 static int unload_module(void)
@@ -2627,6 +2736,8 @@
 	ast_module_user_hangup_all();
 	ast_devstate_prov_del("Meetme");
 
+	destroy_sla();
+
 	return res;
 }
 

Modified: team/russell/sla_rewrite/include/asterisk/app.h
URL: http://svn.digium.com/view/asterisk/team/russell/sla_rewrite/include/asterisk/app.h?view=diff&rev=51345&r1=51344&r2=51345
==============================================================================
--- team/russell/sla_rewrite/include/asterisk/app.h (original)
+++ team/russell/sla_rewrite/include/asterisk/app.h Fri Jan 19 18:59:20 2007
@@ -306,6 +306,9 @@
 	unsigned int arg_index;
 };
 
+#define BEGIN_OPTIONS {
+#define END_OPTIONS }
+
 /*!
   \brief Declares an array of options for an application.
   \param holder The name of the array to be created

Modified: team/russell/sla_rewrite/include/asterisk/linkedlists.h
URL: http://svn.digium.com/view/asterisk/team/russell/sla_rewrite/include/asterisk/linkedlists.h?view=diff&rev=51345&r1=51344&r2=51345
==============================================================================
--- team/russell/sla_rewrite/include/asterisk/linkedlists.h (original)
+++ team/russell/sla_rewrite/include/asterisk/linkedlists.h Fri Jan 19 18:59:20 2007
@@ -37,6 +37,28 @@
 */
 #define AST_LIST_LOCK(head)						\
 	ast_mutex_lock(&(head)->lock) 
+
+/*!
+  \brief Write locks a list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place an exclusive write lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_WRLOCK(head)                                         \
+        ast_rwlock_wrlock(&(head)->lock)
+
+/*!
+  \brief Read locks a list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place a read lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_RDLOCK(head)                                         \
+        ast_rwlock_rdlock(&(head)->lock)
 	
 /*!
   \brief Locks a list, without blocking if the list is locked.
@@ -48,6 +70,28 @@
 */
 #define AST_LIST_TRYLOCK(head)						\
 	ast_mutex_trylock(&(head)->lock) 
+
+/*!
+  \brief Write locks a list, without blocking if the list is locked.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place an exclusive write lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_TRYWRLOCK(head)                                      \
+        ast_rwlock_trywrlock(&(head)->lock)
+
+/*!
+  \brief Read locks a list, without blocking if the list is locked.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place a read lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_TRYRDLOCK(head)                                      \
+        ast_rwlock_tryrdlock(&(head)->lock)
 	
 /*!
   \brief Attempts to unlock a list.
@@ -59,6 +103,17 @@
 */
 #define AST_LIST_UNLOCK(head) 						\
 	ast_mutex_unlock(&(head)->lock)
+
+/*!
+  \brief Attempts to unlock a read/write based list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to remove a read or write lock from the
+  list head structure pointed to by head. If the list
+  was not locked by this thread, this macro has no effect.
+*/
+#define AST_RWLIST_UNLOCK(head)                                         \
+        ast_rwlock_unlock(&(head)->lock)
 
 /*!
   \brief Defines a structure to be used to hold a list of specified type.
@@ -87,7 +142,7 @@
 }
 
 /*!
-  \brief Defines a structure to be used to hold a list of specified type (with no lock).
+  \brief Defines a structure to be used to hold a read/write list of specified type.
   \param name This will be the name of the defined structure.
   \param type This is the type of each list entry.
 
@@ -99,6 +154,32 @@
 
   Example usage:
   \code
+  static AST_RWLIST_HEAD(entry_list, entry) entries;
+  \endcode
+
+  This would define \c struct \c entry_list, and declare an instance of it named
+  \a entries, all intended to hold a list of type \c struct \c entry.
+*/
+#define AST_RWLIST_HEAD(name, type)                                     \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+}
+
+/*!
+  \brief Defines a structure to be used to hold a list of specified type (with no lock).
+  \param name This will be the name of the defined structure.
+  \param type This is the type of each list entry.
+
+  This macro creates a structure definition that can be used
+  to hold a list of the entries of type \a type. It does not actually
+  declare (allocate) a structure; to do that, either follow this
+  macro with the desired name of the instance you wish to declare,
+  or use the specified \a name to declare instances elsewhere.
+
+  Example usage:
+  \code
   static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
   \endcode
 
@@ -119,6 +200,15 @@
 	.last = NULL,					\
 	.lock = AST_MUTEX_INIT_VALUE,			\
 	}
+
+/*!
+  \brief Defines initial values for a declaration of AST_RWLIST_HEAD
+*/
+#define AST_RWLIST_HEAD_INIT_VALUE      {               \
+        .first = NULL,                                  \
+        .last = NULL,                                   \
+        .lock = AST_RWLOCK_INIT_VALUE,                  \
+        }
 
 /*!
   \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
@@ -171,6 +261,48 @@
 #endif
 
 /*!
+  \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
+  \param name This will be the name of the defined structure.
+  \param type This is the type of each list entry.
+
+  This macro creates a structure definition that can be used
+  to hold a list of the entries of type \a type, and allocates an instance
+  of it, initialized to be empty.
+
+  Example usage:
+  \code
+  static AST_RWLIST_HEAD_STATIC(entry_list, entry);
+  \endcode
+
+  This would define \c struct \c entry_list, intended to hold a list of
+  type \c struct \c entry.
+*/
+#ifndef AST_RWLOCK_INIT_VALUE
+#define AST_RWLIST_HEAD_STATIC(name, type)                              \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+} name;                                                                 \
+static void  __attribute__ ((constructor)) init_##name(void)            \
+{                                                                       \
+        AST_RWLIST_HEAD_INIT(&name);                                    \
+}                                                                       \
+static void  __attribute__ ((destructor)) fini_##name(void)             \
+{                                                                       \
+        AST_RWLIST_HEAD_DESTROY(&name);                                 \
+}                                                                       \
+struct __dummy_##name
+#else
+#define AST_RWLIST_HEAD_STATIC(name, type)                              \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+} name = AST_RWLIST_HEAD_INIT_VALUE
+#endif
+
+/*!
   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
 
   This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
@@ -193,6 +325,20 @@
 	(head)->first = (entry);					\
 	(head)->last = (entry);						\
 	ast_mutex_init(&(head)->lock);					\
+} while (0)
+
+/*!
+  \brief Initializes an rwlist head structure with a specified first entry.
+  \param head This is a pointer to the list head structure
+  \param entry pointer to the list entry that will become the head of the list
+
+  This macro initializes a list head structure by setting the head
+  entry to the supplied value and recreating the embedded lock.
+*/
+#define AST_RWLIST_HEAD_SET(head, entry) do {                           \
+        (head)->first = (entry);                                        \
+        (head)->last = (entry);                                         \
+        ast_rwlock_init(&(head)->lock);                                 \
 } while (0)
 
 /*!
@@ -229,6 +375,8 @@
 struct {								\
 	struct type *next;						\
 }
+
+#define AST_RWLIST_ENTRY AST_LIST_ENTRY
  
 /*!
   \brief Returns the first entry contained in a list.
@@ -236,11 +384,15 @@
  */
 #define	AST_LIST_FIRST(head)	((head)->first)
 
+#define AST_RWLIST_FIRST AST_LIST_FIRST
+
 /*!
   \brief Returns the last entry contained in a list.
   \param head This is a pointer to the list head structure
  */
 #define	AST_LIST_LAST(head)	((head)->last)
+
+#define AST_RWLIST_LAST AST_LIST_LAST
 
 /*!
   \brief Returns the next entry in the list after the given entry.
@@ -250,6 +402,8 @@
 */
 #define AST_LIST_NEXT(elm, field)	((elm)->field.next)
 
+#define AST_RWLIST_NEXT AST_LIST_NEXT
+
 /*!
   \brief Checks whether the specified list contains any entries.
   \param head This is a pointer to the list head structure
@@ -257,6 +411,8 @@
   Returns non-zero if the list has entries, zero if not.
  */
 #define	AST_LIST_EMPTY(head)	(AST_LIST_FIRST(head) == NULL)
+
+#define AST_RWLIST_EMPTY AST_LIST_EMPTY
 
 /*!
   \brief Loops over (traverses) the entries in a list.
@@ -297,6 +453,8 @@
 #define AST_LIST_TRAVERSE(head,var,field) 				\
 	for((var) = (head)->first; (var); (var) = (var)->field.next)
 
+#define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
+
 /*!
   \brief Loops safely over (traverses) the entries in a list.
   \param head This is a pointer to the list head structure
@@ -342,6 +500,8 @@
 	     __list_next = (var) ? (var)->field.next : NULL				\
 	    )
 
+#define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
+
 /*!
   \brief Removes the \a current entry from a list during a traversal.
   \param head This is a pointer to the list head structure
@@ -363,6 +523,8 @@
 	if (!__list_next)								\
 		(head)->last = __list_prev;
 
+#define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
+
 /*!
   \brief Inserts a list entry before the current entry during a traversal.
   \param head This is a pointer to the list head structure
@@ -384,10 +546,14 @@
 	__new_prev = (elm);						\
 } while (0)
 
+#define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
+
 /*!
   \brief Closes a safe loop traversal block.
  */
 #define AST_LIST_TRAVERSE_SAFE_END  }
+
+#define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
 
 /*!
   \brief Initializes a list head structure.
@@ -403,6 +569,19 @@
 }
 
 /*!
+  \brief Initializes an rwlist head structure.
+  \param head This is a pointer to the list head structure
+
+  This macro initializes a list head structure by setting the head
+  entry to \a NULL (empty list) and recreating the embedded lock.
+*/
+#define AST_RWLIST_HEAD_INIT(head) {                                    \
+        (head)->first = NULL;                                           \
+        (head)->last = NULL;                                            \
+        ast_rwlock_init(&(head)->lock);                                 \
+}
+
+/*!
   \brief Destroys a list head structure.
   \param head This is a pointer to the list head structure
 
@@ -414,6 +593,20 @@
 	(head)->first = NULL;						\
 	(head)->last = NULL;						\
 	ast_mutex_destroy(&(head)->lock);				\
+}
+
+/*!
+  \brief Destroys an rwlist head structure.
+  \param head This is a pointer to the list head structure
+
+  This macro destroys a list head structure by setting the head
+  entry to \a NULL (empty list) and destroying the embedded lock.
+  It does not free the structure from memory.
+*/
+#define AST_RWLIST_HEAD_DESTROY(head) {                                 \
+        (head)->first = NULL;                                           \
+        (head)->last = NULL;                                            \
+        ast_rwlock_destroy(&(head)->lock);                              \
 }
 
 /*!
@@ -445,6 +638,8 @@
 		(head)->last = (elm);					\
 } while (0)
 
+#define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
+
 /*!
   \brief Inserts a list entry at the head of a list.
   \param head This is a pointer to the list head structure
@@ -458,6 +653,8 @@
 		if (!(head)->last)					\
 			(head)->last = (elm);				\
 } while (0)
+
+#define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
 
 /*!
   \brief Appends a list entry to the tail of a list.
@@ -480,6 +677,8 @@
       }									\
 } while (0)
 
+#define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
+
 /*!
   \brief Appends a whole list to the tail of a list.
   \param head This is a pointer to the list head structure
@@ -496,6 +695,8 @@
 		(head)->last = (list)->last;				\
       }									\
 } while (0)
+
+#define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
 
 /*!
   \brief Removes and returns the head entry from a list.
@@ -516,6 +717,8 @@
 		}							\
 		cur;							\
 	})
+
+#define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
 
 /*!
   \brief Removes a specific entry from a list.
@@ -543,4 +746,6 @@
         (elm)->field.next = NULL;                                       \
 } while (0)
 
+#define AST_RWLIST_REMOVE AST_LIST_REMOVE
+
 #endif /* _ASTERISK_LINKEDLISTS_H */



More information about the asterisk-commits mailing list