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 #include <sra/extern.h>
28 
29 #include <klib/namelist.h>
30 #include <klib/refcount.h>
31 #include <klib/log.h>
32 #include <klib/rc.h>
33 #include <kfs/directory.h>
34 #include <kfg/config.h>
35 #include <vfs/manager.h>
36 #include <vfs/resolver.h>
37 #include <vfs/path.h>
38 #include <kdb/manager.h>
39 #include <kdb/kdb-priv.h>
40 #include <vdb/manager.h>
41 #include <vdb/schema.h>
42 #include <vdb/vdb-priv.h>
43 #include <sra/sradb.h>
44 #include <sra/sraschema.h>
45 #include <sra/srapath.h>
46 #include <sra/sradb-priv.h>
47 #include <sysalloc.h>
48 #include <atomic.h>
49 
50 #include "sra-priv.h"
51 
52 #include <stdlib.h>
53 #include <stdarg.h>
54 #include <string.h>
55 #include <assert.h>
56 
57 
58 /* Whack
59  *  will not refuse request, and ignores errors
60  */
61 static
SRAMgrWhack(const SRAMgr * that)62 rc_t SRAMgrWhack ( const SRAMgr *that )
63 {
64     SRAMgr *self = ( SRAMgr* ) that;
65 
66     VSchemaRelease ( self -> schema );
67     VDBManagerRelease ( self -> vmgr );
68     SRACacheWhack ( self -> cache );
69 
70     /* must check here for NULL because
71        SRAPathRelease is weak-linked */
72     if ( self -> _pmgr != NULL )
73     {
74 #if OLD_SRAPATH_MGR
75         SRAPathRelease ( self -> _pmgr );
76 #else
77         VResolverRelease ( ( const VResolver* ) self -> _pmgr );
78 #endif
79     }
80 
81     free ( self );
82     return 0;
83 }
84 
85 
86 /* Release
87  *  releases reference to object
88  *  obtained from MakeRead, MakeUpdate,
89  *  or AddRef(see above)
90  */
SRAMgrRelease(const SRAMgr * self)91 LIB_EXPORT rc_t CC SRAMgrRelease ( const SRAMgr *self )
92 {
93     if ( self != NULL )
94     {
95         switch ( KRefcountDrop ( & self -> refcount, "SRAMgr" ) )
96         {
97         case krefWhack:
98             return SRAMgrWhack ( ( SRAMgr* ) self );
99         case krefNegative:
100             return RC ( rcSRA, rcMgr, rcReleasing, rcRange, rcExcessive );
101         }
102     }
103     return 0;
104 }
105 
106 
107 /* AddRef
108  *  attach a new reference to an existing object
109  *  ( see above)
110  */
SRAMgrAddRef(const SRAMgr * self)111 LIB_EXPORT rc_t CC SRAMgrAddRef ( const SRAMgr *self )
112 {
113     if ( self != NULL )
114     {
115         switch ( KRefcountAdd ( & self -> refcount, "SRAMgr" ) )
116         {
117         case krefLimit:
118             return RC ( rcSRA, rcMgr, rcAttaching, rcRange, rcExcessive );
119         }
120     }
121     return 0;
122 }
123 
124 /* Attach
125  * Sever
126  */
SRAMgrAttach(const SRAMgr * self)127 SRAMgr *SRAMgrAttach ( const SRAMgr *self )
128 {
129     if ( self != NULL )
130     {
131         switch ( KRefcountAddDep ( & self -> refcount, "SRAMgr" ) )
132         {
133         case krefLimit:
134             return NULL;
135         }
136     }
137     return ( SRAMgr* ) self;
138 }
139 
SRAMgrSever(const SRAMgr * self)140 rc_t SRAMgrSever ( const SRAMgr *self )
141 {
142     if ( self != NULL )
143     {
144         switch ( KRefcountDropDep ( & self -> refcount, "SRAMgr" ) )
145         {
146         case krefWhack:
147             return SRAMgrWhack ( ( SRAMgr* ) self );
148         case krefNegative:
149             return RC ( rcSRA, rcMgr, rcReleasing, rcRange, rcExcessive );
150         }
151     }
152     return 0;
153 }
154 
155 
156 /* Make
157  */
158 static
SRAMgrInitPath(SRAMgr * mgr,KConfig * kfg,const KDirectory * wd)159 rc_t SRAMgrInitPath ( SRAMgr *mgr, KConfig *kfg, const KDirectory *wd )
160 {
161     VFSManager *vfs;
162     rc_t rc = VFSManagerMake ( & vfs );
163     if ( rc == 0 )
164     {
165         rc = VFSManagerMakeResolver ( vfs, ( VResolver** ) & mgr -> _pmgr, kfg );
166         VFSManagerRelease ( vfs );
167     }
168 
169     if ( rc != 0 )
170         mgr -> _pmgr = NULL;
171 
172     return 0;
173 }
174 
SRAMgrMake(SRAMgr ** mgrp,const VDBManager * vmgr,const KDirectory * wd)175 rc_t SRAMgrMake ( SRAMgr **mgrp,
176     const VDBManager *vmgr, const KDirectory *wd )
177 {
178     rc_t rc;
179 
180     /* require sraschema object */
181     SRAMgr *mgr = malloc ( sizeof * mgr );
182     if ( mgr == NULL )
183         rc = RC ( rcSRA, rcMgr, rcConstructing, rcMemory, rcExhausted );
184     else
185     {
186         VSchema *schema;
187         rc = VDBManagerMakeSRASchema ( vmgr, & schema );
188         if ( rc == 0 )
189         {
190             KConfig* kfg;
191             rc = KConfigMake ( & kfg, wd );
192             if ( rc == 0 )
193             {
194                 rc = SRAMgrInitPath ( mgr, kfg, wd );
195                 if ( rc == 0 )
196                 {
197                     rc = SRACacheInit ( & mgr -> cache, kfg );
198                     if ( rc == 0 )
199                     {
200                         KRefcountInit ( & mgr -> refcount, 1, "SRAMgr", "SRAMgrMake", "sramgr" );
201                         mgr -> vmgr = vmgr;
202                         mgr -> schema = schema;
203                         mgr -> mode = kcmCreate; /* TBD - should this include parents? */
204                         mgr -> read_only = true;
205                         * mgrp = mgr;
206                         KConfigRelease ( kfg );
207                         return 0;
208                     }
209                 }
210                 KConfigRelease ( kfg );
211             }
212 
213             VSchemaRelease ( schema );
214         }
215 
216         free ( mgr );
217     }
218 
219     * mgrp = NULL;
220     return rc;
221 }
222 
223 
224 /* Writable
225  *  returns 0 if table is writable
226  *  rcLocked if locked, rcReadonly if read-only
227  *  other code upon error
228  *
229  *  "path" [ IN ] - NUL terminated table path
230  */
SRAMgrVWritable(const SRAMgr * self,const char * path,va_list args)231 LIB_EXPORT rc_t CC SRAMgrVWritable ( const SRAMgr *self,
232         const char *path, va_list args )
233 {
234     if ( self == NULL )
235         return RC ( rcSRA, rcMgr, rcAccessing, rcSelf, rcNull );
236     return VDBManagerVWritable ( self -> vmgr, path, args );
237 }
238 
SRAMgrWritable(const SRAMgr * self,const char * path,...)239 LIB_EXPORT rc_t CC SRAMgrWritable ( const SRAMgr *self,
240         const char *path, ... )
241 {
242     rc_t rc;
243 
244     va_list args;
245     va_start ( args, path );
246 
247     rc = SRAMgrVWritable ( self, path, args );
248 
249     va_end ( args );
250 
251     return rc;
252 }
253 
SRAMgrResolve(const SRAMgr * self,const char * acc,char * buf,size_t buf_size)254 LIB_EXPORT rc_t CC SRAMgrResolve( const SRAMgr *self, const char* acc, char* buf, size_t buf_size )
255 {
256     if ( self == NULL )
257         return RC ( rcSRA, rcMgr, rcResolving, rcSelf, rcNull );
258     if ( acc == NULL || buf == NULL)
259         return RC ( rcSRA, rcMgr, rcResolving, rcParam, rcNull );
260     else
261     {
262         VFSManager *vfs;
263         rc_t rc = VFSManagerMake ( & vfs );
264         if (rc == 0)
265         {
266 			rc_t rc2;
267             VPath* path;
268             rc = VFSManagerMakePath(vfs, &path, "ncbi-acc:%s", acc);
269             if (rc == 0)
270             {
271                 const VPath* resolved;
272                 rc = VResolverQuery ( (const struct VResolver*)self->_pmgr, 0, path, &resolved, NULL, NULL );
273                 if (rc == 0)
274                 {
275                     rc = VPathReadPath ( resolved, buf, buf_size, NULL );
276                     rc2 = VPathRelease(resolved);
277                     if (rc == 0)
278                         rc = rc2;
279                 }
280 
281                 rc2 = VPathRelease(path);
282                 if (rc == 0)
283                     rc = rc2;
284             }
285             rc2 = VFSManagerRelease(vfs);
286             if (rc == 0)
287                 rc = rc2;
288         }
289 
290         return rc;
291     }
292 }
293 
SRAMgrConfigReload(const SRAMgr * cself,const KDirectory * wd)294 LIB_EXPORT rc_t CC SRAMgrConfigReload( const SRAMgr *cself, const KDirectory *wd )
295 {
296 #if OLD_SRAPATH_MGR
297     SRAMgr *self = cself;
298 
299     /* create a new SRAPath object */
300     SRAPath *pnew;
301     rc_t rc = SRAPathMake ( & pnew, wd );
302     if ( rc == 0 )
303     {
304         /* swap with the old guy */
305         SRAPath *pold = self -> _pmgr;
306         if ( atomic_test_and_set_ptr ( ( void *volatile* ) & self -> _pmgr, pnew, pold ) == ( void* ) pold )
307             SRAPathRelease ( pold );
308         else
309             SRAPathRelease ( pnew );
310     }
311 
312     return rc;
313 #else
314     return 0;
315 #endif
316 
317 #if 0
318 
319 
320     /* do not reload VDBManager config for now
321        it cannot reload properly and grows in memory */
322     rc_t rc = 0;
323     /* (not thread) safely re-instanciate sra path config */
324     SRAMgr *self = (SRAMgr*)cself;
325     SRAPath* p = cself->_pmgr;
326     self->_pmgr = NULL;
327     if( (rc = SRAMgrInitPath(self, wd)) == 0 ) {
328         SRAPathRelease(p);
329     } else {
330         /* roll back */
331         self->_pmgr = p;
332     }
333     return rc;
334 #endif
335 
336 }
337 
338 /* GetVDBManager
339  *  returns a new reference to VDBManager used by SRAMgr
340  */
SRAMgrGetVDBManagerRead(const SRAMgr * self,const VDBManager ** vmgr)341 LIB_EXPORT rc_t CC SRAMgrGetVDBManagerRead ( const SRAMgr *self, const VDBManager **vmgr )
342 {
343     rc_t rc;
344 
345     if ( vmgr == NULL )
346         rc = RC ( rcSRA, rcMgr, rcAccessing, rcParam, rcNull );
347     else
348     {
349         if ( self == NULL )
350             rc = RC ( rcSRA, rcMgr, rcAccessing, rcSelf, rcNull );
351         else
352         {
353             * vmgr = self -> vmgr;
354             return VDBManagerAddRef ( * vmgr );
355         }
356 
357         * vmgr = NULL;
358     }
359 
360     return rc;
361 }
362 
363 /* GetKDBManager
364  *  returns a new reference to KDBManager used indirectly by SRAMgr
365  */
SRAMgrGetKDBManagerRead(const SRAMgr * self,struct KDBManager const ** kmgr)366 LIB_EXPORT rc_t CC SRAMgrGetKDBManagerRead ( const SRAMgr *self,
367         struct KDBManager const **kmgr )
368 {
369     rc_t rc;
370 
371     if ( kmgr == NULL )
372         rc = RC ( rcSRA, rcMgr, rcAccessing, rcParam, rcNull );
373     else
374     {
375         if ( self == NULL )
376             rc = RC ( rcSRA, rcMgr, rcAccessing, rcSelf, rcNull );
377         else
378         {
379             return VDBManagerGetKDBManagerRead ( self -> vmgr, kmgr );
380         }
381 
382         * kmgr = NULL;
383     }
384 
385     return rc;
386 }
387 
388 
389 /* ModDate
390  *  return a modification timestamp for table
391  */
SRAMgrVGetTableModDate(const SRAMgr * self,KTime_t * mtime,const char * spec,va_list args)392 LIB_EXPORT rc_t CC SRAMgrVGetTableModDate ( const SRAMgr *self,
393     KTime_t *mtime, const char *spec, va_list args )
394 {
395     rc_t rc;
396 
397     if ( mtime == NULL )
398         rc = RC ( rcSRA, rcMgr, rcAccessing, rcParam, rcNull );
399     else
400     {
401         * mtime = 0;
402         if ( self == NULL )
403             rc = RC ( rcSRA, rcMgr, rcAccessing, rcSelf, rcNull );
404         else
405         {
406             char path[4096];
407             rc = ResolveTablePath(self, path, sizeof path, spec, args);
408             if( rc == 0 ) {
409                 struct KDBManager const *kmgr;
410                 rc = VDBManagerGetKDBManagerRead ( self -> vmgr, & kmgr );
411                 if ( rc == 0 )
412                 {
413                     rc = KDBManagerGetTableModDate(kmgr, mtime, "%s", path);
414                     KDBManagerRelease ( kmgr );
415                 }
416             }
417         }
418     }
419 
420     return rc;
421 }
422 
SRAMgrGetTableModDate(const SRAMgr * self,KTime_t * mtime,const char * spec,...)423 LIB_EXPORT rc_t CC SRAMgrGetTableModDate ( const SRAMgr *self,
424     KTime_t *mtime, const char *spec, ... )
425 {
426     rc_t rc;
427 
428     va_list args;
429     va_start ( args, spec );
430     rc = SRAMgrVGetTableModDate ( self, mtime, spec, args );
431     va_end ( args );
432 
433     return rc;
434 }
435 
SRAMgrSingleFileArchiveExt(const SRAMgr * self,const char * spec,const bool lightweight,const char ** ext)436 LIB_EXPORT rc_t CC SRAMgrSingleFileArchiveExt(const SRAMgr *self, const char* spec, const bool lightweight, const char** ext)
437 {
438     rc_t rc;
439 
440     if( self == NULL || spec == NULL || ext == NULL ) {
441         rc = RC(rcSRA, rcFile, rcConstructing, rcParam, rcNull);
442     } else {
443         char buf[4096];
444         va_list args;
445 
446         if( (rc = ResolveTablePath(self, buf, sizeof(buf), spec, args)) == 0 ) {
447             const KDBManager* kmgr;
448             if( (rc = SRAMgrGetKDBManagerRead(self, &kmgr)) == 0 ) {
449                 int type = KDBManagerPathType(kmgr, "%s", buf) & ~kptAlias;
450                 if( type == kptDatabase ) {
451                     *ext = CSRA_EXT(lightweight);
452                 } else if( type == kptTable ) {
453                     *ext = SRA_EXT(lightweight);
454                 } else {
455                     rc = RC(rcSRA, rcPath, rcResolving, rcType, rcUnknown);
456                 }
457                 KDBManagerRelease(kmgr);
458             }
459         }
460     }
461     return rc;
462 }
463 
464 /*
465  * FlushPath
466  * FlushRun
467  * RunBGTasks
468  *  stubbed functions to manipulate a cache, if implemented
469  */
SRAMgrGetCacheUsage(const SRAMgr * self,struct SRACacheUsage * stats)470 LIB_EXPORT rc_t CC SRAMgrGetCacheUsage( const SRAMgr *self, struct SRACacheUsage* stats )
471 {
472     rc_t rc = 0;
473     if ( self == NULL || stats == NULL || self->cache == NULL)
474         rc = RC(rcSRA, rcMgr, rcAccessing, rcParam, rcNull);
475     else
476         rc = SRACacheGetUsage(self->cache, stats);
477     return rc;
478 }
479 
SRAMgrFlush(struct SRAMgr const * self,const struct SRACacheMetrics * thr)480 LIB_EXPORT rc_t CC SRAMgrFlush ( struct SRAMgr const *self, const struct SRACacheMetrics* thr )
481 {
482     rc_t rc = 0;
483     if( self == NULL  || self->cache == NULL)
484         rc = RC(rcSRA, rcFile, rcProcessing, rcSelf, rcNull);
485     else if( thr == NULL )
486         rc = RC(rcSRA, rcFile, rcProcessing, rcParam, rcNull);
487     else
488     {
489         SRACacheMetrics saved;
490         rc = SRACacheGetSoftThreshold(self->cache, &saved);
491         if (rc == 0)
492         {
493             rc = SRACacheSetSoftThreshold(self->cache, thr);
494             if (rc == 0)
495             {
496                 rc_t rc2;
497                 rc = SRACacheFlush(self->cache);
498                 rc2 = SRACacheSetSoftThreshold(self->cache, &saved);
499                 if (rc == 0)
500                     rc = rc2;
501             }
502         }
503     }
504     return rc;
505 }
506 
SRAMgrRunBGTasks(const SRAMgr * self)507 LIB_EXPORT rc_t CC SRAMgrRunBGTasks ( const SRAMgr *self )
508 {
509     rc_t rc;
510 
511     if( self == NULL  )
512         rc = RC(rcSRA, rcMgr, rcProcessing, rcSelf, rcNull);
513 
514     rc = SRACacheFlush(self->cache);
515 
516     return rc;
517 }
518 
SRAMgrConfigureCache(const SRAMgr * self,int32_t soft_threshold,int32_t hard_threshold)519 LIB_EXPORT rc_t CC SRAMgrConfigureCache( const SRAMgr *self,  int32_t soft_threshold, int32_t hard_threshold )
520 {
521     rc_t rc = 0;
522     if( self == NULL  || self->cache == NULL)
523         rc = RC(rcSRA, rcFile, rcProcessing, rcSelf, rcNull);
524     else if( soft_threshold < -1  || hard_threshold < -1 )
525         rc = RC(rcSRA, rcFile, rcProcessing, rcParam, rcNull);
526     else
527     {
528         if ( soft_threshold > -1 )
529         {
530             SRACacheMetrics metrics;
531             memset(&metrics, 0, sizeof(metrics));
532             metrics.elements = soft_threshold;
533             rc = SRACacheSetSoftThreshold(self->cache, &metrics);
534         }
535         if ( rc == 0 && hard_threshold > -1 )
536         {
537             SRACacheMetrics metrics;
538             memset(&metrics, 0, sizeof(metrics));
539             metrics.elements = hard_threshold;
540             rc = SRACacheSetHardThreshold(self->cache, &metrics);
541         }
542         /* if a new threshold is low enough to cause a flush, do it right away */
543         rc = SRACacheFlush(self->cache);
544     }
545     return rc;
546 }
547 
548 /*--------------------------------------------------------------------------
549  * SRANamelist
550  *  redirecting functions
551  */
552 
553 
SRANamelistAddRef(const SRANamelist * self)554 LIB_EXPORT rc_t CC SRANamelistAddRef ( const SRANamelist *self )
555 {
556     return KNamelistAddRef ( ( const KNamelist* ) self );
557 }
558 
SRANamelistRelease(const SRANamelist * self)559 LIB_EXPORT rc_t CC SRANamelistRelease ( const SRANamelist *self )
560 {
561     return KNamelistRelease ( ( const KNamelist* ) self );
562 }
563 
SRANamelistCount(const SRANamelist * self,uint32_t * count)564 LIB_EXPORT rc_t CC SRANamelistCount ( const SRANamelist *self, uint32_t *count )
565 {
566     return KNamelistCount ( ( const KNamelist* ) self, count );
567 }
568 
SRANamelistGet(const SRANamelist * self,uint32_t idx,const char ** name)569 LIB_EXPORT rc_t CC SRANamelistGet ( const SRANamelist *self, uint32_t idx, const char **name )
570 {
571     return KNamelistGet ( ( const KNamelist* ) self, idx, name );
572 }
573 
574 /*--------------------------------------------------------------------------
575  * SRASchema - DEPRECATED
576  */
577 
SRASchemaMake(struct VSchema ** schema,struct VDBManager const * mgr)578 LIB_EXPORT rc_t CC SRASchemaMake ( struct VSchema **schema, struct VDBManager const *mgr )
579 {
580     if ( schema )
581     {
582         *schema = NULL;
583     }
584     return 0;
585 }
586