Line data Source code
1 : #include <specreader.hpp>
2 :
3 : #include <backendbuilder.hpp>
4 :
5 : #include <helper/keyhelper.hpp>
6 :
7 : #include <unordered_set>
8 :
9 :
10 : namespace kdb
11 : {
12 :
13 : namespace tools
14 : {
15 :
16 76 : SpecBackendBuilder::SpecBackendBuilder (BackendBuilderInit const & bbi) : MountBackendBuilder (bbi), nodes (0)
17 : {
18 76 : }
19 :
20 :
21 72 : SpecReader::SpecReader (BackendBuilderInit const & abbi) : bbi (abbi)
22 : {
23 36 : }
24 :
25 72 : SpecReader::~SpecReader ()
26 : {
27 36 : }
28 :
29 228 : class SpecMountpointReader
30 : {
31 : private:
32 : KeySet ks;
33 : Key mp;
34 : KeySet backendConfig;
35 : KeySet mountConf;
36 : typedef std::unordered_map<Key, SpecBackendBuilder> Backends;
37 : Backends & backends;
38 : BackendBuilderInit const & bbi;
39 : SpecBackendBuilder bb;
40 :
41 : public:
42 190 : SpecMountpointReader (Backends & b, BackendBuilderInit const & bbi_) : backends (b), bbi (bbi_), bb (bbi)
43 : {
44 38 : }
45 :
46 : void processKey (Key const & ck);
47 : SpecBackendBuilder readMountpointSpecification (KeySet const & cks);
48 : };
49 :
50 : namespace
51 : {
52 3597 : bool startsWith (std::string const & str, std::string const & start)
53 : {
54 3597 : if (str.length () < start.length ())
55 : {
56 : return false;
57 : }
58 7521 : return std::equal (start.begin (), start.end (), str.begin ());
59 : }
60 :
61 183 : bool isToBeIgnored (std::string const & name)
62 : {
63 : // TODO: read from METADATA.ini
64 2013 : return startsWith (name, "infos") || startsWith (name, "exports") || startsWith (name, "constants") ||
65 915 : startsWith (name, "exports") ||
66 :
67 : // spec-plugin
68 1830 : startsWith (name, "conflict") || startsWith (name, "require") || startsWith (name, "array") ||
69 :
70 1971 : startsWith (name, "fallback") || startsWith (name, "override") || startsWith (name, "namespace") || name == "default" ||
71 282 : name == "context" ||
72 :
73 : // always ignore stuff internal to plugins
74 747 : startsWith (name, "internal") ||
75 :
76 747 : startsWith (name, "callback") ||
77 :
78 747 : startsWith (name, "binary") ||
79 :
80 : // code generator
81 1436 : startsWith (name, "opt") || startsWith (name, "env") || startsWith (name, "gen") ||
82 :
83 : // docu
84 1302 : startsWith (name, "comment") || startsWith (name, "description") || startsWith (name, "see") ||
85 1044 : startsWith (name, "rationale") || startsWith (name, "example") ||
86 :
87 744 : name == "mountpoint" || startsWith (name, "config");
88 : }
89 : } // namespace
90 :
91 108 : void SpecMountpointReader::processKey (Key const & ck)
92 : {
93 216 : Key k (ck);
94 108 : k.rewindMeta ();
95 108 : Key m;
96 1300 : while ((m = k.nextMeta ()))
97 : {
98 651 : std::string const & cn = "config/needs";
99 434 : if (startsWith (m.getName (), cn))
100 : {
101 30 : Key bKey = m.dup ();
102 40 : bKey.setName ("user" + bKey.getName ().substr (cn.length ()));
103 20 : backendConfig.append (bKey);
104 : }
105 621 : else if (m.getName () == "infos/plugins")
106 : {
107 24 : bb.addPlugins (parseArguments (m.getString ()));
108 : }
109 597 : else if (m.getName () == "infos/needs")
110 : {
111 32 : bb.needPlugin (m.getString ());
112 : }
113 549 : else if (m.getName () == "infos/recommends")
114 : {
115 0 : bb.recommendPlugin (m.getString ());
116 : }
117 366 : else if (isToBeIgnored (m.getName ()))
118 : {
119 : }
120 : else
121 : {
122 170 : bb.needMetadata (m.getName ());
123 : }
124 : }
125 108 : }
126 :
127 38 : SpecBackendBuilder SpecMountpointReader::readMountpointSpecification (KeySet const & cks)
128 : {
129 38 : ks = cks;
130 190 : mp = ks.head ().dup ();
131 :
132 152 : Key rmp (mp.dup ());
133 38 : helper::removeNamespace (rmp);
134 :
135 190 : bb.setMountpoint (rmp, mountConf);
136 :
137 38 : processKey (mp);
138 38 : bb.nodes++; // count mp
139 :
140 114 : ks.lookup (mp, KDB_O_POP);
141 :
142 76 : ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
143 436 : for (Key k = ks.next (); k; k = ks.next ())
144 : {
145 : // search for mountpoint
146 430 : Key m = k.getMeta<const Key> ("mountpoint");
147 72 : if (m)
148 : {
149 4 : SpecMountpointReader smr (backends, bbi);
150 14 : backends[k] = smr.readMountpointSpecification (ks.cut (k));
151 : continue;
152 : }
153 :
154 70 : processKey (k);
155 70 : bb.nodes++;
156 : }
157 :
158 38 : bb.setBackendConfig (backendConfig);
159 190 : bb.useConfigFile (mp.getMeta<std::string> ("mountpoint"));
160 114 : return bb;
161 : }
162 :
163 36 : void SpecReader::readSpecification (KeySet const & cks)
164 : {
165 72 : KeySet ks;
166 72 : Key mp;
167 :
168 : // only accept keys in 'spec' namespace
169 504 : for (Key k : cks)
170 : {
171 132 : if (k.isSpec ())
172 : {
173 : ks.append (k);
174 : }
175 : }
176 :
177 36 : ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
178 276 : for (Key k = ks.next (); k; k = ks.next ())
179 : {
180 : // search for mountpoint
181 360 : Key m = k.getMeta<const Key> ("mountpoint");
182 60 : if (m)
183 : {
184 72 : SpecMountpointReader smr (backends, bbi);
185 252 : backends[k] = smr.readMountpointSpecification (ks.cut (k));
186 : }
187 : }
188 36 : }
189 : } // namespace tools
190 : } // namespace kdb
|