Skip to content

Commit 7a2ff03

Browse files
committed
Copy out master list from config
Config locking during update_from_master is now avoided. This method is still inefficient as the copy is performed each master-update-interval when it could be done only when the config changes
1 parent c06dcec commit 7a2ff03

File tree

1 file changed

+109
-37
lines changed

1 file changed

+109
-37
lines changed

src/slave.c

Lines changed: 109 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,99 @@ static volatile int update_all_mounts = 0;
6363
static volatile unsigned int max_interval = 0;
6464
static mutex_t _slave_mutex; // protects update_settings, update_all_mounts, max_interval
6565

66-
master_server *master_free (master_server *master)
66+
67+
/* free a master and return its next master */
68+
master_server *master_free(master_server *master)
6769
{
6870
master_server *next = master->next;
6971
ICECAST_LOG_DEBUG("freeing master %s:%d", master->server, master->port);
70-
xmlFree (master->server);
72+
xmlFree(master->server);
7173
if (master->username)
72-
xmlFree (master->username);
74+
xmlFree(master->username);
7375
if (master->password)
74-
xmlFree (master->password);
76+
xmlFree(master->password);
7577
if (master->namespace)
7678
xmlFree(master->namespace);
77-
free (master);
79+
free(master);
7880
return next;
7981
}
8082

83+
84+
/* copy a master and return the copy */
85+
static master_server *master_copy(master_server *master)
86+
{
87+
master_server *copy = calloc(1, sizeof(*master));
88+
89+
if (copy)
90+
{
91+
copy->server = (char *)xmlCharStrdup(master->server);
92+
if (master->username)
93+
copy->username = (char *)xmlCharStrdup(master->username);
94+
if (master->password)
95+
copy->password = (char *)xmlCharStrdup(master->password);
96+
if (master->namespace)
97+
copy->namespace = (char *)xmlCharStrdup(master->namespace);
98+
copy->port = master->port;
99+
copy->on_demand = master->on_demand;
100+
}
101+
return copy;
102+
}
103+
104+
105+
/* free master list and return NULL */
106+
static master_server *master_list_free(master_server *list)
107+
{
108+
while ((list = master_free(list)));
109+
return list;
110+
}
111+
112+
113+
/* insert a master into a master list and return the list head */
114+
static master_server *master_list_insert(master_server *list, master_server *master)
115+
{
116+
master->next = list;
117+
return master;
118+
}
119+
120+
121+
/* copy a master list and return copied list */
122+
static master_server *master_list_copy(master_server *list) {
123+
master_server *list_copy = NULL;
124+
125+
while (list)
126+
{
127+
master_server *copy = master_copy(list);
128+
if (copy == NULL)
129+
{
130+
list_copy = master_list_free(list_copy);
131+
break;
132+
}
133+
list_copy = master_list_insert(list_copy, copy);
134+
list = list->next;
135+
}
136+
137+
return list_copy;
138+
}
139+
140+
141+
/* turn a legacy master (from config) into a master and return it */
142+
static master_server *master_from_legacy(ice_config_t *config) {
143+
master_server *master = calloc(1, sizeof(*master));
144+
145+
if (master) {
146+
master->username = strdup(config->master_username);
147+
if (config->master_password)
148+
master->password = strdup(config->master_password);
149+
if (config->master_server)
150+
master->server = strdup(config->master_server);
151+
master->port = config->master_server_port;
152+
master->on_demand = config->on_demand;
153+
}
154+
155+
return master;
156+
}
157+
158+
81159
relay_server *relay_free (relay_server *relay)
82160
{
83161
relay_server *next = relay->next;
@@ -719,27 +797,6 @@ static int update_from_master(master_server *master)
719797
return ret;
720798
}
721799

722-
static int update_from_master_legacy(ice_config_t *config)
723-
{
724-
master_server *master = calloc (1, sizeof (master_server));
725-
int ret = 0;
726-
727-
if (master) {
728-
master->username = strdup(config->master_username);
729-
if (config->master_password)
730-
master->password = strdup(config->master_password);
731-
if (config->master_server)
732-
master->server = strdup(config->master_server);
733-
master->port = config->master_server_port;
734-
master->on_demand = config->on_demand;
735-
ret = update_from_master(master);
736-
master_free(master);
737-
}
738-
739-
return ret;
740-
}
741-
742-
743800
static void *_slave_thread(void *arg)
744801
{
745802
ice_config_t *config;
@@ -780,27 +837,42 @@ static void *_slave_thread(void *arg)
780837
thread_mutex_lock(&_slave_mutex);
781838
if (max_interval <= interval)
782839
{
783-
master_server *master;
840+
master_server *list = NULL;
841+
784842
ICECAST_LOG_DEBUG("checking master stream list");
785-
config = config_get_config();
786843

787844
if (max_interval == 0)
788845
skip_timer = 1;
789846
interval = 0;
847+
848+
config = config_get_config();
790849
max_interval = config->master_update_interval;
850+
config_release_config();
851+
791852
thread_mutex_unlock(&_slave_mutex);
792853

793-
/* update all non-legacy master servers. the config lock is being
794-
* held for the entire update process. consider making a copy of
795-
* the master linked list and releasing the lock */
796-
master = config->master;
797-
while (master) {
798-
update_from_master(master);
799-
master = master->next;
854+
/* copy master list and insert legacy master from config. note:
855+
* keeping a global list of master servers that only changes on a
856+
* config change would be much more efficient than performing a
857+
* copy each time we do an update -- implement this (and the
858+
* locking that goes with along with this approach) */
859+
config = config_get_config();
860+
list = master_list_insert(
861+
master_list_copy(config->master),
862+
master_from_legacy(config)
863+
);
864+
config_release_config();
865+
866+
/* update all master servers */
867+
while (list) {
868+
update_from_master(list);
869+
list = list->next;
800870
}
801871

802-
/* update legacy master server */
803-
update_from_master_legacy (config);
872+
if (list)
873+
master_list_free(list);
874+
875+
config = config_get_config();
804876

805877
thread_mutex_lock (&(config_locks()->relay_lock));
806878

0 commit comments

Comments
 (0)