void testVarint(uint64_t val, std::initializer_list<uint8_t> bytes) { size_t n = bytes.size(); ByteRange expected(&*bytes.begin(), n); { uint8_t buf[kMaxVarintLength64]; EXPECT_EQ(expected.size(), encodeVarint(val, buf)); EXPECT_TRUE(ByteRange(buf, expected.size()) == expected); } { ByteRange r = expected; uint64_t decoded = decodeVarint(r); EXPECT_TRUE(r.empty()); EXPECT_EQ(val, decoded); } if (n < kMaxVarintLength64) { // Try from a full buffer too, different code path uint8_t buf[kMaxVarintLength64]; memcpy(buf, &*bytes.begin(), n); uint8_t fills[] = {0, 0x7f, 0x80, 0xff}; for (uint8_t fill : fills) { memset(buf + n, fill, kMaxVarintLength64 - n); ByteRange r(buf, kMaxVarintLength64); uint64_t decoded = decodeVarint(r); EXPECT_EQ(val, decoded); EXPECT_EQ(kMaxVarintLength64 - n, r.size()); } } }
inline int decodeBlockHandle(BlockHandle* blockHandle,const Slice* slice) { size_t offset = 0; blockHandle->offset_ = decodeVarint(slice->data_,&offset); blockHandle->size_ = decodeVarint(slice->data_,&offset); return slice->size_; }
/* * 将BlockEntry转化成IndexBlockEntry */ inline int blockEntryToIndexBlock(IndexBlockEntry* index,const BlockEntry* entry) { size_t offset = 0; index->key_ = entry->key_; index->blockhandle.offset_ = decodeVarint(entry->value_.data_,&offset); index->blockhandle.size_ = decodeVarint(entry->value_.data_,&offset); return entry->value_.size_; }
/* ** Create a description for a single cell. ** ** The return value is the local cell size. */ static int describeCell( unsigned char cType, /* Page type */ unsigned char *a, /* Cell content */ int showCellContent, /* Show cell content if true */ char **pzDesc /* Store description here */ ){ int i; int nDesc = 0; int n = 0; int leftChild; i64 nPayload; i64 rowid; int nLocal; static char zDesc[1000]; i = 0; if( cType<=5 ){ leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3]; a += 4; n += 4; sprintf(zDesc, "lx: %d ", leftChild); nDesc = strlen(zDesc); } if( cType!=5 ){ i = decodeVarint(a, &nPayload); a += i; n += i; sprintf(&zDesc[nDesc], "n: %lld ", nPayload); nDesc += strlen(&zDesc[nDesc]); nLocal = localPayload(nPayload, cType); }else{ nPayload = nLocal = 0; } if( cType==5 || cType==13 ){ i = decodeVarint(a, &rowid); a += i; n += i; sprintf(&zDesc[nDesc], "r: %lld ", rowid); nDesc += strlen(&zDesc[nDesc]); } if( nLocal<nPayload ){ int ovfl; unsigned char *b = &a[nLocal]; ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3]; sprintf(&zDesc[nDesc], "ov: %d ", ovfl); nDesc += strlen(&zDesc[nDesc]); n += 4; } if( showCellContent && cType!=5 ){ nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]); } *pzDesc = zDesc; return nLocal+n; }
TEST(Varint, Interface) { // Make sure decodeVarint() accepts all of StringPiece, MutableStringPiece, // ByteRange, and MutableByteRange. char c = 0; StringPiece sp(&c, 1); EXPECT_EQ(decodeVarint(sp), 0); MutableStringPiece msp(&c, 1); EXPECT_EQ(decodeVarint(msp), 0); ByteRange br(reinterpret_cast<unsigned char*>(&c), 1); EXPECT_EQ(decodeVarint(br), 0); MutableByteRange mbr(reinterpret_cast<unsigned char*>(&c), 1); EXPECT_EQ(decodeVarint(mbr), 0); }
/* * 获取重启点的key值 */ inline int getBlockEntryKey(const unsigned char* data,Slice* key) { size_t offset = 0; //uint64_t i = 0; uint64_t sharedKeyLen = decodeVarint(data,&offset); uint64_t nosharedKeyLen = decodeVarint(data,&offset); uint64_t valueLen = decodeVarint(data,&offset); printf("sharedKeyLen(%lu),nosharedKeyLen(%lu),valueLen(%lu).\n",sharedKeyLen,nosharedKeyLen,valueLen); if(sharedKeyLen > 0 && key->size_ == 0){ printf("error:This is not a restart point.\n"); return 0; } resetSliceLength(key,nosharedKeyLen); memcpy(key->data_,data+offset,nosharedKeyLen); key->size_ = nosharedKeyLen; return 1; }
/* ** Find overflow pages of a cell and describe their usage. */ static void page_usage_cell( unsigned char cType, /* Page type */ unsigned char *a, /* Cell content */ int pgno, /* page containing the cell */ int cellno /* Index of the cell on the page */ ){ int i; int nDesc = 0; int n = 0; i64 nPayload; i64 rowid; int nLocal; i = 0; if( cType<=5 ){ a += 4; n += 4; } if( cType!=5 ){ i = decodeVarint(a, &nPayload); a += i; n += i; nLocal = localPayload(nPayload, cType); }else{ nPayload = nLocal = 0; } if( cType==5 || cType==13 ){ i = decodeVarint(a, &rowid); a += i; n += i; } if( nLocal<nPayload ){ int ovfl = decodeInt32(a+nLocal); int cnt = 0; while( ovfl && (cnt++)<mxPage ){ page_usage_msg(ovfl, "overflow %d from cell %d of page %d", cnt, cellno, pgno); a = getContent((ovfl-1)*pagesize, 4); ovfl = decodeInt32(a); free(a); } } }
/* * 解析Block项 */ inline size_t decodeBlockEntry(BlockEntry* blockEntry,const unsigned char* data,Slice* lastKey) { size_t offset = 0; //uint64_t i = 0; uint64_t sharedKeyLen = decodeVarint(data,&offset); uint64_t nosharedKeyLen = decodeVarint(data,&offset); uint64_t valueLen = decodeVarint(data,&offset); //printf("sharedKeyLen = %llu,nosharedKeyLen = %llu,valueLen = %llu\n",sharedKeyLen,nosharedKeyLen,valueLen); if(lastKey->size_ < sharedKeyLen){ printf("lastKey length is wrong!\n"); return 0; } /* 读取key */ blockEntry->key_.size_ = sharedKeyLen + nosharedKeyLen; resetSliceLength(&blockEntry->key_,blockEntry->key_.size_); memcpy(blockEntry->key_.data_,lastKey->data_,sharedKeyLen); memcpy(blockEntry->key_.data_+sharedKeyLen,data+offset,nosharedKeyLen); offset += nosharedKeyLen; /* 更新lastkey */ resetSliceLength(lastKey,blockEntry->key_.size_); lastKey->size_ = blockEntry->key_.size_; memcpy(lastKey->data_,blockEntry->key_.data_,blockEntry->key_.size_); /*读取value*/ blockEntry->value_.size_ = valueLen; resetSliceLength(&blockEntry->value_,valueLen); memcpy(blockEntry->value_.data_,data+offset,valueLen); offset+=valueLen; //showIndexBlockEntry(blockEntry); /* 返回此blockEntry占用的字节数 */ return offset; }
/* ** Describe cell content. */ static int describeContent( unsigned char *a, /* Cell content */ int nLocal, /* Bytes in a[] */ char *zDesc /* Write description here */ ){ int nDesc = 0; int n, i, j; i64 x, v; const unsigned char *pData; const unsigned char *pLimit; char sep = ' '; pLimit = &a[nLocal]; n = decodeVarint(a, &x); pData = &a[x]; a += n; i = x - n; while( i>0 && pData<=pLimit ){ n = decodeVarint(a, &x); a += n; i -= n; nLocal -= n; zDesc[0] = sep; sep = ','; nDesc++; zDesc++; if( x==0 ){ sprintf(zDesc, "*"); /* NULL is a "*" */ }else if( x>=1 && x<=6 ){ v = (signed char)pData[0]; pData++; switch( x ){ case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; case 4: v = (v<<8) + pData[0]; pData++; case 3: v = (v<<8) + pData[0]; pData++; case 2: v = (v<<8) + pData[0]; pData++; } sprintf(zDesc, "%lld", v); }else if( x==7 ){ sprintf(zDesc, "real"); pData += 8; }else if( x==8 ){ sprintf(zDesc, "0"); }else if( x==9 ){ sprintf(zDesc, "1"); }else if( x>=12 ){ int size = (x-12)/2; if( (x&1)==0 ){ sprintf(zDesc, "blob(%d)", size); }else{ sprintf(zDesc, "txt(%d)", size); } pData += size; } j = strlen(zDesc); zDesc += j; nDesc += j; } return nDesc; }
int main(int argc, char **argv){ sqlite3 *db; sqlite3_stmt *pStmt; char *zIdx = 0; int rc, j, x, y, mxHdr; const unsigned char *aSample; int nSample; i64 iVal; const char *zSep; int iRow = 0; if( argc!=2 ){ fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]); exit(1); } rc = sqlite3_open(argv[1], &db); if( rc!=SQLITE_OK || db==0 ){ fprintf(stderr, "Cannot open database file [%s]\n", argv[1]); exit(1); } rc = sqlite3_prepare_v2(db, "SELECT tbl||'.'||idx, nEq, nLT, nDLt, sample " "FROM sqlite_stat4 ORDER BY 1", -1, &pStmt, 0); if( rc!=SQLITE_OK || pStmt==0 ){ fprintf(stderr, "%s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } while( SQLITE_ROW==sqlite3_step(pStmt) ){ if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){ if( zIdx ) printf("\n**************************************" "**************\n\n"); sqlite3_free(zIdx); zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0)); iRow = 0; } printf("%s sample %d ------------------------------------\n", zIdx, ++iRow); printf(" nEq = %s\n", sqlite3_column_text(pStmt,1)); printf(" nLt = %s\n", sqlite3_column_text(pStmt,2)); printf(" nDLt = %s\n", sqlite3_column_text(pStmt,3)); printf(" sample = x'"); aSample = sqlite3_column_blob(pStmt,4); nSample = sqlite3_column_bytes(pStmt,4); for(j=0; j<nSample; j++) printf("%02x", aSample[j]); printf("'\n "); zSep = " "; x = decodeVarint(aSample, &iVal); if( iVal<x || iVal>nSample ){ printf(" <error>\n"); continue; } y = mxHdr = (int)iVal; while( x<mxHdr ){ int sz; i64 v; x += decodeVarint(aSample+x, &iVal); if( x>mxHdr ) break; if( iVal<0 ) break; switch( iVal ){ case 0: sz = 0; break; case 1: sz = 1; break; case 2: sz = 2; break; case 3: sz = 3; break; case 4: sz = 4; break; case 5: sz = 6; break; case 6: sz = 8; break; case 7: sz = 8; break; case 8: sz = 0; break; case 9: sz = 0; break; case 10: case 11: sz = 0; break; default: sz = (int)(iVal-12)/2; break; } if( y+sz>nSample ) break; if( iVal==0 ){ printf("%sNULL", zSep); }else if( iVal==8 || iVal==9 ){ printf("%s%d", zSep, ((int)iVal)-8); }else if( iVal<=7 ){ v = (signed char)aSample[y]; for(j=1; j<sz; j++){ v = (v<<8) + aSample[y+j]; } if( iVal==7 ){ double r; memcpy(&r, &v, sizeof(r)); printf("%s%#g", zSep, r); }else{ printf("%s%lld", zSep, v); } }else if( (iVal&1)==0 ){ printf("%sx'", zSep); for(j=0; j<sz; j++){ printf("%02x", aSample[y+j]); } printf("'"); }else{ printf("%s\"", zSep); for(j=0; j<sz; j++){ char c = (char)aSample[y+j]; if( ISPRINT(c) ){ if( c=='"' || c=='\\' ) putchar('\\'); putchar(c); }else if( c=='\n' ){ printf("\\n"); }else if( c=='\t' ){ printf("\\t"); }else if( c=='\r' ){ printf("\\r"); }else{ printf("\\%03o", c); } } printf("\""); } zSep = ","; y += sz; } printf("\n"); } sqlite3_free(zIdx); sqlite3_finalize(pStmt); sqlite3_close(db); return 0; }
/* ** Write a full decode on stdout for the cell at a[ofst]. ** Assume the page contains a header of size szPgHdr bytes. */ static void decodeCell( unsigned char *a, /* Page content (without the page-1 header) */ unsigned pgno, /* Page number */ int iCell, /* Cell index */ int szPgHdr, /* Size of the page header. 0 or 100 */ int ofst /* Cell begins at a[ofst] */ ){ int i, j = 0; int leftChild; i64 k; i64 nPayload; i64 rowid; i64 nHdr; i64 iType; i64 nLocal; unsigned char *x = a + ofst; unsigned char *end; unsigned char cType = a[0]; int nCol = 0; int szCol[2000]; int ofstCol[2000]; int typeCol[2000]; printf("Cell[%d]:\n", iCell); if( cType<=5 ){ leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3]; printBytes(a, x, 4); printf("left child page:: %d\n", leftChild); x += 4; } if( cType!=5 ){ i = decodeVarint(x, &nPayload); printBytes(a, x, i); nLocal = localPayload(nPayload, cType); if( nLocal==nPayload ){ printf("payload-size: %lld\n", nPayload); }else{ printf("payload-size: %lld (%lld local, %lld overflow)\n", nPayload, nLocal, nPayload-nLocal); } x += i; }else{ nPayload = nLocal = 0; } end = x + nLocal; if( cType==5 || cType==13 ){ i = decodeVarint(x, &rowid); printBytes(a, x, i); printf("rowid: %lld\n", rowid); x += i; } if( nLocal>0 ){ i = decodeVarint(x, &nHdr); printBytes(a, x, i); printf("record-header-size: %d\n", (int)nHdr); j = i; nCol = 0; k = nHdr; while( x+j<end && j<nHdr ){ const char *zTypeName; int sz = 0; char zNm[30]; i = decodeVarint(x+j, &iType); printBytes(a, x+j, i); printf("typecode[%d]: %d - ", nCol, (int)iType); switch( iType ){ case 0: zTypeName = "NULL"; sz = 0; break; case 1: zTypeName = "int8"; sz = 1; break; case 2: zTypeName = "int16"; sz = 2; break; case 3: zTypeName = "int24"; sz = 3; break; case 4: zTypeName = "int32"; sz = 4; break; case 5: zTypeName = "int48"; sz = 6; break; case 6: zTypeName = "int64"; sz = 8; break; case 7: zTypeName = "double"; sz = 8; break; case 8: zTypeName = "zero"; sz = 0; break; case 9: zTypeName = "one"; sz = 0; break; case 10: case 11: zTypeName = "error"; sz = 0; break; default: { sz = (int)(iType-12)/2; sprintf(zNm, (iType&1)==0 ? "blob(%d)" : "text(%d)", sz); zTypeName = zNm; break; } } printf("%s\n", zTypeName); szCol[nCol] = sz; ofstCol[nCol] = (int)k; typeCol[nCol] = (int)iType; k += sz; nCol++; j += i; } for(i=0; i<nCol && ofstCol[i]+szCol[i]<=nLocal; i++){ int s = ofstCol[i]; i64 v; const unsigned char *pData; if( szCol[i]==0 ) continue; printBytes(a, x+s, szCol[i]); printf("data[%d]: ", i); pData = x+s; if( typeCol[i]<=7 ){ v = (signed char)pData[0]; for(k=1; k<szCol[i]; k++){ v = (v<<8) + pData[k]; } if( typeCol[i]==7 ){ double r; memcpy(&r, &v, sizeof(r)); printf("%#g\n", r); }else{ printf("%lld\n", v); } }else{ int ii, jj; char zConst[32]; if( (typeCol[i]&1)==0 ){ zConst[0] = 'x'; zConst[1] = '\''; for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){ sprintf(zConst+ii, "%02x", pData[jj]); } }else{ zConst[0] = '\''; for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){ zConst[ii] = ISPRINT(pData[jj]) ? pData[jj] : '.'; } zConst[ii] = 0; } if( jj<szCol[i] ){ memcpy(zConst+ii, "...'", 5); }else{ memcpy(zConst+ii, "'", 2); } printf("%s\n", zConst); } j = ofstCol[i] + szCol[i]; } } if( j<nLocal ){ printBytes(a, x+j, 0); printf("... %lld bytes of content ...\n", nLocal-j); } if( nLocal<nPayload ){ printBytes(a, x+nLocal, 4); printf("overflow-page: %d\n", decodeInt32(x+nLocal)); } }