1*9507f98cSAndroid Build Coastguard Workerleveldb Log format 2*9507f98cSAndroid Build Coastguard Worker================== 3*9507f98cSAndroid Build Coastguard WorkerThe log file contents are a sequence of 32KB blocks. The only exception is that 4*9507f98cSAndroid Build Coastguard Workerthe tail of the file may contain a partial block. 5*9507f98cSAndroid Build Coastguard Worker 6*9507f98cSAndroid Build Coastguard WorkerEach block consists of a sequence of records: 7*9507f98cSAndroid Build Coastguard Worker 8*9507f98cSAndroid Build Coastguard Worker block := record* trailer? 9*9507f98cSAndroid Build Coastguard Worker record := 10*9507f98cSAndroid Build Coastguard Worker checksum: uint32 // crc32c of type and data[] ; little-endian 11*9507f98cSAndroid Build Coastguard Worker length: uint16 // little-endian 12*9507f98cSAndroid Build Coastguard Worker type: uint8 // One of FULL, FIRST, MIDDLE, LAST 13*9507f98cSAndroid Build Coastguard Worker data: uint8[length] 14*9507f98cSAndroid Build Coastguard Worker 15*9507f98cSAndroid Build Coastguard WorkerA record never starts within the last six bytes of a block (since it won't fit). 16*9507f98cSAndroid Build Coastguard WorkerAny leftover bytes here form the trailer, which must consist entirely of zero 17*9507f98cSAndroid Build Coastguard Workerbytes and must be skipped by readers. 18*9507f98cSAndroid Build Coastguard Worker 19*9507f98cSAndroid Build Coastguard WorkerAside: if exactly seven bytes are left in the current block, and a new non-zero 20*9507f98cSAndroid Build Coastguard Workerlength record is added, the writer must emit a FIRST record (which contains zero 21*9507f98cSAndroid Build Coastguard Workerbytes of user data) to fill up the trailing seven bytes of the block and then 22*9507f98cSAndroid Build Coastguard Workeremit all of the user data in subsequent blocks. 23*9507f98cSAndroid Build Coastguard Worker 24*9507f98cSAndroid Build Coastguard WorkerMore types may be added in the future. Some Readers may skip record types they 25*9507f98cSAndroid Build Coastguard Workerdo not understand, others may report that some data was skipped. 26*9507f98cSAndroid Build Coastguard Worker 27*9507f98cSAndroid Build Coastguard Worker FULL == 1 28*9507f98cSAndroid Build Coastguard Worker FIRST == 2 29*9507f98cSAndroid Build Coastguard Worker MIDDLE == 3 30*9507f98cSAndroid Build Coastguard Worker LAST == 4 31*9507f98cSAndroid Build Coastguard Worker 32*9507f98cSAndroid Build Coastguard WorkerThe FULL record contains the contents of an entire user record. 33*9507f98cSAndroid Build Coastguard Worker 34*9507f98cSAndroid Build Coastguard WorkerFIRST, MIDDLE, LAST are types used for user records that have been split into 35*9507f98cSAndroid Build Coastguard Workermultiple fragments (typically because of block boundaries). FIRST is the type 36*9507f98cSAndroid Build Coastguard Workerof the first fragment of a user record, LAST is the type of the last fragment of 37*9507f98cSAndroid Build Coastguard Workera user record, and MIDDLE is the type of all interior fragments of a user 38*9507f98cSAndroid Build Coastguard Workerrecord. 39*9507f98cSAndroid Build Coastguard Worker 40*9507f98cSAndroid Build Coastguard WorkerExample: consider a sequence of user records: 41*9507f98cSAndroid Build Coastguard Worker 42*9507f98cSAndroid Build Coastguard Worker A: length 1000 43*9507f98cSAndroid Build Coastguard Worker B: length 97270 44*9507f98cSAndroid Build Coastguard Worker C: length 8000 45*9507f98cSAndroid Build Coastguard Worker 46*9507f98cSAndroid Build Coastguard Worker**A** will be stored as a FULL record in the first block. 47*9507f98cSAndroid Build Coastguard Worker 48*9507f98cSAndroid Build Coastguard Worker**B** will be split into three fragments: first fragment occupies the rest of 49*9507f98cSAndroid Build Coastguard Workerthe first block, second fragment occupies the entirety of the second block, and 50*9507f98cSAndroid Build Coastguard Workerthe third fragment occupies a prefix of the third block. This will leave six 51*9507f98cSAndroid Build Coastguard Workerbytes free in the third block, which will be left empty as the trailer. 52*9507f98cSAndroid Build Coastguard Worker 53*9507f98cSAndroid Build Coastguard Worker**C** will be stored as a FULL record in the fourth block. 54*9507f98cSAndroid Build Coastguard Worker 55*9507f98cSAndroid Build Coastguard Worker---- 56*9507f98cSAndroid Build Coastguard Worker 57*9507f98cSAndroid Build Coastguard Worker## Some benefits over the recordio format: 58*9507f98cSAndroid Build Coastguard Worker 59*9507f98cSAndroid Build Coastguard Worker1. We do not need any heuristics for resyncing - just go to next block boundary 60*9507f98cSAndroid Build Coastguard Worker and scan. If there is a corruption, skip to the next block. As a 61*9507f98cSAndroid Build Coastguard Worker side-benefit, we do not get confused when part of the contents of one log 62*9507f98cSAndroid Build Coastguard Worker file are embedded as a record inside another log file. 63*9507f98cSAndroid Build Coastguard Worker 64*9507f98cSAndroid Build Coastguard Worker2. Splitting at approximate boundaries (e.g., for mapreduce) is simple: find the 65*9507f98cSAndroid Build Coastguard Worker next block boundary and skip records until we hit a FULL or FIRST record. 66*9507f98cSAndroid Build Coastguard Worker 67*9507f98cSAndroid Build Coastguard Worker3. We do not need extra buffering for large records. 68*9507f98cSAndroid Build Coastguard Worker 69*9507f98cSAndroid Build Coastguard Worker## Some downsides compared to recordio format: 70*9507f98cSAndroid Build Coastguard Worker 71*9507f98cSAndroid Build Coastguard Worker1. No packing of tiny records. This could be fixed by adding a new record type, 72*9507f98cSAndroid Build Coastguard Worker so it is a shortcoming of the current implementation, not necessarily the 73*9507f98cSAndroid Build Coastguard Worker format. 74*9507f98cSAndroid Build Coastguard Worker 75*9507f98cSAndroid Build Coastguard Worker2. No compression. Again, this could be fixed by adding new record types. 76