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 "VByteBlob.h"
28 
29 #include <kfc/except.h>
30 #include <kfc/xc.h>
31 
32 #include <vdb/blob.h>
33 #include <../libs/vdb/blob-priv.h>
34 #include <../libs/vdb/page-map.h>
35 
36 /* Calculate the biggest available contiguous data portion of the blob:
37 *  starts at rowId, ends before a repeated value or at the end of the blob
38 */
39 void
VByteBlob_ContiguousChunk(const VBlob * p_blob,ctx_t ctx,int64_t p_rowId,uint64_t p_maxRows,bool p_stopAtRepeat,const void ** p_data,uint64_t * p_size,uint64_t * p_rowCount)40 VByteBlob_ContiguousChunk ( const VBlob*    p_blob,
41                             ctx_t           ctx,
42                             int64_t         p_rowId,
43                             uint64_t        p_maxRows,
44                             bool            p_stopAtRepeat,
45                             const void **   p_data,
46                             uint64_t *      p_size,
47                             uint64_t *      p_rowCount)
48 {
49     FUNC_ENTRY ( ctx, rcSRA, rcBlob, rcAccessing );
50 
51     assert ( p_blob );
52     assert ( p_data );
53     assert ( p_size );
54 
55     {
56         uint32_t elem_bits;
57         const void *base;
58         uint32_t boff;
59         uint32_t row_len;
60         TRY ( VByteBlob_CellData ( p_blob,
61                                    ctx,
62                                    p_rowId,
63                                    & elem_bits,
64                                    & base,
65                                    & boff,
66                                    & row_len ) )
67         {
68             int64_t first;
69             uint64_t count;
70 
71             assert( elem_bits == 8 );
72             assert( boff == 0 );
73             *p_data = base;
74             *p_size = 0;
75 
76             TRY ( VByteBlob_IdRange ( p_blob, ctx, & first, & count ) )
77             {
78                 if ( p_stopAtRepeat )
79                 {   /* iterate until enough rows are collected, or a repeated row is seen, or we are out of rows in this blob */
80                     PageMapIterator pmIt;
81 
82                     assert ( p_rowId >= first && p_rowId < first + (int64_t)count );
83 
84                     if ( p_rowId - first + 1 < (int64_t)count ) /* more rows in the blob after p_rowId */
85                     {   /* *p_size is the size of value on rowId. Increase size to include subsequent rows, until we see a repeat, p_maxRows is reached or the blob ends */
86                         TRY ( VByteBlob_PageMapNewIterator ( p_blob, ctx, &pmIt, p_rowId - first, count - ( p_rowId - first ) ) ) /* here, rowId is relative to the blob */
87                         {   /* there will always be at least one row */
88                             uint64_t rowCount = 0;
89                             do
90                             {
91                                 ++ rowCount;
92                                 * p_size += PageMapIteratorDataLength ( &pmIt );
93                                 if ( PageMapIteratorRepeatCount ( &pmIt ) > 1 )
94                                 {   /* repeated row found */
95                                     break;
96                                 }
97                                 if ( p_maxRows != 0 && rowCount == p_maxRows )
98                                 {   /* this is all we were asked for  */
99                                     break;
100                                 }
101                             }
102                             while ( PageMapIteratorNext ( &pmIt ) );
103 
104                             if ( p_rowCount != 0 )
105                             {
106                                 * p_rowCount = rowCount;
107                             }
108                         }
109                     }
110                     else /* p_rowId is the last row of the blob; return the entire blob */
111                     {
112                         * p_size = row_len;
113                         if ( p_rowCount != 0 )
114                         {
115                             * p_rowCount = count;
116                         }
117                     }
118                 }
119                 else if ( p_maxRows > 0 && p_maxRows < count - ( p_rowId - first ) )
120                 {   /* return the size of the first p_maxRows rows */
121                     const uint8_t* firstRow = (const uint8_t*)base;
122                     VByteBlob_CellData ( p_blob,
123                                          ctx,
124                                          p_rowId + p_maxRows,
125                                          & elem_bits,
126                                          & base,
127                                          & boff,
128                                          & row_len );
129                     * p_size = (const uint8_t*)( base ) - firstRow;
130                     if ( p_rowCount != 0 )
131                     {
132                         * p_rowCount = p_maxRows;
133                     }
134                 }
135                 else
136                 {   /* set the size to include the rest of the blob's data */
137                     * p_size = BlobBufferBytes ( p_blob ) - ( (const uint8_t*)( base ) - (const uint8_t*)( p_blob -> data . base ) );
138                     if ( p_rowCount != 0 )
139                     {
140                         * p_rowCount = count;
141                     }
142                 }
143             }
144         }
145     }
146 }
147 
148 void
VByteBlob_IdRange(const struct VBlob * p_blob,ctx_t ctx,int64_t * p_first,uint64_t * p_count)149 VByteBlob_IdRange ( const struct VBlob * p_blob,  ctx_t ctx, int64_t * p_first, uint64_t * p_count )
150 {
151     FUNC_ENTRY ( ctx, rcSRA, rcBlob, rcAccessing );
152     rc_t rc = VBlobIdRange ( p_blob, p_first, p_count );
153     if ( rc != 0  )
154     {
155         INTERNAL_ERROR ( xcUnexpected, "VBlobIdRange() rc = %R", rc );
156     }
157 }
158 
VByteBlob_CellData(const struct VBlob * p_blob,ctx_t ctx,int64_t p_row_id,uint32_t * p_elem_bits,const void ** p_base,uint32_t * p_boff,uint32_t * p_row_len)159 void VByteBlob_CellData ( const struct VBlob *  p_blob,
160                           ctx_t                 ctx,
161                           int64_t               p_row_id,
162                           uint32_t *            p_elem_bits,
163                           const void **         p_base,
164                           uint32_t *            p_boff,
165                           uint32_t *            p_row_len )
166 {
167     FUNC_ENTRY ( ctx, rcSRA, rcBlob, rcAccessing );
168     rc_t rc = VBlobCellData ( p_blob, p_row_id, p_elem_bits, p_base, p_boff, p_row_len );
169     if ( rc != 0  )
170     {
171         INTERNAL_ERROR ( xcUnexpected, "VBlobCellData() rc = %R", rc );
172     }
173 }
174 
VByteBlob_PageMapNewIterator(const struct VBlob * p_blob,ctx_t ctx,PageMapIterator * p_iter,uint64_t p_first_row,uint64_t p_num_rows)175 void VByteBlob_PageMapNewIterator ( const struct VBlob *    p_blob,
176                                     ctx_t                   ctx,
177                                     PageMapIterator *       p_iter,
178                                     uint64_t                p_first_row,
179                                     uint64_t                p_num_rows )
180 {
181     FUNC_ENTRY ( ctx, rcSRA, rcBlob, rcAccessing );
182     rc_t rc = PageMapNewIterator ( p_blob -> pm, p_iter, p_first_row, p_num_rows );
183     if ( rc != 0  )
184     {
185         INTERNAL_ERROR ( xcUnexpected, "PageMapNewIterator() rc = %R", rc );
186     }
187 }
188