storage.h 4.4 KB
Newer Older
S
superjom 已提交
1 2
#ifndef VISUALDL_STORAGE_STORAGE_H
#define VISUALDL_STORAGE_STORAGE_H
S
superjom 已提交
3

S
superjom 已提交
4
#include <glog/logging.h>
S
superjom 已提交
5
#include <algorithm>
S
superjom 已提交
6
#include <set>
S
superjom 已提交
7
#include <vector>
S
superjom 已提交
8

S
superjom 已提交
9
#include "visualdl/logic/im.h"
S
superjom 已提交
10
#include "visualdl/storage/storage.pb.h"
S
superjom 已提交
11
#include "visualdl/storage/tablet.h"
S
superjom 已提交
12
#include "visualdl/utils/filesystem.h"
S
superjom 已提交
13
#include "visualdl/utils/guard.h"
S
superjom 已提交
14 15

namespace visualdl {
S
superjom 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
static const std::string meta_file_name = "storage.meta";

static std::string meta_path(const std::string& dir) {
  CHECK(!dir.empty()) << "dir is empty";
  return dir + "/" + meta_file_name;
}
static std::string tablet_path(const std::string& dir, const std::string& tag) {
  CHECK(!dir.empty()) << "dir should be set first";
  return dir + "/" + tag;
}

struct SimpleSyncMeta {
  void Inc() { counter++; }

  bool ToSync() { return counter % cycle == 0; }

  size_t counter{0};
  int cycle;
};

36
/*
S
superjom 已提交
37
 * Helper for operations on storage::Storage.
38
 */
S
superjom 已提交
39
struct Storage {
S
superjom 已提交
40 41 42 43
  DECL_GUARD(Storage)

  mutable SimpleSyncMeta meta;

S
superjom 已提交
44
  Storage() {
S
superjom 已提交
45
    dir_ = std::make_shared<std::string>();
S
superjom 已提交
46 47 48
    data_ = std::make_shared<storage::Storage>();
    tablets_ = std::make_shared<std::map<std::string, storage::Tablet>>();
    modes_ = std::make_shared<std::set<std::string>>();
49 50
    time_t t;
    time(&t);
S
superjom 已提交
51
    data_->set_timestamp(t);
52
  }
S
superjom 已提交
53
  Storage(const Storage& other)
S
superjom 已提交
54 55 56
      : data_(other.data_), tablets_(other.tablets_), modes_(other.modes_) {
    dir_ = other.dir_;
  }
57

S
superjom 已提交
58 59
  // write operations
  void AddMode(const std::string& x) {
S
superjom 已提交
60
    // avoid duplicate modes.
S
superjom 已提交
61
    if (modes_->count(x) != 0) return;
S
superjom 已提交
62
    *data_->add_modes() = x;
S
superjom 已提交
63
    modes_->insert(x);
S
superjom 已提交
64
    WRITE_GUARD
S
Superjom 已提交
65
  }
66

S
superjom 已提交
67
  Tablet AddTablet(const std::string& x) {
S
superjom 已提交
68 69
    CHECK(tablets_->count(x) == 0) << "tablet [" << x << "] has existed";
    (*tablets_)[x] = storage::Tablet();
S
superjom 已提交
70 71
    AddTag(x);
    LOG(INFO) << "really add tag " << x;
S
superjom 已提交
72 73 74
    // WRITE_GUARD
    PersistToDisk();
    return Tablet(&(*tablets_)[x], this);
S
superjom 已提交
75
  }
76

S
superjom 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  void SetDir(const std::string& dir) {
    *dir_ = dir;
  }
  std::string dir() const { return *dir_; }
  void PersistToDisk() {
    CHECK(!dir_->empty()) << "dir should be set.";
    try {
      fs::TryRecurMkdir(*dir_);

      fs::SerializeToFile(*data_, meta_path(*dir_));
      for (auto tag : data_->tags()) {
        auto it = tablets_->find(tag);
        CHECK(it != tablets_->end()) << "tag " << tag << " not exist.";
        fs::SerializeToFile(it->second, tablet_path(*dir_, tag));
      }
    } catch (...) {
    }
  }
S
superjom 已提交
95 96 97 98 99 100 101 102 103
  /*
   * Save memory to disk.
   */
  void PersistToDisk(const std::string& dir) {
    CHECK(!dir.empty()) << "dir should be set.";
    fs::TryRecurMkdir(dir);

    fs::SerializeToFile(*data_, meta_path(dir));
    for (auto tag : data_->tags()) {
S
superjom 已提交
104 105
      auto it = tablets_->find(tag);
      CHECK(it != tablets_->end()) << "tag " << tag << " not exist.";
S
superjom 已提交
106 107 108 109 110 111
      fs::SerializeToFile(it->second, tablet_path(dir, tag));
    }
  }

  Storage* parent() { return this; }

S
superjom 已提交
112
protected:
S
superjom 已提交
113 114
  void AddTag(const std::string& x) {
    *data_->add_tags() = x;
S
superjom 已提交
115
    WRITE_GUARD
S
superjom 已提交
116
  }
117

118
private:
S
superjom 已提交
119
  std::shared_ptr<std::string> dir_;
S
superjom 已提交
120
  std::shared_ptr<std::map<std::string, storage::Tablet>> tablets_;
S
superjom 已提交
121
  std::shared_ptr<storage::Storage> data_;
S
superjom 已提交
122
  std::shared_ptr<std::set<std::string>> modes_;
S
superjom 已提交
123 124 125 126 127 128 129 130 131
};

/*
 * Storage reader, each interface will trigger a read.
 */
struct StorageReader {
  StorageReader(const std::string& dir) : dir_(dir) {}

  // read operations
S
superjom 已提交
132
  std::vector<std::string> all_tags() {
S
superjom 已提交
133 134 135 136 137
    storage::Storage storage;
    Reload(storage);
    return std::vector<std::string>(storage.tags().begin(),
                                    storage.tags().end());
  }
S
superjom 已提交
138 139 140 141 142 143 144 145 146 147 148
  std::vector<std::string> tags(Tablet::Type component) {
    auto tags = all_tags();
    auto it =
        std::remove_if(tags.begin(), tags.end(), [&](const std::string& tag) {
          auto tb = tablet(tag);
          return tb.type() != component;
        });
    tags.resize(it - tags.begin());
    return tags;
  }
  std::vector<std::string> modes() {
S
superjom 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    storage::Storage storage;
    Reload(storage);
    return std::vector<std::string>(storage.modes().begin(),
                                    storage.modes().end());
  }

  TabletReader tablet(const std::string& tag) const {
    auto path = tablet_path(dir_, tag);
    storage::Tablet tablet;
    fs::DeSerializeFromFile(&tablet, path);
    return TabletReader(tablet);
  }

protected:
  void Reload(storage::Storage& storage) {
    const std::string path = meta_path(dir_);
    fs::DeSerializeFromFile(&storage, path);
  }

private:
  std::string dir_;
170 171 172
};

}  // namespace visualdl
S
superjom 已提交
173

S
superjom 已提交
174
#endif