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 | |
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 | |
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 | |
57 | inline auto RecordIOReader::cbegin() const -> Iterator { |
58 | return seek(0); |
59 | } |
60 | inline auto RecordIOReader::begin() const -> Iterator { |
61 | return cbegin(); |
62 | } |
63 | inline auto RecordIOReader::cend() const -> Iterator { |
64 | return seek(off_t(-1)); |
65 | } |
66 | inline auto RecordIOReader::end() const -> Iterator { |
67 | return cend(); |
68 | } |
69 | inline auto RecordIOReader::seek(off_t pos) const -> Iterator { |
70 | return Iterator(map_.range(), fileId_, pos); |
71 | } |
72 | |
73 | namespace recordio_helpers { |
74 | |
75 | namespace recordio_detail { |
76 | |
77 | FOLLY_PACK_PUSH |
78 | struct { |
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 = 0xeac313a1; |
84 | uint32_t ; |
85 | uint8_t ; // backwards incompatible version, currently 0 |
86 | uint8_t ; // 0 = SpookyHashV2 |
87 | uint16_t ; // reserved (must be 0) |
88 | uint32_t ; // unique file ID |
89 | uint32_t ; |
90 | std::size_t ; |
91 | uint32_t ; // must be last |
92 | } FOLLY_PACK_ATTR; |
93 | FOLLY_PACK_POP |
94 | |
95 | static_assert( |
96 | offsetof(Header, headerHash) + sizeof(Header::headerHash) == sizeof(Header), |
97 | "invalid header layout" ); |
98 | |
99 | } // namespace recordio_detail |
100 | |
101 | constexpr size_t () { |
102 | return sizeof(recordio_detail::Header); |
103 | } |
104 | |
105 | inline RecordInfo findRecord(ByteRange range, uint32_t fileId) { |
106 | return findRecord(range, range, fileId); |
107 | } |
108 | |
109 | } // namespace recordio_helpers |
110 | |
111 | } // namespace folly |
112 | |