예제 #1
0
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;
}
예제 #2
0
/* 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;
}