1/**
2 * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * \author guonix
17 * \date Nov 2020
18 * \brief
19 */
20
21#include "meta_cache.h"
22#include "common/error_code.h"
23#include "common/logger.h"
24
25namespace proxima {
26namespace be {
27namespace meta {
28
29//! Select all filter
30CollectionFilter MetaCache::PassAllFilter =
31 [](const CollectionImplPtr &) -> bool { return true; };
32
33
34//! Current Collection filter
35CollectionFilter MetaCache::IsCurrentFilter =
36 [](const CollectionImplPtr &collection) -> bool {
37 return collection->meta()->is_current();
38};
39
40namespace {
41// Static empty pointer
42static const CollectionImplPtr EmptyCollectionPtr;
43
44static const CollectionImplPtr &FindCollectionIf(
45 const CollectionImplPtrList &collections, CollectionFilter filter) {
46 static CollectionImplPtr NotFound{nullptr};
47 auto collection =
48 std::find_if_not(collections.begin(), collections.end(),
49 [&filter](const CollectionImplPtr &c) -> bool {
50 return filter ? !filter(c) : true;
51 });
52 return collection != collections.end() ? *collection : NotFound;
53}
54
55} // namespace
56void MetaCache::clear() {
57 cache_.clear();
58 mapping_.clear();
59}
60
61void MetaCache::delete_collection(const std::string &name) {
62 auto iter = cache_.find(name);
63 if (iter != cache_.end()) {
64 for (auto &collection : iter->second) {
65 mapping_.erase(collection->uuid());
66 }
67 cache_.erase(iter);
68 }
69}
70
71bool MetaCache::exist_collection(const std::string &name) const {
72 return cache_.find(name) != cache_.end();
73}
74
75const CollectionImplPtr &MetaCache::get_collection(
76 const std::string &name) const {
77 return get_collection(name, IsCurrentFilter);
78}
79
80//! Retrieve collection by name
81const CollectionImplPtr &MetaCache::get_latest_collection(
82 const std::string &name) const {
83 auto iter = cache_.find(name);
84 if (iter != cache_.end()) {
85 return *iter->second.begin();
86 }
87 return EmptyCollectionPtr;
88}
89
90//! Retrieve collection
91const CollectionImplPtr &MetaCache::get_collection(
92 const std::string &name, const CollectionFilter &filter) const {
93 auto iter = cache_.find(name);
94 if (iter != cache_.end()) {
95 return FindCollectionIf(iter->second, filter);
96 }
97 return EmptyCollectionPtr;
98}
99
100void MetaCache::get_collections(CollectionMetaPtrList *collections) const {
101 for (auto &iter : cache_) {
102 auto &collection = FindCollectionIf(iter.second, IsCurrentFilter);
103 if (collection) {
104 collections->push_back(collection->meta());
105 } else {
106 LOG_WARN("There is collection, which not enabled yet");
107 }
108 }
109}
110
111//! Retrieve collections with specific collection name
112void MetaCache::get_collections(const std::string &collection,
113 CollectionMetaPtrList *collections) const {
114 auto iter = cache_.find(collection);
115 if (iter != cache_.end()) {
116 for (auto &collection_ptr : iter->second) {
117 collections->push_back(collection_ptr->meta());
118 }
119 }
120}
121
122//! Retrieve all the collections
123void MetaCache::get_collections(const CollectionFilter &filter,
124 CollectionMetaPtrList *collections) const {
125 for (auto &iter : mapping_) {
126 if (!filter || filter(iter.second)) {
127 collections->push_back(iter.second->meta());
128 }
129 }
130}
131
132//! Retrieve collections with specific repository
133void MetaCache::get_collections_by_repo(
134 const std::string &repo, CollectionMetaPtrList *collections) const {
135 for (auto &iter : cache_) {
136 auto &collection = FindCollectionIf(
137 iter.second, [&repo](const CollectionImplPtr &c) -> bool {
138 return c->repository() && c->repository()->name() == repo &&
139 c->meta()->is_current() && c->serving();
140 });
141 if (collection) {
142 collections->push_back(collection->meta());
143 }
144 }
145}
146
147int MetaCache::append_collection(const CollectionImplPtr &collection) {
148 if (!collection) {
149 return PROXIMA_BE_ERROR_CODE(InvalidArgument);
150 }
151 auto &collections = cache_[collection->name()];
152 // Append collection
153 collections.push_back(collection);
154 // Sort collection
155 collections.sort([](const CollectionImplPtr &left,
156 const CollectionImplPtr &right) -> bool {
157 return left->revision() > right->revision();
158 });
159
160 // Append to uuid -> collection mapping
161 mapping_[collection->uuid()] = collection;
162 return 0;
163}
164
165int MetaCache::append_column(ColumnImplPtr column) {
166 if (!column) {
167 return PROXIMA_BE_ERROR_CODE(InvalidArgument);
168 }
169
170 auto iter = mapping_.find(column->collection_uuid());
171 if (iter == mapping_.end()) {
172 LOG_WARN("Can't find collection");
173 return PROXIMA_BE_ERROR_CODE(InvalidArgument);
174 }
175
176 return iter->second->append(column);
177}
178
179int MetaCache::append_repository(DatabaseRepositoryImplPtr repository) {
180 if (!repository) {
181 return PROXIMA_BE_ERROR_CODE(InvalidArgument);
182 }
183
184 auto iter = mapping_.find(repository->collection_uuid());
185 if (iter == mapping_.end()) {
186 LOG_WARN("Can't find collection");
187 return PROXIMA_BE_ERROR_CODE(InvalidArgument);
188 }
189
190 return iter->second->set_repository(repository);
191}
192
193} // namespace meta
194} // namespace be
195} // namespace proxima
196