LevelDB.cpp 7.34 KB
Newer Older
kladkogex's avatar
kladkogex committed
1
/*
2
    Copyright (C) 2019-Present SKALE Labs
kladkogex's avatar
kladkogex committed
3

4
    This file is part of sgxwallet.
kladkogex's avatar
kladkogex committed
5

6
    sgxwallet is free software: you can redistribute it and/or modify
kladkogex's avatar
kladkogex committed
7 8 9 10
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

11
    sgxwallet is distributed in the hope that it will be useful,
kladkogex's avatar
kladkogex committed
12 13 14 15 16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
17
    along with sgxwallet.  If not, see <https://www.gnu.org/licenses/>.
kladkogex's avatar
kladkogex committed
18 19 20 21 22 23 24 25 26 27

    @file LevelDB.cpp
    @author Stan Kladko
    @date 2019
*/


#include <stdexcept>
#include <memory>
#include <string>
28
#include <iostream>
kladkogex's avatar
kladkogex committed
29 30 31 32


#include "leveldb/db.h"

kladkogex's avatar
kladkogex committed
33 34
#include "sgxwallet_common.h"
#include "RPCException.h"
kladkogex's avatar
kladkogex committed
35 36
#include "LevelDB.h"

37 38
#include "ServerInit.h"

39
#include "spdlog/spdlog.h"
40 41
#include "common.h"

42

kladkogex's avatar
kladkogex committed
43 44 45
using namespace leveldb;


46

kladkogex's avatar
kladkogex committed
47 48 49 50
static WriteOptions writeOptions;
static ReadOptions readOptions;


51

kladkogex's avatar
kladkogex committed
52

53
std::shared_ptr<string> LevelDB::readString(const string &_key) {
kladkogex's avatar
kladkogex committed
54

kladkogex's avatar
kladkogex committed
55 56
    std::lock_guard<std::recursive_mutex> lock(mutex);

57
    auto result = std::make_shared<string>();
kladkogex's avatar
kladkogex committed
58 59

    if (db == nullptr) {
kladkogex's avatar
kladkogex committed
60
        throw RPCException(NULL_DATABASE, "Null db");
kladkogex's avatar
kladkogex committed
61 62 63 64
    }

    auto status = db->Get(readOptions, _key, &*result);

65
    if (DEBUG_PRINT) {
66 67
      spdlog::info("key to read from db: {}",_key );
      //std::cerr << "key to read from db: " << _key << std::endl;
68
    }
69

kladkogex's avatar
kladkogex committed
70 71 72 73 74 75 76 77
    throwExceptionOnError(status);

    if (status.IsNotFound())
        return nullptr;

    return result;
}

78
void LevelDB::writeString(const string &_key, const string &_value) {
kladkogex's avatar
kladkogex committed
79

kladkogex's avatar
kladkogex committed
80 81
    std::lock_guard<std::recursive_mutex> lock(mutex);

kladkogex's avatar
kladkogex committed
82 83 84
    auto status = db->Put(writeOptions, Slice(_key), Slice(_value));

    throwExceptionOnError(status);
85

86
    if (DEBUG_PRINT) {
87 88
        spdlog::info("written key: {}",_key );
       // std::cerr << "written key " << _key  << std::endl;
89
    }
kladkogex's avatar
kladkogex committed
90 91
}

92

93
void LevelDB::deleteDHDKGKey (const string &_key) {
94 95 96

    std::lock_guard<std::recursive_mutex> lock(mutex);

97
    string full_key = "DKG_DH_KEY_" + _key;
98 99 100 101 102

    auto status = db->Delete(writeOptions, Slice(_key));

    throwExceptionOnError(status);

103 104 105 106
    if (DEBUG_PRINT) {
      spdlog::info("key deleted: {}",full_key );
      //std::cerr << "key deleted " << full_key << std::endl;
    }
107 108
}

109
void LevelDB::deleteTempNEK(const string &_key){
110 111 112

    std::lock_guard<std::recursive_mutex> lock(mutex);

113
    string prefix = _key.substr(0,8);
114 115 116 117 118 119 120 121 122 123 124
    if (prefix != "tmp_NEK:") {
      return;
    }

    auto status = db->Delete(writeOptions, Slice(_key));

    throwExceptionOnError(status);

    std::cerr << "key deleted " << _key << std::endl;
}

125
void LevelDB::deleteKey(const string &_key){
126 127 128 129 130 131 132

    std::lock_guard<std::recursive_mutex> lock(mutex);

    auto status = db->Delete(writeOptions, Slice(_key));

    throwExceptionOnError(status);

133
    if (DEBUG_PRINT) {
134 135
      spdlog::info("key deleted: {}",_key );
      // std::cerr << "key deleted " << _key << std::endl;
136
    }
137 138
}

139

140

kladkogex's avatar
kladkogex committed
141 142 143
void LevelDB::writeByteArray(const char *_key, size_t _keyLen, const char *value,
                             size_t _valueLen) {

kladkogex's avatar
kladkogex committed
144 145
    std::lock_guard<std::recursive_mutex> lock(mutex);

kladkogex's avatar
kladkogex committed
146 147 148 149 150 151
    auto status = db->Put(writeOptions, Slice(_key, _keyLen), Slice(value, _valueLen));

    throwExceptionOnError(status);
}


152
void LevelDB::writeByteArray(string &_key, const char *value,
kladkogex's avatar
kladkogex committed
153 154
                             size_t _valueLen) {

kladkogex's avatar
kladkogex committed
155 156
    std::lock_guard<std::recursive_mutex> lock(mutex);

kladkogex's avatar
kladkogex committed
157 158 159 160 161 162
    auto status = db->Put(writeOptions, Slice(_key), Slice(value, _valueLen));

    throwExceptionOnError(status);
}

void LevelDB::throwExceptionOnError(Status _status) {
163

kladkogex's avatar
kladkogex committed
164 165
    if (_status.IsNotFound())
        return;
kladkogex's avatar
kladkogex committed
166

kladkogex's avatar
kladkogex committed
167
    if (!_status.ok()) {
kladkogex's avatar
kladkogex committed
168
        throw RPCException(COULD_NOT_ACCESS_DATABASE, ("Could not access database database:" + _status.ToString()).c_str());
kladkogex's avatar
kladkogex committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    }

}

uint64_t LevelDB::visitKeys(LevelDB::KeyVisitor *_visitor, uint64_t _maxKeysToVisit) {

    uint64_t readCounter = 0;

    leveldb::Iterator *it = db->NewIterator(readOptions);
    for (it->SeekToFirst(); it->Valid(); it->Next()) {
        _visitor->visitDBKey(it->key().data());
        readCounter++;
        if (readCounter >= _maxKeysToVisit) {
            break;
        }
    }

    delete it;

    return readCounter;
}

191
std::vector<string> LevelDB::writeKeysToVector1(uint64_t _maxKeysToVisit){
192
  uint64_t readCounter = 0;
193
  std::vector<string> keys;
194 195 196

  leveldb::Iterator *it = db->NewIterator(readOptions);
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
197
    string cur_key(it->key().data(), it->key().size());
198 199 200 201 202 203 204 205 206 207 208 209 210
    keys.push_back(cur_key);
   // keys.push_back(it->key().data());
    readCounter++;
    if (readCounter >= _maxKeysToVisit) {
      break;
    }
  }

  delete it;

  return keys;
}

211
void LevelDB::writeDataUnique(const string & Name, const string &value) {
212 213 214 215

  auto key = Name;

  if (readString(Name) != nullptr) {
216 217
    spdlog::info("name {}",Name, " already exists");
     // std::cerr << "name " << Name << " already exists" << std::endl;
218 219 220 221
    throw RPCException(KEY_SHARE_ALREADY_EXISTS, "Data with this name already exists");
  }

  writeString(key, value);
222 223 224 225
  if (DEBUG_PRINT) {
      spdlog::info("{}",Name, " is written to db");
    //std::cerr << Name << " is written to db " << std::endl;
  }
226 227 228
}


229
LevelDB::LevelDB(string &filename) {
kladkogex's avatar
kladkogex committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247


    leveldb::Options options;
    options.create_if_missing = true;

    if (!leveldb::DB::Open(options, filename, (leveldb::DB **) &db).ok()) {
        throw std::runtime_error("Unable to open levelDB database");
    }

    if (db == nullptr) {
        throw std::runtime_error("Null levelDB object");
    }

}

LevelDB::~LevelDB() {
}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
const std::shared_ptr<LevelDB> &LevelDB::getLevelDb() {
    CHECK_STATE(levelDb)
    return levelDb;
}

const std::shared_ptr<LevelDB> &LevelDB::getCsrDb() {
    CHECK_STATE(csrDb)
    return csrDb;
}

const std::shared_ptr<LevelDB> &LevelDB::getCsrStatusDb() {
    CHECK_STATE(csrStatusDb)
    return csrStatusDb;
}


std::shared_ptr<LevelDB> LevelDB::levelDb = nullptr;

std::shared_ptr<LevelDB> LevelDB::csrDb = nullptr;
kladkogex's avatar
kladkogex committed
267

268
std::shared_ptr<LevelDB> LevelDB::csrStatusDb = nullptr;
kladkogex's avatar
kladkogex committed
269

kladko's avatar
kladko committed
270
string LevelDB::sgx_data_folder;
271 272 273

bool LevelDB::isInited = false;

kladko's avatar
kladko committed
274
void LevelDB::initDataFolderAndDBs() {
275 276 277 278

    if (isInited)
        return;

kladko's avatar
kladko committed
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    char cwd[PATH_MAX];
    if (getcwd(cwd, sizeof(cwd)) == NULL) {
        spdlog::error("could not get cwd");
        exit(-1);
    }


    sgx_data_folder = string(cwd) + "/" + SGXDATA_FOLDER;

    struct stat info;
    if (stat(sgx_data_folder.c_str(), &info) !=0 ){
        spdlog::info("going to create sgx_data folder");
        std::string make_sgx_data_folder = "mkdir " + sgx_data_folder;
        if (system(make_sgx_data_folder.c_str()) == 0){
            spdlog::info("sgx_data folder was created");
        }
        else{
            spdlog::error("creating sgx_data folder failed");
            exit(-1);
        }
    }


    auto dbName = sgx_data_folder +  WALLETDB_NAME;
303 304
    levelDb = make_shared<LevelDB>(dbName);

kladko's avatar
kladko committed
305
    auto csr_dbname = sgx_data_folder + "CSR_DB";
306 307
    csrDb = make_shared<LevelDB>(csr_dbname);

kladko's avatar
kladko committed
308
    auto csr_status_dbname = sgx_data_folder + "CSR_STATUS_DB";
309 310 311
    csrStatusDb = make_shared<LevelDB>(csr_status_dbname);

}
kladko's avatar
kladko committed
312 313 314 315

const string &LevelDB::getSgxDataFolder() {
    return sgx_data_folder;
}