]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: optimize idnodes (split to domains)
authorJaroslav Kysela <perex@perex.cz>
Mon, 22 Sep 2014 14:36:22 +0000 (16:36 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 22 Sep 2014 15:08:14 +0000 (17:08 +0200)
13 files changed:
src/api/api_idnode.c
src/channels.h
src/descrambler/capmt.c
src/dvr/dvr.h
src/idnode.c
src/idnode.h
src/input/mpegts.h
src/input/mpegts/linuxdvb/linuxdvb_frontend.c
src/input/mpegts/mpegts_network_dvb.c
src/input/mpegts/satip/satip_frontend.c
src/main.c
src/service.c
src/service.h

index 997b8742e39c3cdbeeaea768012e8a4efc37f64a..4cf0bf1c49d5a9a2c1925b61a4023f1e750fa98f 100644 (file)
@@ -185,7 +185,7 @@ api_idnode_load_by_class
   assert(idc);
 
   l = htsmsg_create_list();
-  if ((is = idnode_find_all(idc))) {
+  if ((is = idnode_find_all(idc, NULL))) {
     for (i = 0; i < is->is_count; i++) {
       in = is->is_array[i];
 
@@ -256,10 +256,12 @@ api_idnode_load
 
   /* Multiple */
   if (uuids) {
+    const idnodes_rb_t *domain = NULL;
     l = htsmsg_create_list();
     HTSMSG_FOREACH(f, uuids) {
       if (!(uuid = htsmsg_field_get_str(f))) continue;
-      if (!(in   = idnode_find(uuid, NULL))) continue;
+      if (!(in   = idnode_find(uuid, NULL, domain))) continue;
+      domain = in->in_domain;
       if (idnode_perm(in, perm, NULL)) {
         err = EPERM;
         continue;
@@ -276,7 +278,7 @@ api_idnode_load
 
   /* Single */
   } else {
-    if (!(in = idnode_find(uuid, NULL)))
+    if (!(in = idnode_find(uuid, NULL, NULL)))
       err = ENOENT;
     else {
       if (idnode_perm(in, perm, NULL)) {
@@ -326,7 +328,7 @@ api_idnode_save
   if (!msg->hm_islist) {
     if (!(uuid = htsmsg_get_str(msg, "uuid")))
       goto exit;
-    if (!(in = idnode_find(uuid, NULL)))
+    if (!(in = idnode_find(uuid, NULL, NULL)))
       goto exit;
     if (idnode_perm(in, perm, msg)) {
       err = EPERM;
@@ -337,13 +339,15 @@ api_idnode_save
 
   /* Multiple */
   } else {
+    const idnodes_rb_t *domain = NULL;
     HTSMSG_FOREACH(f, msg) {
       if (!(conf = htsmsg_field_get_map(f)))
         continue;
       if (!(uuid = htsmsg_get_str(conf, "uuid")))
         continue;
-      if (!(in = idnode_find(uuid, NULL)))
+      if (!(in = idnode_find(uuid, NULL, domain)))
         continue;
+      domain = in->in_domain;
       if (idnode_perm(in, perm, conf)) {
         err = EPERM;
         continue;
@@ -389,7 +393,7 @@ api_idnode_tree
   pthread_mutex_lock(&global_lock);
 
   if (!isroot || root) {
-    if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
+    if (!(node = idnode_find(isroot ? root : uuid, NULL, NULL))) {
       pthread_mutex_unlock(&global_lock);
       return EINVAL;
     }
@@ -477,16 +481,18 @@ api_idnode_handler
 
   /* Multiple */
   if (uuids) {
+    const idnodes_rb_t *domain = NULL;
     HTSMSG_FOREACH(f, uuids) {
       if (!(uuid = htsmsg_field_get_string(f))) continue;
-      if (!(in   = idnode_find(uuid, NULL))) continue;
+      if (!(in   = idnode_find(uuid, NULL, domain))) continue;
+      domain = in->in_domain;
       handler(perm, in);
     }
   
   /* Single */
   } else {
     uuid = htsmsg_field_get_string(f);
-    if (!(in   = idnode_find(uuid, NULL)))
+    if (!(in   = idnode_find(uuid, NULL, NULL)))
       err = ENOENT;
     else
       handler(perm, in);
index cb5b717d7d64452a9444d8e56410e4086421a5d1..3993c43660686c8f3b147f27ee528220e401b61c 100644 (file)
@@ -145,7 +145,7 @@ void channel_delete(channel_t *ch, int delconf);
 
 channel_t *channel_find_by_name(const char *name);
 #define channel_find_by_uuid(u)\
-  (channel_t*)idnode_find(u, &channel_class)
+  (channel_t*)idnode_find(u, &channel_class, NULL)
 
 channel_t *channel_find_by_id(uint32_t id);
 
@@ -165,7 +165,7 @@ channel_tag_t *channel_tag_find_by_name(const char *name, int create);
 channel_tag_t *channel_tag_find_by_identifier(uint32_t id);
 
 static inline channel_tag_t *channel_tag_find_by_uuid(const char *uuid)
-  {  return (channel_tag_t*)idnode_find(uuid, &channel_tag_class); }
+  {  return (channel_tag_t*)idnode_find(uuid, &channel_tag_class, NULL); }
 
 void channel_tag_save(channel_tag_t *ct);
 
index eabe16a7fb7151a08927ed05306e5ac2243641cd..6e3122641d2035e5a79d9532397743cebd0473a6 100644 (file)
@@ -1456,7 +1456,7 @@ capmt_thread(void *aux)
           int i, n;
           extern const idclass_t linuxdvb_adapter_class;
           linuxdvb_adapter_t *la;
-          idnode_set_t *is = idnode_find_all(&linuxdvb_adapter_class);
+          idnode_set_t *is = idnode_find_all(&linuxdvb_adapter_class, NULL);
           for (i = 0; i < is->is_count; i++) {
             la = (linuxdvb_adapter_t*)is->is_array[i];
             if (!la || !la->la_is_enabled(la)) continue;
index 0bc370677539710788d0d74ed15add8551f2b637..eccace4364c522eaee5c9de3a2d043af836d6b49 100644 (file)
@@ -344,7 +344,7 @@ dvr_config_t *dvr_config_find_by_name_default(const char *name);
 dvr_config_t *dvr_config_create(const char *name, const char *uuid, htsmsg_t *conf);
 
 static inline dvr_config_t *dvr_config_find_by_uuid(const char *uuid)
-  { return (dvr_config_t*)idnode_find(uuid, &dvr_config_class); }
+  { return (dvr_config_t*)idnode_find(uuid, &dvr_config_class, NULL); }
 
 void dvr_config_delete(const char *name);
 
@@ -431,7 +431,7 @@ void dvr_event_updated(epg_broadcast_t *e);
 dvr_entry_t *dvr_entry_find_by_id(int id);
 
 static inline dvr_entry_t *dvr_entry_find_by_uuid(const char *uuid)
-  { return (dvr_entry_t*)idnode_find(uuid, &dvr_entry_class); }
+  { return (dvr_entry_t*)idnode_find(uuid, &dvr_entry_class, NULL); }
 
 dvr_entry_t *dvr_entry_find_by_event(epg_broadcast_t *e);
 
@@ -490,7 +490,7 @@ void dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge);
 
 static inline dvr_autorec_entry_t *
 dvr_autorec_find_by_uuid(const char *uuid)
-  { return (dvr_autorec_entry_t*)idnode_find(uuid, &dvr_autorec_entry_class); }
+  { return (dvr_autorec_entry_t*)idnode_find(uuid, &dvr_autorec_entry_class, NULL); }
 
 
 htsmsg_t * dvr_autorec_entry_class_time_list(void *o, const char *null);
@@ -526,7 +526,7 @@ dvr_timerec_create(const char *uuid, htsmsg_t *conf);
 
 static inline dvr_timerec_entry_t *
 dvr_timerec_find_by_uuid(const char *uuid)
-  { return (dvr_timerec_entry_t*)idnode_find(uuid, &dvr_timerec_entry_class); }
+  { return (dvr_timerec_entry_t*)idnode_find(uuid, &dvr_timerec_entry_class, NULL); }
 
 
 void dvr_timerec_save(dvr_timerec_entry_t *dae);
index 6764d589c74315c1dfbce648824cf59a15a8c6e9..27b65e32ede576bba524a0569b317b92f973d823 100644 (file)
 #include "settings.h"
 #include "uuid.h"
 
+static const idnodes_rb_t * idnode_domain ( const idclass_t *idc );
+static void idclass_root_register ( idnode_t *in );
+
 typedef struct idclass_link
 {
-  const idclass_t        *idc;
+  const idclass_t       *idc;
+  idnodes_rb_t           nodes;
   RB_ENTRY(idclass_link) link;
 } idclass_link_t;
 
-static RB_HEAD(,idnode)       idnodes;
+static idnodes_rb_t           idnodes;
 static RB_HEAD(,idclass_link) idclasses;
+static RB_HEAD(,idclass_link) idrootclasses;
 static pthread_cond_t         idnode_cond;
 static pthread_mutex_t        idnode_mutex;
 static htsmsg_t              *idnode_queue;
@@ -58,6 +63,14 @@ in_cmp(const idnode_t *a, const idnode_t *b)
   return memcmp(a->in_uuid, b->in_uuid, sizeof(a->in_uuid));
 }
 
+static int
+ic_cmp ( const idclass_link_t *a, const idclass_link_t *b )
+{
+  assert(a->idc->ic_class);
+  assert(b->idc->ic_class);
+  return strcmp(a->idc->ic_class, b->idc->ic_class);
+}
+
 /* **************************************************************************
  * Registration
  * *************************************************************************/
@@ -71,6 +84,9 @@ void
 idnode_init(void)
 {
   idnode_queue = NULL;
+  RB_INIT(&idnodes);
+  RB_INIT(&idclasses);
+  RB_INIT(&idrootclasses);
   pthread_mutex_init(&idnode_mutex, NULL);
   pthread_cond_init(&idnode_cond, NULL);
   tvhthread_create(&idnode_tid, NULL, idnode_thread, NULL);
@@ -91,15 +107,16 @@ idnode_done(void)
     RB_REMOVE(&idclasses, il, link);
     free(il);
   }
+  while ((il = RB_FIRST(&idrootclasses)) != NULL) {
+    RB_REMOVE(&idrootclasses, il, link);
+    free(il);
+  }
   SKEL_FREE(idclasses_skel);
 }
 
 static const idclass_t *
-idnode_root_class(idnode_t *in)
+idnode_root_class(const idclass_t *idc)
 {
-  const idclass_t *idc;
-
-  idc = in->in_class;
   while (idc && idc->ic_super)
     idc = idc->ic_super;
   return idc;
@@ -112,12 +129,13 @@ int
 idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class, int flags)
 {
   idnode_t *c;
-  lock_assert(&global_lock);
   tvh_uuid_t u;
   int retries = 5;
   uint32_t u32;
   const idclass_t *idc;;
 
+  lock_assert(&global_lock);
+
   in->in_class = class;
   do {
 
@@ -130,9 +148,9 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class, int flags)
     c = NULL;
     if (flags & IDNODE_SHORT_UUID) {
       u32 = idnode_get_short_uuid(in);
-      idc = idnode_root_class(in);
+      idc = idnode_root_class(in->in_class);
       RB_FOREACH(c, &idnodes, in_link) {
-        if (idc != idnode_root_class(c))
+        if (idc != idnode_root_class(c->in_class))
           continue;
         if (idnode_get_short_uuid(c) == u32)
           break;
@@ -153,6 +171,10 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class, int flags)
 
   /* Register the class */
   idclass_register(class); // Note: we never actually unregister
+  idclass_root_register(in);
+  assert(in->in_domain);
+  c = RB_INSERT_SORTED(in->in_domain, in, in_domain_link, in_cmp);
+  assert(c == NULL);
 
   /* Fire event */
   idnode_notify_simple(in);
@@ -168,6 +190,7 @@ idnode_unlink(idnode_t *in)
 {
   lock_assert(&global_lock);
   RB_REMOVE(&idnodes, in, in_link);
+  RB_REMOVE(in->in_domain, in, in_domain_link);
   tvhtrace("idnode", "unlink node %s", idnode_uuid_as_str(in));
   idnode_notify_simple(in);
 }
@@ -521,8 +544,24 @@ idnode_get_time
 /**
  *
  */
+static const idnodes_rb_t *
+idnode_domain(const idclass_t *idc)
+{
+  if (idc) {
+    idclass_link_t lskel, *l;
+    const idclass_t *root = idnode_root_class(idc);
+    lskel.idc = root;
+    l = RB_FIND(&idrootclasses, &lskel, link, ic_cmp);
+    if (l == NULL)
+      return NULL;
+    return &l->nodes;
+  } else {
+    return NULL;
+  }
+}
+
 void *
-idnode_find(const char *uuid, const idclass_t *idc)
+idnode_find ( const char *uuid, const idclass_t *idc, const idnodes_rb_t *domain )
 {
   idnode_t skel, *r;
 
@@ -531,7 +570,12 @@ idnode_find(const char *uuid, const idclass_t *idc)
     return NULL;
   if(hex2bin(skel.in_uuid, sizeof(skel.in_uuid), uuid))
     return NULL;
-  r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
+  if (domain == NULL)
+    domain = idnode_domain(idc);
+  if (domain == NULL)
+    r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
+  else
+    r = RB_FIND(domain, &skel, in_domain_link, in_cmp);
   if(r != NULL && idc != NULL) {
     const idclass_t *c = r->in_class;
     for(;c != NULL; c = c->ic_super) {
@@ -544,21 +588,37 @@ idnode_find(const char *uuid, const idclass_t *idc)
 }
 
 idnode_set_t *
-idnode_find_all ( const idclass_t *idc )
+idnode_find_all ( const idclass_t *idc, const idnodes_rb_t *domain )
 {
   idnode_t *in;
   const idclass_t *ic;
   tvhtrace("idnode", "find class %s", idc->ic_class);
   idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
-  RB_FOREACH(in, &idnodes, in_link) {
-    ic = in->in_class;
-    while (ic) {
-      if (ic == idc) {
-        tvhtrace("idnode", "  add node %s", idnode_uuid_as_str(in));
-        idnode_set_add(is, in, NULL);
-        break;
+  if (domain == NULL)
+    domain = idnode_domain(idc);
+  if (domain == NULL) {
+    RB_FOREACH(in, &idnodes, in_link) {
+      ic = in->in_class;
+      while (ic) {
+        if (ic == idc) {
+          tvhtrace("idnode", "  add node %s", idnode_uuid_as_str(in));
+          idnode_set_add(is, in, NULL);
+          break;
+        }
+        ic = ic->ic_super;
+      }
+    }
+  } else {
+    RB_FOREACH(in, domain, in_domain_link) {
+      ic = in->in_class;
+      while (ic) {
+        if (ic == idc) {
+          tvhtrace("idnode", "  add node %s", idnode_uuid_as_str(in));
+          idnode_set_add(is, in, NULL);
+          break;
+        }
+        ic = ic->ic_super;
       }
-      ic = ic->ic_super;
     }
   }
   return is;
@@ -1099,14 +1159,6 @@ idclass_get_property_groups (const idclass_t *idc)
   return NULL;
 }
 
-static int
-ic_cmp ( const idclass_link_t *a, const idclass_link_t *b )
-{
-  assert(a->idc->ic_class);
-  assert(b->idc->ic_class);
-  return strcmp(a->idc->ic_class, b->idc->ic_class);
-}
-
 void
 idclass_register(const idclass_t *idc)
 {
@@ -1115,12 +1167,33 @@ idclass_register(const idclass_t *idc)
     idclasses_skel->idc = idc;
     if (RB_INSERT_SORTED(&idclasses, idclasses_skel, link, ic_cmp))
       break;
+    RB_INIT(&idclasses_skel->nodes); /* not used, but for sure */
     SKEL_USED(idclasses_skel);
     tvhtrace("idnode", "register class %s", idc->ic_class);
     idc = idc->ic_super;
   }
 }
 
+static void
+idclass_root_register(idnode_t *in)
+{
+  const idclass_t *idc = in->in_class;
+  idclass_link_t *r;
+  idc = idnode_root_class(idc);
+  SKEL_ALLOC(idclasses_skel);
+  idclasses_skel->idc = idc;
+  r = RB_INSERT_SORTED(&idrootclasses, idclasses_skel, link, ic_cmp);
+  if (r) {
+    in->in_domain = &r->nodes;
+    return;
+  }
+  RB_INIT(&idclasses_skel->nodes);
+  r = idclasses_skel;
+  SKEL_USED(idclasses_skel);
+  tvhtrace("idnode", "register root class %s", idc->ic_class);
+  in->in_domain = &r->nodes;
+}
+
 const idclass_t *
 idclass_find ( const char *class )
 {
@@ -1296,7 +1369,7 @@ idnode_thread ( void *p )
     pthread_mutex_lock(&global_lock);
 
     HTSMSG_FOREACH(f, q) {
-      node  = idnode_find(f->hmf_name, NULL);
+      node  = idnode_find(f->hmf_name, NULL, NULL);
       event = htsmsg_field_get_str(f);
       m     = htsmsg_create_map();
       htsmsg_add_str(m, "uuid", f->hmf_name);
index f3d03387a2d2039cf000188eba5164b76e4aaf03..12693533b945e0b3d6c278d5aa89f3fc5632edf2 100644 (file)
@@ -73,12 +73,17 @@ struct idclass {
   int             (*ic_perm)       (idnode_t *self, struct access *a, htsmsg_t *msg_to_write);
 };
 
+
+typedef RB_HEAD(, idnode) idnodes_rb_t;
+
 /*
  * Node definition
  */
 struct idnode {
   uint8_t           in_uuid[UUID_BIN_SIZE]; ///< Unique ID
   RB_ENTRY(idnode)  in_link;                ///< Global hash
+  RB_ENTRY(idnode)  in_domain_link;         ///< Root class link (domain)
+  idnodes_rb_t     *in_domain;              ///< Domain nodes
   const idclass_t  *in_class;               ///< Class definition
 };
 
@@ -149,8 +154,8 @@ void          idnode_movedown     (idnode_t *in);
 
 void          idnode_changed      (idnode_t *in);
 
-void         *idnode_find    (const char *uuid, const idclass_t *idc);
-idnode_set_t *idnode_find_all(const idclass_t *idc);
+void         *idnode_find    (const char *uuid, const idclass_t *idc, const idnodes_rb_t *nodes);
+idnode_set_t *idnode_find_all(const idclass_t *idc, const idnodes_rb_t *nodes);
 
 
 void idnode_notify (idnode_t *in, int event);
index 2bb75b4a94321c1bbfd6777dd2777d11868a3121..b6a0e24a51b2d4d479d9f14b039a5331275cd7de 100644 (file)
@@ -640,7 +640,8 @@ void mpegts_input_stop_all ( mpegts_input_t *mi );
 
 void mpegts_input_delete ( mpegts_input_t *mi, int delconf );
 
-#define mpegts_input_find(u) idnode_find(u, &mpegts_input_class);
+static inline mpegts_input_t *mpegts_input_find(const char *uuid)
+  { return idnode_find(uuid, &mpegts_input_class, NULL); }
 
 int mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg );
 
@@ -680,8 +681,8 @@ mpegts_network_t *mpegts_network_create0
 
 extern const idclass_t mpegts_network_class;
 
-#define mpegts_network_find(u)\
-  idnode_find(u, &mpegts_network_class)
+static inline mpegts_network_t *mpegts_network_find(const char *uuid)
+  { return idnode_find(uuid, &mpegts_network_class, NULL); }
 
 mpegts_mux_t *mpegts_network_find_mux
   (mpegts_network_t *mn, uint16_t onid, uint16_t tsid);
@@ -706,8 +707,8 @@ mpegts_mux_t *mpegts_mux_create0
   mpegts_mux_create0(calloc(1, sizeof(mpegts_mux_t)), &mpegts_mux_class, uuid,\
                      mn, onid, tsid, conf)
 
-#define mpegts_mux_find(u)\
-  idnode_find(u, &mpegts_mux_class)
+static inline mpegts_mux_t *mpegts_mux_find(const char *uuid)
+  { return idnode_find(uuid, &mpegts_mux_class, NULL); }
 
 #define mpegts_mux_delete_by_uuid(u, delconf)\
   { mpegts_mux_t *mm = mpegts_mux_find(u); if (mm) mm->mm_delete(mm, delconf); }
@@ -814,8 +815,8 @@ mpegts_service_t *mpegts_service_create0
 mpegts_service_t *mpegts_service_find 
   ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, int create, int *save );
 
-#define mpegts_service_find_by_uuid(u)\
-  idnode_find(u, &mpegts_service_class)
+static inline mpegts_service_t *mpegts_service_find_by_uuid(const char *uuid)
+  { return idnode_find(uuid, &mpegts_service_class, NULL); }
 
 void mpegts_service_delete ( service_t *s, int delconf );
 
index be3cb32c02c2719104ea83cf29f9d6278772b5c5..8de4f471e6644b4831a0553620ab8e6b03e562d5 100644 (file)
@@ -398,7 +398,7 @@ linuxdvb_frontend_network_list ( mpegts_input_t *mi )
   else
     return NULL;
 
-  return idnode_find_all(idc);
+  return idnode_find_all(idc, NULL);
 }
 
 /* **************************************************************************
index 12916f57bb78bf59fda3bda0096ffb78a8e3b396..f2237218b4e3577dc80308abc251b77764de0e57 100644 (file)
@@ -640,8 +640,7 @@ void dvb_network_done ( void )
 dvb_network_t*
 dvb_network_find_by_uuid(const char *uuid)
 {
-  idnode_t *in = idnode_find(uuid, &dvb_network_class);
-  return (dvb_network_t*)in;
+  return idnode_find(uuid, &dvb_network_class, NULL);
 }
 
 int dvb_network_get_orbital_pos
index 763280d51c6af9524b0327ee711768a246c315f6..686ca576400742feb026944cc71b95bfea4dc987 100644 (file)
@@ -638,7 +638,7 @@ satip_frontend_network_list ( mpegts_input_t *mi )
   else
     return NULL;
 
-  return idnode_find_all(idc);
+  return idnode_find_all(idc, NULL);
 }
 
 /* **************************************************************************
index 9bc8685603f8a0fdc192e19d13f093165e213647..2e77000ec9bc4363707cfb97e82f2b13a1c18444 100644 (file)
@@ -924,7 +924,6 @@ main(int argc, char **argv)
   tvhftrace("main", avahi_done);
   tvhftrace("main", bonjour_done);
   tvhftrace("main", imagecache_done);
-  tvhftrace("main", idnode_done);
   tvhftrace("main", lang_code_done);
   tvhftrace("main", api_done);
   tvhftrace("main", config_done);
@@ -934,6 +933,7 @@ main(int argc, char **argv)
   tvhftrace("main", esfilter_done);
   tvhftrace("main", intlconv_done);
   tvhftrace("main", urlparse_done);
+  tvhftrace("main", idnode_done);
 
   tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
   tvhlog_end();
index 68f4f87e8796c33e96bea667bf1697a59d467871..8de4dfb351159dace8745b2adaafd8d15b344900 100644 (file)
@@ -861,16 +861,6 @@ service_create0
   return t;
 }
 
-/**
- * Find a service based on the given identifier
- */
-service_t *
-service_find(const char *identifier)
-{
-  return idnode_find(identifier, &service_class);
-}
-
-
 /**
  *
  */
index d7706e4fdb191bbd4fa9301fe25c8f087332702b..b6d56ac33e04dcad24d9b5bb1b1e3a36b9b12dc5 100644 (file)
@@ -461,7 +461,8 @@ void service_unref(service_t *t);
 
 void service_ref(service_t *t);
 
-service_t *service_find(const char *identifier);
+static inline service_t *service_find(const char *identifier)
+  { return idnode_find(identifier, &service_class, NULL); }
 #define service_find_by_identifier service_find
 
 service_instance_t *service_find_instance(struct service *s,