afs: Allow database switching on sighup.
[paraslash.git] / filter_common.c
1 /* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file filter_common.c Common helper functions for filter input/output. */
4
5 #include <regex.h>
6 #include <sys/types.h>
7 #include <lopsub.h>
8
9 #include "filter_cmd.lsg.h"
10 #include "para.h"
11 #include "list.h"
12 #include "sched.h"
13 #include "fd.h"
14 #include "buffer_tree.h"
15 #include "filter.h"
16 #include "error.h"
17 #include "string.h"
18
19 /** Iterate over all filters. */
20 #define FOR_EACH_FILTER(j) for (j = 1; FILTER_CMD(j); j++)
21
22 /**
23 * Obtain a reference to a filter structure.
24 *
25 * \param filter_num Between zero and NUM_SUPPORTED_FILTERS, inclusively.
26 *
27 * \return Pointer to the filter identified by the given filter number, or
28 * NULL if the filter number is out of range.
29 *
30 * \sa filter_name().
31 */
32 const struct filter *filter_get(int filter_num)
33 {
34 if (filter_num < 1 || filter_num > LSG_NUM_FILTER_CMD_SUBCOMMANDS)
35 return NULL;
36 return lls_user_data(FILTER_CMD(filter_num));
37 }
38
39 static inline bool filter_supported(int filter_num)
40 {
41 return lls_user_data(FILTER_CMD(filter_num));
42 }
43
44 /**
45 * Return the name of a filter, given its number.
46 *
47 * \param filter_num See \ref filter_get().
48 *
49 * \return A pointer to a string literal, or NULL if filter_num is out of
50 * range. The caller must not attempt to call free(3) on the returned pointer.
51 */
52 const char *filter_name(int filter_num)
53 {
54 if (filter_num < 1 || filter_num > LSG_NUM_FILTER_CMD_SUBCOMMANDS)
55 return NULL;
56 return lls_command_name(FILTER_CMD(filter_num));
57 }
58
59 /**
60 * Parse a filter command line and call the corresponding ->setup method.
61 *
62 * \param fa The filter argument.
63 * \param conf Points to filter-specific setup upon successful return.
64 * \param lprp Parsed command line options are returned here.
65 *
66 * Check if the given filter argument starts with the name of a supported
67 * filter, optionally followed by options for this filter. If yes, call the
68 * command line parser of that filter and its ->setup method.
69 *
70 * \return This function either succeeds or does not return. On success, the
71 * number of the filter is returned and conf is initialized to point to the
72 * filter configuration as returned by the filter's ->setup() method, if any.
73 * Moreover, *lprp is initialized to contain the parsed command line options.
74 * On errors, the function calls exit(EXIT_FAILURE).
75 */
76 int filter_setup(const char *fa, void **conf, struct lls_parse_result **lprp)
77 {
78 int ret, filter_num, argc;
79 char *errctx = NULL, **argv;
80 const struct lls_command *cmd;
81 const struct filter *f;
82
83 ret = create_argv(fa, " \t\n", &argv);
84 if (ret < 0)
85 goto fail;
86 argc = ret;
87 ret = lls(lls_lookup_subcmd(argv[0], filter_cmd_suite, &errctx));
88 if (ret < 0)
89 goto free_argv;
90 filter_num = ret;
91 cmd = FILTER_CMD(filter_num);
92 if (!filter_supported(filter_num)) {
93 ret = -E_UNSUPPORTED_FILTER;
94 errctx = make_message("bad filter name: %s",
95 lls_command_name(cmd));
96 goto free_argv;
97 }
98 ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx));
99 if (ret < 0)
100 goto free_argv;
101 f = filter_get(filter_num);
102 *conf = f->setup? f->setup(*lprp) : NULL;
103 ret = filter_num;
104 free_argv:
105 free_argv(argv);
106 if (ret >= 0)
107 return ret;
108 fail:
109 if (errctx)
110 PARA_ERROR_LOG("%s\n", errctx);
111 free(errctx);
112 PARA_EMERG_LOG("%s\n", para_strerror(-ret));
113 exit(EXIT_FAILURE);
114 }
115
116 /**
117 * Print help text of each filter to stdout.
118 *
119 * \param detailed Whether to print short or long help.
120 */
121 void print_filter_helps(bool detailed)
122 {
123 int i, num = 0;
124
125 printf("\nAvailable filters: ");
126 FOR_EACH_FILTER(i) {
127 if (!filter_supported(i))
128 continue;
129 if (num > 50) {
130 printf("\n ");
131 num = 0;
132 }
133 num += printf("%s%s", i? " " : "", filter_name(i));
134 }
135 printf("\n");
136
137 FOR_EACH_FILTER(i) {
138 const struct lls_command *cmd = FILTER_CMD(i);
139 char *help;
140
141 if (!filter_supported(i))
142 continue;
143 help = detailed? lls_long_help(cmd) : lls_short_help(cmd);
144 if (!help)
145 continue;
146 printf("%s\n", help);
147 free(help);
148 }
149 }
150
151 /**
152 * Print a short summary of all available filters to stdout.
153 *
154 * For each supported filter, the filter name and the purpose text is printed
155 * in a single line. Since no options are shown, the filter list is more
156 * concise than the text obtained from print_filter_helps().
157 */
158 void print_filter_list(void)
159 {
160 int i;
161
162 printf("Available filters:\n");
163 FOR_EACH_FILTER(i) {
164 const struct lls_command *cmd = FILTER_CMD(i);
165 if (!filter_supported(i))
166 continue;
167 printf("%-9s %s\n", filter_name(i), lls_purpose(cmd));
168 }
169 }
170
171 /**
172 * Set select timeout of the scheduler.
173 *
174 * \param s The scheduler.
175 * \param context Pointer to the filter node (task context).
176 *
177 * This looks at the status of the btr node of the filter. If data is available
178 * in the input queue of the filter, or if an error occurred, a minimal timeout
179 * for the next select call is requested from the scheduler. Otherwise the
180 * scheduler timeout is left unchanged.
181 */
182 void generic_filter_pre_select(struct sched *s, void *context)
183 {
184 struct filter_node *fn = context;
185
186 if (btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL) != 0)
187 sched_min_delay(s);
188 }
189
190 #ifdef WORDS_BIGENDIAN
191 #define DECODER_SAMPLE_FORMAT SF_S16_BE
192 #else
193 #define DECODER_SAMPLE_FORMAT SF_S16_LE
194 #endif
195
196 /**
197 * Execute a btr command for a decoder.
198 *
199 * The buffer tree nodes of the writers ask the parent nodes about sample_rate,
200 * channels count and sample format. This function is called by all decoders to
201 * answer these queries.
202 *
203 * \param cmd The command to be executed by the child node.
204 * \param sample_rate Known to the decoder.
205 * \param channels Known to the decoder.
206 * \param result Ascii representation on the answer is stored here.
207 *
208 * \return Standard.
209 */
210 int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels,
211 char **result)
212 {
213 if (!strcmp(cmd, "sample_rate")) {
214 if (sample_rate == 0)
215 return -E_BTR_NAVAIL;
216 *result = make_message("%u", sample_rate);
217 return 1;
218 }
219 if (!strcmp(cmd, "channels")) {
220 if (channels == 0)
221 return -E_BTR_NAVAIL;
222 *result = make_message("%u", channels);
223 return 1;
224 }
225 if (!strcmp(cmd, "sample_format")) {
226 *result = make_message("%d", DECODER_SAMPLE_FORMAT);
227 return 1;
228 }
229 return -ERRNO_TO_PARA_ERROR(ENOTSUP);
230 }