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