00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "memdb/memdb.hpp"
00029 #include "base/list.hpp"
00030 #include "base/memory.hpp"
00031 #include "base/vector.hpp"
00032
00033 BEGIN_TERIMBER_NAMESPACE
00034 #pragma pack(4)
00035
00037
00038 memtable::memtable()
00039 {
00040 }
00041
00042
00043
00044
00045
00046 memtable::~memtable()
00047 {
00048 uninit();
00049 }
00050
00051 void
00052 memtable::uninit()
00053 {
00054 mutex_keeper guard(_mtx);
00055 for (list_indexes_t::iterator iiter = _indexes.begin(); iiter != _indexes.end(); ++iiter)
00056 delete *iiter;
00057
00058 _indexes.clear();
00059
00060 for (list_values_t::iterator viter = _values.begin(); viter != _values.end(); ++viter)
00061 delete *viter;
00062
00063 _values.clear();
00064
00065 _cols.clear();
00066 _rowset.clear();
00067 _allocator.clear_all();
00068 }
00069
00070
00071
00072
00073 const char*
00074 memtable::get_last_error()
00075 {
00076 return _error;
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 bool
00090 memtable::populate(dbserver* server, size_t start_row, size_t max_rows)
00091 {
00092 uninit();
00093
00094
00095 if (!server->fetch_data(false, start_row, max_rows, true))
00096 {
00097 _error = server->get_error();
00098 return false;
00099 }
00100
00101
00102 size_t col_count = server->get_column_count();
00103 if (!col_count)
00104 {
00105 _error = "no columns found";
00106 return false;
00107 }
00108
00109 binder dummy;
00110 _cols.resize(_allocator, col_count, dummy);
00111 if (_cols.size() != col_count)
00112 return false;
00113
00114 for (size_t icol = 0; icol < col_count; ++icol)
00115 {
00116 _cols[icol]._type = server->get_column_type(icol);
00117 _cols[icol]._max_length = server->get_column_max_length(icol);
00118 _cols[icol]._value.nullVal = server->get_column_nullable(icol);
00119 _cols[icol]._precision = server->get_column_precision(icol);
00120 _cols[icol]._scale = server->get_column_scale(icol);
00121 _cols[icol].set_name(&_allocator, server->get_column_name(icol));
00122 }
00123
00124 while (server->next())
00125 {
00126
00127 memdb_row dummy_row;
00128 _rowset.push_back(dummy_row);
00129 memdb_row& row = _rowset.back();
00130
00131 row._row.resize(_allocator, col_count);
00132 row._status = status_original;
00133
00134 if (!copy_db_row(server, row, _cols, _cols.size(), _allocator, _error))
00135 return false;
00136
00137 }
00138
00139 return true;
00140 }
00141
00142 bool
00143 memtable::create(size_t columns, const terimber_table_column_desc desc[])
00144 {
00145 uninit();
00146
00147 binder dummy;
00148 _cols.resize(_allocator, columns, dummy);
00149 if (_cols.size() != columns)
00150 return false;
00151
00152 for (size_t icol = 0; icol < columns; ++icol)
00153 {
00154 _cols[icol]._type = desc[icol]._type;
00155 _cols[icol]._max_length = desc[icol]._max_length;
00156 _cols[icol]._value.nullVal = desc[icol]._nullable;
00157 _cols[icol]._precision = desc[icol]._precision;
00158 _cols[icol]._scale = desc[icol]._scale;
00159 _cols[icol].set_name(&_allocator, desc[icol]._name);
00160 }
00161
00162 return true;
00163 }
00164
00165
00166
00167 void
00168 memtable::refresh()
00169 {
00170
00171 for (memdb_rowset_t::iterator it = _rowset.begin(); it != _rowset.end(); ++it)
00172 {
00173 it->_status = status_original;
00174 }
00175 }
00176
00177
00178
00179
00180 size_t
00181 memtable::get_row_count()
00182 {
00183 return _rowset.size();
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 size_t
00194 memtable::get_column_count() const
00195 {
00196 return _cols.size();
00197 }
00198
00199
00200
00201
00202 dbtypes
00203 memtable::get_column_type(size_t index) const
00204 {
00205 return index >= _cols.size() ? db_unknown : _cols[index]._type;
00206 }
00207
00208
00209
00210
00211 const char*
00212 memtable::get_column_name(size_t index) const
00213 {
00214 return index >= _cols.size() ? 0 : _cols[index]._name;
00215 }
00216
00217
00218
00219
00220 bool
00221 memtable::get_column_nullable(size_t index) const
00222 {
00223 return index >= _cols.size() ? false : _cols[index]._value.nullVal;
00224 }
00225
00226
00227
00228
00229 size_t
00230 memtable::get_column_scale(size_t index) const
00231 {
00232 return index >= _cols.size() ? 0 : _cols[index]._scale;
00233 }
00234
00235
00236
00237 size_t
00238 memtable::get_column_precision(size_t index) const
00239 {
00240 return index >= _cols.size() ? 0 : _cols[index]._precision;
00241 }
00242
00243
00244
00245
00246 size_t
00247 memtable::get_column_max_length(size_t index) const
00248 {
00249 return index >= _cols.size() ? 0 : _cols[index]._max_length;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 terimber_memindex*
00267 memtable::add_index(size_t columns, const terimber_index_column_info info[])
00268 {
00269 terimber_index_column_array_t vec_info;
00270 vec_info.resize(columns);
00271
00272
00273 if (columns > _cols.size())
00274 {
00275 _error = "info size exceeds the number of available columns";
00276 return 0;
00277 }
00278
00279 for (size_t icol = 0; icol < columns; ++icol)
00280 {
00281 vec_info[icol]._asc_sort = info[icol]._asc_sort;
00282 vec_info[icol]._case_insensitive = info[icol]._case_insensitive;
00283 vec_info[icol]._index = info[icol]._index;
00284
00285 if (vec_info[icol]._index >= _cols.size())
00286 {
00287 char buf[128];
00288 str_template::strprint(buf, 128, "specified index %d is out of range", vec_info[icol]._index);
00289 _error = buf;
00290 return 0;
00291 }
00292
00293 vec_info[icol]._type = _cols[vec_info[icol]._index]._type;
00294 }
00295
00296 memdb_rowset_less pred(vec_info);
00297
00298 memindex* obj = new memindex(*this, pred);
00299 if (obj)
00300 {
00301
00302 if (!obj->construct())
00303 {
00304 delete obj;
00305 return 0;
00306 }
00307
00308
00309 mutex_keeper guard(_mtx);
00310 _indexes.push_back(obj);
00311 }
00312
00313 obj->log_on(this);
00314
00315 return obj;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324 bool
00325 memtable::remove_index(terimber_memindex* obj)
00326 {
00327 mutex_keeper guard(_mtx);
00328 for (list_indexes_t::iterator iter = _indexes.begin(); iter != _indexes.end(); ++iter)
00329 if (*iter == obj)
00330 {
00331 (*iter)->log_on(0);
00332 delete *iter;
00333 _indexes.erase(iter);
00334 return true;
00335 }
00336
00337 return false;
00338 }
00339
00340 terimber_db_value_vector*
00341 memtable::allocate_db_values(size_t count)
00342 {
00343
00344 terimber_db_value_vector_impl* obj = new terimber_db_value_vector_impl(count);
00345 if (obj)
00346 {
00347 mutex_keeper guard(_mtx);
00348 _values.push_back(obj);
00349 }
00350
00351 return obj;
00352 }
00353
00354 void
00355 memtable::destroy_db_values(terimber_db_value_vector* obj)
00356 {
00357 mutex_keeper guard(_mtx);
00358 for (list_values_t::iterator iter = _values.begin(); iter != _values.end(); ++iter)
00359 if (*iter == obj)
00360 {
00361 delete *iter;
00362 _values.erase(iter);
00363 return;
00364 }
00365 }
00366
00368 bool
00369 memtable::insert_row(const terimber_db_value_vector* info)
00370 {
00371 size_t col_count = _cols.size();
00372
00373 if (info->get_size() != col_count)
00374 {
00375 _error = "Out of range";
00376 return false;
00377 }
00378
00379
00380 memdb_row dummy_row;
00381 _rowset.push_back(dummy_row);
00382 memdb_row& row = _rowset.back();
00383
00384 row._row.resize(_allocator, col_count);
00385 row._status = status_new;
00386
00387 if (!copy_db_row(info, row, _cols, _cols.size(), _allocator, _error))
00388 return false;
00389
00390 memdb_rowset_citerator_t new_iter = --_rowset.end();
00391
00392
00393 mutex_keeper guard(_mtx);
00394 for (list_indexes_t::iterator iter = _indexes.begin(); iter != _indexes.end(); ++iter)
00395 (*iter)->notify(new_iter, true);
00396
00397 return true;
00398 }
00399
00400 bool
00401 memtable::update_row(memdb_rowset_citerator_t iter, const terimber_db_value_vector* info)
00402 {
00403
00404 mutex_keeper guard(_mtx);
00405
00406 for (list_indexes_t::iterator diter = _indexes.begin(); diter != _indexes.end(); ++diter)
00407 (*diter)->notify(iter, false);
00408
00409
00410 memdb_rowset_iterator_t uiter(iter.node());
00411
00412 uiter->_status = status_new;
00413
00414 if (!copy_db_row(info, *uiter, _cols, _cols.size(), _allocator, _error))
00415 return false;
00416
00417 switch (uiter->_status)
00418 {
00419 case status_new:
00420 break;
00421 case status_updated:
00422 break;
00423 case status_original:
00424 uiter->_status = status_updated;
00425 break;
00426 case status_deleted:
00427 assert(false);
00428 }
00429
00430
00431 for (list_indexes_t::iterator niter = _indexes.begin(); niter != _indexes.end(); ++niter)
00432 (*niter)->notify(uiter, true);
00433
00434 return true;
00435 }
00436
00437 bool
00438 memtable::delete_row(memdb_rowset_citerator_t iter)
00439 {
00440
00441 mutex_keeper guard(_mtx);
00442 for (list_indexes_t::iterator diter = _indexes.begin(); diter != _indexes.end(); ++diter)
00443 (*diter)->notify(iter, false);
00444
00445
00446 memdb_rowset_iterator_t uiter(iter.node());
00447
00448 switch (uiter->_status)
00449 {
00450 case status_new:
00451 _rowset.erase(uiter);
00452 break;
00453 case status_updated:
00454 break;
00455 case status_original:
00456 uiter->_status = status_deleted;
00457 break;
00458 case status_deleted:
00459 assert(false);
00460 }
00461
00462 return true;
00463 }
00464
00465
00466 #pragma pack()
00467 END_TERIMBER_NAMESPACE