]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2013 Inktank Storage, Inc. | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef ECUTIL_H | |
16 | #define ECUTIL_H | |
17 | ||
7c673cae FG |
18 | #include "erasure-code/ErasureCodeInterface.h" |
19 | #include "include/buffer_fwd.h" | |
20 | #include "include/assert.h" | |
21 | #include "include/encoding.h" | |
22 | #include "common/Formatter.h" | |
23 | ||
24 | namespace ECUtil { | |
25 | ||
26 | const uint64_t CHUNK_ALIGNMENT = 64; | |
27 | const uint64_t CHUNK_INFO = 8; | |
28 | const uint64_t CHUNK_PADDING = 8; | |
29 | const uint64_t CHUNK_OVERHEAD = 16; // INFO + PADDING | |
30 | ||
31 | class stripe_info_t { | |
32 | const uint64_t stripe_width; | |
33 | const uint64_t chunk_size; | |
34 | public: | |
35 | stripe_info_t(uint64_t stripe_size, uint64_t stripe_width) | |
36 | : stripe_width(stripe_width), | |
37 | chunk_size(stripe_width / stripe_size) { | |
38 | assert(stripe_width % stripe_size == 0); | |
39 | } | |
40 | bool logical_offset_is_stripe_aligned(uint64_t logical) const { | |
41 | return (logical % stripe_width) == 0; | |
42 | } | |
43 | uint64_t get_stripe_width() const { | |
44 | return stripe_width; | |
45 | } | |
46 | uint64_t get_chunk_size() const { | |
47 | return chunk_size; | |
48 | } | |
49 | uint64_t logical_to_prev_chunk_offset(uint64_t offset) const { | |
50 | return (offset / stripe_width) * chunk_size; | |
51 | } | |
52 | uint64_t logical_to_next_chunk_offset(uint64_t offset) const { | |
53 | return ((offset + stripe_width - 1)/ stripe_width) * chunk_size; | |
54 | } | |
55 | uint64_t logical_to_prev_stripe_offset(uint64_t offset) const { | |
56 | return offset - (offset % stripe_width); | |
57 | } | |
58 | uint64_t logical_to_next_stripe_offset(uint64_t offset) const { | |
59 | return ((offset % stripe_width) ? | |
60 | (offset - (offset % stripe_width) + stripe_width) : | |
61 | offset); | |
62 | } | |
63 | uint64_t aligned_logical_offset_to_chunk_offset(uint64_t offset) const { | |
64 | assert(offset % stripe_width == 0); | |
65 | return (offset / stripe_width) * chunk_size; | |
66 | } | |
67 | uint64_t aligned_chunk_offset_to_logical_offset(uint64_t offset) const { | |
68 | assert(offset % chunk_size == 0); | |
69 | return (offset / chunk_size) * stripe_width; | |
70 | } | |
31f18b77 FG |
71 | std::pair<uint64_t, uint64_t> aligned_offset_len_to_chunk( |
72 | std::pair<uint64_t, uint64_t> in) const { | |
73 | return std::make_pair( | |
7c673cae FG |
74 | aligned_logical_offset_to_chunk_offset(in.first), |
75 | aligned_logical_offset_to_chunk_offset(in.second)); | |
76 | } | |
31f18b77 FG |
77 | std::pair<uint64_t, uint64_t> offset_len_to_stripe_bounds( |
78 | std::pair<uint64_t, uint64_t> in) const { | |
7c673cae FG |
79 | uint64_t off = logical_to_prev_stripe_offset(in.first); |
80 | uint64_t len = logical_to_next_stripe_offset( | |
81 | (in.first - off) + in.second); | |
31f18b77 | 82 | return std::make_pair(off, len); |
7c673cae FG |
83 | } |
84 | }; | |
85 | ||
86 | int decode( | |
87 | const stripe_info_t &sinfo, | |
88 | ErasureCodeInterfaceRef &ec_impl, | |
31f18b77 | 89 | std::map<int, bufferlist> &to_decode, |
7c673cae FG |
90 | bufferlist *out); |
91 | ||
92 | int decode( | |
93 | const stripe_info_t &sinfo, | |
94 | ErasureCodeInterfaceRef &ec_impl, | |
31f18b77 FG |
95 | std::map<int, bufferlist> &to_decode, |
96 | std::map<int, bufferlist*> &out); | |
7c673cae FG |
97 | |
98 | int encode( | |
99 | const stripe_info_t &sinfo, | |
100 | ErasureCodeInterfaceRef &ec_impl, | |
101 | bufferlist &in, | |
31f18b77 FG |
102 | const std::set<int> &want, |
103 | std::map<int, bufferlist> *out); | |
7c673cae FG |
104 | |
105 | class HashInfo { | |
106 | uint64_t total_chunk_size = 0; | |
31f18b77 | 107 | std::vector<uint32_t> cumulative_shard_hashes; |
7c673cae FG |
108 | |
109 | // purely ephemeral, represents the size once all in-flight ops commit | |
110 | uint64_t projected_total_chunk_size = 0; | |
111 | public: | |
112 | HashInfo() {} | |
113 | explicit HashInfo(unsigned num_chunks) : | |
114 | cumulative_shard_hashes(num_chunks, -1) {} | |
31f18b77 | 115 | void append(uint64_t old_size, std::map<int, bufferlist> &to_append); |
7c673cae FG |
116 | void clear() { |
117 | total_chunk_size = 0; | |
31f18b77 | 118 | cumulative_shard_hashes = std::vector<uint32_t>( |
7c673cae FG |
119 | cumulative_shard_hashes.size(), |
120 | -1); | |
121 | } | |
122 | void encode(bufferlist &bl) const; | |
123 | void decode(bufferlist::iterator &bl); | |
124 | void dump(Formatter *f) const; | |
31f18b77 | 125 | static void generate_test_instances(std::list<HashInfo*>& o); |
7c673cae FG |
126 | uint32_t get_chunk_hash(int shard) const { |
127 | assert((unsigned)shard < cumulative_shard_hashes.size()); | |
128 | return cumulative_shard_hashes[shard]; | |
129 | } | |
130 | uint64_t get_total_chunk_size() const { | |
131 | return total_chunk_size; | |
132 | } | |
133 | uint64_t get_projected_total_chunk_size() const { | |
134 | return projected_total_chunk_size; | |
135 | } | |
136 | uint64_t get_total_logical_size(const stripe_info_t &sinfo) const { | |
137 | return get_total_chunk_size() * | |
138 | (sinfo.get_stripe_width()/sinfo.get_chunk_size()); | |
139 | } | |
140 | uint64_t get_projected_total_logical_size(const stripe_info_t &sinfo) const { | |
141 | return get_projected_total_chunk_size() * | |
142 | (sinfo.get_stripe_width()/sinfo.get_chunk_size()); | |
143 | } | |
144 | void set_projected_total_logical_size( | |
145 | const stripe_info_t &sinfo, | |
146 | uint64_t logical_size) { | |
147 | assert(sinfo.logical_offset_is_stripe_aligned(logical_size)); | |
148 | projected_total_chunk_size = sinfo.aligned_logical_offset_to_chunk_offset( | |
149 | logical_size); | |
150 | } | |
151 | void set_total_chunk_size_clear_hash(uint64_t new_chunk_size) { | |
152 | cumulative_shard_hashes.clear(); | |
153 | total_chunk_size = new_chunk_size; | |
154 | } | |
155 | bool has_chunk_hash() const { | |
156 | return !cumulative_shard_hashes.empty(); | |
157 | } | |
158 | void update_to(const HashInfo &rhs) { | |
159 | auto ptcs = projected_total_chunk_size; | |
160 | *this = rhs; | |
161 | projected_total_chunk_size = ptcs; | |
162 | } | |
163 | }; | |
164 | ||
165 | typedef ceph::shared_ptr<HashInfo> HashInfoRef; | |
166 | ||
31f18b77 FG |
167 | bool is_hinfo_key_string(const std::string &key); |
168 | const std::string &get_hinfo_key(); | |
7c673cae FG |
169 | |
170 | } | |
171 | WRITE_CLASS_ENCODER(ECUtil::HashInfo) | |
172 | #endif |