DataStore.cpp 9.02 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 12 13 14 15
#include <vector>
#include <functional>
#include <iostream>
#include <yaml-cpp/yaml.h>
#include <sdskv-client.h>
#include <bake-client.h>
#include <ch-placement.h>
#include "hepnos/Exception.hpp"
#include "hepnos/DataStore.hpp"
#include "hepnos/DataSet.hpp"
16
#include "private/DataStoreImpl.hpp"
17 18 19

namespace hepnos {

20 21 22 23
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore implementation
////////////////////////////////////////////////////////////////////////////////////////////

24 25 26 27 28 29 30 31 32
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);
}

33
DataStore::DataStore(const std::string& configFile) 
34
: m_impl(std::make_unique<DataStore::Impl>(this)) {
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    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);
}
    
DataStore::~DataStore() {
    if(m_impl) {
        m_impl->cleanup();
    }
}

55
DataStore::iterator DataStore::find(const std::string& datasetPath) {
56
    int ret;
57 58 59

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

    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);
    }

76
    std::vector<char> data;
77
    bool b = m_impl->load(level, containerName, datasetName, data);
78 79
    if(!b) {
        return m_impl->m_end;
80
    }
81
    return iterator(DataSet(this, level, containerName, datasetName));
82 83
}

Matthieu Dorier's avatar
Matthieu Dorier committed
84 85 86 87 88
DataSet DataStore::operator[](const std::string& datasetName) const {
    auto it = find(datasetName);
    return std::move(*it);
}

89
DataStore::const_iterator DataStore::find(const std::string& datasetName) const {
90 91
    DataStore::iterator it = const_cast<DataStore*>(this)->find(datasetName);
    return it;
92 93 94
}

DataStore::iterator DataStore::begin() {
95
    DataSet ds(this, 1, "", "");
96
    ds = ds.next();
97
    if(ds.valid()) return iterator(std::move(ds));
98
    else return end();
99 100
}

101 102 103 104 105
DataStore::const_iterator DataStore::begin() const {
    iterator it = const_cast<DataStore*>(this)->begin();
    return const_iterator(std::move(it));
}

106 107 108 109
DataStore::iterator DataStore::end() {
    return m_impl->m_end;
}

110 111 112 113
DataStore::const_iterator DataStore::end() const {
    return m_impl->m_end;
}

114
DataStore::const_iterator DataStore::cbegin() const {
115
    return const_cast<DataStore*>(this)->begin();
116 117 118
}

DataStore::const_iterator DataStore::cend() const {
119
    return const_cast<DataStore*>(this)->end();
120 121 122
}

DataStore::iterator DataStore::lower_bound(const std::string& lb) {
123 124 125 126 127 128 129 130 131
    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;
    }
132
    DataSet ds(this, 1, "", lb2);
133 134
    ds = ds.next();
    if(!ds.valid()) return end();
135
    else return iterator(std::move(ds));
136 137 138
}

DataStore::const_iterator DataStore::lower_bound(const std::string& lb) const {
139 140
    iterator it = const_cast<DataStore*>(this)->lower_bound(lb);
    return it;
141 142 143
}

DataStore::iterator DataStore::upper_bound(const std::string& ub) {
144
    DataSet ds(this, 1, "", ub);
145 146
    ds = ds.next();
    if(!ds.valid()) return end();
147
    else return iterator(std::move(ds));
148 149 150
}

DataStore::const_iterator DataStore::upper_bound(const std::string& ub) const {
151 152
    iterator it = const_cast<DataStore*>(this)->upper_bound(ub);
    return it;
153 154 155
}

DataSet DataStore::createDataSet(const std::string& name) {
156 157 158
    if(name.find('/') != std::string::npos
    || name.find('%') != std::string::npos) {
        throw Exception("Invalid character ('/' or '%') in dataset name");
159
    }
160
    m_impl->store(1, "", name, std::vector<char>());
161
    return DataSet(this, 1, "", name);
162 163
}

164 165
void DataStore::shutdown() {
    for(auto addr : m_impl->m_addrs) {
Matthieu Dorier's avatar
Matthieu Dorier committed
166
        margo_shutdown_remote_instance(m_impl->m_mid, addr.second);
167 168 169
    }
}

170 171 172 173
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::const_iterator::Impl implementation
////////////////////////////////////////////////////////////////////////////////////////////

174 175 176 177
class DataStore::const_iterator::Impl {
    public:
        DataSet    m_current_dataset;

178 179
        Impl()
        : m_current_dataset()
180
        {}
181

182 183 184 185 186 187
        Impl(const DataSet& dataset)
        : m_current_dataset(dataset)
        {}

        Impl(DataSet&& dataset)
        : m_current_dataset(std::move(dataset))
188
        {}
189 190

        Impl(const Impl& other)
191
        : m_current_dataset(other.m_current_dataset) 
192 193 194
        {}

        bool operator==(const Impl& other) const {
195
            return m_current_dataset == other.m_current_dataset;
196
        }
197 198
};

199 200 201
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::const_iterator::Impl implementation
////////////////////////////////////////////////////////////////////////////////////////////
202

203 204
DataStore::const_iterator::const_iterator()
: m_impl(std::make_unique<Impl>()) {}
205

206 207 208 209 210
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))) {}
211

212
DataStore::const_iterator::~const_iterator() {}
213 214

DataStore::const_iterator::const_iterator(const DataStore::const_iterator& other) 
215
: m_impl(std::make_unique<Impl>(*other.m_impl)) {}
216 217

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

220 221 222 223
DataStore::const_iterator& DataStore::const_iterator::operator=(const DataStore::const_iterator& other) {
    if(&other == this) return *this;
    m_impl = std::make_unique<Impl>(*other.m_impl);
    return *this;
224 225
}

226 227 228 229
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;
230 231 232
}

DataStore::const_iterator::self_type DataStore::const_iterator::operator++() {
233 234 235 236 237
    if(!m_impl) {
        throw Exception("Trying to increment an invalid iterator");
    }
    m_impl->m_current_dataset = m_impl->m_current_dataset.next();
    return *this;
238 239 240
}

DataStore::const_iterator::self_type DataStore::const_iterator::operator++(int) {
241 242 243
    const_iterator copy = *this;
    ++(*this);
    return copy;
244 245 246
}

const DataStore::const_iterator::reference DataStore::const_iterator::operator*() {
247 248 249 250
    if(!m_impl) {
        throw Exception("Trying to dereference an invalid iterator");
    }
    return m_impl->m_current_dataset;
251 252 253
}

const DataStore::const_iterator::pointer DataStore::const_iterator::operator->() {
254 255
    if(!m_impl) return nullptr;
    return &(m_impl->m_current_dataset);
256 257 258
}

bool DataStore::const_iterator::operator==(const self_type& rhs) const {
259 260 261 262
    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);
263 264 265
}

bool DataStore::const_iterator::operator!=(const self_type& rhs) const {
266
    return !(*this == rhs);
267 268
}

269 270 271 272
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::iterator implementation
////////////////////////////////////////////////////////////////////////////////////////////

273 274 275 276 277
DataStore::iterator::iterator(const DataSet& current)
: const_iterator(current) {}

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

279 280
DataStore::iterator::iterator()
: const_iterator() {}
281

282
DataStore::iterator::~iterator() {}
283 284

DataStore::iterator::iterator(const DataStore::iterator& other)
285
: const_iterator(other) {}
286 287

DataStore::iterator::iterator(DataStore::iterator&& other) 
288
: const_iterator(std::move(other)) {}
289 290

DataStore::iterator& DataStore::iterator::operator=(const DataStore::iterator& other) {
291 292 293
    if(this == &other) return *this;
    m_impl = std::make_unique<Impl>(*other.m_impl);
    return *this;
294 295 296
}

DataStore::iterator& DataStore::iterator::operator=(DataStore::iterator&& other) {
297 298 299
    if(this == &other) return *this;
    m_impl = std::move(other.m_impl);
    return *this;
300 301 302
}

DataStore::iterator::reference DataStore::iterator::operator*() {
303
    return const_cast<reference>(const_iterator::operator*());
304 305 306
}

DataStore::iterator::pointer DataStore::iterator::operator->() {
307
    return const_cast<pointer>(const_iterator::operator->());
308 309 310 311
}

}