DataStore.cpp 11.3 KB
Newer Older
Matthieu Dorier's avatar
Matthieu Dorier committed
1 2 3 4 5
/*
 * (C) 2018 The University of Chicago
 * 
 * See COPYRIGHT in top-level directory.
 */
6 7 8 9 10 11
#include <vector>
#include <functional>
#include <iostream>
#include "hepnos/Exception.hpp"
#include "hepnos/DataStore.hpp"
#include "hepnos/DataSet.hpp"
12
#include "hepnos/WriteBatch.hpp"
13
#include "private/DataStoreImpl.hpp"
14
#include "private/WriteBatchImpl.hpp"
15 16 17

namespace hepnos {

18 19 20 21
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore implementation
////////////////////////////////////////////////////////////////////////////////////////////

22 23 24 25 26 27 28 29 30
DataStore::DataStore() 
: m_impl(std::make_unique<DataStore::Impl>(this)) {
    char* file = getenv("HEPNOS_CONFIG_FILE");
    if(file == nullptr) 
        throw Exception("HEPNOS_CONFIG_FILE environment variable not set");
    std::string configFile(file);
    m_impl->init(configFile);
}

31
DataStore::DataStore(const std::string& configFile) 
32
: m_impl(std::make_unique<DataStore::Impl>(this)) {
33 34 35 36 37 38 39 40 41 42 43 44
    m_impl->init(configFile);
}

DataStore::DataStore(DataStore&& other)
: m_impl(std::move(other.m_impl)) {}

DataStore& DataStore::operator=(DataStore&& other) {
    if(&other == this) return *this;
    if(m_impl) {
        m_impl->cleanup();
    }
    m_impl = std::move(other.m_impl);
45
    return *this;
46 47 48 49 50 51 52 53
}
    
DataStore::~DataStore() {
    if(m_impl) {
        m_impl->cleanup();
    }
}

54
DataStore::iterator DataStore::find(const std::string& datasetPath) {
55 56 57 58
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }

59
    int ret;
60 61 62

    if(datasetPath.find('%') != std::string::npos) {
        throw Exception("Invalid character ('%') in dataset name");
63
    }
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

    size_t slash_count = std::count(datasetPath.begin(), datasetPath.end(), '/');
    size_t level = 1 + slash_count;
    std::string containerName;
    std::string datasetName;

    if(slash_count == 0) {
        datasetName = datasetPath;
        containerName = "";
    } else {
        size_t c = datasetPath.find_last_of('/');
        containerName = datasetPath.substr(0,c);
        datasetName   = datasetPath.substr(c+1);
    }

79
    std::string data;
80
    bool b = m_impl->load(level, containerName, datasetName, data);
81 82
    if(!b) {
        return m_impl->m_end;
83
    }
84
    return iterator(DataSet(this, level, std::make_shared<std::string>(containerName), datasetName));
85 86
}

Matthieu Dorier's avatar
Matthieu Dorier committed
87 88
DataSet DataStore::operator[](const std::string& datasetName) const {
    auto it = find(datasetName);
89 90
    if(!it->valid())
        throw Exception("Requested DataSet does not exist");
Matthieu Dorier's avatar
Matthieu Dorier committed
91 92 93
    return std::move(*it);
}

94
DataStore::const_iterator DataStore::find(const std::string& datasetName) const {
95 96
    DataStore::iterator it = const_cast<DataStore*>(this)->find(datasetName);
    return it;
97 98 99
}

DataStore::iterator DataStore::begin() {
100 101 102
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
103
    DataSet ds(this, 1, std::make_shared<std::string>(""), "");
104
    ds = ds.next();
105
    if(ds.valid()) return iterator(std::move(ds));
106
    else return end();
107 108
}

109 110 111 112 113
DataStore::const_iterator DataStore::begin() const {
    iterator it = const_cast<DataStore*>(this)->begin();
    return const_iterator(std::move(it));
}

114
DataStore::iterator DataStore::end() {
115 116 117
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
118 119 120
    return m_impl->m_end;
}

121
DataStore::const_iterator DataStore::end() const {
122 123 124
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
125 126 127
    return m_impl->m_end;
}

128
DataStore::const_iterator DataStore::cbegin() const {
129
    return const_cast<DataStore*>(this)->begin();
130 131 132
}

DataStore::const_iterator DataStore::cend() const {
133
    return const_cast<DataStore*>(this)->end();
134 135 136
}

DataStore::iterator DataStore::lower_bound(const std::string& lb) {
137 138 139 140 141 142 143 144 145
    std::string lb2 = lb;
    size_t s = lb2.size();
    lb2[s-1] -= 1; // sdskv_list_keys's start_key is exclusive
    iterator it = find(lb2);
    if(it != end()) {
        // we found something before the specified lower bound
        ++it;
        return it;
    }
146
    DataSet ds(this, 1, std::make_shared<std::string>(""), lb2);
147 148
    ds = ds.next();
    if(!ds.valid()) return end();
149
    else return iterator(std::move(ds));
150 151 152
}

DataStore::const_iterator DataStore::lower_bound(const std::string& lb) const {
153 154
    iterator it = const_cast<DataStore*>(this)->lower_bound(lb);
    return it;
155 156 157
}

DataStore::iterator DataStore::upper_bound(const std::string& ub) {
158 159 160
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
161
    DataSet ds(this, 1, std::make_shared<std::string>(""), ub);
162 163
    ds = ds.next();
    if(!ds.valid()) return end();
164
    else return iterator(std::move(ds));
165 166 167
}

DataStore::const_iterator DataStore::upper_bound(const std::string& ub) const {
168 169
    iterator it = const_cast<DataStore*>(this)->upper_bound(ub);
    return it;
170 171 172
}

DataSet DataStore::createDataSet(const std::string& name) {
173 174 175
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
176 177 178
    if(name.find('/') != std::string::npos
    || name.find('%') != std::string::npos) {
        throw Exception("Invalid character ('/' or '%') in dataset name");
179
    }
180
    m_impl->store(1, "", name);
181
    return DataSet(this, 1, std::make_shared<std::string>(""), name);
182 183 184 185 186 187 188 189 190 191
}

DataSet DataStore::createDataSet(WriteBatch& batch, const std::string& name) {
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
    if(name.find('/') != std::string::npos
    || name.find('%') != std::string::npos) {
        throw Exception("Invalid character ('/' or '%') in dataset name");
    }
192
    batch.m_impl->store(1, "", name);
193
    return DataSet(this, 1, std::make_shared<std::string>(""), name);
194 195
}

196
void DataStore::shutdown() {
197 198 199
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
200
    for(auto addr : m_impl->m_addrs) {
Matthieu Dorier's avatar
Matthieu Dorier committed
201
        margo_shutdown_remote_instance(m_impl->m_mid, addr.second);
202 203 204
    }
}

205
bool DataStore::loadRawProduct(const ProductID& productID, std::string& buffer) {
206 207 208
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
209 210 211
    return m_impl->load(productID.m_level, productID.m_containerName, productID.m_objectName, buffer);
}

212 213 214 215 216 217 218
bool DataStore::loadRawProduct(const ProductID& productID, char* data, size_t* size) {
    if(!m_impl) {
        throw Exception("Calling DataStore member function on an invalid DataStore object");
    }
    return m_impl->load(productID.m_level, productID.m_containerName, productID.m_objectName, data, size);
}

219 220 221 222
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::const_iterator::Impl implementation
////////////////////////////////////////////////////////////////////////////////////////////

223 224 225 226
class DataStore::const_iterator::Impl {
    public:
        DataSet    m_current_dataset;

227 228
        Impl()
        : m_current_dataset()
229
        {}
230

231 232 233 234 235 236
        Impl(const DataSet& dataset)
        : m_current_dataset(dataset)
        {}

        Impl(DataSet&& dataset)
        : m_current_dataset(std::move(dataset))
237
        {}
238 239

        Impl(const Impl& other)
240
        : m_current_dataset(other.m_current_dataset) 
241 242 243
        {}

        bool operator==(const Impl& other) const {
244
            return m_current_dataset == other.m_current_dataset;
245
        }
246 247
};

248 249 250
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::const_iterator::Impl implementation
////////////////////////////////////////////////////////////////////////////////////////////
251

252 253
DataStore::const_iterator::const_iterator()
: m_impl(std::make_unique<Impl>()) {}
254

255 256 257 258 259
DataStore::const_iterator::const_iterator(const DataSet& dataset)
: m_impl(std::make_unique<Impl>(dataset)) {}

DataStore::const_iterator::const_iterator(DataSet&& dataset)
: m_impl(std::make_unique<Impl>(std::move(dataset))) {}
260

261
DataStore::const_iterator::~const_iterator() {}
262

263 264 265 266 267
DataStore::const_iterator::const_iterator(const DataStore::const_iterator& other) {
    if(other.m_impl) {
        m_impl = std::make_unique<Impl>(*other.m_impl);
    }
}
268 269

DataStore::const_iterator::const_iterator(DataStore::const_iterator&& other) 
270
: m_impl(std::move(other.m_impl)) {}
271

272 273
DataStore::const_iterator& DataStore::const_iterator::operator=(const DataStore::const_iterator& other) {
    if(&other == this) return *this;
274 275 276 277
    if(other.m_impl)
        m_impl = std::make_unique<Impl>(*other.m_impl);
    else
        m_impl.reset();
278
    return *this;
279 280
}

281 282 283 284
DataStore::const_iterator& DataStore::const_iterator::operator=(DataStore::const_iterator&& other) {
    if(&other == this) return *this;
    m_impl = std::move(other.m_impl);
    return *this;
285 286 287
}

DataStore::const_iterator::self_type DataStore::const_iterator::operator++() {
288 289 290 291 292
    if(!m_impl) {
        throw Exception("Trying to increment an invalid iterator");
    }
    m_impl->m_current_dataset = m_impl->m_current_dataset.next();
    return *this;
293 294 295
}

DataStore::const_iterator::self_type DataStore::const_iterator::operator++(int) {
296 297 298
    const_iterator copy = *this;
    ++(*this);
    return copy;
299 300 301
}

const DataStore::const_iterator::reference DataStore::const_iterator::operator*() {
302 303 304 305
    if(!m_impl) {
        throw Exception("Trying to dereference an invalid iterator");
    }
    return m_impl->m_current_dataset;
306 307 308
}

const DataStore::const_iterator::pointer DataStore::const_iterator::operator->() {
309 310 311
    if(!m_impl) {
        throw Exception("Trying to dereference an invalid iterator");
    }
312
    return &(m_impl->m_current_dataset);
313 314 315
}

bool DataStore::const_iterator::operator==(const self_type& rhs) const {
316 317 318 319
    if(!m_impl && !rhs.m_impl)  return true;
    if(m_impl  && !rhs.m_impl)  return false;
    if(!m_impl && rhs.m_impl)   return false;
    return *m_impl == *(rhs.m_impl);
320 321 322
}

bool DataStore::const_iterator::operator!=(const self_type& rhs) const {
323
    return !(*this == rhs);
324 325
}

326 327 328 329
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::iterator implementation
////////////////////////////////////////////////////////////////////////////////////////////

330 331 332 333 334
DataStore::iterator::iterator(const DataSet& current)
: const_iterator(current) {}

DataStore::iterator::iterator(DataSet&& current)
: const_iterator(std::move(current)) {}
335

336 337
DataStore::iterator::iterator()
: const_iterator() {}
338

339
DataStore::iterator::~iterator() {}
340 341

DataStore::iterator::iterator(const DataStore::iterator& other)
342
: const_iterator(other) {}
343 344

DataStore::iterator::iterator(DataStore::iterator&& other) 
345
: const_iterator(std::move(other)) {}
346 347

DataStore::iterator& DataStore::iterator::operator=(const DataStore::iterator& other) {
348
    if(this == &other) return *this;
349 350 351 352
    if(other.m_impl)
        m_impl = std::make_unique<Impl>(*other.m_impl);
    else
        m_impl.reset();
353
    return *this;
354 355 356
}

DataStore::iterator& DataStore::iterator::operator=(DataStore::iterator&& other) {
357 358 359
    if(this == &other) return *this;
    m_impl = std::move(other.m_impl);
    return *this;
360 361 362
}

DataStore::iterator::reference DataStore::iterator::operator*() {
363
    return const_cast<reference>(const_iterator::operator*());
364 365 366
}

DataStore::iterator::pointer DataStore::iterator::operator->() {
367
    return const_cast<pointer>(const_iterator::operator->());
368 369 370 371
}

}