1+ /* *
2+ * \file src/plugins/output/fds/src/Config.cpp
3+ * \author Lukas Hutak <[email protected] > 4+ * \brief Parser of XML configuration (source file)
5+ * \date 2019
6+ *
7+ * Copyright(c) 2019 CESNET z.s.p.o.
8+ * SPDX-License-Identifier: BSD-3-Clause
9+ */
10+
11+ #include " Config.hpp"
12+ #include < memory>
13+ #include < stdexcept>
14+
15+ /*
16+ * <params>
17+ * <storagePath>...</storagePath>
18+ * <compression>...</compression> <!-- optional -->
19+ * <dumpInterval> <!-- optional -->
20+ * <timeWindow>...</timeWindow> <!-- optional -->
21+ * <align>...</align> <!-- optional -->
22+ * </dumpInterval>
23+ * <asyncIO>...</asyncIO> <!-- optional -->
24+ * </params>
25+ */
26+
27+ // / XML nodes
28+ enum params_xml_nodes {
29+ NODE_STORAGE = 1 ,
30+ NODE_COMPRESS,
31+ NODE_DUMP,
32+ NODE_ASYNCIO,
33+
34+ DUMP_WINDOW,
35+ DUMP_ALIGN
36+ };
37+
38+ // / Definition of the \<dumpInterval\> node
39+ static const struct fds_xml_args args_dump[] = {
40+ FDS_OPTS_ELEM (DUMP_WINDOW, " timeWindow" , FDS_OPTS_T_UINT, FDS_OPTS_P_OPT),
41+ FDS_OPTS_ELEM (DUMP_ALIGN, " align" , FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
42+ FDS_OPTS_END
43+ };
44+
45+ // / Definition of the \<params\> node
46+ static const struct fds_xml_args args_params[] = {
47+ FDS_OPTS_ROOT (" params" ),
48+ FDS_OPTS_ELEM (NODE_STORAGE, " storagePath" , FDS_OPTS_T_STRING, 0 ),
49+ FDS_OPTS_ELEM (NODE_COMPRESS, " compression" , FDS_OPTS_T_STRING, FDS_OPTS_P_OPT),
50+ FDS_OPTS_NESTED (NODE_DUMP, " dumpInterval" , args_dump, FDS_OPTS_P_OPT),
51+ FDS_OPTS_ELEM (NODE_ASYNCIO, " asyncIO" , FDS_OPTS_T_BOOL, FDS_OPTS_P_OPT),
52+ FDS_OPTS_END
53+ };
54+
55+ Config::Config (const char *params)
56+ {
57+ set_default ();
58+
59+ // Create XML parser
60+ std::unique_ptr<fds_xml_t , decltype (&fds_xml_destroy)> xml (fds_xml_create (), &fds_xml_destroy);
61+ if (!xml) {
62+ throw std::runtime_error (" Failed to create an XML parser!" );
63+ }
64+
65+ if (fds_xml_set_args (xml.get (), args_params) != FDS_OK) {
66+ throw std::runtime_error (" Failed to parse the description of an XML document!" );
67+ }
68+
69+ fds_xml_ctx_t *params_ctx = fds_xml_parse_mem (xml.get (), params, true );
70+ if (!params_ctx) {
71+ std::string err = fds_xml_last_err (xml.get ());
72+ throw std::runtime_error (" Failed to parse the configuration: " + err);
73+ }
74+
75+ // Parse parameters and check configuration
76+ try {
77+ parse_root (params_ctx);
78+ validate ();
79+ } catch (std::exception &ex) {
80+ throw std::runtime_error (" Failed to parse the configuration: " + std::string (ex.what ()));
81+ }
82+ }
83+
84+ /* *
85+ * @brief Set default parameters
86+ */
87+ void
88+ Config::set_default ()
89+ {
90+ m_path.clear ();
91+ m_calg = calg::NONE;
92+ m_async = true ;
93+
94+ m_window.align = true ;
95+ m_window.size = WINDOW_SIZE;
96+ }
97+
98+ /* *
99+ * @brief Check if the configuration is valid
100+ * @throw runtime_error if the configuration breaks some rules
101+ */
102+ void
103+ Config::validate ()
104+ {
105+ if (m_path.empty ()) {
106+ throw std::runtime_error (" Storage path cannot be empty!" );
107+ }
108+
109+ if (m_window.size == 0 ) {
110+ throw std::runtime_error (" Window size cannot be zero!" );
111+ }
112+ }
113+
114+ /* *
115+ * @brief Process \<params\> node
116+ * @param[in] ctx XML context to process
117+ * @throw runtime_error if the parser fails
118+ */
119+ void
120+ Config::parse_root (fds_xml_ctx_t *ctx)
121+ {
122+ const struct fds_xml_cont *content;
123+ while (fds_xml_next (ctx, &content) != FDS_EOC) {
124+ switch (content->id ) {
125+ case NODE_STORAGE:
126+ // Storage path
127+ assert (content->type == FDS_OPTS_T_STRING);
128+ m_path = content->ptr_string ;
129+ break ;
130+ case NODE_COMPRESS:
131+ // Compression method
132+ assert (content->type == FDS_OPTS_T_STRING);
133+ if (strcasecmp (content->ptr_string , " none" ) == 0 ) {
134+ m_calg = calg::NONE;
135+ } else if (strcasecmp (content->ptr_string , " lz4" ) == 0 ) {
136+ m_calg = calg::LZ4;
137+ } else if (strcasecmp (content->ptr_string , " zstd" ) == 0 ) {
138+ m_calg = calg::ZSTD;
139+ } else {
140+ const std::string inv_str = content->ptr_string ;
141+ throw std::runtime_error (" Unknown compression algorithm '" + inv_str + " '" );
142+ }
143+ break ;
144+ case NODE_ASYNCIO:
145+ // Asynchronous I/O
146+ assert (content->type == FDS_OPTS_T_BOOL);
147+ m_async = content->val_bool ;
148+ break ;
149+ case NODE_DUMP:
150+ // Dump window
151+ assert (content->type == FDS_OPTS_T_CONTEXT);
152+ parse_dump (content->ptr_ctx );
153+ break ;
154+ default :
155+ // Internal error
156+ throw std::runtime_error (" Unknown XML node" );
157+ }
158+ }
159+ }
160+
161+ /* *
162+ * @brief Auxiliary function for parsing \<dumpInterval\> options
163+ * @param[in] ctx XML context to process
164+ * @throw runtime_error if the parser fails
165+ */
166+ void
167+ Config::parse_dump (fds_xml_ctx_t *ctx)
168+ {
169+ const struct fds_xml_cont *content;
170+ while (fds_xml_next (ctx, &content) != FDS_EOC) {
171+ switch (content->id ) {
172+ case DUMP_WINDOW:
173+ // Window size
174+ assert (content->type == FDS_OPTS_T_UINT);
175+ if (content->val_uint > UINT32_MAX) {
176+ throw std::runtime_error (" Window size is too long!" );
177+ }
178+ m_window.size = static_cast <uint32_t >(content->val_uint );
179+ break ;
180+ case DUMP_ALIGN:
181+ // Window alignment
182+ assert (content->type == FDS_OPTS_T_BOOL);
183+ m_window.align = content->val_bool ;
184+ break ;
185+ default :
186+ // Internal error
187+ throw std::runtime_error (" Unknown XML node" );
188+ }
189+ }
190+ }
0 commit comments