1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2015 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 #include "buckets.h"
18 #include "mc_time.h"
19 #include "stats.h"
20 #include "topkeys.h"
21 #include <memcached/dcp.h>
22 #include <memcached/engine.h>
23 
24 Bucket::Bucket() = default;
25 
reset()26 void Bucket::reset() {
27     std::lock_guard<std::mutex> guard(mutex);
28     state = Bucket::State::None;
29     name[0] = '\0';
30     setEngine(nullptr);
31     topkeys.reset();
32     clusterConfiguration.reset();
33     max_document_size = default_max_item_size;
34     supportedFeatures = {};
35     for (auto& c : responseCounters) {
36         c.reset();
37     }
38     subjson_operation_times.reset();
39     timings.reset();
40     for (auto& s : stats) {
41         s.reset();
42     }
43 
44     for (auto& h : engine_event_handlers) {
45         h.clear();
46     }
47     type = Type::Unknown;
48 }
49 
supports(cb::engine::Feature feature)50 bool Bucket::supports(cb::engine::Feature feature) {
51     return supportedFeatures.find(feature) != supportedFeatures.end();
52 }
53 
getDcpIface() const54 DcpIface* Bucket::getDcpIface() const {
55     return bucketDcp;
56 }
57 
getEngine() const58 EngineIface* Bucket::getEngine() const {
59     return engine;
60 }
61 
setEngine(EngineIface* engine)62 void Bucket::setEngine(EngineIface* engine) {
63     Bucket::engine = engine;
64     bucketDcp = dynamic_cast<DcpIface*>(engine);
65 }
66 
67 namespace BucketValidator {
validateBucketName(const std::string& name, std::string& errors)68     bool validateBucketName(const std::string& name, std::string& errors) {
69         if (name.empty()) {
70             errors.assign("BucketValidator::validateBucketName: "
71                               "Name can't be empty");
72             return false;
73         }
74 
75         if (name.length() > MAX_BUCKET_NAME_LENGTH) {
76             errors.assign("BucketValidator::validateBucketName: Name"
77                               " too long (exceeds " +
78                           std::to_string(MAX_BUCKET_NAME_LENGTH) +
79                           ")");
80             return false;
81         }
82 
83         // Verify that the bucket name only consists of legal characters
84         for (const uint8_t ii : name) {
85             if (!(isupper(ii) || islower(ii) || isdigit(ii))) {
86                 switch (ii) {
87                 case '_':
88                 case '-':
89                 case '.':
90                 case '%':
91                     break;
92                 default:
93                     errors.assign("BucketValidator::validateBucketName: "
94                                       "name contains invalid characters");
95                     return false;
96                 }
97             }
98         }
99 
100         return true;
101     }
102 
validateBucketType(const Bucket::Type& type, std::string& errors)103     bool validateBucketType(const Bucket::Type& type, std::string& errors) {
104         if (type == Bucket::Type::Unknown) {
105             errors.assign("BucketValidator::validateBucketType: "
106                               "Unsupported bucket type");
107             return false;
108         }
109 
110         return true;
111     }
112 }
113 
to_string(Bucket::Type type)114 std::string to_string(Bucket::Type type) {
115     switch (type) {
116     case Bucket::Type::Memcached:
117         return "Memcached";
118     case Bucket::Type::Couchstore:
119         return "Couchstore";
120     case Bucket::Type::EWouldBlock:
121         return "EWouldBlock";
122     case Bucket::Type::NoBucket:
123         return "No Bucket";
124     case Bucket::Type::Unknown:
125         return "Uknown";
126     }
127     throw std::logic_error("Invalid bucket type: " + std::to_string(int(type)));
128 }
129 
to_string(Bucket::State state)130 std::string to_string(Bucket::State state) {
131     switch (state) {
132     case Bucket::State::None:
133         return "none";
134     case Bucket::State::Creating:
135         return "creating";
136     case Bucket::State::Initializing:
137         return "initializing";
138     case Bucket::State::Ready:
139         return "ready";
140     case Bucket::State::Stopping:
141         return "stopping";
142     case Bucket::State::Destroying:
143         return "destroying";
144     }
145     throw std::invalid_argument("Invalid bucket state: " +
146                                 std::to_string(int(state)));
147 }
148