Skip to content

Commit

Permalink
bcommand: Add tri-state filter support.
Browse files Browse the repository at this point in the history
This adds so called tri-state support to the filtering which allows to
return a tri-state (e.g. show, suppress, unknown) which fits better then
a boolean that only can have 2 values. When the filter column is not
filled we cannot really check if a resource is enabled/disabled/exists
or passes an ACL so we now return OF_FILTER_STATE_UNKNOWN indicating
this. We now count all OF_FILTER_STATE_SHOW and OF_FILTER_STATE_UNKNOWN
states returned by the different filters set (set in the calling function)
when all filters are applied and there are no filters returning an
explicit OF_FILTER_STATE_SHOW and we do have one or more
OF_FILTER_STATE_UNKNOWN return values we will explicitly suppress this
value as we cannot be sure that we should or should not show the data.
  • Loading branch information
Marco van Wieringen committed Sep 1, 2016
1 parent 08bb7f1 commit 32dc0a5
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/dird/protos.h
Expand Up @@ -349,7 +349,7 @@ void update_inchanger_for_export(UAContext *ua, STORERES *store, changer_vol_lis

/* ua_output.c */
void bsendmsg(void *ua_ctx, const char *fmt, ...);
bool filterit(void *ctx, void *data, of_filter_tuple *tuple);
of_filter_state filterit(void *ctx, void *data, of_filter_tuple *tuple);
bool printit(void *ctx, const char *msg);
bool complete_jcr_for_job(JCR *jcr, JOBRES *job, POOLRES *pool);
RUNRES *find_next_run(RUNRES *run, JOBRES *job, utime_t &runtime, int ndays);
Expand Down
51 changes: 29 additions & 22 deletions src/dird/ua_output.c
Expand Up @@ -1548,11 +1548,11 @@ bool messages_cmd(UAContext *ua, const char *cmd)
/*
* Callback routine for "filtering" database listing.
*/
bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
of_filter_state filterit(void *ctx, void *data, of_filter_tuple *tuple)
{
bool retval = true;
char **row = (char **)data;
UAContext *ua = (UAContext *)ctx;
of_filter_state retval = OF_FILTER_STATE_SHOW;

switch (tuple->type) {
case OF_FILTER_LIMIT:
Expand All @@ -1562,27 +1562,33 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
tuple->u.limit_filter.limit--;
} else {
Dmsg0(200, "filterit: limit filter reached don't display entry\n");
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}
goto bail_out;
case OF_FILTER_ACL:
if (row[tuple->u.acl_filter.column] &&
strlen(row[tuple->u.acl_filter.column]) &&
!ua->acl_access_ok(tuple->u.acl_filter.acltype,
row[tuple->u.acl_filter.column], false)) {
Dmsg2(200, "filterit: Filter on acl_type %d value %s, suppress output\n",
tuple->u.acl_filter.acltype, row[tuple->u.acl_filter.column]);
retval = false;
if (!row[tuple->u.acl_filter.column] ||
strlen(row[tuple->u.acl_filter.column]) == 0) {
retval = OF_FILTER_STATE_UNKNOWN;
} else {
if (!ua->acl_access_ok(tuple->u.acl_filter.acltype,
row[tuple->u.acl_filter.column], false)) {
Dmsg2(200, "filterit: Filter on acl_type %d value %s, suppress output\n",
tuple->u.acl_filter.acltype, row[tuple->u.acl_filter.column]);
retval = OF_FILTER_STATE_SUPPRESS;
}
}
goto bail_out;
case OF_FILTER_RESOURCE:
if (row[tuple->u.res_filter.column] &&
strlen(row[tuple->u.res_filter.column]) &&
!GetResWithName(tuple->u.res_filter.restype,
row[tuple->u.res_filter.column], false)) {
Dmsg2(200, "filterit: Filter on resource_type %d value %s, suppress output\n",
tuple->u.res_filter.restype, row[tuple->u.res_filter.column]);
retval = false;
if (!row[tuple->u.res_filter.column] ||
strlen(row[tuple->u.res_filter.column]) == 0) {
retval = OF_FILTER_STATE_UNKNOWN;
} else {
if (!GetResWithName(tuple->u.res_filter.restype,
row[tuple->u.res_filter.column], false)) {
Dmsg2(200, "filterit: Filter on resource_type %d value %s, suppress output\n",
tuple->u.res_filter.restype, row[tuple->u.res_filter.column]);
retval = OF_FILTER_STATE_SUPPRESS;
}
}
goto bail_out;
case OF_FILTER_ENABLED:
Expand All @@ -1591,6 +1597,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)

if (!row[tuple->u.res_filter.column] ||
strlen(row[tuple->u.res_filter.column]) == 0) {
retval = OF_FILTER_STATE_UNKNOWN;
goto bail_out;
}

Expand All @@ -1606,7 +1613,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
if (!client || client->enabled != enabled) {
Dmsg2(200, "filterit: Filter on Client, %s is not %sabled\n",
row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis");
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}
goto bail_out;
}
Expand All @@ -1617,7 +1624,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
if (!job || job->enabled != enabled) {
Dmsg2(200, "filterit: Filter on Job, %s is not %sabled\n",
row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis");
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}
goto bail_out;
}
Expand All @@ -1628,7 +1635,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
if (!store || store->enabled != enabled) {
Dmsg2(200, "filterit: Filter on Storage, %s is not %sabled\n",
row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis");
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}
goto bail_out;
}
Expand All @@ -1639,7 +1646,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
if (!schedule || schedule->enabled != enabled) {
Dmsg2(200, "filterit: Filter on Schedule, %s is not %sabled\n",
row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis");
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}
goto bail_out;
}
Expand All @@ -1649,7 +1656,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple)
break;
}
default:
retval = false;
retval = OF_FILTER_STATE_SUPPRESS;
}

bail_out:
Expand Down
31 changes: 30 additions & 1 deletion src/lib/output_formatter.c
Expand Up @@ -514,20 +514,49 @@ bool OUTPUT_FORMATTER::has_acl_filters()

bool OUTPUT_FORMATTER::filter_data(void *data)
{
of_filter_state state;
of_filter_tuple *tuple;
int acl_filter_show = 0,
acl_filter_unknown = 0;

/*
* See if a filtering function is registered.
* See if there are any filters.
*/
if (filter_func && filters && !filters->empty()) {
foreach_alist(tuple, filters) {
if (!filter_func(filter_ctx, data, tuple)) {
state = filter_func(filter_ctx, data, tuple);

Dmsg1(800, "filter_state %d\n", state);
switch (state) {
case OF_FILTER_STATE_SHOW:
if (tuple->type == OF_FILTER_ACL) {
acl_filter_show++;
}
break;
case OF_FILTER_STATE_SUPPRESS:
return false;
case OF_FILTER_STATE_UNKNOWN:
if (tuple->type == OF_FILTER_ACL) {
acl_filter_unknown++;
}
break;
}
}
}

/*
* If we have multiple ACL filters and none gave an
* explicit show state we suppress the entry just to
* be sure we do not show to much information if we
* are not sure if we should show the item.
*/
if (acl_filter_unknown > 0 && acl_filter_show == 0) {
Dmsg2(200, "tri-state filtering acl_filter_unknown %d, acl_filter_show %d\n",
acl_filter_unknown, acl_filter_show);
return false;
}

return true;
}

Expand Down
11 changes: 10 additions & 1 deletion src/lib/output_formatter.h
Expand Up @@ -50,6 +50,15 @@ typedef struct json_t json_t;
#endif
#endif

/*
* Filtering states.
*/
typedef enum of_filter_state {
OF_FILTER_STATE_SHOW,
OF_FILTER_STATE_SUPPRESS,
OF_FILTER_STATE_UNKNOWN
} of_filter_state;

/*
* Filtering types.
*/
Expand Down Expand Up @@ -93,7 +102,7 @@ class OUTPUT_FORMATTER : public SMARTALLOC {
* Typedefs.
*/
typedef bool (SEND_HANDLER)(void *ctx, const char *msg);
typedef bool (FILTER_HANDLER)(void *ctx, void *data, of_filter_tuple *tuple);
typedef of_filter_state (FILTER_HANDLER)(void *ctx, void *data, of_filter_tuple *tuple);

private:
/*
Expand Down

0 comments on commit 32dc0a5

Please sign in to comment.