1 /*==============================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 // helper.h
28 #include <exception>
29 #include <string.h>
30 
31 #include <stdint.h>
32 
33 #include <vdb/manager.h>
34 #include <vdb/schema.h>
35 #include <vdb/database.h>
36 #include <vdb/table.h>
37 #include <vdb/cursor.h>
38 #include <klib/printf.h>
39 #include <klib/vector.h>
40 #include <kapp/args.h>
41 #include <kapp/progressbar.h>
42 #include <kapp/log-xml.h>
43 
44 
45 #ifndef countof
46 #define countof(arr) (sizeof(arr)/sizeof(arr[0]))
47 #endif
48 
49 #ifdef _WIN32
50 #pragma warning (disable:4503)
51 #endif
52 
53 #define USING_UINT64_BITMAP 0
54 #define MANAGER_WRITABLE 1
55 #define DEBUG_PRINT 0
56 
57 namespace KLib
58 {
59     class CKVector
60     {
61     public:
62         CKVector();
63         CKVector (CKVector const& x);
64         CKVector& operator= (CKVector const& x);
65         ~CKVector();
66 
67         void SetBool (uint64_t key, bool value);
68         void VisitBool (rc_t ( * f ) ( uint64_t key, bool value, void *user_data ), void *user_data) const;
69 
70     private:
71         void Make();
72         void Release();
73 
74         ::KVector* m_pSelf;
75     };
76 }
77 
78 namespace Utils
79 {
80     class CErrorMsg : public std::exception
81     {
82     public:
83         CErrorMsg(rc_t rc, char const* fmt_str, ...);
84 
85         rc_t getRC() const;
86         virtual char const* what() const throw();
87 
88     private:
89         char m_szDescr[256];
90         rc_t m_rc;
91     };
92 
atoi_t(char const * str_val)93     template <typename T> T atoi_t ( char const* str_val )
94     {
95         if ( str_val [0] == '\0' )
96             throw Utils::CErrorMsg(0, "atoi_t: invalid input string (empty)");
97 
98         size_t i = 0;
99         char sign = '+';
100         if ( str_val[0] == '-' || str_val[0] == '+' )
101         {
102             ++i;
103             sign = str_val[0];
104         }
105 
106         T ret = 0;
107         for (; str_val[i] != '\0'; ++i )
108         {
109             if ( str_val[i] < '0' || str_val[i] > '9' )
110                 throw Utils::CErrorMsg(0, "atoi_t: invalid input string \"%s\" (invalid character: '%c' at pos=%zu)", str_val, str_val[i], i+1);
111             ret = ret*10 + str_val[i] - '0';
112         }
113 
114         return sign == '-' ? -ret : ret;
115     }
116 
atou_t(char const * str_val)117     template <typename T> T atou_t ( char const* str_val )
118     {
119         if ( str_val [0] == '\0' )
120             throw Utils::CErrorMsg(0, "atou_t: invalid input string (empty)");
121 
122         T ret = 0;
123         for ( size_t i = 0; str_val[i] != '\0'; ++i )
124         {
125             if ( str_val[i] < '0' || str_val[i] > '9' )
126                 throw Utils::CErrorMsg(0, "atoi_t: invalid input string \"%s\" (invalid character: '%c' at pos=%zu)", str_val, str_val[i], i+1);
127             ret = ret*10 + str_val[i] - '0';
128         }
129 
130         return ret;
131     }
132 
133     enum ErrorHandlerCode
134     {
135         rcUnknown     = -2,
136         rcErrorStdExc = -1,
137         rcInvalid     = -99
138         // value > 0 means rc_t returned from a VDB-function
139         // zero shall not be returned
140     };
141 
142     // This function must be called inside catch block only
143     // if bSilent == true then produce no output, only return ErrorHandlerCode
144     // pErrDesc and sizeErrDesc - the buffer to write error description to (NULL - OK)
145     int64_t HandleException ( bool bSilent, char* pErrDesc, size_t sizeErrDesc );
146 }
147 
148 namespace VDBObjects
149 {
150     /* functor to remove trailing '\n' from char reads */
151     template<typename T> class CPostReadAction
152     {
153         T* m_pBuf;
154         uint32_t m_nCount;
155     public:
CPostReadAction(T * pBuf,uint32_t nCount)156         CPostReadAction(T* pBuf, uint32_t nCount) : m_pBuf(pBuf), m_nCount(nCount) {}
157         void operator()() const;
158     };
operator()159     template<typename T> inline void CPostReadAction<T>::operator()() const {}
operator()160     template<> inline void CPostReadAction<char>::operator()() const { m_pBuf[m_nCount] = '\0'; }
operator()161     template<> inline void CPostReadAction<unsigned char>::operator()() const { m_pBuf[m_nCount] = '\0'; }
162 
163     class CVCursor;
164     class CVTable;
165     class CVDatabase;
166     class CVSchema;
167 
168 /////////////////////////////////////////////////////////////////////////////////
169 
170     class CVDBManager
171     {
172     public:
173         CVDBManager();
174         ~CVDBManager();
175         CVDBManager(CVDBManager const& x);
176         CVDBManager& operator=(CVDBManager const& x);
177 
178         void Make();
179         void Release();
180         CVDatabase OpenDB ( char const* pszDBName ) const;
181         CVDatabase CreateDB ( CVSchema const& schema, char const* pszTypeDesc, ::KCreateMode cmode, char const* pszPath );
182         CVSchema MakeSchema () const;
183 
184     private:
185         ::VDBManager* m_pSelf;
186     };
187 
188 /////////////////////////////////////////////////////////////////////////////////
189 
190     class CVSchema
191     {
192     public:
193         friend CVSchema CVDBManager::MakeSchema () const;
194         friend CVDatabase CVDBManager::CreateDB ( CVSchema const& schema, char const* pszTypeDesc, ::KCreateMode cmode, char const* pszPath );
195 
196         CVSchema();
197         ~CVSchema();
198         CVSchema(CVSchema const& x);
199         CVSchema& operator=(CVSchema const& x);
200 
201         void Make();
202         void Release();
203         void VSchemaParseFile(char const* pszFilePath);
204 
205     private:
206         void Clone ( CVSchema const& x );
207         ::VSchema* m_pSelf;
208     };
209 
210 /////////////////////////////////////////////////////////////////////////////////
211 
212     class CVDatabase
213     {
214     public:
215         friend CVDatabase CVDBManager::OpenDB ( char const* pszDBName ) const;
216         friend CVDatabase CVDBManager::CreateDB ( CVSchema const& schema, char const* pszTypeDesc, ::KCreateMode cmode, char const* pszPath );
217 
218         CVDatabase();
219         ~CVDatabase();
220         CVDatabase(CVDatabase const& x);
221         CVDatabase& operator=(CVDatabase const& x);
222 
223         void Release();
224         CVTable OpenTable ( char const* pszTableName ) const;
225         CVTable CreateTable ( char const* pszTableName );
226         void ColumnCreateParams ( ::KCreateMode cmode, ::KChecksum checksum, size_t pgsize );
227 
228     private:
229         void Clone(CVDatabase const& x);
230         ::VDatabase* m_pSelf;
231     };
232 
233 //////////////////////////////////////////////////////////////
234 
235     class CVTable
236     {
237     public:
238         friend CVTable CVDatabase::OpenTable(char const* pszTableName) const;
239         friend CVTable CVDatabase::CreateTable ( char const* pszTableName );
240 
241         CVTable();
242         ~CVTable();
243         CVTable(CVTable const& x);
244         CVTable& operator=(CVTable const& x);
245 
246         void Release();
247         CVCursor CreateCursorRead ( size_t cache_size ) const;
248         CVCursor CreateCursorWrite ( ::KCreateMode mode );
249 
250     private:
251         void Clone(CVTable const& x);
252         ::VTable* m_pSelf;
253     };
254 
255 ////////////////////////////////////////////////////////////////////////////
256 
257     class CVCursor
258     {
259     public:
260         friend CVCursor CVTable::CreateCursorRead ( size_t cache_size ) const;
261         friend CVCursor CVTable::CreateCursorWrite (::KCreateMode mode);
262 
263         CVCursor();
264         ~CVCursor();
265         CVCursor(CVCursor const& x);
266         CVCursor& operator=(CVCursor const& x);
267 
268         void Release();
269         void PermitPostOpenAdd() const;
270 #if MANAGER_WRITABLE != 0
271         void InitColumnIndex(char const* const* ColumnNames, uint32_t* pColumnIndex, size_t nCount, bool set_default);
272 #else
273         void InitColumnIndex(char const* const* ColumnNames, uint32_t* pColumnIndex, size_t nCount);
274 #endif
275         void Open() const;
276         void GetIdRange(int64_t& idFirstRow, uint64_t& nRowCount) const;
277 
ReadItems(int64_t idRow,uint32_t idxCol,T * pBuf,uint32_t nBufLen)278         template <typename T> uint32_t ReadItems (int64_t idRow, uint32_t idxCol, T* pBuf, uint32_t nBufLen) const
279         {
280             uint32_t nItemsRead = 0;
281 
282             rc_t rc = ::VCursorReadDirect(m_pSelf, idRow, idxCol, 8*sizeof(T), pBuf, nBufLen, &nItemsRead);
283             if (rc)
284                 throw Utils::CErrorMsg(rc, "VCursorReadDirect: row_id=%ld, idxCol=%u", idRow, idxCol);
285 
286             //CPostReadAction<T>(pBuf, nItemsRead)();
287 
288             return nItemsRead;
289         }
290 
Write(uint32_t idxCol,T const * pBuf,uint64_t count)291         template <typename T> void Write (uint32_t idxCol, T const* pBuf, uint64_t count)
292         {
293             rc_t rc = ::VCursorWrite ( m_pSelf, idxCol, 8 * sizeof(T), pBuf, 0, count );
294             if (rc)
295                 throw Utils::CErrorMsg(rc, "VCursorWrite: idxCol=%u", idxCol);
296         }
297 
298         int64_t GetRowId () const;
299         void SetRowId (int64_t row_id) const;
300         void OpenRow () const;
301         void CommitRow ();
302         void RepeatRow ( uint64_t count );
303         void CloseRow () const;
304         void Commit ();
305 
306     private:
307         void Clone(CVCursor const& x);
308         ::VCursor* m_pSelf;
309     };
310 }
311 
312 ///////////////////////
313 
314 namespace KApp
315 {
316     class CArgs;
317     class CXMLLogger
318     {
319     public:
320         CXMLLogger ( CArgs const& args );
321         CXMLLogger (CXMLLogger const& x);
322         CXMLLogger& operator= (CXMLLogger const& x);
323         ~CXMLLogger ();
324 
325         void Make ( CArgs const& args );
326 
327     private:
328         void Release ();
329 
330         XMLLogger const* m_pSelf;
331     };
332 
333 /////////////////////////////////////////
334 
335     class CArgs
336     {
337     public:
338         friend void CXMLLogger::Make ( CArgs const& args );
339 
340         CArgs ( int argc, char** argv, ::OptDef const* pOptions, size_t option_count );
341         CArgs ( int argc, char** argv, ::OptDef const* pOptions1, size_t option_count1, ::OptDef const* pOptions2, size_t option_count2 );
342         CArgs ( CArgs const& x );
343         CArgs& operator= ( CArgs const& x );
344         ~CArgs ();
345 
346         ::Args const* GetArgs () const;
347         uint32_t GetParamCount () const;
348         char const* GetParamValue ( uint32_t iteration ) const;
349         uint32_t GetOptionCount ( char const* option_name ) const;
350         char const* GetOptionValue ( char const* option_name, uint32_t iteration ) const;
351 
GetOptionValueInt(char const * option_name,uint32_t iteration)352         template <typename T> T GetOptionValueInt ( char const* option_name, uint32_t iteration ) const
353         {
354             char const* str_val = GetOptionValue ( option_name, iteration );
355             return Utils::atoi_t <T> ( str_val );
356         }
GetOptionValueUInt(char const * option_name,uint32_t iteration)357         template <typename T> T GetOptionValueUInt ( char const* option_name, uint32_t iteration ) const
358         {
359             char const* str_val = GetOptionValue ( option_name, iteration );
360             return Utils::atou_t <T> ( str_val );
361         }
362 
363     private:
364 
365         void MakeAndHandle ( int argc, char** argv, ::OptDef const* pOptions, size_t option_count );
366         // TODO: it's better to make ::ArgsMakeAndHandle be able to take va_list
367         void MakeAndHandle ( int argc, char** argv, ::OptDef const* pOptions1, size_t option_count1, ::OptDef const* pOptions2, size_t option_count2 );
368         void Release ();
369 
370         ::Args* m_pSelf;
371     };
372 
373     class CProgressBar
374     {
375     public:
376         CProgressBar ( uint64_t size );
377         CProgressBar ( CProgressBar const& x );
378         CProgressBar& operator= ( CProgressBar const& x );
379         ~CProgressBar ();
380 
381         void Append ( uint64_t chunk );
382         void Process ( uint64_t chunk, bool force_report );
383 
384     private:
385         void Make ( uint64_t size );
386         void Release ();
387 
388         KLoadProgressbar const* m_pSelf;
389     };
390 }
391