Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / erasure-code / shec / ErasureCodeShecTableCache.cc
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) 2014 FUJITSU LIMITED
7  * Copyright (C) 2014 CERN (Switzerland)
8  *
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>
12  *
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.
17  *
18  */
19
20 // -----------------------------------------------------------------------------
21 #include "ErasureCodeShecTableCache.h"
22 #include "common/debug.h"
23 // -----------------------------------------------------------------------------
24 using namespace std;
25
26 // -----------------------------------------------------------------------------
27 #define dout_context g_ceph_context
28 #define dout_subsys ceph_subsys_osd
29 #undef dout_prefix
30 #define dout_prefix _tc_prefix(_dout)
31 // -----------------------------------------------------------------------------
32
33 // -----------------------------------------------------------------------------
34
35 static ostream&
36 _tc_prefix(std::ostream* _dout) {
37   return *_dout << "ErasureCodeShecTableCache: ";
38 }
39
40 // -----------------------------------------------------------------------------
41
42 ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
43 {
44   Mutex::Locker lock(codec_tables_guard);
45
46   // clean-up all allocated tables
47   {
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;
53
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);
62                 }
63                 delete table_it->second;
64               }
65             }
66           }
67         }
68       }
69     }
70   }
71
72   {
73     std::map<int, lru_map_t*>::const_iterator lru_map_it;
74     std::map<int, lru_list_t*>::const_iterator lru_list_it;
75
76     for (lru_map_it = decoding_tables.begin();
77          lru_map_it != decoding_tables.end();
78          ++lru_map_it) {
79       if (lru_map_it->second) {
80         delete lru_map_it->second;
81       }
82     }
83
84     for (lru_list_it = decoding_tables_lru.begin();
85          lru_list_it != decoding_tables_lru.end();
86          ++lru_list_it) {
87       if (lru_list_it->second) {
88         delete lru_list_it->second;
89       }
90     }
91   }
92 }
93
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);
98
99   // create an lru_map if not yet allocated
100   if (!decoding_tables[technique]) {
101     decoding_tables[technique] = new lru_map_t;
102   }
103   return decoding_tables[technique];
104 }
105
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);
110
111   // create an lru_list if not yet allocated
112   if (!decoding_tables_lru[technique]) {
113     decoding_tables_lru[technique] = new lru_list_t;
114   }
115   return decoding_tables_lru[technique];
116 }
117
118 int**
119 ErasureCodeShecTableCache::getEncodingTable(int technique, int k, int m, int c, int w)
120 {
121   Mutex::Locker lock(codec_tables_guard);
122   return getEncodingTableNoLock(technique,k,m,c,w);
123 }
124
125 // -----------------------------------------------------------------------------
126
127 int**
128 ErasureCodeShecTableCache::getEncodingTableNoLock(int technique, int k, int m, int c, int w)
129 {
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;
134   }
135   return encoding_table[technique][k][m][c][w];
136 }
137
138 int*
139 ErasureCodeShecTableCache::setEncodingTable(int technique, int k, int m, int c, int w, int* ec_in_table)
140 {
141   Mutex::Locker lock(codec_tables_guard);
142   int** ec_out_table = getEncodingTableNoLock(technique, k, m, c, w);
143   if (*ec_out_table) {
144     // somebody might have deposited this table in the meanwhile, so clean
145     // the input table and return the stored one
146     free (ec_in_table);
147     return *ec_out_table;
148   } else {
149     // we store the provided input table and return this one
150     *encoding_table[technique][k][m][c][w] = ec_in_table;
151     return ec_in_table;
152   }
153 }
154
155 Mutex*
156 ErasureCodeShecTableCache::getLock()
157 {
158   return &codec_tables_guard;
159 }
160
161 uint64_t
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);
169
170   for (int i=0; i < k+m; i++) {
171     signature |= ((uint64_t)(avails[i] ? 1 : 0) << (24+i));
172   }
173   for (int i=0; i < k+m; i++) {
174     signature |= ((uint64_t)(erased[i] ? 1 : 0) << (44+i));
175   }
176   return signature;
177 }
178
179 bool
180 ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix,
181                                                      int* dm_row,
182                                                      int* dm_column,
183                                                      int* minimum,
184                                                      int technique,
185                                                      int k,
186                                                      int m,
187                                                      int c,
188                                                      int w,
189                                                      int* erased,
190                                                      int* avails) {
191   // --------------------------------------------------------------------------
192   // LRU decoding matrix cache
193   // --------------------------------------------------------------------------
194
195   uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
196   Mutex::Locker lock(codec_tables_guard);
197
198   dout(20) << "[ get table    ] = " << signature << dendl;
199
200   // we try to fetch a decoding table from an LRU cache
201   lru_map_t* decode_tbls_map =
202     getDecodingTables(technique);
203
204   lru_list_t* decode_tbls_lru =
205     getDecodingTablesLru(technique);
206
207   lru_map_t::iterator decode_tbls_map_it = decode_tbls_map->find(signature);
208   if (decode_tbls_map_it == decode_tbls_map->end()) {
209     return false;
210   }
211
212   dout(20) << "[ cached table ] = " << signature << dendl;
213   // copy parameters out of the cache
214
215   memcpy(decoding_matrix,
216          decode_tbls_map_it->second.second.decoding_matrix,
217          k * k * sizeof(int));
218   memcpy(dm_row,
219          decode_tbls_map_it->second.second.dm_row,
220          k * sizeof(int));
221   memcpy(dm_column,
222          decode_tbls_map_it->second.second.dm_column,
223          k * sizeof(int));
224   memcpy(minimum,
225          decode_tbls_map_it->second.second.minimum,
226          (k+m) * sizeof(int));
227
228   // find item in LRU queue and push back
229   decode_tbls_lru->splice(decode_tbls_lru->end(),
230                           *decode_tbls_lru,
231                           decode_tbls_map_it->second.first);
232   return true;
233 }
234
235 void
236 ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix,
237                                                    int* dm_row,
238                                                    int* dm_column,
239                                                    int* minimum,
240                                                    int technique,
241                                                    int k,
242                                                    int m,
243                                                    int c,
244                                                    int w,
245                                                    int* erased,
246                                                    int* avails) {
247   // --------------------------------------------------------------------------
248   // LRU decoding matrix cache
249   // --------------------------------------------------------------------------
250
251   Mutex::Locker lock(codec_tables_guard);
252
253   uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
254   dout(20) << "[ put table    ] = " << signature << dendl;
255
256   // we store a new table to the cache
257
258   //  bufferptr cachetable;
259
260   lru_map_t* decode_tbls_map =
261     getDecodingTables(technique);
262
263   lru_list_t* decode_tbls_lru =
264     getDecodingTablesLru(technique);
265
266   if (decode_tbls_map->count(signature)) {
267     dout(20) << "[ already on table ] = " << signature << dendl;
268
269     // find item in LRU queue and push back
270     decode_tbls_lru->splice(decode_tbls_lru->end(),
271                             *decode_tbls_lru,
272                             (*decode_tbls_map)[signature].first);
273     return;
274   }
275
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;
280     // remove from map
281     decode_tbls_map->erase(decode_tbls_lru->front());
282     // remove from lru
283     decode_tbls_lru->pop_front();
284   }
285
286   {
287     dout(20) << "[ store table  ] = " << signature << dendl;
288
289     decode_tbls_lru->push_back(signature);
290
291     // allocate a new buffer
292     lru_list_t::iterator it_end = decode_tbls_lru->end();
293     --it_end;
294
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];
302
303     memcpy(map_value.second.decoding_matrix,
304            decoding_matrix,
305            k * k * sizeof(int));
306     memcpy(map_value.second.dm_row,
307            dm_row,
308            k * sizeof(int));
309     memcpy(map_value.second.dm_column,
310            dm_column,
311            k * sizeof(int));
312     memcpy(map_value.second.minimum,
313            minimum,
314            (k+m) * sizeof(int));
315
316     dout(20) << "[ cache size   ] = " << decode_tbls_lru->size() << dendl;
317   }
318 }