summaryrefslogtreecommitdiff
path: root/sys/src/libdtracy/prov.c
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2018-12-13 10:42:49 +0000
committeraiju <devnull@localhost>2018-12-13 10:42:49 +0000
commitc7304ea03caf68cf035d14f50f6e24e0c16ccdfe (patch)
treef4b5e8047078c41caa0d98cc0ea3d5012c4d17f9 /sys/src/libdtracy/prov.c
parentdae5a44111dfb21a714824a5cec2abee4f9f9080 (diff)
dtracy: get rid of DTName struct, support more than three parts in a probe name, wildcard matching
Diffstat (limited to 'sys/src/libdtracy/prov.c')
-rw-r--r--sys/src/libdtracy/prov.c126
1 files changed, 106 insertions, 20 deletions
diff --git a/sys/src/libdtracy/prov.c b/sys/src/libdtracy/prov.c
index 8becbc756..c9e4f822c 100644
--- a/sys/src/libdtracy/prov.c
+++ b/sys/src/libdtracy/prov.c
@@ -14,14 +14,12 @@ dtstrdup(char *n)
}
DTProbe *
-dtpnew(DTName name, DTProvider *prov, void *aux)
+dtpnew(char *name, DTProvider *prov, void *aux)
{
DTProbe *p, **pp;
p = dtmalloc(sizeof(DTProbe));
- p->provider = dtstrdup(name.provider);
- p->function = dtstrdup(name.function);
- p->name = dtstrdup(name.name);
+ p->name = dtstrdup(name);
p->prov = prov;
p->aux = aux;
p->enablist.probnext = p->enablist.probprev = &p->enablist;
@@ -31,46 +29,134 @@ dtpnew(DTName name, DTProvider *prov, void *aux)
return p;
}
+/* does the pattern match at most one probe (or provider if provonly)? */
+static int
+patunique(char *pat, int provonly)
+{
+ for(;; pat++)
+ switch(*pat){
+ case ':':
+ if(provonly){
+ case 0:
+ return 1;
+ }
+ break;
+ case '?':
+ case '*':
+ return 0;
+ }
+}
+
+static char *
+partmatch(char *pat, char *str, int provonly)
+{
+ for(;; pat++, str++){
+ if(*pat == '*')
+ return pat;
+ if(*pat != *str && (*pat != '?' || *str == ':') && (!provonly || *pat != ':' || *str != 0))
+ return nil;
+ if(*pat == 0 || *pat == ':' && provonly)
+ return (void*)-1;
+ }
+}
+
+/*
+ do a wildcard match with * and ?, but don't match : against a wildcard
+ if provonly, stop at the first :
+
+ replacing empty parts with * is done in user space
+*/
int
-dtstrmatch(char *a, char *b)
+dtnamematch(char *pat, char *str, int provonly)
{
- if(a == nil || *a == 0) return 1;
- if(b == nil) return 0;
- return strcmp(a, b) == 0;
+ char *patp, *strp, *p;
+
+ patp = partmatch(pat, str, provonly);
+ if(patp == nil) return 0;
+ if(patp == (void*)-1) return 1;
+ /* reached a * */
+ strp = str + (patp - pat);
+ patp++;
+ for(;;){
+ /* try the rest of the pattern against each position */
+ p = partmatch(patp, strp, provonly);
+ if(p == nil){
+ if(*strp == 0 || *strp == ':') return 0;
+ strp++;
+ continue;
+ }
+ if(p == (void*)-1)
+ return 1;
+ /* reached another * */
+ strp += p - patp;
+ patp = p + 1;
+ }
}
int
-dtpmatch(DTName name, DTProbe ***ret)
+dtpmatch(char *name, DTProbe ***ret)
{
DTProbe **l;
int nl;
DTProvider **provp, *prov;
DTProbe **pp, *p;
+ int unique, uniqueprov;
l = nil;
nl = 0;
+ unique = patunique(name, 0);
+ uniqueprov = patunique(name, 1);
for(provp = dtproviders; prov = *provp, prov != nil; provp++){
- if(!dtstrmatch(name.provider, prov->name))
+ if(!dtnamematch(name, prov->name, 1))
continue;
- for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext)
- if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){
+ if(!prov->provided){
+ prov->provided = 1;
+ prov->provide(prov);
+ }
+ for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
+ if(dtnamematch(name, p->name, 0)){
if(ret != nil){
l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
l[nl] = p;
}
nl++;
+ if(unique) goto out;
}
- prov->provide(prov, name);
- for(; p = *pp, p != nil; pp = &p->provnext)
- if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){
- if(ret != nil){
- l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
- l[nl] = p;
- }
- nl++;
+ }
+ if(uniqueprov) goto out;
+ }
+out:
+ if(ret != nil)
+ *ret = l;
+ return nl;
+}
+
+int
+dtplist(DTProbe ***ret)
+{
+ DTProbe **l;
+ int nl;
+ DTProvider **provp, *prov;
+ DTProbe **pp, *p;
+
+ l = nil;
+ nl = 0;
+ for(provp = dtproviders; prov = *provp, prov != nil; provp++){
+ if(!prov->provided){
+ prov->provided = 1;
+ prov->provide(prov);
+ }
+ for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
+ if(ret != nil){
+ l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
+ l[nl] = p;
}
+ nl++;
+ }
}
if(ret != nil)
*ret = l;
+ else
+ dtfree(l);
return nl;
}