2 * Ceph - scalable distributed file system
4 * Copyright (C) 2014 CERN (Switzerland)
6 * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch>
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.
17 * @file ErasureCodeIsaTableCache.cc
19 * @brief Erasure Code Isa CODEC Table Cache
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.
26 // -----------------------------------------------------------------------------
27 #include "ErasureCodeIsaTableCache.h"
28 #include "ErasureCodeIsa.h"
29 #include "common/debug.h"
30 // -----------------------------------------------------------------------------
32 // -----------------------------------------------------------------------------
33 #define dout_context g_ceph_context
34 #define dout_subsys ceph_subsys_osd
36 #define dout_prefix _tc_prefix(_dout)
37 // -----------------------------------------------------------------------------
39 // -----------------------------------------------------------------------------
42 _tc_prefix(std::ostream
* _dout
)
44 return *_dout
<< "ErasureCodeIsaTableCache: ";
47 // -----------------------------------------------------------------------------
49 ErasureCodeIsaTableCache::~ErasureCodeIsaTableCache()
51 Mutex::Locker
lock(codec_tables_guard
);
53 codec_technique_tables_t::const_iterator ttables_it
;
54 codec_tables_t::const_iterator tables_it
;
55 codec_table_t::const_iterator table_it
;
57 std::map
<int, lru_map_t
*>::const_iterator lru_map_it
;
58 std::map
<int, lru_list_t
*>::const_iterator lru_list_it
;
60 // clean-up all allocated tables
61 for (ttables_it
= encoding_coefficient
.begin(); ttables_it
!= encoding_coefficient
.end(); ++ttables_it
) {
62 for (tables_it
= ttables_it
->second
.begin(); tables_it
!= ttables_it
->second
.end(); ++tables_it
) {
63 for (table_it
= tables_it
->second
.begin(); table_it
!= tables_it
->second
.end(); ++table_it
) {
64 if (table_it
->second
) {
65 if (*(table_it
->second
)) {
66 delete *(table_it
->second
);
68 delete table_it
->second
;
74 for (ttables_it
= encoding_table
.begin(); ttables_it
!= encoding_table
.end(); ++ttables_it
) {
75 for (tables_it
= ttables_it
->second
.begin(); tables_it
!= ttables_it
->second
.end(); ++tables_it
) {
76 for (table_it
= tables_it
->second
.begin(); table_it
!= tables_it
->second
.end(); ++table_it
) {
77 if (table_it
->second
) {
78 if (*(table_it
->second
)) {
79 delete *(table_it
->second
);
81 delete table_it
->second
;
87 for (lru_map_it
= decoding_tables
.begin(); lru_map_it
!= decoding_tables
.end(); ++lru_map_it
) {
88 if (lru_map_it
->second
) {
89 delete lru_map_it
->second
;
93 for (lru_list_it
= decoding_tables_lru
.begin(); lru_list_it
!= decoding_tables_lru
.end(); ++lru_list_it
) {
94 if (lru_list_it
->second
) {
95 delete lru_list_it
->second
;
100 // -----------------------------------------------------------------------------
103 ErasureCodeIsaTableCache::getDecodingTableCacheSize(int matrixtype
)
105 Mutex::Locker
lock(codec_tables_guard
);
106 if (decoding_tables
[matrixtype
])
107 return decoding_tables
[matrixtype
]->size();
112 // -----------------------------------------------------------------------------
114 ErasureCodeIsaTableCache::lru_map_t
*
115 ErasureCodeIsaTableCache::getDecodingTables(int matrix_type
)
117 // the caller must hold the guard mutex:
118 // => Mutex::Locker lock(codec_tables_guard);
120 // create an lru_map if not yet allocated
121 if (!decoding_tables
[matrix_type
]) {
122 decoding_tables
[matrix_type
] = new lru_map_t
;
124 return decoding_tables
[matrix_type
];
127 // -----------------------------------------------------------------------------
129 ErasureCodeIsaTableCache::lru_list_t
*
130 ErasureCodeIsaTableCache::getDecodingTablesLru(int matrix_type
)
132 // the caller must hold the guard mutex:
133 // => Mutex::Locker lock(codec_tables_guard);
135 // create an lru_list if not yet allocated
136 if (!decoding_tables_lru
[matrix_type
]) {
137 decoding_tables_lru
[matrix_type
] = new lru_list_t
;
139 return decoding_tables_lru
[matrix_type
];
142 // -----------------------------------------------------------------------------
145 ErasureCodeIsaTableCache::getEncodingTable(int matrix
, int k
, int m
)
147 Mutex::Locker
lock(codec_tables_guard
);
148 return getEncodingTableNoLock(matrix
,k
,m
);
151 // -----------------------------------------------------------------------------
154 ErasureCodeIsaTableCache::getEncodingTableNoLock(int matrix
, int k
, int m
)
156 // create a pointer to store an encoding table address
157 if (!encoding_table
[matrix
][k
][m
]) {
158 encoding_table
[matrix
][k
][m
] = new (unsigned char*);
159 *encoding_table
[matrix
][k
][m
] = 0;
161 return encoding_table
[matrix
][k
][m
];
164 // -----------------------------------------------------------------------------
167 ErasureCodeIsaTableCache::getEncodingCoefficient(int matrix
, int k
, int m
)
169 Mutex::Locker
lock(codec_tables_guard
);
170 return getEncodingCoefficientNoLock(matrix
,k
,m
);
173 // -----------------------------------------------------------------------------
176 ErasureCodeIsaTableCache::getEncodingCoefficientNoLock(int matrix
, int k
, int m
)
178 // create a pointer to store an encoding coefficients adddress
179 if (!encoding_coefficient
[matrix
][k
][m
]) {
180 encoding_coefficient
[matrix
][k
][m
] = new (unsigned char*);
181 *encoding_coefficient
[matrix
][k
][m
] = 0;
183 return encoding_coefficient
[matrix
][k
][m
];
186 // -----------------------------------------------------------------------------
189 ErasureCodeIsaTableCache::setEncodingTable(int matrix
, int k
, int m
, unsigned char* ec_in_table
)
191 Mutex::Locker
lock(codec_tables_guard
);
192 unsigned char** ec_out_table
= getEncodingTableNoLock(matrix
, k
, m
);
194 // somebody might have deposited this table in the meanwhile, so clean
195 // the input table and return the stored one
197 return *ec_out_table
;
199 // we store the provided input table and return this one
200 *encoding_table
[matrix
][k
][m
] = ec_in_table
;
205 // -----------------------------------------------------------------------------
208 ErasureCodeIsaTableCache::setEncodingCoefficient(int matrix
, int k
, int m
, unsigned char* ec_in_coeff
)
210 Mutex::Locker
lock(codec_tables_guard
);
211 unsigned char** ec_out_coeff
= getEncodingCoefficientNoLock(matrix
, k
, m
);
213 // somebody might have deposited these coefficients in the meanwhile, so clean
214 // the input coefficients and return the stored ones
216 return *ec_out_coeff
;
218 // we store the provided input coefficients and return these
219 *encoding_coefficient
[matrix
][k
][m
] = ec_in_coeff
;
224 // -----------------------------------------------------------------------------
227 ErasureCodeIsaTableCache::getLock()
229 return &codec_tables_guard
;
232 // -----------------------------------------------------------------------------
235 ErasureCodeIsaTableCache::getDecodingTableFromCache(std::string
&signature
,
236 unsigned char* &table
,
241 // --------------------------------------------------------------------------
242 // LRU decoding matrix cache
243 // --------------------------------------------------------------------------
245 dout(12) << "[ get table ] = " << signature
<< dendl
;
247 // we try to fetch a decoding table from an LRU cache
250 Mutex::Locker
lock(codec_tables_guard
);
252 lru_map_t
* decode_tbls_map
=
253 getDecodingTables(matrixtype
);
255 lru_list_t
* decode_tbls_lru
=
256 getDecodingTablesLru(matrixtype
);
258 if (decode_tbls_map
->count(signature
)) {
259 dout(12) << "[ cached table ] = " << signature
<< dendl
;
260 // copy the table out of the cache
261 memcpy(table
, (*decode_tbls_map
)[signature
].second
.c_str(), k
* (m
+ k
)*32);
262 // find item in LRU queue and push back
263 dout(12) << "[ cache size ] = " << decode_tbls_lru
->size() << dendl
;
264 decode_tbls_lru
->splice( (decode_tbls_lru
->begin()), *decode_tbls_lru
, (*decode_tbls_map
)[signature
].first
);
271 // -----------------------------------------------------------------------------
274 ErasureCodeIsaTableCache::putDecodingTableToCache(std::string
&signature
,
275 unsigned char* &table
,
280 // --------------------------------------------------------------------------
281 // LRU decoding matrix cache
282 // --------------------------------------------------------------------------
284 dout(12) << "[ put table ] = " << signature
<< dendl
;
286 // we store a new table to the cache
288 bufferptr cachetable
;
290 Mutex::Locker
lock(codec_tables_guard
);
292 lru_map_t
* decode_tbls_map
=
293 getDecodingTables(matrixtype
);
295 lru_list_t
* decode_tbls_lru
=
296 getDecodingTablesLru(matrixtype
);
298 // evt. shrink the LRU queue/map
299 if ((int) decode_tbls_lru
->size() >= ErasureCodeIsaTableCache::decoding_tables_lru_length
) {
300 dout(12) << "[ shrink lru ] = " << signature
<< dendl
;
302 cachetable
= (*decode_tbls_map
)[decode_tbls_lru
->back()].second
;
304 if ((int) cachetable
.length() != (k
* (m
+ k
)*32)) {
305 // we need to replace this with a different size buffer
306 cachetable
= buffer::create(k
* (m
+ k
)*32);
310 decode_tbls_map
->erase(decode_tbls_lru
->back());
312 decode_tbls_lru
->pop_back();
313 // add to the head of lru
314 decode_tbls_lru
->push_front(signature
);
315 // add the new to the map
316 (*decode_tbls_map
)[signature
] = std::make_pair(decode_tbls_lru
->begin(), cachetable
);
318 dout(12) << "[ store table ] = " << signature
<< dendl
;
319 // allocate a new buffer
320 cachetable
= buffer::create(k
* (m
+ k
)*32);
321 decode_tbls_lru
->push_front(signature
);
322 (*decode_tbls_map
)[signature
] = std::make_pair(decode_tbls_lru
->begin(), cachetable
);
323 dout(12) << "[ cache size ] = " << decode_tbls_lru
->size() << dendl
;
326 // copy-in the new table
327 memcpy(cachetable
.c_str(), table
, k
* (m
+ k
)*32);