1/*
2 * Copyright 2013-present 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/hash/SpookyHashV2.h>
24
25namespace folly {
26
27class 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
34 private:
35 Iterator(ByteRange range, uint32_t fileId, off_t pos);
36
37 reference dereference() const {
38 return recordAndPos_;
39 }
40 bool equal(const Iterator& other) const {
41 return range_ == other.range_;
42 }
43 void increment() {
44 size_t skip = recordio_helpers::headerSize() + recordAndPos_.first.size();
45 recordAndPos_.second += off_t(skip);
46 range_.advance(skip);
47 advanceToValid();
48 }
49
50 void advanceToValid();
51 ByteRange range_;
52 uint32_t fileId_;
53 // stored as a pair so we can return by reference in dereference()
54 std::pair<ByteRange, off_t> recordAndPos_;
55};
56
57inline auto RecordIOReader::cbegin() const -> Iterator {
58 return seek(0);
59}
60inline auto RecordIOReader::begin() const -> Iterator {
61 return cbegin();
62}
63inline auto RecordIOReader::cend() const -> Iterator {
64 return seek(off_t(-1));
65}
66inline auto RecordIOReader::end() const -> Iterator {
67 return cend();
68}
69inline auto RecordIOReader::seek(off_t pos) const -> Iterator {
70 return Iterator(map_.range(), fileId_, pos);
71}
72
73namespace recordio_helpers {
74
75namespace recordio_detail {
76
77FOLLY_PACK_PUSH
78struct Header {
79 // First 4 bytes of SHA1("zuck"), big-endian
80 // Any values will do, except that the sequence must not have a
81 // repeated prefix (that is, if we see kMagic, we know that the next
82 // occurrence must start at least 4 bytes later)
83 static constexpr uint32_t kMagic = 0xeac313a1;
84 uint32_t magic;
85 uint8_t version; // backwards incompatible version, currently 0
86 uint8_t hashFunction; // 0 = SpookyHashV2
87 uint16_t flags; // reserved (must be 0)
88 uint32_t fileId; // unique file ID
89 uint32_t dataLength;
90 std::size_t dataHash;
91 uint32_t headerHash; // must be last
92} FOLLY_PACK_ATTR;
93FOLLY_PACK_POP
94
95static_assert(
96 offsetof(Header, headerHash) + sizeof(Header::headerHash) == sizeof(Header),
97 "invalid header layout");
98
99} // namespace recordio_detail
100
101constexpr size_t headerSize() {
102 return sizeof(recordio_detail::Header);
103}
104
105inline RecordInfo findRecord(ByteRange range, uint32_t fileId) {
106 return findRecord(range, range, fileId);
107}
108
109} // namespace recordio_helpers
110
111} // namespace folly
112