Copyright 2013 -> 2014
[folly.git] / folly / io / RecordIO-inl.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_IO_RECORDIO_H_
18 #error This file may only be included from folly/io/RecordIO.h
19 #endif
20
21 #include <boost/iterator/iterator_facade.hpp>
22
23 #include "folly/SpookyHashV2.h"
24
25 namespace folly {
26
27 class RecordIOReader::Iterator : public boost::iterator_facade<
28     RecordIOReader::Iterator,
29     const std::pair<ByteRange, off_t>,
30     boost::forward_traversal_tag> {
31   friend class boost::iterator_core_access;
32   friend class RecordIOReader;
33  private:
34   Iterator(ByteRange range, uint32_t fileId, off_t pos);
35
36   reference dereference() const { return recordAndPos_; }
37   bool equal(const Iterator& other) const { return range_ == other.range_; }
38   void increment() {
39     size_t skip = recordio_helpers::headerSize() + recordAndPos_.first.size();
40     recordAndPos_.second += skip;
41     range_.advance(skip);
42     advanceToValid();
43   }
44
45   void advanceToValid();
46   ByteRange range_;
47   uint32_t fileId_;
48   // stored as a pair so we can return by reference in dereference()
49   std::pair<ByteRange, off_t> recordAndPos_;
50 };
51
52 inline auto RecordIOReader::cbegin() const -> Iterator { return seek(0); }
53 inline auto RecordIOReader::begin() const -> Iterator { return cbegin(); }
54 inline auto RecordIOReader::cend() const -> Iterator { return seek(off_t(-1)); }
55 inline auto RecordIOReader::end() const -> Iterator { return cend(); }
56 inline auto RecordIOReader::seek(off_t pos) const -> Iterator {
57   return Iterator(map_.range(), fileId_, pos);
58 }
59
60 namespace recordio_helpers {
61
62 namespace detail {
63
64 struct Header {
65   // First 4 bytes of SHA1("zuck"), big-endian
66   // Any values will do, except that the sequence must not have a
67   // repeated prefix (that is, if we see kMagic, we know that the next
68   // occurrence must start at least 4 bytes later)
69   static constexpr uint32_t kMagic = 0xeac313a1;
70   uint32_t magic;
71   uint8_t  version;       // backwards incompatible version, currently 0
72   uint8_t  hashFunction;  // 0 = SpookyHashV2
73   uint16_t flags;         // reserved (must be 0)
74   uint32_t fileId;        // unique file ID
75   uint32_t dataLength;
76   uint64_t dataHash;
77   uint32_t headerHash;  // must be last
78 } __attribute__((packed));
79
80 static_assert(offsetof(Header, headerHash) + sizeof(Header::headerHash) ==
81               sizeof(Header), "invalid header layout");
82
83 }  // namespace detail
84
85 constexpr size_t headerSize() { return sizeof(detail::Header); }
86
87 inline RecordInfo findRecord(ByteRange range, uint32_t fileId) {
88   return findRecord(range, range, fileId);
89 }
90
91 }  // namespace recordio_helpers
92
93 }  // namespaces
94