]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Ceph - scalable distributed file system | |
3 | * | |
4 | * Copyright (C) 2014 CERN (Switzerland) | |
5 | * | |
6 | * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch> | |
7 | * | |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | */ | |
14 | ||
15 | ||
16 | /** | |
17 | * @file ErasureCodeIsaTableCache.cc | |
18 | * | |
19 | * @brief Erasure Code Isa CODEC Table Cache | |
20 | * | |
21 | * The INTEL ISA-L library supports two pre-defined encoding matrices (cauchy = default, reed_sol_van = default) | |
22 | * The default CODEC implementation using these two matrices is implemented in class ErasureCodeIsaDefault. | |
23 | * ISA-L allows to use custom matrices which might be added later as implementations deriving from the base class ErasoreCodeIsa. | |
24 | */ | |
25 | ||
26 | // ----------------------------------------------------------------------------- | |
27 | #include "ErasureCodeIsaTableCache.h" | |
7c673cae FG |
28 | #include "common/debug.h" |
29 | // ----------------------------------------------------------------------------- | |
30 | ||
31 | // ----------------------------------------------------------------------------- | |
32 | #define dout_context g_ceph_context | |
33 | #define dout_subsys ceph_subsys_osd | |
34 | #undef dout_prefix | |
35 | #define dout_prefix _tc_prefix(_dout) | |
36 | // ----------------------------------------------------------------------------- | |
37 | ||
38 | // ----------------------------------------------------------------------------- | |
39 | ||
40 | static ostream& | |
41 | _tc_prefix(std::ostream* _dout) | |
42 | { | |
43 | return *_dout << "ErasureCodeIsaTableCache: "; | |
44 | } | |
45 | ||
46 | // ----------------------------------------------------------------------------- | |
47 | ||
48 | ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache() | |
49 | { | |
50 | Mutex::Locker lock(codec_tables_guard); | |
51 | ||
52 | codec_technique_tables_t::const_iterator ttables_it; | |
53 | codec_tables_t::const_iterator tables_it; | |
54 | codec_table_t::const_iterator table_it; | |
55 | ||
56 | std::map<int, lru_map_t*>::const_iterator lru_map_it; | |
57 | std::map<int, lru_list_t*>::const_iterator lru_list_it; | |
58 | ||
59 | // clean-up all allocated tables | |
60 | for (ttables_it = encoding_coefficient.begin(); ttables_it != encoding_coefficient.end(); ++ttables_it) { | |
61 | for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) { | |
62 | for (table_it = tables_it->second.begin(); table_it != tables_it->second.end(); ++table_it) { | |
63 | if (table_it->second) { | |
64 | if (*(table_it->second)) { | |
65 | delete *(table_it->second); | |
66 | } | |
67 | delete table_it->second; | |
68 | } | |
69 | } | |
70 | } | |
71 | } | |
72 | ||
73 | for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) { | |
74 | for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) { | |
75 | for (table_it = tables_it->second.begin(); table_it != tables_it->second.end(); ++table_it) { | |
76 | if (table_it->second) { | |
77 | if (*(table_it->second)) { | |
78 | delete *(table_it->second); | |
79 | } | |
80 | delete table_it->second; | |
81 | } | |
82 | } | |
83 | } | |
84 | } | |
85 | ||
86 | for (lru_map_it = decoding_tables.begin(); lru_map_it != decoding_tables.end(); ++lru_map_it) { | |
87 | if (lru_map_it->second) { | |
88 | delete lru_map_it->second; | |
89 | } | |
90 | } | |
91 | ||
92 | for (lru_list_it = decoding_tables_lru.begin(); lru_list_it != decoding_tables_lru.end(); ++lru_list_it) { | |
93 | if (lru_list_it->second) { | |
94 | delete lru_list_it->second; | |
95 | } | |
96 | } | |
97 | } | |
98 | ||
99 | // ----------------------------------------------------------------------------- | |
100 | ||
101 | int | |
102 | ErasureCodeIsaTableCache::getDecodingTableCacheSize(int matrixtype) | |
103 | { | |
104 | Mutex::Locker lock(codec_tables_guard); | |
105 | if (decoding_tables[matrixtype]) | |
106 | return decoding_tables[matrixtype]->size(); | |
107 | else | |
108 | return -1; | |
109 | } | |
110 | ||
111 | // ----------------------------------------------------------------------------- | |
112 | ||
113 | ErasureCodeIsaTableCache::lru_map_t* | |
114 | ErasureCodeIsaTableCache::getDecodingTables(int matrix_type) | |
115 | { | |
116 | // the caller must hold the guard mutex: | |
117 | // => Mutex::Locker lock(codec_tables_guard); | |
118 | ||
119 | // create an lru_map if not yet allocated | |
120 | if (!decoding_tables[matrix_type]) { | |
121 | decoding_tables[matrix_type] = new lru_map_t; | |
122 | } | |
123 | return decoding_tables[matrix_type]; | |
124 | } | |
125 | ||
126 | // ----------------------------------------------------------------------------- | |
127 | ||
128 | ErasureCodeIsaTableCache::lru_list_t* | |
129 | ErasureCodeIsaTableCache::getDecodingTablesLru(int matrix_type) | |
130 | { | |
131 | // the caller must hold the guard mutex: | |
132 | // => Mutex::Locker lock(codec_tables_guard); | |
133 | ||
134 | // create an lru_list if not yet allocated | |
135 | if (!decoding_tables_lru[matrix_type]) { | |
136 | decoding_tables_lru[matrix_type] = new lru_list_t; | |
137 | } | |
138 | return decoding_tables_lru[matrix_type]; | |
139 | } | |
140 | ||
141 | // ----------------------------------------------------------------------------- | |
142 | ||
143 | unsigned char** | |
144 | ErasureCodeIsaTableCache::getEncodingTable(int matrix, int k, int m) | |
145 | { | |
146 | Mutex::Locker lock(codec_tables_guard); | |
147 | return getEncodingTableNoLock(matrix,k,m); | |
148 | } | |
149 | ||
150 | // ----------------------------------------------------------------------------- | |
151 | ||
152 | unsigned char** | |
153 | ErasureCodeIsaTableCache::getEncodingTableNoLock(int matrix, int k, int m) | |
154 | { | |
155 | // create a pointer to store an encoding table address | |
156 | if (!encoding_table[matrix][k][m]) { | |
157 | encoding_table[matrix][k][m] = new (unsigned char*); | |
158 | *encoding_table[matrix][k][m] = 0; | |
159 | } | |
160 | return encoding_table[matrix][k][m]; | |
161 | } | |
162 | ||
163 | // ----------------------------------------------------------------------------- | |
164 | ||
165 | unsigned char** | |
166 | ErasureCodeIsaTableCache::getEncodingCoefficient(int matrix, int k, int m) | |
167 | { | |
168 | Mutex::Locker lock(codec_tables_guard); | |
169 | return getEncodingCoefficientNoLock(matrix,k,m); | |
170 | } | |
171 | ||
172 | // ----------------------------------------------------------------------------- | |
173 | ||
174 | unsigned char** | |
175 | ErasureCodeIsaTableCache::getEncodingCoefficientNoLock(int matrix, int k, int m) | |
176 | { | |
177 | // create a pointer to store an encoding coefficients adddress | |
178 | if (!encoding_coefficient[matrix][k][m]) { | |
179 | encoding_coefficient[matrix][k][m] = new (unsigned char*); | |
180 | *encoding_coefficient[matrix][k][m] = 0; | |
181 | } | |
182 | return encoding_coefficient[matrix][k][m]; | |
183 | } | |
184 | ||
185 | // ----------------------------------------------------------------------------- | |
186 | ||
187 | unsigned char* | |
188 | ErasureCodeIsaTableCache::setEncodingTable(int matrix, int k, int m, unsigned char* ec_in_table) | |
189 | { | |
190 | Mutex::Locker lock(codec_tables_guard); | |
191 | unsigned char** ec_out_table = getEncodingTableNoLock(matrix, k, m); | |
192 | if (*ec_out_table) { | |
193 | // somebody might have deposited this table in the meanwhile, so clean | |
194 | // the input table and return the stored one | |
195 | free (ec_in_table); | |
196 | return *ec_out_table; | |
197 | } else { | |
198 | // we store the provided input table and return this one | |
199 | *encoding_table[matrix][k][m] = ec_in_table; | |
200 | return ec_in_table; | |
201 | } | |
202 | } | |
203 | ||
204 | // ----------------------------------------------------------------------------- | |
205 | ||
206 | unsigned char* | |
207 | ErasureCodeIsaTableCache::setEncodingCoefficient(int matrix, int k, int m, unsigned char* ec_in_coeff) | |
208 | { | |
209 | Mutex::Locker lock(codec_tables_guard); | |
210 | unsigned char** ec_out_coeff = getEncodingCoefficientNoLock(matrix, k, m); | |
211 | if (*ec_out_coeff) { | |
212 | // somebody might have deposited these coefficients in the meanwhile, so clean | |
213 | // the input coefficients and return the stored ones | |
214 | free (ec_in_coeff); | |
215 | return *ec_out_coeff; | |
216 | } else { | |
217 | // we store the provided input coefficients and return these | |
218 | *encoding_coefficient[matrix][k][m] = ec_in_coeff; | |
219 | return ec_in_coeff; | |
220 | } | |
221 | } | |
222 | ||
223 | // ----------------------------------------------------------------------------- | |
224 | ||
225 | Mutex* | |
226 | ErasureCodeIsaTableCache::getLock() | |
227 | { | |
228 | return &codec_tables_guard; | |
229 | } | |
230 | ||
231 | // ----------------------------------------------------------------------------- | |
232 | ||
233 | bool | |
234 | ErasureCodeIsaTableCache::getDecodingTableFromCache(std::string &signature, | |
235 | unsigned char* &table, | |
236 | int matrixtype, | |
237 | int k, | |
238 | int m) | |
239 | { | |
240 | // -------------------------------------------------------------------------- | |
241 | // LRU decoding matrix cache | |
242 | // -------------------------------------------------------------------------- | |
243 | ||
244 | dout(12) << "[ get table ] = " << signature << dendl; | |
245 | ||
246 | // we try to fetch a decoding table from an LRU cache | |
247 | bool found = false; | |
248 | ||
249 | Mutex::Locker lock(codec_tables_guard); | |
250 | ||
251 | lru_map_t* decode_tbls_map = | |
252 | getDecodingTables(matrixtype); | |
253 | ||
254 | lru_list_t* decode_tbls_lru = | |
255 | getDecodingTablesLru(matrixtype); | |
256 | ||
257 | if (decode_tbls_map->count(signature)) { | |
258 | dout(12) << "[ cached table ] = " << signature << dendl; | |
259 | // copy the table out of the cache | |
260 | memcpy(table, (*decode_tbls_map)[signature].second.c_str(), k * (m + k)*32); | |
261 | // find item in LRU queue and push back | |
262 | dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl; | |
263 | decode_tbls_lru->splice( (decode_tbls_lru->begin()), *decode_tbls_lru, (*decode_tbls_map)[signature].first); | |
264 | found = true; | |
265 | } | |
266 | ||
267 | return found; | |
268 | } | |
269 | ||
270 | // ----------------------------------------------------------------------------- | |
271 | ||
272 | void | |
273 | ErasureCodeIsaTableCache::putDecodingTableToCache(std::string &signature, | |
274 | unsigned char* &table, | |
275 | int matrixtype, | |
276 | int k, | |
277 | int m) | |
278 | { | |
279 | // -------------------------------------------------------------------------- | |
280 | // LRU decoding matrix cache | |
281 | // -------------------------------------------------------------------------- | |
282 | ||
283 | dout(12) << "[ put table ] = " << signature << dendl; | |
284 | ||
285 | // we store a new table to the cache | |
286 | ||
287 | bufferptr cachetable; | |
288 | ||
289 | Mutex::Locker lock(codec_tables_guard); | |
290 | ||
291 | lru_map_t* decode_tbls_map = | |
292 | getDecodingTables(matrixtype); | |
293 | ||
294 | lru_list_t* decode_tbls_lru = | |
295 | getDecodingTablesLru(matrixtype); | |
296 | ||
297 | // evt. shrink the LRU queue/map | |
298 | if ((int) decode_tbls_lru->size() >= ErasureCodeIsaTableCache::decoding_tables_lru_length) { | |
299 | dout(12) << "[ shrink lru ] = " << signature << dendl; | |
300 | // reuse old buffer | |
301 | cachetable = (*decode_tbls_map)[decode_tbls_lru->back()].second; | |
302 | ||
303 | if ((int) cachetable.length() != (k * (m + k)*32)) { | |
304 | // we need to replace this with a different size buffer | |
305 | cachetable = buffer::create(k * (m + k)*32); | |
306 | } | |
307 | ||
308 | // remove from map | |
309 | decode_tbls_map->erase(decode_tbls_lru->back()); | |
310 | // remove from lru | |
311 | decode_tbls_lru->pop_back(); | |
312 | // add to the head of lru | |
313 | decode_tbls_lru->push_front(signature); | |
314 | // add the new to the map | |
315 | (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable); | |
316 | } else { | |
317 | dout(12) << "[ store table ] = " << signature << dendl; | |
318 | // allocate a new buffer | |
319 | cachetable = buffer::create(k * (m + k)*32); | |
320 | decode_tbls_lru->push_front(signature); | |
321 | (*decode_tbls_map)[signature] = std::make_pair(decode_tbls_lru->begin(), cachetable); | |
322 | dout(12) << "[ cache size ] = " << decode_tbls_lru->size() << dendl; | |
323 | } | |
324 | ||
325 | // copy-in the new table | |
326 | memcpy(cachetable.c_str(), table, k * (m + k)*32); | |
327 | } |