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 <sra/sradb.h>
30 #include <sra/srapath.h>
31 #include <sra/types.h>
32 #include <sra/sraschema.h>
33 #include <sra/sradb-priv.h>
34 #include <vdb/database.h>
35 #include <vdb/schema.h>
36 #include <vdb/table.h>
37 #include <vdb/cursor.h>
38 #include <vdb/vdb-priv.h>
39 #include <vdb/dependencies.h>
40 #include <kdb/meta.h>
41 #include <kdb/manager.h>
42 #include <kdb/table.h>
43 #include <kdb/database.h>
44 #include <kdb/kdb-priv.h>
45 #include <vfs/manager.h>
46 #include <vfs/path.h>
47 #include <vfs/path-priv.h>
48 #include <vfs/resolver.h>
49 #include <klib/refcount.h>
50 #include <klib/log.h>
51 #include <klib/debug.h>
52 #include <klib/rc.h>
53 #include <klib/text.h>
54 #include <klib/printf.h>
55 #include <kfs/toc.h>
56 #include <kfs/file.h>
57 #include <sysalloc.h>
58
59 #include "sra-priv.h"
60
61 #include <stdlib.h>
62 #include <stdarg.h>
63 #include <string.h>
64 #include <stdio.h>
65 #include <assert.h>
66 #include <va_copy.h>
67
68 #ifdef __GNUC__
69 #pragma GCC diagnostic ignored "-Wpedantic"
70 #endif
71
72 /* Destroy
73 */
74 static
column_release(void * item,void * ignore)75 void CC column_release ( void *item, void *ignore )
76 {
77 SRAColumn *self = item;
78 self -> tbl = NULL;
79 SRAColumnWhack ( self );
80 }
81
SRATableDestroy(SRATable * self)82 void SRATableDestroy ( SRATable *self )
83 {
84 VectorWhack ( & self -> wcol, column_release, NULL );
85 VCursorRelease(self->curs);
86 KMetadataRelease ( self -> meta );
87 VTableRelease ( self -> vtbl );
88 SRAMgrSever ( self -> mgr );
89
90 memset(self, 0, sizeof *self);
91
92 free ( self );
93 }
94
95 /* AddRef
96 * Release
97 * see REFERENCE COUNTING, above
98 */
SRATableAddRef(const SRATable * self)99 LIB_EXPORT rc_t CC SRATableAddRef( const SRATable *self )
100 {
101 if ( self != NULL )
102 {
103 switch ( KRefcountAdd ( & self -> refcount, "SRATable" ) )
104 {
105 case krefLimit:
106 return RC ( rcSRA, rcTable, rcAttaching, rcRange, rcExcessive );
107 }
108 }
109 return 0;
110 }
111
SRATableRelease(const SRATable * self)112 LIB_EXPORT rc_t CC SRATableRelease( const SRATable *self )
113 {
114 rc_t rc = 0;
115
116 if (self)
117 {
118 switch (KRefcountDrop(&self->refcount, "SRATable"))
119 {
120 case krefWhack:
121 return SRATableWhack ( ( SRATable* ) self );
122 case krefNegative:
123 rc = RC (rcSRA, rcTable, rcDestroying, rcSelf, rcDestroyed);
124 PLOGERR (klogInt,(klogInt, rc, "Released an SRATable $(B) with no more references",
125 PLOG_P(self)));
126 break;
127 }
128 }
129 return rc;
130 }
131
132 /* Attach
133 * Sever
134 */
SRATableAttach(const SRATable * self)135 SRATable *SRATableAttach ( const SRATable *self )
136 {
137 if ( self != NULL )
138 {
139 switch ( KRefcountAddDep ( & self -> refcount, "SRATable" ) )
140 {
141 case krefLimit:
142 return NULL;
143 }
144 }
145 return ( SRATable* ) self;
146 }
147
SRATableSever(const SRATable * self)148 rc_t SRATableSever ( const SRATable *self )
149 {
150 if ( self != NULL )
151 {
152 switch ( KRefcountDropDep ( & self -> refcount, "SRATable" ) )
153 {
154 case krefWhack:
155 return SRATableWhack ( ( SRATable* ) self );
156 case krefNegative:
157 return RC ( rcSRA, rcTable, rcReleasing, rcRange, rcExcessive );
158 }
159 }
160 return 0;
161 }
162
163
164 /* FillOutTableRead
165 * creates an empty cursor
166 * accesses metadata
167 */
ReadSpotSequence_v1(SRATable * self)168 static rc_t ReadSpotSequence_v1(SRATable *self)
169 {
170 const KMDataNode *n;
171 rc_t rc = KMetadataOpenNodeRead(self->meta, &n, ".seq");
172 if (rc == 0)
173 {
174 rc = KMDataNodeReadAsU64(n, &self->spot_count);
175 KMDataNodeRelease(n);
176 }
177 return rc;
178 }
179
180 typedef enum {
181 eNotRead,
182 eNotFound,
183 eFailed,
184 eRead
185 } EState;
186 typedef struct {
187 EState state;
188 rc_t rc;
189 } State;
190 typedef struct {
191 uint64_t value;
192 State state;
193 } U64;
194 typedef struct {
195 uint32_t value;
196 State state;
197 } U32;
198 typedef struct {
199 U64 BASE_COUNT;
200 U32 MAX_SPOT_ID;
201 U32 MIN_SPOT_ID;
202 U64 SPOT_COUNT;
203 } PseudoMeta;
204 static
VCursor_ReadPseudoMeta(rc_t rc,const VCursor * self,const char * name,void * buffer,uint32_t blen,State * state)205 rc_t VCursor_ReadPseudoMeta(rc_t rc, const VCursor *self,
206 const char *name, void *buffer, uint32_t blen, State *state)
207 {
208 uint32_t idx = ~0;
209 uint32_t row_len = ~0;
210
211 assert(state);
212 state->rc = 0;
213
214 if (rc != 0)
215 { return rc; }
216
217 state->state = eNotRead;
218
219 rc = VCursorAddColumn(self, &idx, "%s", name);
220
221 if (rc != 0) {
222 state->rc = rc;
223
224 if ( GetRCObject( rc ) == (enum RCObject)rcColumn && GetRCState( rc ) == rcNotFound ) {
225 rc = 0;
226 state->state = eNotFound;
227 }
228 else {
229 state->state = eFailed;
230 }
231 }
232
233 if (state->rc == 0) {
234 rc = VCursorReadDirect(self, 1, idx, blen * 8, buffer, blen, &row_len);
235
236 state->rc = rc;
237
238 if (rc != 0)
239 { state->state = eFailed; }
240 else
241 { state->state = eRead; }
242
243 }
244
245 return rc;
246 }
247
248 static
VCursor_ReadPseudoMetaU32(rc_t rc,const VCursor * self,const char * name,U32 * val)249 rc_t VCursor_ReadPseudoMetaU32(rc_t rc, const VCursor *self,
250 const char *name, U32 *val)
251 {
252 assert(val);
253 return VCursor_ReadPseudoMeta(rc, self,
254 name, &val->value, sizeof val->value, &val->state);
255 }
256
257 static
VCursor_ReadPseudoMetaU64(rc_t rc,const VCursor * self,const char * name,U64 * val)258 rc_t VCursor_ReadPseudoMetaU64(rc_t rc, const VCursor *self,
259 const char *name, U64 *val)
260 {
261 assert(val);
262 return VCursor_ReadPseudoMeta(rc, self,
263 name, &val->value, sizeof val->value, &val->state);
264 }
265
266 static
PseudoMetaInit(PseudoMeta * self,const VCursor * curs,bool readSpotCount,uint64_t spot_count)267 rc_t PseudoMetaInit(PseudoMeta *self, const VCursor *curs,
268 bool readSpotCount, uint64_t spot_count)
269 {
270 rc_t rc = 0;
271
272 assert(self);
273
274 memset(self, 0, sizeof *self);
275
276 if (readSpotCount) {
277 rc =
278 VCursor_ReadPseudoMetaU64(rc, curs, "SPOT_COUNT", &self->SPOT_COUNT);
279 }
280 else {
281 self->SPOT_COUNT.value = spot_count;
282 self->SPOT_COUNT.state.state = eRead;
283 }
284
285 rc = VCursor_ReadPseudoMetaU64(rc, curs, "BASE_COUNT", &self->BASE_COUNT);
286
287 rc = VCursor_ReadPseudoMetaU32(rc, curs, "MIN_SPOT_ID", &self->MIN_SPOT_ID);
288
289 rc = VCursor_ReadPseudoMetaU32(rc, curs, "MAX_SPOT_ID", &self->MAX_SPOT_ID);
290
291 return rc;
292 }
293
294 static
PseudoMetaFix(PseudoMeta * self)295 rc_t PseudoMetaFix(PseudoMeta *self)
296 {
297 rc_t rc = 0;
298
299 assert(self);
300
301 if (self->MIN_SPOT_ID.state.state != eRead)
302 { self->MIN_SPOT_ID.value = 1; }
303
304 if (self->SPOT_COUNT.state.state != eRead &&
305 self->MAX_SPOT_ID.state.state != eRead)
306 {
307 return self->SPOT_COUNT.state.rc;
308 }
309 else if (self->SPOT_COUNT.state.state == eRead) {
310 if (self->MAX_SPOT_ID.state.state != eRead) {
311 self->MAX_SPOT_ID.value
312 = self->MIN_SPOT_ID.value + self->SPOT_COUNT.value - 1;
313 }
314 else if (self->MAX_SPOT_ID.value >= self->MIN_SPOT_ID.value) {
315 uint32_t delta = (uint32_t) (self->SPOT_COUNT.value - (self->MAX_SPOT_ID.value - self->MIN_SPOT_ID.value + 1)); /** SPOT_COUNT is 64 bit, but M*_SPOT_ID is 32; anticipate rollover **/
316 if ( delta )
317 {
318 self->SPOT_COUNT.value
319 = self->MAX_SPOT_ID.value - self->MIN_SPOT_ID.value + 1;
320 }
321 }
322 }
323 else {
324 self->SPOT_COUNT.value
325 = self->MAX_SPOT_ID.value - self->MIN_SPOT_ID.value - 1;
326 }
327
328 return rc;
329 }
330
331 static
SRATableLoadMetadata(SRATable * self)332 rc_t SRATableLoadMetadata(SRATable * self)
333 {
334 rc_t rc = 0;
335 PseudoMeta meta;
336 bool readSpotCount = true;
337
338 assert(self && self->curs != NULL);
339 assert(self->curs_open == true);
340
341 readSpotCount = self->metavers > 1;
342 if (!readSpotCount) {
343 rc = ReadSpotSequence_v1(self);
344 if (rc != 0)
345 { return rc; }
346 }
347
348 rc = PseudoMetaInit(&meta, self->curs, readSpotCount, self->spot_count);
349 if (rc != 0)
350 { return rc; }
351
352 rc = PseudoMetaFix(&meta);
353 if (rc != 0)
354 { return rc; }
355
356 self->spot_count = meta.SPOT_COUNT.value;
357 self->base_count = meta.BASE_COUNT.value;
358 self->min_spot_id = meta.MIN_SPOT_ID.value;
359 self->max_spot_id = meta.MAX_SPOT_ID.value;
360
361 {
362 int64_t delta = self->spot_count - (self->max_spot_id-self->min_spot_id+1);
363 if(delta>0 && ((uint32_t)delta)==0){/* there was a rollover*/
364 self->max_spot_id = self->min_spot_id + self->spot_count - 1;
365 }
366 }
367
368 return rc;
369 }
370
371 /* detect min and max spot-id from a temp. cursor */
SRATableGetMinMax(SRATable * self)372 static rc_t SRATableGetMinMax( SRATable * self )
373 {
374 const VCursor *temp_cursor;
375 rc_t rc;
376
377 assert( self != NULL );
378 assert( self->vtbl != NULL);
379 rc = VTableCreateCursorRead( self->vtbl, &temp_cursor );
380 if ( rc == 0 )
381 {
382 uint32_t idx;
383 rc = VCursorAddColumn ( temp_cursor, &idx, "READ" );
384 if ( rc == 0 )
385 {
386 rc = VCursorOpen( temp_cursor );
387 if ( rc == 0 )
388 {
389 int64_t first;
390 uint64_t count;
391 rc = VCursorIdRange( temp_cursor, 0, &first, &count );
392 if ( rc == 0 )
393 {
394 self->min_spot_id = first;
395 self->max_spot_id = first + count;
396 self->spot_count = count;
397 }
398 }
399 }
400 VCursorRelease( temp_cursor );
401 }
402 return rc;
403 }
404
SRATableFillOut(SRATable * self,bool update)405 rc_t SRATableFillOut ( SRATable *self, bool update )
406 {
407 rc_t rc;
408
409 /* require these operations to succeed */
410 rc = VCursorPermitPostOpenAdd( self->curs );
411 if ( rc != 0 )
412 return rc;
413 rc = VCursorOpen( self->curs );
414 if ( rc != 0 )
415 return rc;
416 self -> curs_open = true;
417 if ( ! update )
418 {
419 rc = SRATableLoadMetadata( self );
420 if ( rc != 0 )
421 rc = SRATableGetMinMax( self );
422 }
423 return rc;
424 }
425
426
427 /* ResolveTablePath
428 * takes either an accession or path
429 * substitutes any arguments
430 * resolves via SRAPath mgr if present
431 */
ResolveTablePath(const SRAMgr * mgr,char * path,size_t psize,const char * spec,va_list args)432 rc_t ResolveTablePath ( const SRAMgr *mgr,
433 char *path, size_t psize, const char *spec, va_list args )
434 {
435 #if OLD_SRAPATH_MGR
436 int len;
437 char tblpath [ 4096 ];
438 const SRAPath *pmgr = mgr -> _pmgr;
439
440 /* if no path manager or if the spec string has embedded path separators,
441 then this can't be an accession - just print it out */
442 if ( mgr -> _pmgr == NULL || strchr( spec, '/' ) != NULL )
443 {
444 len = vsnprintf ( path, psize, spec, args );
445 if ( len < 0 || ( size_t ) len >= psize )
446 return RC ( rcSRA, rcTable, rcOpening, rcPath, rcExcessive );
447 return 0;
448 }
449
450 /* create a copy - not likely to be too large */
451 len = vsnprintf ( tblpath, sizeof tblpath, spec, args );
452 if ( len < 0 || ( size_t ) len >= sizeof tblpath )
453 return RC ( rcSRA, rcTable, rcOpening, rcPath, rcExcessive );
454
455 /* test if the path exists in current directory, i.e. with assumed dot */
456 if ( ! SRAPathTest ( pmgr, tblpath ) )
457 {
458 rc_t rc = SRAPathFind ( pmgr, tblpath, path, psize );
459 if ( rc == 0 )
460 return 0;
461 }
462
463 /* use the path given */
464 if ( ( size_t ) len >= psize )
465 return RC ( rcSRA, rcTable, rcOpening, rcBuffer, rcInsufficient );
466 strcpy ( path, tblpath );
467
468 return 0;
469 #else
470 VFSManager *vfs;
471 rc_t rc = VFSManagerMake ( & vfs );
472 if ( rc == 0 )
473 {
474 VPath *accession;
475 const VPath *tblpath = NULL;
476 rc = VFSManagerVMakePath ( vfs, & accession, spec, args );
477 if ( rc == 0 )
478 {
479 rc = VResolverLocal ( ( const VResolver* ) mgr -> _pmgr, accession, & tblpath );
480 if ( rc == 0 )
481 {
482 size_t size;
483 rc = VPathReadPath ( tblpath, path, psize, & size );
484 VPathRelease ( tblpath );
485 }
486 VPathRelease ( accession );
487 }
488
489 VFSManagerRelease ( vfs );
490 }
491 return rc;
492 #endif
493 }
494
495 /* OpenRead
496 * open an existing table
497 *
498 * "tbl" [ OUT ] - return parameter for table
499 *
500 * "spec" [ IN ] - NUL terminated UTF-8 string giving path
501 * to table.
502 */
503 static
SRAMgrVOpenAltTableRead(const SRAMgr * self,const SRATable ** rslt,const char * altname,const char * spec,va_list args)504 rc_t CC SRAMgrVOpenAltTableRead ( const SRAMgr *self,
505 const SRATable **rslt, const char *altname, const char *spec, va_list args )
506 {
507 rc_t rc;
508
509 if ( rslt == NULL )
510 rc = RC ( rcSRA, rcTable, rcOpening, rcParam, rcNull );
511 else
512 {
513 if ( self == NULL )
514 rc = RC ( rcSRA, rcMgr, rcAccessing, rcSelf, rcNull );
515 else if ( spec == NULL )
516 rc = RC ( rcSRA, rcTable, rcOpening, rcName, rcNull );
517 else if ( spec [ 0 ] == 0 )
518 rc = RC ( rcSRA, rcTable, rcOpening, rcName, rcEmpty );
519 else
520 {
521 SRATable *tbl = calloc ( 1, sizeof *tbl );
522 if ( tbl == NULL )
523 rc = RC ( rcSRA, rcTable, rcConstructing, rcMemory, rcExhausted );
524 else
525 {
526 VSchema *schema = NULL;
527
528 rc = VDBManagerMakeSRASchema(self -> vmgr, & schema);
529 if ( rc == 0 )
530 {
531 va_list args_copy;
532 va_copy ( args_copy, args );
533 rc = VDBManagerVOpenTableRead ( self -> vmgr, & tbl -> vtbl, schema, spec, args );
534 if ( rc != 0 && GetRCObject ( rc ) == (enum RCObject)rcTable && GetRCState ( rc ) == rcIncorrect )
535 {
536 const VDatabase *db;
537 rc_t rc2 = VDBManagerVOpenDBRead ( self -> vmgr, & db, schema, spec, args_copy );
538 if ( rc2 == 0 )
539 {
540 rc2 = VDatabaseOpenTableRead ( db, & tbl -> vtbl, "%s", altname );
541 if ( rc2 == 0 )
542 rc = 0;
543
544 VDatabaseRelease ( db );
545 }
546 }
547 va_end ( args_copy );
548
549 VSchemaRelease(schema);
550
551 if ( rc == 0 )
552 {
553 rc = VTableOpenMetadataRead ( tbl -> vtbl, & tbl -> meta );
554 if ( rc == 0 )
555 {
556 rc = KMetadataVersion ( tbl -> meta, & tbl -> metavers );
557 if ( rc == 0 )
558 {
559 rc = VTableCreateCursorRead ( tbl -> vtbl, & tbl -> curs );
560 if ( rc == 0 )
561 {
562 tbl -> mode = self -> mode;
563 tbl -> read_only = true;
564 KRefcountInit ( & tbl -> refcount, 1, "SRATable", "OpenTableRead", spec );
565
566 rc = SRATableFillOut ( tbl, false );
567 if ( rc == 0 )
568 {
569 * rslt = tbl;
570 return 0;
571 }
572 }
573 }
574 }
575 }
576
577 }
578 SRATableWhack ( tbl );
579 }
580 }
581
582 * rslt = NULL;
583 }
584 return rc;
585 }
586
587 /* OpenRead
588 * open an existing table
589 *
590 * "tbl" [ OUT ] - return parameter for table
591 *
592 * "spec" [ IN ] - NUL terminated UTF-8 string giving path
593 * to table.
594 */
SRAMgrVOpenTableRead(const SRAMgr * self,const SRATable ** crslt,const char * spec,va_list args)595 LIB_EXPORT rc_t CC SRAMgrVOpenTableRead ( const SRAMgr *self,
596 const SRATable **crslt, const char *spec, va_list args )
597 {
598 rc_t rc;
599 char tblpath [ 4096 ];
600 int num_writ = vsnprintf ( tblpath, sizeof tblpath, spec, args );
601 if ( num_writ < 0 || ( size_t ) num_writ >= sizeof tblpath )
602 rc = RC ( rcSRA, rcMgr, rcOpening, rcPath, rcExcessive );
603 else
604 {
605 SRATable **rslt = (SRATable **)crslt; /* to avoid "const_casts" below */
606 rc = SRACacheGetTable( self->cache, tblpath, crslt );
607 if (rc == 0 )
608 {
609 if ( *crslt == NULL )
610 {
611 rc = SRAMgrOpenAltTableRead ( self, crslt, "SEQUENCE", tblpath );
612 if ( rc == 0 )
613 {
614 rc = SRACacheAddTable( self->cache, tblpath, *rslt);
615 if ( GetRCObject(rc) == rcParam && GetRCState(rc) == rcExists )
616 { /* the same object has appeared in the cache since our call to SRACacheGetTable above; */
617 rc = 0; /* return the new object, never mind the cache */
618 }
619 else if ( ! SRACacheMetricsLessThan(&self->cache->current, &self->cache->hardThreshold) )
620 rc = SRACacheFlush(self->cache);
621 }
622 }
623 }
624 else if ( (GetRCObject(rc) == rcName && GetRCState(rc) == rcInvalid) || /* accessions with irregular names are not cached */
625 (GetRCObject(rc) == rcParam && GetRCState(rc) == rcBusy) ) /* in cache but in use */
626 {
627 rc = SRAMgrOpenAltTableRead ( self, crslt, "SEQUENCE", tblpath );
628 if (rc == 0)
629 (*rslt)->mgr = SRAMgrAttach(self);
630 }
631 }
632
633 return rc;
634 }
635
SRAMgrOpenTableRead(const SRAMgr * self,const SRATable ** tbl,const char * spec,...)636 LIB_EXPORT rc_t CC SRAMgrOpenTableRead ( const SRAMgr *self,
637 const SRATable **tbl, const char *spec, ... )
638 {
639 rc_t rc;
640
641 va_list args;
642 va_start ( args, spec );
643
644 rc = SRAMgrVOpenTableRead ( self, tbl, spec, args );
645
646 va_end ( args );
647
648 return rc;
649 }
650
651
652 /* Read - PRIVATE
653 * column message sent via table
654 */
SRATableRead(const SRATable * self,spotid_t id,uint32_t idx,const void ** base,bitsz_t * offset,bitsz_t * size)655 rc_t SRATableRead ( const SRATable *self, spotid_t id, uint32_t idx,
656 const void **base, bitsz_t *offset, bitsz_t *size )
657 {
658 rc_t rc;
659
660 if ( base == NULL || offset == NULL || size == NULL )
661 rc = RC ( rcSRA, rcColumn, rcReading, rcParam, rcNull );
662 else if ( self == NULL )
663 rc = RC ( rcSRA, rcTable, rcAccessing, rcSelf, rcNull );
664 else
665 {
666 rc = 0;
667
668 /* open cursor */
669 if ( ! self -> curs_open )
670 {
671 rc = VCursorOpen(self->curs);
672 if ( rc == 0 )
673 ((SRATable *)self)->curs_open = true;
674 }
675
676 if ( rc == 0 )
677 {
678 uint32_t elem_bits, elem_off, elem_cnt;
679 rc = VCursorCellDataDirect ( self -> curs, id, idx,
680 & elem_bits, base, & elem_off, & elem_cnt );
681 if ( rc == 0 )
682 {
683 * offset = elem_off * elem_bits;
684 * size = elem_cnt * elem_bits;
685 return 0;
686 } else if( UIError(rc, NULL, self->vtbl) ) {
687 UITableLOGError(rc, self->vtbl, true);
688 }
689 }
690 }
691
692 if ( base != NULL )
693 * base = NULL;
694 if ( offset != NULL )
695 * offset = 0;
696 if ( size != NULL )
697 * size = 0;
698
699 return rc;
700 }
701
702 /* GetSpotId
703 * convert spot name to spot id
704 *
705 * "id" [ OUT ] - return parameter for min(spot_id)-max(spot_id)
706 *
707 * "spot_name" [ IN ] - external spot name string
708 * in platform canonical format.
709 */
SRATableGetSpotId(const SRATable * self,spotid_t * rslt,const char * spot_name)710 LIB_EXPORT rc_t CC SRATableGetSpotId ( const SRATable *self,
711 spotid_t *rslt, const char *spot_name )
712 {
713 rc_t rc;
714 if( self == NULL || spot_name == NULL){
715 rc=RC(rcSRA, rcTable, rcListing, rcSelf, rcName);
716 } else {
717 rc=VCursorParamsSet((struct VCursorParams*)self->curs,"QUERY_BY_NAME" ,spot_name);
718 if( rc == 0) {
719 struct {
720 uint64_t start_id;
721 uint64_t id_count;
722 int64_t x;
723 int64_t y;
724 } out;
725 uint32_t idx,len;
726 rc = VCursorAddColumn(self->curs, &idx, "SPOT_IDS_FOUND");
727 if( rc == 0 || GetRCState(rc) == rcExists){
728 rc = VCursorReadDirect(self->curs,1,idx,sizeof(out) * 8,&out, 1 , &len);
729 if ( rc == 0 ) {
730 if(out.id_count==1) {
731 if(rslt) *rslt=out.start_id;
732 return 0;
733 } else if(out.id_count > 1) { /*** doing table range scan in Name space - not relying on X and Y***/
734 uint32_t x_idx;
735 rc = VCursorAddColumn(self->curs, &x_idx, "X");
736 if( rc == 0 || GetRCState(rc) == rcExists){
737 uint32_t y_idx;
738 rc = VCursorAddColumn(self->curs, &y_idx, "Y");
739 if(rc == 0 || GetRCState(rc) == rcExists){
740 spotid_t rowid;
741 for(rowid = out.start_id; rowid < out.start_id + out.id_count; rowid ++){
742 int32_t x,y;
743 rc = VCursorReadDirect(self->curs,rowid,x_idx,32,&x,1, &len);
744 if(rc == 0){
745 rc = VCursorReadDirect(self->curs,rowid,y_idx,32,&y,1, &len);
746 if(rc == 0 && x==out.x && y==out.y){
747 if(rslt) *rslt=rowid;
748 return 0;
749 }
750 }
751 }
752 }
753 }
754 }
755 rc = RC ( rcSRA, rcIndex, rcSearching, rcColumn, rcNotFound );
756 }
757 }
758 }
759 }
760 return rc;
761 }
762
763
764 /* ListCol
765 * returns a list of simple column names
766 * each name represents at least one typed column
767 *
768 * "names" [ out ] - return parameter for names list
769 */
SRATableListCol(const SRATable * self,SRANamelist ** rslt)770 LIB_EXPORT rc_t CC SRATableListCol( const SRATable *self, SRANamelist **rslt ) {
771 if ( self != NULL )
772 return VTableListCol ( self -> vtbl, (KNamelist **)rslt );
773 return RC(rcSRA, rcTable, rcListing, rcSelf, rcName);
774 }
775
776
777 /* ColDatatypes
778 * returns list of typedecls for named column
779 *
780 * "col" [ IN ] - column name
781 *
782 * "dflt_idx" [ OUT, NULL OKAY ] - returns the zero-based index
783 * into "typedecls" of the default datatype for the named column
784 *
785 * "typedecls" [ OUT ] - list of datatypes available for named column
786 */
SRATableColDatatypes(const SRATable * self,const char * col,uint32_t * dflt_idx,SRANamelist ** rslt)787 LIB_EXPORT rc_t CC SRATableColDatatypes( const SRATable *self,
788 const char *col, uint32_t *dflt_idx, SRANamelist **rslt ) {
789 if ( self != NULL )
790 return VTableColumnDatatypes ( self -> vtbl, col, dflt_idx, (KNamelist **)rslt );
791 return RC(rcSRA, rcTable, rcListing, rcSelf, rcName);
792 }
793
SRATableColDatatype(const SRATable * self,uint32_t idx,VTypedecl * type,VTypedef * def)794 rc_t SRATableColDatatype ( const SRATable *self,
795 uint32_t idx, VTypedecl *type, VTypedef *def )
796 {
797 rc_t rc;
798 if ( type == NULL && def == NULL )
799 rc = RC ( rcSRA, rcColumn, rcAccessing, rcParam, rcNull );
800 else
801 {
802 union { VTypedecl td; VTypedef def; } dummy;
803 if ( type == NULL )
804 type = & dummy . td;
805 else if ( def == NULL )
806 def = & dummy . def;
807
808 if ( idx == 0 )
809 rc = RC ( rcSRA, rcColumn, rcAccessing, rcSelf, rcNull );
810 else if ( self == NULL )
811 rc = RC ( rcSRA, rcTable, rcAccessing, rcSelf, rcNull );
812 else
813 {
814 VTypedesc desc;
815 rc = VCursorDatatype ( self -> curs, idx, type, & desc );
816 if ( rc == 0 )
817 {
818 rc = VSchemaDescribeTypedef ( VCursorGetSchema(self -> curs), def, type -> type_id );
819 if ( rc == 0 )
820 return 0;
821 }
822 }
823
824 memset ( type, 0, sizeof * type );
825 memset ( def, 0, sizeof * def );
826 }
827 return rc;
828 }
829
830 /* MetaRevision
831 * returns current revision number
832 * where 0(zero) means tip
833 */
SRATableMetaRevision(const SRATable * self,uint32_t * rslt)834 LIB_EXPORT rc_t CC SRATableMetaRevision( const SRATable *self, uint32_t *rslt )
835 {
836 if (self == NULL)
837 return RC(rcSRA, rcTable, rcAccessing, rcSelf, rcNull);
838 return KMetadataRevision (self->meta,rslt);
839 }
840
841
842 /* MaxRevision
843 * returns the maximum revision available
844 */
SRATableMaxMetaRevision(const SRATable * self,uint32_t * rslt)845 LIB_EXPORT rc_t CC SRATableMaxMetaRevision( const SRATable *self, uint32_t *rslt )
846 {
847 if (self == NULL)
848 return RC(rcSRA, rcTable, rcAccessing, rcSelf, rcNull);
849 return KMetadataMaxRevision(self->meta,rslt);
850 }
851
852 /* UseMetaRevision
853 * opens indicated revision of metadata
854 * all non-zero revisions are read-only
855 */
SRATableUseMetaRevision(const SRATable * cself,uint32_t revision)856 LIB_EXPORT rc_t CC SRATableUseMetaRevision ( const SRATable *cself, uint32_t revision )
857 {
858 rc_t rc;
859
860 if ( cself == NULL )
861 rc = RC ( rcSRA, rcTable, rcUpdating, rcSelf, rcNull );
862 else if ( cself -> read_only == false )
863 rc = RC ( rcSRA, rcTable, rcUpdating, rcMetadata, rcBusy );
864 else
865 {
866 uint32_t cur;
867 rc = KMetadataRevision ( cself -> meta, & cur );
868 if ( rc == 0 && cur != revision )
869 {
870 SRATable *self = ( SRATable* ) cself;
871 const KMetadata *meta;
872 rc = KMetadataOpenRevision ( self -> meta, & meta, revision );
873 if ( rc == 0 )
874 {
875 KMetadataRelease ( self -> meta );
876 self -> meta = meta;
877 }
878 }
879 }
880
881 return rc;
882 }
883
884 /* OpenMDataNode
885 * open a metadata node
886 *
887 * "node" [ OUT ] - return parameter for metadata node
888 *
889 * "path" [ IN ] - simple or hierarchical NUL terminated
890 * path to node
891 */
SRATableOpenMDataNodeRead(const SRATable * self,struct KMDataNode const ** node,const char * path,...)892 LIB_EXPORT rc_t CC SRATableOpenMDataNodeRead( const SRATable *self,
893 struct KMDataNode const **node, const char *path, ... ) {
894 va_list va;
895 rc_t rc;
896
897 va_start(va, path);
898 rc = SRATableVOpenMDataNodeRead(self, node, path, va);
899 va_end(va);
900 return rc;
901 }
902
SRATableVOpenMDataNodeRead(const SRATable * self,struct KMDataNode const ** rslt,const char * path,va_list args)903 LIB_EXPORT rc_t CC SRATableVOpenMDataNodeRead( const SRATable *self,
904 struct KMDataNode const **rslt, const char *path, va_list args ) {
905 if (self == NULL)
906 return RC(rcSRA, rcTable, rcAccessing, rcSelf, rcNull);
907
908 return KMetadataVOpenNodeRead(self->meta, rslt, path, args);
909 }
910
911 /* private */
SRATableGetIdRange(const SRATable * self,uint32_t idx,spotid_t id,spotid_t * pfirst,spotid_t * plast)912 rc_t SRATableGetIdRange ( const SRATable *self,
913 uint32_t idx, spotid_t id, spotid_t *pfirst, spotid_t *plast )
914 {
915 rc_t rc;
916
917 if ( pfirst == NULL && plast == NULL )
918 rc = RC ( rcSRA, rcColumn, rcAccessing, rcParam, rcNull );
919 else
920 {
921 spotid_t dummy;
922 if ( pfirst == NULL )
923 pfirst = & dummy;
924 else if ( plast == NULL )
925 plast = & dummy;
926
927 if ( idx == 0 )
928 rc = RC ( rcSRA, rcColumn, rcAccessing, rcSelf, rcNull );
929 else if ( self == NULL )
930 rc = RC ( rcSRA, rcTable, rcAccessing, rcSelf, rcNull );
931 else
932 {
933 int64_t first, last;
934 rc = VCursorPageIdRange ( self -> curs, idx, id, & first, & last );
935 if ( rc == 0 )
936 {
937 * pfirst = ( spotid_t ) first;
938 * plast = ( spotid_t ) last;
939
940 if ( ( int64_t ) * pfirst == first && ( int64_t ) * plast == last )
941 return 0;
942
943 rc = RC ( rcSRA, rcColumn, rcAccessing, rcRange, rcExcessive );
944 }
945 }
946
947 * pfirst = * plast = 0;
948 }
949
950 return rc;
951 }
952
953 /* semi-private for sra-dbcc */
SRATableGetVTableRead(const SRATable * self,const VTable ** rslt)954 LIB_EXPORT rc_t CC SRATableGetVTableRead( const SRATable *self, const VTable **rslt )
955 {
956 if (rslt == NULL)
957 return RC(rcSRA, rcTable, rcAccessing, rcParam, rcNull);
958
959 if (self == NULL)
960 {
961 * rslt = NULL;
962 return RC(rcSRA, rcTable, rcAccessing, rcSelf, rcNull);
963 }
964
965 *rslt = self->vtbl;
966 return VTableAddRef(*rslt);
967 }
968
SRATableGetKTableRead(const SRATable * self,struct KTable const ** ktbl)969 LIB_EXPORT rc_t CC SRATableGetKTableRead ( const SRATable *self, struct KTable const **ktbl )
970 {
971 rc_t rc;
972
973 if ( ktbl == NULL )
974 rc = RC ( rcSRA, rcTable, rcAccessing, rcParam, rcNull );
975 else
976 {
977 if ( self == NULL )
978 rc = RC ( rcSRA, rcTable, rcAccessing, rcSelf, rcNull );
979 else
980 {
981 return VTableGetKTableRead ( self -> vtbl, ktbl );
982 }
983
984 * ktbl = NULL;
985 }
986
987 return rc;
988 }
989
990 /* Locked
991 * returns true if locked
992 */
SRATableLocked(const SRATable * self)993 LIB_EXPORT bool CC SRATableLocked( const SRATable *self )
994 {
995 return self ? VTableLocked(self->vtbl) : false;
996 }
997
SRATableGetSchema(struct SRATable const * self)998 LIB_EXPORT struct VSchema const* CC SRATableGetSchema ( struct SRATable const *self )
999 {
1000 return self ? VCursorGetSchema( self->curs ) : NULL;
1001 }
1002
1003 /* sfa_filter
1004 * if a name is found in list, exclude it
1005 */
1006 #define DEBUG_SORT(msg) DBGMSG (DBG_SRA, DBG_FLAG(DBG_SRA_SORT), msg)
1007
1008 /* sfa_sort
1009 * reorders list
1010 */
1011 enum sfa_path_type_id
1012 {
1013 sfa_not_set = -1,
1014 sfa_exclude,
1015 sfa_non_column,
1016 sfa_required,
1017 sfa_preferred,
1018 sfa_optional
1019 };
1020
1021 #if _DEBUGGING
1022 const char* sfa_path_type_id[] = {
1023 "not_set",
1024 "exclude",
1025 "non_column",
1026 "required",
1027 "preferred",
1028 "optional"
1029 };
1030 #endif
1031
1032 typedef struct reorder_t_struct {
1033 const char * path;
1034 uint64_t size;
1035 enum sfa_path_type_id type_id;
1036 } reorder_t;
1037
1038 typedef enum sfa_path_type_id (CC *sfa_path_type_func)( const char *path );
1039
1040 /*
1041 union u_void_sfa_path_type_func
1042 {
1043 void * func;
1044 sfa_path_type_func sptf;
1045 };
1046
1047 static sfa_path_type_func void_to_sfa_path_type_func( void * func )
1048 {
1049 union u_void_sfa_path_type_func x;
1050 x.func = func;
1051 return x.sptf;
1052 }
1053 */
1054
1055 static
1056 bool CC sfa_filter(const KDirectory *dir, const char *leaf, void* func)
1057 {
1058 bool ret = true;
1059 sfa_path_type_func f = (sfa_path_type_func)func; /* void_to_sfa_path_type_func( func ); */
1060 enum sfa_path_type_id type = f(leaf);
1061
1062 ret = type >= sfa_non_column;
1063 DEBUG_SORT(("%s: %s %s %s\n", __func__, leaf, sfa_path_type_id[type + 1], ret ? "keep" : "drop"));
1064 return ret;
1065 }
1066
1067 static
sfa_filter_light(const KDirectory * dir,const char * leaf,void * func)1068 bool CC sfa_filter_light(const KDirectory *dir, const char *leaf, void* func)
1069 {
1070 bool ret = true;
1071 sfa_path_type_func f = (sfa_path_type_func)func; /* void_to_sfa_path_type_func( func ); */
1072
1073 enum sfa_path_type_id type = f(leaf);
1074
1075 ret = type >= sfa_non_column && type < sfa_optional;
1076 DEBUG_SORT(("%s: %s %s %s\n", __func__, leaf, sfa_path_type_id[type + 1], ret ? "keep" : "drop"));
1077 return ret;
1078 }
1079
1080 #define MATCH( ptr, str ) \
1081 ( (memcmp(ptr, str, sizeof(str) - 2) == 0 && \
1082 ((ptr)[sizeof(str) - 2] == '\0' || (ptr)[sizeof(str) - 2] == '/')) ? \
1083 (ptr) += sizeof(str) - (((ptr)[sizeof(str) - 2] == '/') ? 1 : 2) : (const char*) 0)
1084
1085 static
sfa_path_type_tbl(const char * path)1086 enum sfa_path_type_id CC sfa_path_type_tbl( const char *path )
1087 {
1088 /* use first character as distinguisher for match */
1089 switch ( path [ 0 ] )
1090 {
1091 case 'c':
1092 /* perhaps it's a column */
1093 if ( MATCH ( path, "col/" ) )
1094 {
1095 switch ( path [ 0 ] )
1096 {
1097 case 'D':
1098 if ( MATCH ( path, "DELETION_QV/" ) )
1099 return sfa_optional;
1100 if ( MATCH ( path, "DELETION_TAG/" ) )
1101 return sfa_optional;
1102 break;
1103 case 'H':
1104 if ( MATCH ( path, "HOLE_NUMBER/" ) )
1105 return sfa_optional;
1106 if ( MATCH ( path, "HOLE_STATUS/" ) )
1107 return sfa_optional;
1108 break;
1109 case 'I':
1110 if ( MATCH ( path, "INTENSITY/" ) )
1111 return sfa_optional;
1112 if ( MATCH ( path, "INSERTION_QV/" ) )
1113 return sfa_optional;
1114 break;
1115 case 'N':
1116 if ( MATCH ( path, "NAME_FMT/" ) )
1117 return sfa_preferred;
1118 if ( MATCH ( path, "NAME/" ) )
1119 return sfa_preferred;
1120 if ( MATCH ( path, "NOISE/" ) )
1121 return sfa_optional;
1122 if ( MATCH ( path, "NUM_PASSES/" ) )
1123 return sfa_optional;
1124 break;
1125 case 'P':
1126 if ( MATCH ( path, "POSITION/" ) )
1127 return sfa_optional;
1128 if ( MATCH ( path, "PRE_BASE_FRAMES/" ) )
1129 return sfa_optional;
1130 if ( MATCH ( path, "PULSE_INDEX/" ) )
1131 return sfa_optional;
1132 break;
1133 case 'Q':
1134 if ( MATCH ( path, "QUALITY2/" ) )
1135 return sfa_optional;
1136 break;
1137 case 'S':
1138 if ( MATCH ( path, "SIGNAL/" ) )
1139 return sfa_optional;
1140 if ( MATCH ( path, "SPOT_NAME/" ) )
1141 return sfa_preferred;
1142 if ( MATCH ( path, "SUBSTITUTION_QV/" ) )
1143 return sfa_optional;
1144 if ( MATCH ( path, "SUBSTITUTION_TAG/" ) )
1145 return sfa_optional;
1146 break;
1147 case 'W':
1148 if ( MATCH ( path, "WIDTH_IN_FRAMES/" ) )
1149 return sfa_optional;
1150 break;
1151 case 'X':
1152 case 'Y':
1153 if ( path [ 1 ] == '/' )
1154 return sfa_preferred;
1155 break;
1156 }
1157 }
1158 return sfa_required;
1159
1160 case 'i':
1161 /* look for skey index */
1162 if ( MATCH ( path, "idx/skey" ) )
1163 if ( path [ 0 ] == 0 || strcmp ( path, ".md5" ) == 0 )
1164 return sfa_preferred;
1165 if ( MATCH ( path, "idx/fuse-" ) )
1166 return sfa_exclude;
1167 break;
1168
1169 case 's':
1170 /* look for old skey index */
1171 if ( MATCH ( path, "skey" ) )
1172 if ( path [ 0 ] == 0 || strcmp ( path, ".md5" ) == 0 )
1173 return sfa_preferred;
1174 break;
1175 }
1176 /* anything not recognized is non-column required */
1177 return sfa_non_column;
1178 }
1179
1180 static
sfa_path_type_db(const char * path)1181 enum sfa_path_type_id CC sfa_path_type_db ( const char *path )
1182 {
1183 /* use first character as distinguisher for match */
1184 switch ( path [ 0 ] )
1185 {
1186 case 't':
1187 /* perhaps it's a table */
1188 if ( MATCH ( path, "tbl/" ) )
1189 {
1190 switch ( path [ 0 ] )
1191 {
1192 case 0:
1193 return sfa_non_column;
1194 case 'S':
1195 if ( MATCH ( path, "SEQUENCE/" ) )
1196 return sfa_path_type_tbl(path);
1197 break;
1198 case 'C':
1199 if ( MATCH ( path, "CONSENSUS/" ) )
1200 return sfa_path_type_tbl(path);
1201 break;
1202 case 'P':
1203 if ( MATCH ( path, "PRIMARY_ALIGNMENT/" ) )
1204 return sfa_path_type_tbl(path);
1205 break;
1206 case 'R':
1207 if ( MATCH ( path, "REFERENCE/" ) )
1208 return sfa_path_type_tbl(path);
1209 break;
1210 }
1211 /* all other tables are optional */
1212 return sfa_optional;
1213 }
1214 }
1215 /* anything not recognized is non-column required */
1216 return sfa_non_column;
1217 }
1218 #undef MATCH
1219
1220 static
sfa_path_cmp(const void ** _a,const void ** _b,void * ignored)1221 int64_t CC sfa_path_cmp ( const void **_a, const void **_b, void * ignored )
1222 {
1223 const reorder_t * a = *_a;
1224 const reorder_t * b = *_b;
1225 int64_t ret;
1226
1227 DEBUG_SORT(("%s enter\t%s %s %lu \t%s %s %lu", __func__,
1228 a->path, sfa_path_type_id[a->type_id + 1], a->size,
1229 b->path, sfa_path_type_id[b->type_id + 1], b->size));
1230
1231 ret = a->type_id - b->type_id;
1232 if (ret == 0)
1233 {
1234 if (a->size > b->size)
1235 ret = 1;
1236 else if (a->size < b->size)
1237 ret = -1;
1238 else
1239 ret = strcmp (a->path, b->path);
1240 }
1241 DEBUG_SORT(("\t%d\n", ret));
1242 return ret;
1243 }
1244
1245 typedef
1246 struct to_nv_data_struct
1247 {
1248 const KDirectory * d;
1249 Vector * v;
1250 rc_t rc;
1251 sfa_path_type_func path_type;
1252 } to_nv_data;
1253
1254 static
to_nv(void * _item,void * _data)1255 void CC to_nv (void * _item, void * _data)
1256 {
1257 const char* path = _item;
1258 to_nv_data* data = _data;
1259 reorder_t* obj;
1260
1261 if (data->rc == 0)
1262 {
1263 obj = malloc (sizeof (*obj));
1264 if (obj == NULL)
1265 data->rc = RC (rcSRA, rcVector, rcConstructing, rcMemory, rcExhausted);
1266 else
1267 {
1268 rc_t rc = KDirectoryFileSize (data->d, &obj->size, "%s", path);
1269 if (rc == 0)
1270 {
1271 obj->path = path;
1272 obj->type_id = data->path_type(path);
1273 rc = VectorAppend (data->v, NULL, obj);
1274 }
1275
1276 if (rc)
1277 {
1278 free (obj);
1279 data->rc = rc;
1280 }
1281 }
1282 }
1283 }
1284
1285 static
item_whack(void * item,void * ignored)1286 void CC item_whack (void * item, void * ignored)
1287 {
1288 free (item);
1289 }
1290
1291 static
sfa_sort(const KDirectory * dir,Vector * v,sfa_path_type_func func)1292 rc_t CC sfa_sort( const KDirectory *dir, Vector *v, sfa_path_type_func func )
1293 {
1294 /* assume "v" is a vector of paths - hopefully relative to "dir" */
1295 Vector nv;
1296 to_nv_data data;
1297 uint32_t base;
1298
1299 DEBUG_SORT(("%s enter\n", __func__));
1300
1301 base = VectorStart (v);
1302 VectorInit (&nv, base, VectorLength (v));
1303 data.d = dir;
1304 data.v = &nv;
1305 data.rc = 0;
1306 data.path_type = func;
1307
1308 VectorForEach (v, false, to_nv, &data);
1309
1310 if(data.rc == 0) {
1311 uint32_t idx = 0;
1312 uint32_t limit = VectorLength (v) + base;
1313
1314 VectorReorder(&nv, sfa_path_cmp, NULL);
1315
1316 for (idx = base; idx < limit; ++idx) {
1317 const reorder_t * tmp;
1318 void * ignore;
1319
1320 tmp = VectorGet (&nv, idx);
1321 data.rc = VectorSwap (v, idx + base, tmp->path, &ignore);
1322 if(data.rc) {
1323 break;
1324 }
1325 }
1326 }
1327 VectorWhack (&nv, item_whack, NULL);
1328 DEBUG_SORT(("%s exit %d %R\n", __func__, data.rc, data.rc));
1329 return data.rc;
1330 }
1331
1332 static
sfa_sort_db(const KDirectory * dir,Vector * v)1333 rc_t CC sfa_sort_db( const KDirectory *dir, Vector *v )
1334 {
1335 return sfa_sort(dir, v, sfa_path_type_db);
1336 }
1337
1338 static
sfa_sort_tbl(const KDirectory * dir,Vector * v)1339 rc_t CC sfa_sort_tbl( const KDirectory *dir, Vector *v )
1340 {
1341 return sfa_sort(dir, v, sfa_path_type_tbl);
1342 }
1343
1344 /*
1345 union sptd_2_void
1346 {
1347 sfa_path_type_func func;
1348 void * ptr;
1349 };
1350
1351 static void * sfa_path_type_func_to_void( sfa_path_type_func func )
1352 {
1353 union sptd_2_void u;
1354 u.func = func;
1355 return u.ptr;
1356 }
1357 */
1358
1359 /* MakeSingleFileArchive
1360 * makes a single-file-archive file from an SRA table
1361 *
1362 * contents are ordered by frequency and necessity of access
1363 *
1364 * "lightweight" [ IN ] - when true, include only those components
1365 * required for read and quality operations.
1366 *
1367 * "ext" [OUT,NULL] - optional file name extension to use for file
1368 */
SRATableMakeSingleFileArchive(const SRATable * self,const KFile ** sfa,bool lightweight,const char ** ext)1369 LIB_EXPORT rc_t CC SRATableMakeSingleFileArchive ( const SRATable *self, const KFile **sfa, bool lightweight, const char** ext)
1370 {
1371 rc_t rc;
1372
1373 if ( sfa == NULL )
1374 {
1375 rc = RC( rcSRA, rcFile, rcConstructing, rcParam, rcNull );
1376 }
1377 else
1378 {
1379 *sfa = NULL;
1380 if ( self == NULL )
1381 {
1382 rc = RC( rcSRA, rcTable, rcAccessing, rcSelf, rcNull );
1383 }
1384 else
1385 {
1386 const VDatabase *db;
1387 rc = VTableOpenParentRead( self->vtbl, &db );
1388 if ( rc == 0 && db != NULL )
1389 {
1390 const KDatabase *kdb;
1391 rc = VDatabaseOpenKDatabaseRead( db, &kdb );
1392 if ( rc == 0 )
1393 {
1394 const KDirectory *db_dir;
1395 rc = KDatabaseOpenDirectoryRead( kdb, &db_dir );
1396 if ( rc == 0 )
1397 {
1398 rc = KDirectoryOpenTocFileRead( db_dir,
1399 sfa,
1400 sraAlign4Byte,
1401 lightweight ? sfa_filter_light : sfa_filter,
1402 ( void * )sfa_path_type_db, /* sfa_path_type_func_to_void( sfa_path_type_db ), */
1403 sfa_sort_db );
1404 KDirectoryRelease( db_dir );
1405 if ( ext != NULL )
1406 {
1407 *ext = CSRA_EXT( lightweight );
1408 }
1409 }
1410 KDatabaseRelease( kdb );
1411 }
1412 VDatabaseRelease( db );
1413 }
1414 else
1415 {
1416 const KTable *ktbl;
1417 rc = SRATableGetKTableRead( self, &ktbl );
1418 if ( rc == 0 )
1419 {
1420 const KDirectory *tbl_dir;
1421 rc = KTableGetDirectoryRead( ktbl, &tbl_dir );
1422 if ( rc == 0 )
1423 {
1424 rc = KDirectoryOpenTocFileRead( tbl_dir,
1425 sfa,
1426 sraAlign4Byte,
1427 lightweight ? sfa_filter_light : sfa_filter,
1428 ( void * )sfa_path_type_tbl, /* sfa_path_type_func_to_void( sfa_path_type_tbl ), */
1429 sfa_sort_tbl );
1430 KDirectoryRelease( tbl_dir );
1431 if ( ext != NULL )
1432 {
1433 *ext = SRA_EXT( lightweight );
1434 }
1435 }
1436 KTableRelease(ktbl);
1437 }
1438 }
1439 }
1440 }
1441 return rc;
1442 }
1443
1444 /* OpenAltTableRead
1445 * opens a table within a database structure with a specific name
1446 */
SRAMgrOpenAltTableRead(const SRAMgr * self,const SRATable ** tbl,const char * altname,const char * spec,...)1447 SRA_EXTERN rc_t CC SRAMgrOpenAltTableRead ( const SRAMgr *self,
1448 const SRATable **tbl, const char *altname, const char *spec, ... )
1449 {
1450 rc_t rc;
1451
1452 va_list args;
1453 va_start ( args, spec );
1454
1455 if ( altname == NULL || altname [ 0 ] == 0 ) {
1456 altname = "SEQUENCE";
1457 }
1458 rc = SRAMgrVOpenAltTableRead ( self, tbl, altname, spec, args );
1459
1460 va_end ( args );
1461 return rc;
1462 }
1463