1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 FUJITSU LIMITED
7 * Copyright (C) 2014 CERN (Switzerland)
9 * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
10 * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
11 * Author: Andreas-Joachim Peters <Andreas.Joachim.Peters@cern.ch>
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
20 // -----------------------------------------------------------------------------
21 #include "ErasureCodeShecTableCache.h"
22 #include "common/debug.h"
23 // -----------------------------------------------------------------------------
26 // -----------------------------------------------------------------------------
27 #define dout_context g_ceph_context
28 #define dout_subsys ceph_subsys_osd
30 #define dout_prefix _tc_prefix(_dout)
31 // -----------------------------------------------------------------------------
33 // -----------------------------------------------------------------------------
36 _tc_prefix(std::ostream
* _dout
) {
37 return *_dout
<< "ErasureCodeShecTableCache: ";
40 // -----------------------------------------------------------------------------
42 ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
44 Mutex::Locker
lock(codec_tables_guard
);
46 // clean-up all allocated tables
48 codec_technique_tables_t::const_iterator ttables_it
;
49 codec_tables_t::const_iterator tables_it
;
50 codec_tables_t_::const_iterator tables_it_
;
51 codec_tables_t__::const_iterator tables_it__
;
52 codec_table_t::const_iterator table_it
;
54 for (ttables_it
= encoding_table
.begin(); ttables_it
!= encoding_table
.end(); ++ttables_it
) {
55 for (tables_it
= ttables_it
->second
.begin(); tables_it
!= ttables_it
->second
.end(); ++tables_it
) {
56 for (tables_it_
= tables_it
->second
.begin(); tables_it_
!= tables_it
->second
.end(); ++tables_it_
) {
57 for (tables_it__
= tables_it_
->second
.begin(); tables_it__
!= tables_it_
->second
.end(); ++tables_it__
) {
58 for (table_it
= tables_it__
->second
.begin(); table_it
!= tables_it__
->second
.end(); ++table_it
) {
59 if (table_it
->second
) {
60 if (*(table_it
->second
)) {
61 delete *(table_it
->second
);
63 delete table_it
->second
;
73 std::map
<int, lru_map_t
*>::const_iterator lru_map_it
;
74 std::map
<int, lru_list_t
*>::const_iterator lru_list_it
;
76 for (lru_map_it
= decoding_tables
.begin();
77 lru_map_it
!= decoding_tables
.end();
79 if (lru_map_it
->second
) {
80 delete lru_map_it
->second
;
84 for (lru_list_it
= decoding_tables_lru
.begin();
85 lru_list_it
!= decoding_tables_lru
.end();
87 if (lru_list_it
->second
) {
88 delete lru_list_it
->second
;
94 ErasureCodeShecTableCache::lru_map_t
*
95 ErasureCodeShecTableCache::getDecodingTables(int technique
) {
96 // the caller must hold the guard mutex:
97 // => Mutex::Locker lock(codec_tables_guard);
99 // create an lru_map if not yet allocated
100 if (!decoding_tables
[technique
]) {
101 decoding_tables
[technique
] = new lru_map_t
;
103 return decoding_tables
[technique
];
106 ErasureCodeShecTableCache::lru_list_t
*
107 ErasureCodeShecTableCache::getDecodingTablesLru(int technique
) {
108 // the caller must hold the guard mutex:
109 // => Mutex::Locker lock(codec_tables_guard);
111 // create an lru_list if not yet allocated
112 if (!decoding_tables_lru
[technique
]) {
113 decoding_tables_lru
[technique
] = new lru_list_t
;
115 return decoding_tables_lru
[technique
];
119 ErasureCodeShecTableCache::getEncodingTable(int technique
, int k
, int m
, int c
, int w
)
121 Mutex::Locker
lock(codec_tables_guard
);
122 return getEncodingTableNoLock(technique
,k
,m
,c
,w
);
125 // -----------------------------------------------------------------------------
128 ErasureCodeShecTableCache::getEncodingTableNoLock(int technique
, int k
, int m
, int c
, int w
)
130 // create a pointer to store an encoding table address
131 if (!encoding_table
[technique
][k
][m
][c
][w
]) {
132 encoding_table
[technique
][k
][m
][c
][w
] = new (int*);
133 *encoding_table
[technique
][k
][m
][c
][w
] = 0;
135 return encoding_table
[technique
][k
][m
][c
][w
];
139 ErasureCodeShecTableCache::setEncodingTable(int technique
, int k
, int m
, int c
, int w
, int* ec_in_table
)
141 Mutex::Locker
lock(codec_tables_guard
);
142 int** ec_out_table
= getEncodingTableNoLock(technique
, k
, m
, c
, w
);
144 // somebody might have deposited this table in the meanwhile, so clean
145 // the input table and return the stored one
147 return *ec_out_table
;
149 // we store the provided input table and return this one
150 *encoding_table
[technique
][k
][m
][c
][w
] = ec_in_table
;
156 ErasureCodeShecTableCache::getLock()
158 return &codec_tables_guard
;
162 ErasureCodeShecTableCache::getDecodingCacheSignature(int k
, int m
, int c
, int w
,
163 int *erased
, int *avails
) {
164 uint64_t signature
= 0;
165 signature
= (uint64_t)k
;
166 signature
|= ((uint64_t)m
<< 6);
167 signature
|= ((uint64_t)c
<< 12);
168 signature
|= ((uint64_t)w
<< 18);
170 for (int i
=0; i
< k
+m
; i
++) {
171 signature
|= ((uint64_t)(avails
[i
] ? 1 : 0) << (24+i
));
173 for (int i
=0; i
< k
+m
; i
++) {
174 signature
|= ((uint64_t)(erased
[i
] ? 1 : 0) << (44+i
));
180 ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix
,
191 // --------------------------------------------------------------------------
192 // LRU decoding matrix cache
193 // --------------------------------------------------------------------------
195 uint64_t signature
= getDecodingCacheSignature(k
, m
, c
, w
, erased
, avails
);
196 Mutex::Locker
lock(codec_tables_guard
);
198 dout(20) << "[ get table ] = " << signature
<< dendl
;
200 // we try to fetch a decoding table from an LRU cache
201 lru_map_t
* decode_tbls_map
=
202 getDecodingTables(technique
);
204 lru_list_t
* decode_tbls_lru
=
205 getDecodingTablesLru(technique
);
207 lru_map_t::iterator decode_tbls_map_it
= decode_tbls_map
->find(signature
);
208 if (decode_tbls_map_it
== decode_tbls_map
->end()) {
212 dout(20) << "[ cached table ] = " << signature
<< dendl
;
213 // copy parameters out of the cache
215 memcpy(decoding_matrix
,
216 decode_tbls_map_it
->second
.second
.decoding_matrix
,
217 k
* k
* sizeof(int));
219 decode_tbls_map_it
->second
.second
.dm_row
,
222 decode_tbls_map_it
->second
.second
.dm_column
,
225 decode_tbls_map_it
->second
.second
.minimum
,
226 (k
+m
) * sizeof(int));
228 // find item in LRU queue and push back
229 decode_tbls_lru
->splice(decode_tbls_lru
->end(),
231 decode_tbls_map_it
->second
.first
);
236 ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix
,
247 // --------------------------------------------------------------------------
248 // LRU decoding matrix cache
249 // --------------------------------------------------------------------------
251 Mutex::Locker
lock(codec_tables_guard
);
253 uint64_t signature
= getDecodingCacheSignature(k
, m
, c
, w
, erased
, avails
);
254 dout(20) << "[ put table ] = " << signature
<< dendl
;
256 // we store a new table to the cache
258 // bufferptr cachetable;
260 lru_map_t
* decode_tbls_map
=
261 getDecodingTables(technique
);
263 lru_list_t
* decode_tbls_lru
=
264 getDecodingTablesLru(technique
);
266 if (decode_tbls_map
->count(signature
)) {
267 dout(20) << "[ already on table ] = " << signature
<< dendl
;
269 // find item in LRU queue and push back
270 decode_tbls_lru
->splice(decode_tbls_lru
->end(),
272 (*decode_tbls_map
)[signature
].first
);
276 // evt. shrink the LRU queue/map
277 if ((int)decode_tbls_lru
->size() >=
278 ErasureCodeShecTableCache::decoding_tables_lru_length
) {
279 dout(20) << "[ shrink lru ] = " << signature
<< dendl
;
281 decode_tbls_map
->erase(decode_tbls_lru
->front());
283 decode_tbls_lru
->pop_front();
287 dout(20) << "[ store table ] = " << signature
<< dendl
;
289 decode_tbls_lru
->push_back(signature
);
291 // allocate a new buffer
292 lru_list_t::iterator it_end
= decode_tbls_lru
->end();
295 lru_entry_t
&map_value
=
296 (*decode_tbls_map
)[signature
] =
297 std::make_pair(it_end
, DecodingCacheParameter());
298 map_value
.second
.decoding_matrix
= new int[k
*k
];
299 map_value
.second
.dm_row
= new int[k
];
300 map_value
.second
.dm_column
= new int[k
];
301 map_value
.second
.minimum
= new int[k
+m
];
303 memcpy(map_value
.second
.decoding_matrix
,
305 k
* k
* sizeof(int));
306 memcpy(map_value
.second
.dm_row
,
309 memcpy(map_value
.second
.dm_column
,
312 memcpy(map_value
.second
.minimum
,
314 (k
+m
) * sizeof(int));
316 dout(20) << "[ cache size ] = " << decode_tbls_lru
->size() << dendl
;