1 #ifndef ADIOS2_QUERY_H
2 #define ADIOS2_QUERY_H
3 
4 #include <ios>      //std::ios_base::failure
5 #include <iostream> //std::cout
6 
7 #include <numeric>   // accumulate
8 #include <stdexcept> //std::invalid_argument std::exception
9 #include <vector>
10 
11 //#include "adios2.h"
12 #include "adios2/common/ADIOSTypes.h"
13 #include "adios2/core/ADIOS.h"
14 #include "adios2/core/Engine.h"
15 #include "adios2/core/IO.h"
16 #include "adios2/core/Variable.h"
17 namespace adios2
18 {
19 namespace query
20 {
21 enum Op
22 {
23     GT,
24     LT,
25     GE,
26     LE,
27     NE,
28     EQ
29 };
30 
31 enum Relation
32 {
33     AND,
34     OR,
35     NOT
36 };
37 
strToRelation(std::string relationStr)38 static adios2::query::Relation strToRelation(std::string relationStr) noexcept
39 {
40     if ((relationStr.compare("or") == 0) || (relationStr.compare("OR") == 0))
41         return adios2::query::Relation::OR;
42 
43     return adios2::query::Relation::AND; // default
44 }
45 
strToQueryOp(std::string opStr)46 static adios2::query::Op strToQueryOp(std::string opStr) noexcept
47 {
48     if ((opStr.compare("lt") == 0) || (opStr.compare("LT") == 0))
49         return adios2::query::Op::LT;
50     if ((opStr.compare("gt") == 0) || (opStr.compare("GT") == 0))
51         return adios2::query::Op::GT;
52     if ((opStr.compare("ge") == 0) || (opStr.compare("GE") == 0))
53         return adios2::query::Op::GE;
54     if ((opStr.compare("le") == 0) || (opStr.compare("LE") == 0))
55         return adios2::query::Op::LE;
56     if ((opStr.compare("eq") == 0) || (opStr.compare("EQ") == 0))
57         return adios2::query::Op::EQ;
58     if ((opStr.compare("ne") == 0) || (opStr.compare("NE") == 0))
59         return adios2::query::Op::NE;
60 
61     return adios2::query::Op::EQ; // default
62 }
63 
split(const std::string & s,char delim)64 static adios2::Dims split(const std::string &s, char delim)
65 {
66     adios2::Dims dim;
67 
68     std::stringstream ss(s);
69     std::string item;
70 
71     while (getline(ss, item, delim))
72     {
73         std::stringstream curr(item);
74         size_t val;
75         curr >> val;
76         dim.push_back(val);
77     }
78 
79     return dim;
80 }
81 
82 //
83 // classes
84 //
85 class Range
86 {
87 public:
88     adios2::query::Op m_Op;
89     std::string m_StrValue;
90     // void* m_Value = nullptr;
91 
92     // template<class T> bool Check(T val) const ;
93 
94     template <class T>
95     bool CheckInterval(T &min, T &max) const;
96 
Print()97     void Print() { std::cout << "===> " << m_StrValue << std::endl; }
98 }; // class Range
99 
100 class RangeTree
101 {
102 public:
AddLeaf(adios2::query::Op op,std::string value)103     void AddLeaf(adios2::query::Op op, std::string value)
104     {
105         Range range;
106         range.m_Op = op;
107         range.m_StrValue = value;
108 
109         m_Leaves.push_back(range);
110     }
111 
AddNode(RangeTree & node)112     void AddNode(RangeTree &node) { m_SubNodes.push_back(node); }
113 
SetRelation(adios2::query::Relation r)114     void SetRelation(adios2::query::Relation r) { m_Relation = r; }
115 
Print()116     void Print()
117     {
118         for (auto leaf : m_Leaves)
119             leaf.Print();
120         for (auto node : m_SubNodes)
121             node.Print();
122     }
123 
124     // template<class T>  bool Check(T value) const ;
125 
126     template <class T>
127     bool CheckInterval(T &min, T &max) const;
128 
129     adios2::query::Relation m_Relation = adios2::query::Relation::AND;
130     std::vector<Range> m_Leaves;
131     std::vector<RangeTree> m_SubNodes;
132 }; // class RangeTree
133 
134 class QueryBase
135 {
136 public:
~QueryBase()137     virtual ~QueryBase(){};
138     virtual bool IsCompatible(const adios2::Box<adios2::Dims> &box) = 0;
139     virtual void Print() = 0;
140     virtual void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
141                                     std::vector<Box<Dims>> &touchedBlocks) = 0;
142 
GetIntersection(const Box<Dims> & box1,const Box<Dims> & box2)143     Box<Dims> GetIntersection(const Box<Dims> &box1,
144                               const Box<Dims> &box2) noexcept
145     {
146         Box<Dims> b1 = adios2::helper::StartEndBox(box1.first, box1.second);
147         Box<Dims> b2 = adios2::helper::StartEndBox(box2.first, box2.second);
148 
149         Box<Dims> result = adios2::helper::IntersectionBox(b1, b2);
150         return adios2::helper::StartCountBox(result.first, result.second);
151     }
152 
UseOutputRegion(const adios2::Box<adios2::Dims> & region)153     bool UseOutputRegion(const adios2::Box<adios2::Dims> &region)
154     {
155         if (!IsCompatible(region))
156             return false;
157 
158         m_OutputRegion = region;
159         BroadcastOutputRegion(region);
160         return true;
161     }
162 
163     virtual void
164     BroadcastOutputRegion(const adios2::Box<adios2::Dims> &region) = 0;
165 
166     void ApplyOutputRegion(std::vector<Box<Dims>> &touchedBlocks,
167                            const adios2::Box<Dims> &referenceRegion);
168 
169     adios2::Box<adios2::Dims> m_OutputRegion;
170 
171 private:
172     // bool ResetToOutputRegion(Box<Dims>& block);
173 };
174 
175 class QueryVar : public QueryBase
176 {
177 public:
QueryVar(const std::string & varName)178     QueryVar(const std::string &varName) : m_VarName(varName) {}
~QueryVar()179     ~QueryVar() {}
180 
GetVarName()181     std::string &GetVarName() { return m_VarName; }
182     void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
183                             std::vector<Box<Dims>> &touchedBlocks);
BroadcastOutputRegion(const adios2::Box<adios2::Dims> & region)184     void BroadcastOutputRegion(const adios2::Box<adios2::Dims> &region)
185     {
186         m_OutputRegion = region;
187     }
188 
Print()189     void Print() { m_RangeTree.Print(); }
190 
IsCompatible(const adios2::Box<adios2::Dims> & box)191     bool IsCompatible(const adios2::Box<adios2::Dims> &box)
192     {
193         if ((m_Selection.first.size() == 0) || (box.first.size() == 0))
194             return true;
195 
196         if (box.first.size() != m_Selection.first.size())
197             return false;
198 
199         for (int n = 0; n < box.second.size(); n++)
200             if (box.second[n] != m_Selection.second[n])
201                 return false;
202 
203         return true;
204     }
205 
SetSelection(adios2::Dims & start,adios2::Dims & count)206     void SetSelection(adios2::Dims &start, adios2::Dims &count)
207     {
208         m_Selection.first = start;
209         m_Selection.second = count;
210     }
211 
212     bool IsSelectionValid(adios2::Dims &varShape) const;
213 
214     bool TouchSelection(adios2::Dims &start, adios2::Dims &count) const;
215 
216     void LoadSelection(const std::string &startStr,
217                        const std::string &countStr);
218 
LimitToSelection(std::vector<Box<Dims>> & touchedBlocks)219     void LimitToSelection(std::vector<Box<Dims>> &touchedBlocks)
220     {
221         for (auto it = touchedBlocks.begin(); it != touchedBlocks.end(); it++)
222         {
223             Box<Dims> overlap = GetIntersection(m_Selection, *it);
224             // adios2::helper::IntersectionBox(m_Selection, *it);
225             it->first = overlap.first;
226             it->second = overlap.second;
227         }
228     }
229 
230     RangeTree m_RangeTree;
231     adios2::Box<adios2::Dims> m_Selection;
232 
233     std::string m_VarName;
234 
235 private:
236 }; // class QueryVar
237 
238 class QueryComposite : public QueryBase
239 {
240 public:
QueryComposite(adios2::query::Relation relation)241     QueryComposite(adios2::query::Relation relation) : m_Relation(relation) {}
~QueryComposite()242     ~QueryComposite()
243     {
244         for (auto n : m_Nodes)
245             delete n;
246         m_Nodes.clear();
247     }
248 
BroadcastOutputRegion(const adios2::Box<adios2::Dims> & region)249     void BroadcastOutputRegion(const adios2::Box<adios2::Dims> &region)
250     {
251         if (m_Nodes.size() == 0)
252             return;
253 
254         for (auto n : m_Nodes)
255             n->BroadcastOutputRegion(region);
256     }
257 
258     void BlockIndexEvaluate(adios2::core::IO &, adios2::core::Engine &,
259                             std::vector<Box<Dims>> &touchedBlocks);
260 
261     bool AddNode(QueryBase *v);
262 
Print()263     void Print()
264     {
265         std::cout << " Composite query" << std::endl;
266         for (auto n : m_Nodes)
267             n->Print();
268     }
269 
IsCompatible(const adios2::Box<adios2::Dims> & box)270     bool IsCompatible(const adios2::Box<adios2::Dims> &box)
271     {
272         if (m_Nodes.size() == 0)
273             return false;
274         return (m_Nodes[0])->IsCompatible(box);
275     }
276 
277 private:
278     adios2::query::Relation m_Relation = adios2::query::Relation::AND;
279 
280     std::vector<QueryBase *> m_Nodes;
281 }; // class QueryComposite
282 
283 /*
284  */
285 
286 } // namespace query
287 } //  namespace adiso2
288 
289 #endif // define
290