1 #ifndef _hpp_tools_vdb_config_util_
2 #define _hpp_tools_vdb_config_util_
3 
4 /*==============================================================================
5 *
6 *                            PUBLIC DOMAIN NOTICE
7 *               National Center for Biotechnology Information
8 *
9 *  This software/database is a "United States Government Work" under the
10 *  terms of the United States Copyright Act.  It was written as part of
11 *  the author's official duties as a United States Government employee and
12 *  thus cannot be copyrighted.  This software/database is freely available
13 *  to the public for use. The National Library of Medicine and the U.S.
14 *  Government have not placed any restriction on its use or reproduction.
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 *  Please cite the author in any work or product based on this material.
25 *
26 * ===========================================================================
27 *
28 */
29 
30 #include <klib/out.h> /* OUTMSG */
31 #include <klib/printf.h> /* string_printf */
32 #include <klib/text.h> /* String */
33 
34 #include <kfg/config.h> /* KConfig */
35 #include <kfs/directory.h> /* KDirectory */
36 
37 #include <kfs/file.h> /* KFile */
38 
39 #include <map>
40 #include <string>
41 #include <vector>
42 
43 #include <cstring>
44 
45 static const bool DEBUG(false);
46 
47 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); \
48     if (rc2 && !rc) { rc = rc2; } obj = NULL; } while (false)
49 
50 
51 class CNoncopyable {
52 public:
CNoncopyable(void)53     CNoncopyable(void) {}
54 protected:
~CNoncopyable(void)55     ~CNoncopyable(void) {}
56 private:
57     // Prohibit copy constructor and assignment operator
58     CNoncopyable(const CNoncopyable&);
59     const CNoncopyable& operator=(const CNoncopyable&);
60 };
61 
62 rc_t StringRelease(const String *self);
63 
64 class CString : CNoncopyable {
65     const String *m_Self;
66 
67 public:
CString(const String * self)68     CString(const String *self) : m_Self(self) {}
69 
~CString()70     ~CString() { free((void*)m_Self); }
71 
Get(void) const72     const String* Get(void) const { return m_Self; }
GetString(void) const73     std::string GetString(void) const {
74         const char *s = GetCString();
75         if (s == NULL)
76             return "";
77         return s;
78     }
GetCString(void) const79     const char* GetCString(void) const {
80         if (Empty())
81             return NULL;
82         return m_Self->addr;
83     }
84 
Empty(void) const85     bool Empty(void) const {
86         return
87             m_Self == NULL || m_Self->addr == NULL || m_Self->addr[0] == '\0';
88     }
89 
Equals(const CString & aString) const90     bool Equals(const CString &aString) const {
91         const String *string = aString.Get();
92 
93         if (m_Self == NULL && string == NULL)
94             return true;
95         return StringEqual(m_Self, string);
96     }
97 
Equals(const char * buffer,size_t bsize=~0) const98     bool Equals(const char *buffer, size_t bsize = ~0) const {
99         if (bsize == (size_t)~0) {
100             bsize = string_size(buffer);
101         }
102 
103         if (m_Self == NULL) {
104             return buffer == NULL || bsize == 0;
105         }
106 
107         String s;
108         StringInit(&s, buffer, bsize, (uint32_t)bsize + 1);
109 
110         return StringEqual(m_Self, &s);
111     }
112 };
113 
114 class CStdIn : CNoncopyable {
115     const KFile *m_Self;
116     uint64_t m_Pos;
117 
118 public:
CStdIn(void)119     CStdIn(void) : m_Self(NULL), m_Pos(0) {
120         rc_t rc = KFileMakeStdIn(&m_Self);
121         if (rc != 0) {
122             throw rc;
123         }
124     }
125 
~CStdIn(void)126     ~CStdIn(void) { KFileRelease(m_Self); }
127 
Read1(void)128     char Read1(void) {
129         char buf[9] = "";
130         rc_t rc = Read(buf, sizeof buf);
131         if (rc != 0) {
132             return -1;
133         }
134         return buf[0];
135     }
136 
137     rc_t Read(char *buffer, size_t bsize, size_t *num_read = NULL);
138 };
139 
140 class CKDirectory : CNoncopyable {
141     KDirectory *m_Self;
142     const uint32_t m_PrivateAccess;
143     const uint32_t m_PublicAccess;
144 public:
CKDirectory(void)145     CKDirectory(void)
146         : m_Self(NULL), m_PrivateAccess(0700), m_PublicAccess(0775)
147     {
148         rc_t rc  = KDirectoryNativeDir(&m_Self);
149         if (rc != 0)
150             throw rc;
151     }
~CKDirectory()152     ~CKDirectory() { KDirectoryRelease(m_Self); }
CheckPrivateAccess(const CString & path,bool & updated,bool verbose) const153     rc_t CheckPrivateAccess(const CString &path, bool &updated, bool verbose)
154         const
155     {   return CheckAccess(path, updated, true, verbose); }
156     rc_t CheckPublicAccess(const CString &path, bool verbose = false) const;
CreateNonExistingPrivateDir(const CString & path,bool verbose=false) const157     rc_t CreateNonExistingPrivateDir(const CString &path, bool verbose = false)
158         const
159     {   return CreateNonExistingDir(path, m_PrivateAccess, verbose); }
160     rc_t CreateNonExistingPublicDir(bool verbose, const char *path, ...) const;
CreateNonExistingPublicDir(const std::string & path,bool verbose=false) const161     rc_t CreateNonExistingPublicDir(const std::string &path,
162         bool verbose = false) const
163     {   return CreateNonExistingDir(path, m_PublicAccess, verbose, true); }
CreateNonExistingPublicDir(const CString & path,bool verbose=false) const164     rc_t CreateNonExistingPublicDir(const CString &path, bool verbose = false)
165         const
166     {   return CreateNonExistingDir(path, m_PublicAccess, verbose); }
CreatePublicDir(const std::string & path,bool verbose=false)167     rc_t CreatePublicDir(const std::string &path, bool verbose = false) {
168         return CreateNonExistingDir(path, m_PublicAccess, verbose, false);
169     }
170     rc_t CanWriteFile(const CString &dir, bool verbose = false) const;
Exists(const std::string & path) const171     bool Exists(const std::string &path) const { return Exists(path.c_str()); }
172     bool Exists(const CString &path) const;
IsDirectory(const std::string & path) const173     bool IsDirectory(const std::string &path) const {
174         return IsDirectory(path.c_str());
175     }
176     bool IsDirectory(const char *path, ...) const;
177     std::string Canonical ( const char * path ) const;
178 private:
Exists(const char * path) const179     bool Exists(const char *path) const
180     {   return KDirectoryPathType(m_Self, path) != kptNotFound; }
181     rc_t CreateNonExistingDir(const CString &path,
182         uint32_t access, bool verbose) const;
183     rc_t CreateNonExistingDir(const std::string &path,
184         uint32_t access, bool verbose, bool chekExistance) const;
185     rc_t CreateNonExistingDir(bool verbose,
186         uint32_t access, const char *path, va_list args) const;
187     rc_t CheckAccess(const CString &path, bool &updated, bool isPrivate,
188         bool verbose = false) const;
189 };
190 
191 class CKConfigNode : CNoncopyable {
192     const KConfigNode *m_Self;
193 
194 public:
CKConfigNode(const KConfigNode * self)195     CKConfigNode(const KConfigNode *self)
196         : m_Self(self)
197     {}
198 
~CKConfigNode(void)199     ~CKConfigNode(void) {
200         KConfigNodeRelease(m_Self);
201     }
202 
OpenNodeRead(const std::string & path) const203     const KConfigNode* OpenNodeRead(const std::string &path) const {
204         const KConfigNode *node = NULL;
205         rc_t rc = KConfigNodeOpenNodeRead(m_Self, &node, path.c_str());
206         if (rc != 0) {
207             return NULL;
208         }
209         return node;
210     }
211 
ReadBool(const std::string & path) const212     bool ReadBool(const std::string &path) const {
213         return ReadString(path) == "true";
214     }
215 
ReadString(const std::string & path) const216     std::string ReadString(const std::string &path) const {
217         const KConfigNode *node = NULL;
218         rc_t rc = KConfigNodeOpenNodeRead(m_Self, &node, path.c_str());
219         if (rc != 0) {
220             return "";
221         }
222 
223         String *result = NULL;
224         rc = KConfigNodeReadString(node, &result);
225         std::string r;
226         if (rc == 0) {
227             assert(result);
228             r = result->addr;
229         }
230 
231         RELEASE(String, result);
232         RELEASE(KConfigNode, node);
233 
234         return r;
235     }
236 };
237 
238 class CKConfig : CNoncopyable {
239     KConfig *m_Self;
240     bool m_Updated;
241     const char *m_RepositoryRemoteAuxDisabled;
242     const char *m_RepositoryRemoteMainDisabled;
243     const char *m_RepositoryUserRoot;
244 public:
245     CKConfig(bool verbose = false);
~CKConfig(void)246     ~CKConfig(void)
247     { KConfigRelease(m_Self); }
Get(void) const248     KConfig* Get(void) const { return m_Self; }
249     void Reload(bool verbose = false);
Updated(void)250     void Updated ( void ) { m_Updated = true; }
IsUpdated(void) const251     bool IsUpdated ( void ) const { return m_Updated; }
252     rc_t Commit(void);
253     const KConfigNode* OpenNodeRead(const char *path, ...) const;
254     bool IsRemoteRepositoryDisabled(void) const;
ReadDefaultConfig(void) const255     const String* ReadDefaultConfig(void) const
256     {   return ReadString("/config/default"); }
ReadHome(void) const257     const String* ReadHome(void) const { return ReadString("HOME"); }
ReadNcbiHome(void) const258     const String* ReadNcbiHome(void) const { return ReadString("NCBI_HOME"); }
ReadUserRepositoryRootPath(void) const259     const String* ReadUserRepositoryRootPath(void) const
260     {   return ReadString(m_RepositoryUserRoot); }
261     rc_t DisableRemoteRepository(bool disable);
262     rc_t UpdateUserRepositoryRootPath(const CString &path);
UpdateUserRepositoryRootPath(const char * buffer,size_t size)263     rc_t UpdateUserRepositoryRootPath(const char *buffer, size_t size) {
264         return UpdateNode(m_RepositoryUserRoot, buffer, false, size);
265     }
266     rc_t FixResolverCgiNodes ( void );
267     bool NodeExists(const std::string &path) const;
268     rc_t UpdateNode(bool verbose, const char *value, const char *name, ...);
269     rc_t UpdateNode(const char *path, const char *buffer,
270         bool verbose = false, size_t size = ~0);
UpdateNode(const std::string & path,const char * buffer)271     rc_t UpdateNode(const std::string &path, const char *buffer) {
272         return UpdateNode(path.c_str(), buffer);
273     }
UpdateNode(const std::string & path,const std::string & buffer)274     rc_t UpdateNode(const std::string &path, const std::string &buffer) {
275         return UpdateNode(path.c_str(), buffer.c_str());
276     }
277     rc_t CreateRemoteRepositories(bool fix = false);
278     rc_t CreateUserRepository(std::string name = "", bool fix = false);
279     const String* ReadString(const char *path) const;
280 };
281 
282 class CSplitter : CNoncopyable {
283     const char *m_Start;
284     size_t m_Size;
285 
286 public:
CSplitter(const std::string & s)287     CSplitter(const std::string &s) : m_Start(s.c_str()), m_Size(s.size()) {}
CSplitter(const String * s)288     CSplitter(const String *s) : m_Start(NULL), m_Size(0) {
289         if (s == NULL) {
290             return;
291         }
292         m_Start = s->addr;
293         m_Size = s->len;
294         SkipEmpties();
295     }
HasNext(void) const296     bool HasNext(void) const { return m_Size != 0; }
Next(void)297     const std::string Next(void) {
298         if (!HasNext()) {
299             return "";
300         }
301         const char *s = m_Start;
302         const char *end = string_chr(m_Start, m_Size, ':');
303         size_t n = m_Size;
304         if (end != NULL) {
305             n = end - m_Start;
306             m_Start = end + 1;
307             if (m_Size >= n + 1) {
308                m_Size -= n + 1;
309             }
310             else {
311                m_Size = 0;
312             }
313         }
314         else {
315             m_Start = NULL;
316             m_Size = 0;
317         }
318         SkipEmpties();
319         return std::string(s, n);
320     }
321     static rc_t Test(void);
322 
323 private:
SkipEmpties(void)324     void SkipEmpties(void) {
325         while (m_Size > 0 && m_Start != NULL && *m_Start == ':') {
326             --m_Size;
327             ++m_Start;
328         }
329     }
330 };
331 
332 class CAppVolume {
333     std::string m_Type;
334     std::string m_Path;
335 
336 public:
CAppVolume(const std::string & type="",const std::string & path="")337     CAppVolume(const std::string &type = "", const std::string &path = "")
338         : m_Type(type)
339         , m_Path(path)
340     {}
341 
GetPath(void) const342     std::string GetPath(void) const { return m_Path; }
343 
Update(CKConfig & kfg,const char * node,const std::string & appVolPath,bool verbose=false) const344     rc_t Update(CKConfig &kfg, const char *node,
345         const std::string &appVolPath, bool verbose = false) const
346     {
347         if (DEBUG) {
348             OUTMSG(("CAppVolume::Update(%s, %s)\n", node, appVolPath.c_str()));
349         }
350 
351         return kfg.UpdateNode(verbose, m_Path.c_str(),
352             "%s/%s/%s", node, appVolPath.c_str(), m_Type.c_str());
353     }
354 
Dump(const char * node,const std::string & appVolPath) const355     void Dump(const char *node, const std::string &appVolPath) const {
356         OUTMSG(("%s/%s/%s = \"%s\"\n", node, appVolPath.c_str(),
357             m_Type.c_str(), m_Path.c_str()));
358     }
359 };
360 
361 class CApp : CNoncopyable {
362     bool m_HasVolume;
363     const std::string m_AppVolPath;
364     typedef std::map<const std::string, CAppVolume> TCAppVolumes;
365     TCAppVolumes m_Volumes;
366 
367 public:
368     typedef TCAppVolumes::const_iterator TCAppVolumesCI;
369 
CApp(const std::string & root,const std::string & name,const std::string & type,const std::string & path)370     CApp(const std::string &root, const std::string &name,
371             const std::string &type, const std::string &path)
372         : m_HasVolume(false), m_AppVolPath("apps/" + name + "/volumes")
373     {
374         Update(root, name, type, path);
375     }
376     CApp(const CKDirectory &dir, const CKConfigNode &rep,
377             const std::string &root, const std::string &name);
378 
Update(const std::string & root,const std::string & name,const std::string & type,const std::string & path)379     void Update(const std::string &root, const std::string &name,
380         const std::string &type, const std::string &path)
381     {
382         m_Volumes[type] = CAppVolume(type, path);
383     }
Update(const CKDirectory & dir,const CKConfigNode & rep,const std::string & root,const std::string & name) const384     void Update(const CKDirectory &dir, const CKConfigNode &rep,
385         const std::string &root, const std::string &name) const
386     {
387         assert(0);
388     }
Update(CKConfig & kfg,const char * node,bool verbose=false) const389     rc_t Update(CKConfig &kfg, const char *node, bool verbose = false) const {
390         rc_t rc = 0;
391         for (TCAppVolumesCI it = m_Volumes.begin(); it != m_Volumes.end(); ++it)
392         {
393             rc_t r2 = (*it).second.Update(kfg, node, m_AppVolPath, verbose);
394             if (r2 != 0 && rc == 0) {
395                 rc = r2;
396             }
397         }
398         return rc;
399     }
Dump(const char * node) const400     void Dump(const char *node) const {
401         for (TCAppVolumesCI it = m_Volumes.begin(); it != m_Volumes.end(); ++it)
402         {
403             (*it).second.Dump(node, m_AppVolPath);
404         }
405     }
406 
VolumesBegin(void) const407     TCAppVolumesCI VolumesBegin(void) const { return m_Volumes.begin(); }
VolumesEnd(void) const408     TCAppVolumesCI VolumesEnd(void) const { return m_Volumes.end(); }
409 };
410 
411 class CApps : public std::map<const std::string, CApp*> {
412 public:
413     typedef std::map<const std::string, CApp*>::const_iterator TCI;
414     typedef std::map<const std::string, CApp*>::iterator TI;
415 
~CApps(void)416     ~CApps(void) {
417         for (TCI it = begin(); it != end(); ++it) {
418             delete((*it).second);
419         }
420     }
421 
Update(const CKDirectory & dir,const CKConfigNode & rep,const std::string & root,const std::string & name)422     void Update(const CKDirectory &dir, const CKConfigNode &rep,
423         const std::string &root, const std::string &name)
424     {
425         TCI it = find(name);
426         if (it == end()) {
427             insert(std::pair<const std::string, CApp*>
428                 (name, new CApp(dir, rep, root, name)));
429         }
430         else {
431             (*it).second->Update(dir, rep, root, name);
432         }
433     }
434 
Update(const std::string & root,const std::string & name,const std::string & type,const std::string & path)435     void Update(const std::string &root, const std::string &name,
436         const std::string &type, const std::string &path)
437     {
438         if (DEBUG) {
439             OUTMSG(("CApps.Update(%s)\n", name.c_str()));
440         }
441 
442         TI it = find(name);
443         if (it == end()) {
444             if (DEBUG) {
445                 OUTMSG(("CApps.Update(not found)\n"));
446             }
447             insert(std::pair<const std::string, CApp*>
448                 (name, new CApp(root, name, type, path)));
449         }
450         else {
451             if (DEBUG) {
452                 OUTMSG(("CApps.Update(found)\n"));
453             }
454             (*it).second->Update(root, name, type, path);
455         }
456     }
457 };
458 
459 class CRepository : CNoncopyable {
460     bool m_Disabled;
461     const std::string m_Category;    // user/site/remote
462     const std::string m_SubCategory; // main/aux/protected
463     const std::string m_Name;
464     std::string m_Root;
465     CApps m_Apps;
466 
RootExists(void) const467     bool RootExists(void) const { return m_Root.size() > 0; }
468 
469 protected:
470     CRepository(const std::string &category, const std::string &type,
471             const std::string &name, const std::string &root);
472     CRepository(const CKDirectory &dir, const CKConfigNode &repo,
473             const std::string &category, const std::string &subCategory,
474             const std::string &name);
475 
SetRoot(const std::string & root)476     void SetRoot(const std::string &root) { m_Root = root; }
FixFileVolume(void)477     void FixFileVolume(void)
478     {   m_Apps.Update(m_Root, "file", "flat", "files"); }
FixNakmerVolume(const std::string & name,const std::string & path)479     void FixNakmerVolume(const std::string &name,
480         const std::string &path)
481     {   m_Apps.Update(m_Root, "nakmer", name, path); }
FixNannotVolume(const std::string & name,const std::string & path)482     void FixNannotVolume(const std::string &name,
483         const std::string &path)
484     {   m_Apps.Update(m_Root, "nannot", name, path); }
FixRefseqVolume(void)485     void FixRefseqVolume(void)
486     {   m_Apps.Update(m_Root, "refseq", "refseq", "refseq"); }
FixRefseqVolume(const std::string & name,const std::string & path)487     void FixRefseqVolume(const std::string &name,
488         const std::string &path)
489     {   m_Apps.Update(m_Root, "sra", name, path); }
FixWgsVolume(const std::string & name)490     void FixWgsVolume(const std::string &name)
491     {   m_Apps.Update(m_Root, "wgs", name, "wgs"); }
492     rc_t Update(CKConfig &kfg, std::string &node, bool verbose = false);
493 
494 public:
ClearApps(void)495     void ClearApps(void) { m_Apps.clear(); }
496     virtual std::string Dump(void) const;
497     bool Is(const std::string &subCategory, const std::string &name = "")
498         const;
GetCategory(void) const499     std::string GetCategory(void) const { return m_Category; }
GetSubCategory(void) const500     std::string GetSubCategory(void) const { return m_SubCategory; }
GetName(void) const501     std::string GetName(void) const { return m_Name; }
GetRoot(void) const502     std::string GetRoot(void) const { return m_Root; }
Disable(bool disable)503     void Disable(bool disable) { m_Disabled = disable; }
504 
AppsBegin(void) const505     CApps::TCI AppsBegin(void) const { return m_Apps.begin(); }
AppsEnd(void) const506     CApps::TCI AppsEnd(void) const { return m_Apps.end(); }
507 };
508 
509 class CRemoteRepository : public CRepository {
510     std::string m_ResolverCgi;
511 
512     static bool EndsWith(const std::string &stack, char needle);
513     static std::string GetCgi(const std::string &stack, char needle);
514     static std::string GetRoot(const std::string &stack, char needle);
FixApps(void)515     void FixApps(void) {
516         FixNakmerVolume("fuseNAKMER", "sadb");
517         FixNannotVolume("fuseNANNOT", "sadb");
518         FixRefseqVolume();
519         FixRefseqVolume("fuse1000", "sra-instant/reads/ByRun/sra");
520         FixWgsVolume("fuseWGS");
521     }
Update(CKConfig & kfg,bool verbose=false)522     rc_t Update(CKConfig &kfg, bool verbose = false) {
523         std::string node;
524         rc_t rc = CRepository::Update(kfg, node, verbose);
525         if (rc != 0) {
526             return rc;
527         }
528         return kfg.UpdateNode(verbose,
529             m_ResolverCgi.c_str(), "%s/resolver-cgi", node.c_str());
530     }
531 
532 public:
CRemoteRepository(const CKDirectory & dir,const CKConfigNode & repo,const std::string & type,const std::string & name)533     CRemoteRepository(const CKDirectory &dir, const CKConfigNode &repo,
534             const std::string &type, const std::string &name)
535         : CRepository(dir, repo, "remote", type, name)
536         , m_ResolverCgi(repo.ReadString("resolver-cgi"))
537     {}
CRemoteRepository(const std::string & category,const std::string & name,const std::string & root)538     CRemoteRepository(const std::string &category,
539             const std::string &name, const std::string &root)
540         : CRepository("remote", category, name, GetRoot(root, 'i'))
541         , m_ResolverCgi(GetCgi(root, 'i'))
542     {
543         if (m_ResolverCgi.size() == 0) {
544             FixApps();
545         }
546     }
547 
Dump(void) const548     virtual std::string Dump(void) const {
549         std::string node(CRepository::Dump());
550         if (m_ResolverCgi.size() > 0) {
551             OUTMSG(("%s/resolver-cgi = \"%s\"\n",
552                 node.c_str(), m_ResolverCgi.c_str()));
553         }
554         return node;
555     }
556     rc_t Fix(CKConfig &kfg, bool disable, bool verbose = false);
557 };
558 
559 class CUserRepositories;
560 class CUserConfigData :  CNoncopyable {
561     std::string m_DefaultRoot;
562     std::string m_CurrentRoot;
563     bool m_CacheEnabled;
564 
565 public:
566     CUserConfigData(const CUserRepositories &repos, const CString &dflt);
567 
GetCurrentRoot(void) const568     std::string GetCurrentRoot(void) const { return m_CurrentRoot; }
GetDefaultRoot(void) const569     std::string GetDefaultRoot(void) const { return m_DefaultRoot; }
GetCacheEnabled(void) const570     bool GetCacheEnabled(void) const { return m_CacheEnabled; }
571 
SetCurrentRoot(const std::string & path)572     void SetCurrentRoot(const std::string &path) { m_CurrentRoot = path; }
SetCacheEnabled(bool enabled)573     void SetCacheEnabled(bool enabled) { m_CacheEnabled = enabled; }
574 };
575 
576 class CUserRepository : public CRepository {
577     bool m_CacheEnabled;
578 
FixApps(void)579     void FixApps(void) {
580         FixFileVolume();
581         FixNakmerVolume("nakmerFlat", "nannot");
582         FixNannotVolume("nannotFlat", "nannot");
583         FixRefseqVolume();
584         FixRefseqVolume("sraFlat", "sra");
585         FixWgsVolume("wgsFlat");
586     }
587     rc_t Fix(CKConfig &kfg,
588         const CUserConfigData *data, const std::string *root);
Update(CKConfig & kfg,bool verbose=false)589     rc_t Update(CKConfig &kfg, bool verbose = false) {
590         std::string node;
591         rc_t rc = CRepository::Update(kfg, node, verbose);
592         if (rc != 0) {
593             return rc;
594         }
595         return kfg.UpdateNode(verbose, m_CacheEnabled ? "true" : "false",
596             "%s/cache-enabled", node.c_str());
597     }
598 
599 public:
CUserRepository(const CKDirectory & dir,const CKConfigNode & repo,const std::string & type,const std::string & name)600     CUserRepository(const CKDirectory &dir, const CKConfigNode &repo,
601             const std::string &type, const std::string &name)
602         : CRepository(dir, repo, "user", type, name)
603         , m_CacheEnabled(repo.ReadBool("cache-enabled"))
604     {}
CUserRepository(const std::string & category,const std::string & name,const std::string & root)605     CUserRepository(const std::string &category,
606             const std::string &name, const std::string &root)
607         : CRepository("user", category, name, root), m_CacheEnabled(true)
608     {
609         FixApps();
610     }
611 
Dump(void) const612     virtual std::string Dump(void) const {
613         const std::string node(CRepository::Dump());
614         OUTMSG(("%s/cache-enabled = \"%s\"\n", node.c_str(),
615             m_CacheEnabled ? "true" : "false"));
616         return node;
617     }
618 
IsCacheEnabled(void) const619     bool IsCacheEnabled(void) const { return m_CacheEnabled; }
Fix(CKConfig & kfg,const std::string & root)620     void Fix(CKConfig &kfg, const std::string &root) { Fix(kfg, NULL, &root); }
Fix(CKConfig & kfg,const CUserConfigData * data)621     void Fix(CKConfig &kfg, const CUserConfigData *data) {
622         Fix(kfg, data, NULL);
623     }
624 };
625 
626 class CUserRepositories : std::vector<CUserRepository*> {
627     typedef std::vector<CUserRepository*>::const_iterator TCI;
628     typedef std::vector<CUserRepository*>::iterator TI;
629     const CUserRepository *FindMainPublic(void) const;
630 
631 public:
~CUserRepositories(void)632     ~CUserRepositories(void) {
633         for (TCI it = begin(); it != end(); ++it) {
634             free(*it);
635         }
636     }
637 
638     rc_t Load(const CKConfig &kfg, const CKDirectory &dir);
GetMainPublicRoot(void) const639     std::string GetMainPublicRoot(void) const {
640         const CUserRepository *r = FindMainPublic();
641         if (r == NULL) {
642             return "";
643         }
644         return r->GetRoot();
645     }
IsMainPublicCacheEnabled(void) const646     bool IsMainPublicCacheEnabled(void) const {
647         const CUserRepository *r = FindMainPublic();
648         if (r == NULL) {
649             return true;
650         }
651         return r->IsCacheEnabled();
652     }
Fix(CKConfig & kfg,const CUserConfigData & data)653     void Fix(CKConfig &kfg, const CUserConfigData &data) {
654         bool publicMainFound = false;
655         for (TI it = begin(); it != end(); ++it) {
656             CUserRepository *r = *it;
657             assert(r);
658             if (r->Is("main", "public")) {
659                 r->Fix(kfg, &data);
660                 publicMainFound = true;
661             }
662             else {
663                 r->Fix(kfg, data.GetDefaultRoot());
664             }
665         }
666         if (!publicMainFound) {
667             CUserRepository *r = new CUserRepository("main", "public", "");
668             r->Fix(kfg, &data);
669             push_back(r);
670         }
671     }
672     rc_t MkAppVolumes(const CKDirectory &dir, bool verbose = false)
673         const;
674 };
675 
676 class CRemoteRepositories : std::vector<CRemoteRepository*> {
677     typedef std::vector<CRemoteRepository*>::const_iterator TCI;
678 
679 public:
~CRemoteRepositories(void)680     ~CRemoteRepositories(void) {
681         for (TCI it = begin(); it != end(); ++it) { free(*it); }
682     }
683 
684     rc_t Load(const CKConfig &kfg, const CKDirectory &dir);
685 
IsDisabled(void) const686     bool IsDisabled(void) const { return false; }
687     void Fix(CKConfig &kfg, bool disable, bool verbose = false);
688 };
689 
690 
691 #endif // _hpp_tools_vdb_config_util_
692