LCOV - code coverage report
Current view: top level - src/leveldb/db - log_writer.cc (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 48 49 98.0 %
Date: 2015-10-12 22:39:14 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file. See the AUTHORS file for names of contributors.
       4             : 
       5             : #include "db/log_writer.h"
       6             : 
       7             : #include <stdint.h>
       8             : #include "leveldb/env.h"
       9             : #include "util/coding.h"
      10             : #include "util/crc32c.h"
      11             : 
      12             : namespace leveldb {
      13             : namespace log {
      14             : 
      15         617 : Writer::Writer(WritableFile* dest)
      16             :     : dest_(dest),
      17         617 :       block_offset_(0) {
      18        3702 :   for (int i = 0; i <= kMaxRecordType; i++) {
      19        3085 :     char t = static_cast<char>(i);
      20        3085 :     type_crc_[i] = crc32c::Value(&t, 1);
      21             :   }
      22         617 : }
      23             : 
      24         617 : Writer::~Writer() {
      25         617 : }
      26             : 
      27        1175 : Status Writer::AddRecord(const Slice& slice) {
      28        1175 :   const char* ptr = slice.data();
      29        1175 :   size_t left = slice.size();
      30             : 
      31             :   // Fragment the record if necessary and emit it.  Note that if slice
      32             :   // is empty, we still want to iterate once to emit a single
      33             :   // zero-length record
      34             :   Status s;
      35        1175 :   bool begin = true;
      36        1207 :   do {
      37        1207 :     const int leftover = kBlockSize - block_offset_;
      38        1207 :     assert(leftover >= 0);
      39        1207 :     if (leftover < kHeaderSize) {
      40             :       // Switch to a new block
      41          32 :       if (leftover > 0) {
      42             :         // Fill the trailer (literal below relies on kHeaderSize being 7)
      43             :         assert(kHeaderSize == 7);
      44           0 :         dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
      45             :       }
      46          32 :       block_offset_ = 0;
      47             :     }
      48             : 
      49             :     // Invariant: we never leave < kHeaderSize bytes in a block.
      50        1207 :     assert(kBlockSize - block_offset_ - kHeaderSize >= 0);
      51             : 
      52        1207 :     const size_t avail = kBlockSize - block_offset_ - kHeaderSize;
      53        1207 :     const size_t fragment_length = (left < avail) ? left : avail;
      54             : 
      55             :     RecordType type;
      56        1207 :     const bool end = (left == fragment_length);
      57        1207 :     if (begin && end) {
      58             :       type = kFullType;
      59          33 :     } else if (begin) {
      60             :       type = kFirstType;
      61          32 :     } else if (end) {
      62             :       type = kLastType;
      63             :     } else {
      64          31 :       type = kMiddleType;
      65             :     }
      66             : 
      67        2414 :     s = EmitPhysicalRecord(type, ptr, fragment_length);
      68        1207 :     ptr += fragment_length;
      69        1207 :     left -= fragment_length;
      70        1207 :     begin = false;
      71        1207 :   } while (s.ok() && left > 0);
      72        1175 :   return s;
      73             : }
      74             : 
      75        1207 : Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) {
      76        1207 :   assert(n <= 0xffff);  // Must fit in two bytes
      77        1207 :   assert(block_offset_ + kHeaderSize + n <= kBlockSize);
      78             : 
      79             :   // Format the header
      80             :   char buf[kHeaderSize];
      81        1207 :   buf[4] = static_cast<char>(n & 0xff);
      82        1207 :   buf[5] = static_cast<char>(n >> 8);
      83        1207 :   buf[6] = static_cast<char>(t);
      84             : 
      85             :   // Compute the crc of the record type and the payload.
      86        1207 :   uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n);
      87        1207 :   crc = crc32c::Mask(crc);                 // Adjust for storage
      88        1207 :   EncodeFixed32(buf, crc);
      89             : 
      90             :   // Write the header and the payload
      91        2414 :   Status s = dest_->Append(Slice(buf, kHeaderSize));
      92        1207 :   if (s.ok()) {
      93        3621 :     s = dest_->Append(Slice(ptr, n));
      94        1207 :     if (s.ok()) {
      95        2414 :       s = dest_->Flush();
      96             :     }
      97             :   }
      98        1207 :   block_offset_ += kHeaderSize + n;
      99        1207 :   return s;
     100             : }
     101             : 
     102             : }  // namespace log
     103             : }  // namespace leveldb

Generated by: LCOV version 1.11