DataSet.cpp 9.32 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
#include "hepnos/DataSet.hpp"
7 8
#include "hepnos/Run.hpp"
#include "hepnos/RunSet.hpp"
9
#include "private/RunSetImpl.hpp"
10 11
#include "private/RunImpl.hpp"
#include "private/DataSetImpl.hpp"
12
#include "private/DataStoreImpl.hpp"
13 14 15

namespace hepnos {

16
DataSet::DataSet()
17
: m_impl(std::make_unique<DataSet::Impl>(this, nullptr, 0, "", "")) {}
18

19
DataSet::DataSet(DataStore* ds, uint8_t level, const std::string& fullname)
20
: m_impl(std::make_unique<DataSet::Impl>(this, ds, level, "", "")) {
21 22
    size_t p = fullname.find_last_of('/');
    if(p == std::string::npos) {
23
        m_impl->m_name = fullname;
24
    } else {
25 26
        m_impl->m_name = fullname.substr(p+1);
        m_impl->m_container = fullname.substr(0, p);
27 28 29
    }
}

30
DataSet::DataSet(DataStore* ds, uint8_t level, const std::string& container, const std::string& name) 
31
: m_impl(std::make_unique<DataSet::Impl>(this, ds, level, container, name)) {}
32

33 34 35
DataSet::DataSet(const DataSet& other) {
    if(other.m_impl) {
        m_impl = std::make_unique<DataSet::Impl>(
36 37 38
            this, other.m_impl->m_datastore,
            other.m_impl->m_level,
            other.m_impl->m_container,
39 40 41
            other.m_impl->m_name);
    }
}
42

43 44
DataSet::DataSet(DataSet&& other) 
: m_impl(std::move(other.m_impl)) {
45 46 47
    if(m_impl) {
        m_impl->m_runset.m_impl->m_dataset = this;
    }
48
}
49 50 51

DataSet& DataSet::operator=(const DataSet& other) {
    if(this == &other) return *this;
52 53 54 55
    if(!other.m_impl) {
        m_impl.reset();
        return *this;
    }
56 57 58 59 60
    m_impl = std::make_unique<DataSet::Impl>(this, 
            other.m_impl->m_datastore,
            other.m_impl->m_level,
            other.m_impl->m_container,
            other.m_impl->m_name);
61 62 63
    return *this;
}

64 65 66
DataSet& DataSet::operator=(DataSet&& other) {
    if(this == &other) return *this;
    m_impl = std::move(other.m_impl);
67 68 69
    if(m_impl) {
        m_impl->m_runset.m_impl->m_dataset = this;
    }
70 71
    return *this;
}
72 73

DataSet::~DataSet() {}
74

75
DataStore* DataSet::getDataStore() const {
76 77 78
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
79 80 81
    return m_impl->m_datastore;
}

82 83 84 85
DataSet DataSet::next() const {
    if(!valid()) return DataSet();
   
    std::vector<std::string> keys; 
86
    size_t s = m_impl->m_datastore->m_impl->nextKeys(
87
            m_impl->m_level, m_impl->m_container, m_impl->m_name, keys, 1);
88
    if(s == 0) return DataSet();
89
    return DataSet(m_impl->m_datastore, m_impl->m_level, keys[0]);
90 91 92
}

bool DataSet::valid() const {
93
    return m_impl && m_impl->m_datastore; 
94 95
}

96
ProductID DataSet::storeRawData(const std::string& key, const std::vector<char>& buffer) {
97
    if(!valid()) {
98
        throw Exception("Calling DataSet member function on an invalid DataSet");
99 100
    }
    // forward the call to the datastore's store function
101
    return m_impl->m_datastore->m_impl->store(0, fullname(), key, buffer);
102 103
}

104
bool DataSet::loadRawData(const std::string& key, std::vector<char>& buffer) const {
105
    if(!valid()) {
106
        throw Exception("Calling DataSet member function on an invalid DataSet");
107 108
    }
    // forward the call to the datastore's load function
109
    return m_impl->m_datastore->m_impl->load(0, fullname(), key, buffer);
110 111 112
}

bool DataSet::operator==(const DataSet& other) const {
113 114 115 116 117
    bool v1 = valid();
    bool v2 = other.valid();
    if(!v1 && !v2) return true;
    if(v1  && !v2) return false;
    if(!v2 &&  v2) return false;
118 119 120 121
    return m_impl->m_datastore == other.m_impl->m_datastore
        && m_impl->m_level     == other.m_impl->m_level
        && m_impl->m_container == other.m_impl->m_container
        && m_impl->m_name      == other.m_impl->m_name;
122 123
}

124 125 126 127
bool DataSet::operator!=(const DataSet& other) const {
    return !(*this == other);
}

128
const std::string& DataSet::name() const {
129 130 131
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
132 133 134 135
    return m_impl->m_name;
}

const std::string& DataSet::container() const {
136 137 138
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
139 140 141 142 143 144 145 146 147 148 149
    return m_impl->m_container;
}

std::string DataSet::fullname() const {
    std::stringstream ss;
    if(container().size() != 0)
        ss << container() << "/";
    ss << name();
    return ss.str();
}

150
DataSet DataSet::createDataSet(const std::string& name) {
151 152 153
    if(name.find('/') != std::string::npos
    || name.find('%') != std::string::npos) {
        throw Exception("Invalid character '/' or '%' in dataset name");
154
    }
155
    std::string parent = fullname();
156
    m_impl->m_datastore->m_impl->store(m_impl->m_level+1, parent, name, std::vector<char>());
157
    return DataSet(m_impl->m_datastore, m_impl->m_level+1, parent, name);
158
}
159

160
Run DataSet::createRun(const RunNumber& runNumber) {
161 162 163
    if(InvalidRunNumber == runNumber) {
        throw Exception("Trying to create a Run with InvalidRunNumber");
    }
164 165 166 167 168 169
    std::string parent = fullname();
    std::string runStr = Run::Impl::makeKeyStringFromRunNumber(runNumber);
    m_impl->m_datastore->m_impl->store(m_impl->m_level+1, parent, runStr, std::vector<char>());
    return Run(m_impl->m_datastore, m_impl->m_level+1, parent, runNumber);
}

170 171
DataSet DataSet::operator[](const std::string& datasetName) const {
    auto it = find(datasetName);
172 173
    if(!it->valid())
        throw Exception("Requested DataSet does not exist");
174 175 176
    return std::move(*it);
}

177
Run DataSet::operator[](const RunNumber& runNumber) const {
178
    auto it = runs().find(runNumber);
179 180
    if(!it->valid())
        throw Exception("Requested Run does not exist");
181 182 183
    return std::move(*it);
}

184
DataSet::iterator DataSet::find(const std::string& datasetPath) {
185 186 187
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
188
    int ret;
189 190
    if(datasetPath.find('%') != std::string::npos) {
        throw Exception("Invalid character '%' in dataset name");
191
    }
192 193 194 195 196 197

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

198
    std::string parent = fullname();
199 200 201 202 203 204 205 206 207 208 209 210 211

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

    std::vector<char> data;

    bool b = m_impl->m_datastore->m_impl->load(level, containerName, datasetName, data);
212 213 214
    if(!b) {
        return m_impl->m_datastore->end();
    }
215
    return iterator(DataSet(m_impl->m_datastore, level, containerName, datasetName));
216 217 218 219 220 221 222 223
}

DataSet::const_iterator DataSet::find(const std::string& datasetName) const {
    iterator it = const_cast<DataSet*>(this)->find(datasetName);
    return it;
}

DataSet::iterator DataSet::begin() {
224 225 226
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
227
    DataSet ds(m_impl->m_datastore, m_impl->m_level+1, fullname(),"");
228
    ds = ds.next();
229
    if(ds.valid()) return iterator(ds);
230 231 232 233
    else return end();
}

DataSet::iterator DataSet::end() {
234 235 236
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
237 238 239
    return m_impl->m_datastore->end();
}

240 241 242 243 244
DataSet::const_iterator DataSet::begin() const {
    return const_iterator(const_cast<DataSet*>(this)->begin());
}

DataSet::const_iterator DataSet::end() const {
245 246 247
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
248 249 250
    return m_impl->m_datastore->cend();
}

251 252 253 254 255
DataSet::const_iterator DataSet::cbegin() const {
    return const_iterator(const_cast<DataSet*>(this)->begin());
}

DataSet::const_iterator DataSet::cend() const {
256 257 258
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
259 260 261 262
    return m_impl->m_datastore->cend();
}

DataSet::iterator DataSet::lower_bound(const std::string& lb) {
263 264 265
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
266 267 268 269 270 271 272 273 274
    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;
    }
275
    DataSet ds(m_impl->m_datastore, m_impl->m_level+1, fullname(), lb2);
276 277
    ds = ds.next();
    if(!ds.valid()) return end();
278
    else return iterator(ds);
279 280 281 282 283 284 285 286
}

DataSet::const_iterator DataSet::lower_bound(const std::string& lb) const {
    iterator it = const_cast<DataSet*>(this)->lower_bound(lb);
    return it;
}

DataSet::iterator DataSet::upper_bound(const std::string& ub) {
287 288 289
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
290
    DataSet ds(m_impl->m_datastore, m_impl->m_level+1, fullname(), ub);
291 292
    ds = ds.next();
    if(!ds.valid()) return end();
293
    else return iterator(ds);
294 295 296 297 298 299 300
}

DataSet::const_iterator DataSet::upper_bound(const std::string& ub) const {
    iterator it = const_cast<DataSet*>(this)->upper_bound(ub);
    return it;
}

301
RunSet& DataSet::runs() {
302 303 304
    if(!valid()) {
        throw Exception("Calling DataSet member function on an invalid DataSet");
    }
305 306 307 308 309 310 311
    return m_impl->m_runset;
}

const RunSet& DataSet::runs() const {
    return const_cast<DataSet*>(this)->runs();
}

312
}