TVDBRowIdRange CVDBTableIndex::Find(const string& value) const { TVDBRowIdRange range; if ( rc_t rc = KIndexFindText(*this, value.c_str(), &range.first, &range.second, 0, 0) ) { if ( GetRCObject(rc) == RCObject(rcString) && GetRCState(rc) == rcNotFound ) { // no such value range.first = range.second = 0; } else { NCBI_THROW2_FMT(CSraException, eOtherError, "Cannot find value in index: "<<*this<<": "<<value, rc); } } return range; }
/* CheckConsistency * runs a consistency check as efficiently as possible * * in all cases, we make use of "PTrieForEach" to visit each node * using the natural storage order. each node returned is counted, * read and inserted into a BSTree whose nodes merge adjacent and * overlapping ids into existing nodes. * * if running a deep "key->id" test, then the key is first regenerated * from the node, and then used to retrieve the id via the KIndex. * * if the projection index exists, the id is tested against the node * to ensure that projection works. if "id->key" is true, then use * the KIndex to produce a key and compare it against the node. */ static bool CC KPTrieIndexCCVisit_v2 ( PTNode *n, void *data ) { KPTrieIndexCCParms_v2 *pb = (KPTrieIndexCCParms_v2 *)data; const KPTrieIndex_v2 *self = pb -> self; rc_t rc; int64_t id; size_t usize; uint64_t span; uint32_t i, ord; /* detect conversion from v1 */ if ( pb -> convertFromV1 && self -> id_bits == 0 ) { uint32_t id32; /* payload of v1 PTNode is a 32-bit spot id */ assert ( n -> data . size == sizeof id32 ); memcpy ( & id32, n -> data . addr, sizeof id32 ); id = self -> byteswap ? bswap_32 ( id32 ) : id32; } else { /* native v2 */ /* TBD - should this pass n -> data . size * 8 ??? */ if ( self -> id_bits != 0 ) { rc = Unpack ( self -> id_bits, sizeof id * 8, n -> data . addr, 0, self -> id_bits, NULL, & id, sizeof id, & usize ); if ( rc != 0 ) { PLOGMSG ( klogWarn, ( klogWarn, "could not determine row id of v2 node $(nid)", "nid=0x%08x", n -> id )); pb -> failed = true; return false; } } else { id = 0; } id += self -> first; } /* convert from row-id to 1-based ordinal index */ ord = KPTrieIndexID2Ord_v2 ( self, id ); if ( ord == 0 ) { /* 0 means not found */ PLOGMSG ( klogWarn, ( klogWarn, "v2 node $(nid): row id $(rid) not found in trie", "nid=0x%08x,rid=%ld", n -> id, id )); pb -> failed = true; return false; } if ( self -> ord2node != NULL ) { /* to calculate span of last entry, where 1-based "ord" == the number of nodes, just find the distance between the last row-id in index ( self->maxid ) and the current row-id */ if ( ord == self -> count ) span = self -> maxid - id + 1; else { /* from here on, we will use "ord" to be the ZERO-BASED index of the slot FOLLOWING the one corresponding to id. we want to find the row-id AFTER the current one and calculate distance */ switch ( self -> variant ) { /* linear array */ case 0: /* starting with the FOLLOWING slot, count duplicate entries */ for ( i = ord; i < self -> count; ++ i ) { if ( n -> id != self -> ord2node [ i ] ) break; } span = self -> first + i - id; break; /* packed ordered array of sparse row-ids from here on we already have "id" for this node, so the span will be the distance from NEXT id - 1-based ord is 0-based next */ case 1: span = self -> first + self -> id2ord . v8 [ ord ] - id; break; case 2: span = self -> first + self -> id2ord . v16 [ ord ] - id; break; case 3: span = self -> first + self -> id2ord . v32 [ ord ] - id; break; case 4: span = self -> first + self -> id2ord . v64 [ ord ] - id; break; default: PLOGMSG ( klogErr, ( klogErr, "PTrie v2 index has bad variant code: $(variant)", "variant=%u", self -> variant )); pb -> rc = RC ( rcDB, rcIndex, rcValidating, rcIndex, rcCorrupt ); return true; } } } else if ( self -> span_bits == 0 ) span = 1; else { /* TBD - this case is never used in practice. it would be an skey without a projection index */ rc = Unpack ( self -> span_bits, sizeof span * 8, n -> data . addr, 0, self -> id_bits, NULL, & span, sizeof span, & usize ); if ( rc != 0 ) { PLOGMSG ( klogWarn, ( klogWarn, "could not determine span of v2 node $(nid), row id $(rid)", "nid=0x%08x,rid=%ld", n -> id, id )); pb -> failed = true; return false; } } /* record the node, row id, span */ pb -> rc = KIdStatsInsert ( & pb -> stats, id, span ); if ( pb -> rc != 0 ) { PLOGERR ( klogSys, ( klogSys, pb -> rc, "failed when examining node id $(nid) with row id $(rid), span $(span)", "nid=0x%08x,span=%u,rid=%ld", n -> id, span, id )); return true; } /* if we have a projection index, test it */ if ( self -> ord2node != NULL ) { if ( id < self -> first || id > self -> last ) { PLOGMSG ( klogWarn, ( klogWarn, "node id $(nid) with row id $(rid) is not within projection range of $(min_rid)..$(max_rid)", "nid=0x%08x,rid=%ld,min_rid=%ld,max_rid=%ld", n -> id, id, self -> first, self -> last )); pb -> failed = true; return false; } for ( i = 0; i < span; ++ i ) { if ( self -> ord2node [ i + ord - 1 ] != n -> id ) { PLOGMSG ( klogWarn, ( klogWarn, "node id $(nid) with row id $(rid) does not match projection node id of $(pnid)", "nid=0x%08x,rid=%ld,pnid=0x%08x", n -> id, id + 1, self -> ord2node [ i + ord - 1 ] )); pb -> failed = true; return false; } if ( ! pb -> all_ids || self -> variant != 0 ) break; } } /* if performing deeper tests */ if ( pb -> key2id || pb -> id2key ) { int64_t start_id; uint64_t id_count; /* need to recover key from given node */ const String *orig; pb -> rc = PTNodeMakeKey ( n, & orig ); if ( pb -> rc != 0 ) { PLOGERR ( klogSys, ( klogSys, pb -> rc, "failed when retrieving text for node id $(nid) with row id $(rid)", "nid=0x%08x,rid=%u", n -> id, id )); return true; } /* key->id test */ if ( pb -> key2id ) { rc = KIndexFindText ( pb -> outer, orig -> addr, & start_id, & id_count, NULL, NULL ); if ( rc != 0 ) { PLOGERR ( klogWarn, ( klogWarn, rc, "failed to retrieve start id and count for key '$(key)', row id $(rid)", "key=%S,rid=%u", orig, id ) ); pb -> failed = true; } else if ( start_id != ( int64_t ) id || id_count != span ) { PLOGERR ( klogWarn, ( klogWarn, rc, "key '$(key)' maps to start id $(start_id), count $(id_count): expected id $(rid), count 1.", "key=%S,rid=%u,start_id=%ld,id_count=%lu", orig, id, start_id, id_count ) ); pb -> failed = true; } } /* id->key test */ if ( pb -> id2key ) { char buffer [ 256 ], *key = buffer; size_t key_size, bsize = sizeof buffer; if ( sizeof buffer <= orig -> size ) { key = (char *)malloc ( bsize = orig -> size + 1 ); if ( key == 0 ) { pb -> rc = RC ( rcDB, rcIndex, rcValidating, rcMemory, rcExhausted ); StringWhack ( ( String* ) orig ); return true; } } for ( i = 0; i < span; ++ i ) { rc = KIndexProjectText ( pb -> outer, id + i, & start_id, & id_count, key, bsize, & key_size ); if ( rc != 0 ) { PLOGERR ( klogWarn, ( klogWarn, rc, "failed to retrieve key, start id and count for row id $(rid)", "rid=%u", id + i ) ); pb -> failed = true; break; } if ( orig -> size != key_size || memcmp ( orig -> addr, key, key_size ) != 0 ) { PLOGERR ( klogWarn, ( klogWarn, rc, "row $(rid) maps to key '$(key)': expected key '$(orig)'.", "rid=%u,key=%.*s,orig=%S", id + i, ( int ) key_size, key, orig ) ); pb -> failed = true; } if ( start_id != id || id_count != ( uint64_t ) span ) { PLOGERR ( klogWarn, ( klogWarn, rc, "row $(rid) maps to start id $(start_id), count $(id_count): expected $(row_start), $(span).", "rid=%u,id_count=%lu,start_id=%ld,row_start=%ld,span=%u", id, id_count, start_id, id, span ) ); pb -> failed = true; } if ( ! pb -> all_ids || pb -> failed ) break; } if ( key != buffer ) free ( key ); } StringWhack ( ( String* ) orig ); } return false; }