aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-03-14 21:45:09 +0100
committercbdev <cb@cbcdn.com>2020-03-14 21:45:09 +0100
commit05cdf563fcc4c7835ec422fa5d7ee86b68a9f1df (patch)
tree454f4cec4caea193c9babbb655451ea35f46b684
parent45945a5130f6f3910aa3924c1f1e5ddcf2ef3283 (diff)
downloadmidimonster-05cdf563fcc4c7835ec422fa5d7ee86b68a9f1df.tar.gz
midimonster-05cdf563fcc4c7835ec422fa5d7ee86b68a9f1df.tar.bz2
midimonster-05cdf563fcc4c7835ec422fa5d7ee86b68a9f1df.zip
Restructure backend and instance registry
-rw-r--r--TODO1
-rw-r--r--backend.c268
-rw-r--r--backend.h4
-rw-r--r--backends/artnet.c5
-rw-r--r--backends/sacn.c5
-rw-r--r--config.c2
6 files changed, 147 insertions, 138 deletions
diff --git a/TODO b/TODO
index 1ea91f4..900cc1b 100644
--- a/TODO
+++ b/TODO
@@ -7,4 +7,3 @@ make event collectors threadsafe to stop marshalling data...
collect & check backend API version
windows strerror
move all connection establishment to _start to be able to hot-stop/start all backends
-only call _handle and _interval on backends with instances
diff --git a/backend.c b/backend.c
index ef8f66a..65cbd7d 100644
--- a/backend.c
+++ b/backend.c
@@ -8,10 +8,15 @@
#include "midimonster.h"
#include "backend.h"
-static size_t nbackends = 0;
-static backend* backends = NULL;
-static size_t ninstances = 0;
-static instance** instances = NULL;
+static struct {
+ size_t n;
+ backend* backends;
+ instance*** instances;
+} registry = {
+ .n = 0
+};
+
+//TODO move channel store into registry
static size_t nchannels = 0;
static channel** channels = NULL;
@@ -20,11 +25,11 @@ int backends_handle(size_t nfds, managed_fd* fds){
int rv = 0;
managed_fd xchg;
- for(u = 0; u < nbackends && !rv; u++){
+ for(u = 0; u < registry.n && !rv; u++){
n = 0;
for(p = 0; p < nfds; p++){
- if(fds[p].backend == backends + u){
+ if(fds[p].backend == registry.backends + u){
xchg = fds[n];
fds[n] = fds[p];
fds[p] = xchg;
@@ -32,10 +37,13 @@ int backends_handle(size_t nfds, managed_fd* fds){
}
}
- DBGPF("Notifying backend %s of %lu waiting FDs\n", backends[u].name, n);
- rv |= backends[u].process(n, fds);
- if(rv){
- fprintf(stderr, "Backend %s failed to handle input\n", backends[u].name);
+ //handle if there is data ready or the backend has active instances for polling
+ if(n || registry.instances[u]){
+ DBGPF("Notifying backend %s of %" PRIsize_t " waiting FDs\n", registry.backends[u].name, n);
+ rv |= registry.backends[u].process(n, fds);
+ if(rv){
+ fprintf(stderr, "Backend %s failed to handle input\n", registry.backends[u].name);
+ }
}
}
return rv;
@@ -45,28 +53,29 @@ int backends_notify(size_t nev, channel** c, channel_value* v){
size_t u, p, n;
int rv = 0;
channel_value xval;
- channel* xchnl;
-
- //TODO eliminate duplicates
- for(u = 0; u < ninstances && !rv; u++){
- n = 0;
+ channel* xchnl = NULL;
- for(p = 0; p < nev; p++){
- if(c[p]->instance == instances[u]){
- xval = v[n];
- xchnl = c[n];
+ for(u = 0; u < nev && !rv; u++){
+ //sort for this instance
+ n = u + 1;
+ for(p = u + 1; p < nev; p++){
+ if(c[p]->instance == c[u]->instance){
+ xval = v[p];
+ xchnl = c[p];
- v[n] = v[p];
- c[n] = c[p];
+ v[p] = v[n];
+ c[p] = c[n];
- v[p] = xval;
- c[p] = xchnl;
+ v[n] = xval;
+ c[n] = xchnl;
n++;
}
}
- DBGPF("Calling handler for instance %s with %lu events\n", instances[u]->name, n);
- rv |= instances[u]->backend->handle(instances[u], n, c, v);
+ //TODO eliminate duplicates
+ DBGPF("Calling handler for instance %s with %" PRIsize_t " events\n", c[u]->instance->name, n - u);
+ rv |= c[u]->instance->backend->handle(c[u]->instance, n - u, c + u, v + u);
+ u = n;
}
return 0;
@@ -76,17 +85,17 @@ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create){
size_t u;
for(u = 0; u < nchannels; u++){
if(channels[u]->instance == inst && channels[u]->ident == ident){
- DBGPF("Requested channel %lu on instance %s already exists, reusing\n", ident, inst->name);
+ DBGPF("Requested channel %" PRIu64 " on instance %s already exists, reusing\n", ident, inst->name);
return channels[u];
}
}
if(!create){
- DBGPF("Requested unknown channel %lu on instance %s\n", ident, inst->name);
+ DBGPF("Requested unknown channel %" PRIu64 " on instance %s\n", ident, inst->name);
return NULL;
}
- DBGPF("Creating previously unknown channel %lu on instance %s\n", ident, inst->name);
+ DBGPF("Creating previously unknown channel %" PRIu64 " on instance %s\n", ident, inst->name);
channel** new_chan = realloc(channels, (nchannels + 1) * sizeof(channel*));
if(!new_chan){
fprintf(stderr, "Failed to allocate memory\n");
@@ -106,34 +115,46 @@ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create){
return channels[nchannels++];
}
-instance* mm_instance(){
- instance** new_inst = realloc(instances, (ninstances + 1) * sizeof(instance*));
- if(!new_inst){
- //TODO free
- fprintf(stderr, "Failed to allocate memory\n");
- ninstances = 0;
- return NULL;
- }
- instances = new_inst;
- instances[ninstances] = calloc(1, sizeof(instance));
- if(!instances[ninstances]){
- fprintf(stderr, "Failed to allocate memory\n");
- return NULL;
+instance* mm_instance(backend* b){
+ size_t u = 0, n = 0;
+
+ for(u = 0; u < registry.n; u++){
+ if(registry.backends + u == b){
+ //count existing instances
+ for(n = 0; registry.instances[u] && registry.instances[u][n]; n++){
+ }
+
+ //extend
+ registry.instances[u] = realloc(registry.instances[u], (n + 2) * sizeof(instance*));
+ if(!registry.instances[u]){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return NULL;
+ }
+ //sentinel
+ registry.instances[u][n + 1] = NULL;
+ registry.instances[u][n] = calloc(1, sizeof(instance));
+ if(!registry.instances[u][n]){
+ fprintf(stderr, "Failed to allocate memory\n");
+ }
+ registry.instances[u][n]->backend = b;
+ return registry.instances[u][n];
+ }
}
- return instances[ninstances++];
+ //this should never happen
+ return NULL;
}
MM_API instance* mm_instance_find(char* name, uint64_t ident){
- size_t u;
- backend* b = backend_match(name);
- if(!b){
- return NULL;
- }
-
- for(u = 0; u < ninstances; u++){
- if(instances[u]->backend == b && instances[u]->ident == ident){
- return instances[u];
+ size_t b = 0;
+ instance** iter = NULL;
+ for(b = 0; b < registry.n; b++){
+ if(!strcmp(registry.backends[b].name, name)){
+ for(iter = registry.instances[b]; iter && *iter; iter++){
+ if((*iter)->ident == ident){
+ return *iter;
+ }
+ }
}
}
@@ -141,55 +162,40 @@ MM_API instance* mm_instance_find(char* name, uint64_t ident){
}
MM_API int mm_backend_instances(char* name, size_t* ninst, instance*** inst){
- backend* b = backend_match(name);
- size_t n = 0, u;
- //count number of affected instances
- for(u = 0; u < ninstances; u++){
- if(instances[u]->backend == b){
- n++;
- }
+ size_t b = 0, i = 0;
+ if(!ninst || !inst){
+ return 1;
}
- *ninst = n;
+ for(b = 0; b < registry.n; b++){
+ if(!strcmp(registry.backends[b].name, name)){
+ //count instances
+ for(i = 0; registry.instances[b] && registry.instances[b][i]; i++){
+ }
- if(!n){
- *inst = NULL;
- return 0;
- }
+ *ninst = i;
+ if(!i){
+ *inst = NULL;
+ return 0;
+ }
- *inst = calloc(n, sizeof(instance*));
- if(!*inst){
- fprintf(stderr, "Failed to allocate memory\n");
- return 1;
- }
+ *inst = calloc(i, sizeof(instance*));
+ if(!*inst){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return 1;
+ }
- n = 0;
- for(u = 0; u < ninstances; u++){
- if(instances[u]->backend == b){
- (*inst)[n] = instances[u];
- n++;
+ memcpy(*inst, registry.instances[b], i * sizeof(instance*));
+ return 0;
}
}
- return 0;
-}
-
-void instances_free(){
- size_t u;
- for(u = 0; u < ninstances; u++){
- free(instances[u]->name);
- instances[u]->name = NULL;
- instances[u]->backend = NULL;
- free(instances[u]);
- instances[u] = NULL;
- }
- free(instances);
- ninstances = 0;
+ return 1;
}
void channels_free(){
size_t u;
for(u = 0; u < nchannels; u++){
- DBGPF("Destroying channel %lu on instance %s\n", channels[u]->ident, channels[u]->instance->name);
+ DBGPF("Destroying channel %" PRIu64 " on instance %s\n", channels[u]->ident, channels[u]->instance->name);
if(channels[u]->impl && channels[u]->instance->backend->channel_free){
channels[u]->instance->backend->channel_free(channels[u]);
}
@@ -200,11 +206,12 @@ void channels_free(){
nchannels = 0;
}
+
backend* backend_match(char* name){
size_t u;
- for(u = 0; u < nbackends; u++){
- if(!strcmp(backends[u].name, name)){
- return backends + u;
+ for(u = 0; u < registry.n; u++){
+ if(!strcmp(registry.backends[u].name, name)){
+ return registry.backends + u;
}
}
return NULL;
@@ -212,9 +219,12 @@ backend* backend_match(char* name){
instance* instance_match(char* name){
size_t u;
- for(u = 0; u < ninstances; u++){
- if(!strcmp(instances[u]->name, name)){
- return instances[u];
+ instance** iter = NULL;
+ for(u = 0; u < registry.n; u++){
+ for(iter = registry.instances[u]; iter && *iter; iter++){
+ if(!strcmp(name, (*iter)->name)){
+ return *iter;
+ }
}
}
return NULL;
@@ -224,16 +234,17 @@ struct timeval backend_timeout(){
size_t u;
uint32_t res, secs = 1, msecs = 0;
- for(u = 0; u < nbackends; u++){
- if(backends[u].interval){
- res = backends[u].interval();
+ for(u = 0; u < registry.n; u++){
+ //only call interval if backend has instances
+ if(registry.instances[u] && registry.backends[u].interval){
+ res = registry.backends[u].interval();
if((res / 1000) < secs){
- DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, backends[u].name);
+ DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, registry.backends[u].name);
secs = res / 1000;
msecs = res % 1000;
}
else if(res / 1000 == secs && (res % 1000) < msecs){
- DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, backends[u].name);
+ DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, registry.backends[u].name);
msecs = res % 1000;
}
}
@@ -248,14 +259,16 @@ struct timeval backend_timeout(){
MM_API int mm_backend_register(backend b){
if(!backend_match(b.name)){
- backends = realloc(backends, (nbackends + 1) * sizeof(backend));
- if(!backends){
+ registry.backends = realloc(registry.backends, (registry.n + 1) * sizeof(backend));
+ registry.instances = realloc(registry.instances, (registry.n + 1) * sizeof(instance**));
+ if(!registry.backends || !registry.instances){
fprintf(stderr, "Failed to allocate memory\n");
- nbackends = 0;
+ registry.n = 0;
return 1;
}
- backends[nbackends] = b;
- nbackends++;
+ registry.backends[registry.n] = b;
+ registry.instances[registry.n] = NULL;
+ registry.n++;
fprintf(stderr, "Registered backend %s\n", b.name);
return 0;
@@ -265,29 +278,25 @@ MM_API int mm_backend_register(backend b){
int backends_start(){
int rv = 0, current;
- size_t n, u, p;
instance** inst = NULL;
+ size_t n, u;
- for(u = 0; u < nbackends; u++){
- //only start backends that have instances
- for(p = 0; p < ninstances && instances[p]->backend != backends + u; p++){
- }
-
- //backend has no instances, skip the start call
- if(p == ninstances){
+ for(u = 0; u < registry.n; u++){
+ //skip backends without instances
+ if(!registry.instances[u]){
continue;
}
//fetch list of instances
- if(mm_backend_instances(backends[u].name, &n, &inst)){
- fprintf(stderr, "Failed to fetch instance list for initialization of backend %s\n", backends[u].name);
+ if(mm_backend_instances(registry.backends[u].name, &n, &inst)){
+ fprintf(stderr, "Failed to fetch instance list for initialization of backend %s\n", registry.backends[u].name);
return 1;
}
//start the backend
- current = backends[u].start(n, inst);
+ current = registry.backends[u].start(n, inst);
if(current){
- fprintf(stderr, "Failed to start backend %s\n", backends[u].name);
+ fprintf(stderr, "Failed to start backend %s\n", registry.backends[u].name);
}
//clean up
@@ -302,20 +311,33 @@ int backends_stop(){
size_t u, n;
instance** inst = NULL;
- for(u = 0; u < nbackends; u++){
+ //shut down the registry
+ for(u = 0; u < registry.n; u++){
//fetch list of instances
- if(mm_backend_instances(backends[u].name, &n, &inst)){
- fprintf(stderr, "Failed to fetch instance list for shutdown of backend %s\n", backends[u].name);
- n = 0;
+ if(mm_backend_instances(registry.backends[u].name, &n, &inst)){
+ fprintf(stderr, "Failed to fetch instance list for shutdown of backend %s\n", registry.backends[u].name);
inst = NULL;
+ n = 0;
}
- backends[u].shutdown(n, inst);
+ registry.backends[u].shutdown(n, inst);
free(inst);
inst = NULL;
+
+ //free instances
+ for(inst = registry.instances[u]; inst && *inst; inst++){
+ free((*inst)->name);
+ (*inst)->name = NULL;
+ (*inst)->backend = NULL;
+ free(*inst);
+ }
+ free(registry.instances[u]);
+ registry.instances[u] = NULL;
}
- free(backends);
- nbackends = 0;
+ channels_free();
+ free(registry.backends);
+ free(registry.instances);
+ registry.n = 0;
return 0;
}
diff --git a/backend.h b/backend.h
index de9b5dc..6a69508 100644
--- a/backend.h
+++ b/backend.h
@@ -8,9 +8,7 @@ instance* instance_match(char* name);
struct timeval backend_timeout();
int backends_start();
int backends_stop();
-void instances_free();
-void channels_free();
-instance* mm_instance();
+instance* mm_instance(backend* b);
/* Backend API */
MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create);
diff --git a/backends/artnet.c b/backends/artnet.c
index 34fc82d..caab6e0 100644
--- a/backends/artnet.c
+++ b/backends/artnet.c
@@ -321,11 +321,6 @@ static inline int artnet_process_frame(instance* inst, artnet_pkt* frame){
chan = data->data.channel + MAPPED_CHANNEL(data->data.map[p]);
}
- if(!chan){
- LOGPF("Active channel %" PRIsize_t " on %s not known to core", p, inst->name);
- return 1;
- }
-
if(IS_WIDE(data->data.map[p])){
data->data.map[MAPPED_CHANNEL(data->data.map[p])] &= ~MAP_MARK;
wide_val = data->data.in[p] << ((data->data.map[p] & MAP_COARSE) ? 8 : 0);
diff --git a/backends/sacn.c b/backends/sacn.c
index 495bdf3..bd5c75a 100644
--- a/backends/sacn.c
+++ b/backends/sacn.c
@@ -436,11 +436,6 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame
chan = inst_data->data.channel + MAPPED_CHANNEL(inst_data->data.map[u]);
}
- if(!chan){
- LOGPF("Active channel %" PRIsize_t " on %s not known to core", u, inst->name);
- return 1;
- }
-
//generate value
if(IS_WIDE(inst_data->data.map[u])){
inst_data->data.map[MAPPED_CHANNEL(inst_data->data.map[u])] &= ~MAP_MARK;
diff --git a/config.c b/config.c
index 920e161..aef4f87 100644
--- a/config.c
+++ b/config.c
@@ -388,7 +388,7 @@ static int config_line(char* line){
return 1;
}
- current_instance = mm_instance();
+ current_instance = mm_instance(current_backend);
if(!current_instance){
return 1;
}