17e10b0aaSTrond Norbye/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
27e10b0aaSTrond Norbye/*
37e10b0aaSTrond Norbye *     Copyright 2015 Couchbase, Inc.
47e10b0aaSTrond Norbye *
57e10b0aaSTrond Norbye *   Licensed under the Apache License, Version 2.0 (the "License");
67e10b0aaSTrond Norbye *   you may not use this file except in compliance with the License.
77e10b0aaSTrond Norbye *   You may obtain a copy of the License at
87e10b0aaSTrond Norbye *
97e10b0aaSTrond Norbye *       http://www.apache.org/licenses/LICENSE-2.0
107e10b0aaSTrond Norbye *
117e10b0aaSTrond Norbye *   Unless required by applicable law or agreed to in writing, software
127e10b0aaSTrond Norbye *   distributed under the License is distributed on an "AS IS" BASIS,
137e10b0aaSTrond Norbye *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147e10b0aaSTrond Norbye *   See the License for the specific language governing permissions and
157e10b0aaSTrond Norbye *   limitations under the License.
167e10b0aaSTrond Norbye */
177e10b0aaSTrond Norbye#pragma once
187e10b0aaSTrond Norbye
193ebda3baSJim Walker#include <boost/optional/optional_fwd.hpp>
20686f003fSTrond Norbye#include <engines/ewouldblock_engine/ewouldblock_engine.h>
21c4b6868aSDave Rigby#include <memcached/engine_error.h>
227e10b0aaSTrond Norbye#include <memcached/openssl.h>
23a21009eeSTrond Norbye#include <memcached/protocol_binary.h>
242196dc1dSTrond Norbye#include <memcached/rbac.h>
25686f003fSTrond Norbye#include <memcached/types.h>
26bd2e50c1STrond Norbye#include <platform/dynamic.h>
27d6ec23d7SMark Nunberg#include <platform/sized_buffer.h>
28f0df2df9STrond Norbye#include <platform/socket.h>
299c34d9c3SDave Rigby
30ba818194SBen Huddleston#include <nlohmann/json_fwd.hpp>
31ba818194SBen Huddleston
32b25307f4SPremkumar#include <chrono>
338e198731STrond Norbye#include <cstdlib>
3423bbc0e3STrond Norbye#include <functional>
35dc57faf5STrond Norbye#include <stdexcept>
36dc57faf5STrond Norbye#include <string>
378e198731STrond Norbye#include <unordered_set>
38b25307f4SPremkumar#include <utility>
39dc57faf5STrond Norbye#include <vector>
407e10b0aaSTrond Norbye
4129f30f9dSTrond Norbyeclass FrameInfo;
4229f30f9dSTrond Norbye
4329f30f9dSTrond Norbyeusing FrameInfoVector = std::vector<std::unique_ptr<FrameInfo>>;
4429f30f9dSTrond Norbyeusing GetFrameInfoFunction = std::function<FrameInfoVector()>;
4529f30f9dSTrond Norbye
467e10b0aaSTrond Norbye/**
477e10b0aaSTrond Norbye * The Frame class is used to represent all of the data included in the
48aae6ed18STrond Norbye * protocol unit going over the wire.
497e10b0aaSTrond Norbye */
507e10b0aaSTrond Norbyeclass Frame {
517e10b0aaSTrond Norbyepublic:
527e10b0aaSTrond Norbye    void reset() {
537e10b0aaSTrond Norbye        payload.resize(0);
547e10b0aaSTrond Norbye    }
55dc57faf5STrond Norbye
567c43f23eSTrond Norbye    cb::mcbp::Magic getMagic() const {
577c43f23eSTrond Norbye        const auto magic(cb::mcbp::Magic(payload.at(0)));
587c43f23eSTrond Norbye        if (!cb::mcbp::is_legal(magic)) {
597c43f23eSTrond Norbye            throw std::invalid_argument(
607c43f23eSTrond Norbye                    "Frame::getMagic: invalid magic provided in buffer");
617c43f23eSTrond Norbye        }
627c43f23eSTrond Norbye
637c43f23eSTrond Norbye        return magic;
647c43f23eSTrond Norbye    }
657c43f23eSTrond Norbye
667c43f23eSTrond Norbye    const cb::mcbp::Request* getRequest() const {
677c43f23eSTrond Norbye        return reinterpret_cast<const cb::mcbp::Request*>(payload.data());
687c43f23eSTrond Norbye    }
697c43f23eSTrond Norbye
707c43f23eSTrond Norbye    const cb::mcbp::Response* getResponse() const {
717c43f23eSTrond Norbye        return reinterpret_cast<const cb::mcbp::Response*>(payload.data());
727c43f23eSTrond Norbye    }
737c43f23eSTrond Norbye
747e10b0aaSTrond Norbye    std::vector<uint8_t> payload;
757e10b0aaSTrond Norbye    typedef std::vector<uint8_t>::size_type size_type;
767e10b0aaSTrond Norbye};
777e10b0aaSTrond Norbye
78a21009eeSTrond Norbyeclass DocumentInfo {
79a21009eeSTrond Norbyepublic:
80a21009eeSTrond Norbye    std::string id;
81a21009eeSTrond Norbye    uint32_t flags;
829e197a92SJim Walker    uint32_t expiration;
832716340fSTrond Norbye    cb::mcbp::Datatype datatype;
84e2063e55STrond Norbye    uint64_t cas;
852ce7d9feSPaolo Cocchi
862ce7d9feSPaolo Cocchi    DocumentInfo()
872ce7d9feSPaolo Cocchi        : id(""),
882ce7d9feSPaolo Cocchi          flags(0),
892ce7d9feSPaolo Cocchi          expiration(0),
902ce7d9feSPaolo Cocchi          datatype(cb::mcbp::Datatype::Raw),
912ce7d9feSPaolo Cocchi          cas(0) {
922ce7d9feSPaolo Cocchi    }
937d346044SDave Rigby
947d346044SDave Rigby    bool operator==(const DocumentInfo& rhs) const {
957d346044SDave Rigby        return (id == rhs.id) && (flags == rhs.flags) &&
967d346044SDave Rigby               (expiration == rhs.expiration) && (datatype == rhs.datatype) &&
977d346044SDave Rigby               (cas == rhs.cas);
987d346044SDave Rigby    }
99a21009eeSTrond Norbye};
100a21009eeSTrond Norbye
1017d346044SDave Rigby::std::ostream& operator<<(::std::ostream& os, const DocumentInfo& info);
1027d346044SDave Rigby
103a21009eeSTrond Norbyeclass Document {
104a21009eeSTrond Norbyepublic:
1057d346044SDave Rigby    bool operator==(const Document& rhs) const {
1067d346044SDave Rigby        return (info == rhs.info) && (value == rhs.value);
1077d346044SDave Rigby    }
1087d346044SDave Rigby
1097728129dSDave Rigby    /**
1107728129dSDave Rigby     * Compress this document using Snappy. Replaces the value with a compressed
1117728129dSDave Rigby     * version, adds Snappy to the set of datatypes.
1127728129dSDave Rigby     */
1137728129dSDave Rigby    void compress();
1147728129dSDave Rigby
115a21009eeSTrond Norbye    DocumentInfo info;
116037d3ff8SDave Rigby    std::string value;
117a21009eeSTrond Norbye};
118a21009eeSTrond Norbye
1197d346044SDave Rigby::std::ostream& operator<<(::std::ostream& os, const Document& doc);
1207d346044SDave Rigby
121a21009eeSTrond Norbyeclass MutationInfo {
122a21009eeSTrond Norbyepublic:
123a21009eeSTrond Norbye    uint64_t cas;
124a21009eeSTrond Norbye    size_t size;
125a21009eeSTrond Norbye    uint64_t seqno;
126a21009eeSTrond Norbye    uint64_t vbucketuuid;
127a21009eeSTrond Norbye};
128a21009eeSTrond Norbye
1297d346044SDave Rigbystruct ObserveInfo {
1307d346044SDave Rigby    uint8_t formatType;
131f871d12bSChristopher Farman    Vbid vbId;
1327d346044SDave Rigby    uint64_t uuid;
1337d346044SDave Rigby    uint64_t lastPersistedSeqno;
1347d346044SDave Rigby    uint64_t currentSeqno;
1357d346044SDave Rigby    uint64_t failoverUUID;
1367d346044SDave Rigby    uint64_t failoverSeqno;
1377d346044SDave Rigby};
1387d346044SDave Rigby
1390b86987aSTrond Norbyeenum class BucketType : uint8_t {
1400b86987aSTrond Norbye    Invalid = 0,
1410b86987aSTrond Norbye    Memcached = 1,
1420b86987aSTrond Norbye    Couchbase = 2,
1430b86987aSTrond Norbye    EWouldBlock = 3
1440b86987aSTrond Norbye};
1450b86987aSTrond Norbye
1460b686891STrond Norbyeenum class MutationType {
1470b686891STrond Norbye    Add, Set, Replace, Append, Prepend
1480b686891STrond Norbye};
1490b686891STrond Norbye
1500b686891STrond Norbyestd::string to_string(MutationType type);
1510b86987aSTrond Norbye
152fe93eb50STrond Norbyeclass BinprotResponse;
1538e198731STrond Norbyeclass BinprotCommand;
154fe93eb50STrond Norbye
155dc57faf5STrond Norbyeclass ConnectionError : public std::runtime_error {
156dc57faf5STrond Norbyepublic:
15745cbd889STrond Norbye    ConnectionError(const std::string& prefix, cb::mcbp::Status reason_);
158fe93eb50STrond Norbye
159fe93eb50STrond Norbye    ConnectionError(const std::string& prefix, const BinprotResponse& response);
160fe93eb50STrond Norbye
16145cbd889STrond Norbye    cb::mcbp::Status getReason() const {
162fe93eb50STrond Norbye        return reason;
163a21009eeSTrond Norbye    }
164a21009eeSTrond Norbye
165fe93eb50STrond Norbye    bool isInvalidArguments() const {
16645cbd889STrond Norbye        return reason == cb::mcbp::Status::Einval;
167fe93eb50STrond Norbye    }
168a21009eeSTrond Norbye
169fe93eb50STrond Norbye    bool isAlreadyExists() const {
17045cbd889STrond Norbye        return reason == cb::mcbp::Status::KeyEexists;
171fe93eb50STrond Norbye    }
172a21009eeSTrond Norbye
173fe93eb50STrond Norbye    bool isNotFound() const {
17445cbd889STrond Norbye        return reason == cb::mcbp::Status::KeyEnoent;
175fe93eb50STrond Norbye    }
176a21009eeSTrond Norbye
177fe93eb50STrond Norbye    bool isNotMyVbucket() const {
17845cbd889STrond Norbye        return reason == cb::mcbp::Status::NotMyVbucket;
179fe93eb50STrond Norbye    }
1807435fb3bSTrond Norbye
181fe93eb50STrond Norbye    bool isNotStored() const {
18245cbd889STrond Norbye        return reason == cb::mcbp::Status::NotStored;
183fe93eb50STrond Norbye    }
184a21009eeSTrond Norbye
185fe93eb50STrond Norbye    bool isAccessDenied() const {
18645cbd889STrond Norbye        return reason == cb::mcbp::Status::Eaccess;
187fe93eb50STrond Norbye    }
188d49a32deSTrond Norbye
189fe93eb50STrond Norbye    bool isDeltaBadval() const {
19045cbd889STrond Norbye        return reason == cb::mcbp::Status::DeltaBadval;
191fe93eb50STrond Norbye    }
1922de9f1feSTrond Norbye
193fe93eb50STrond Norbye    bool isAuthError() const {
19445cbd889STrond Norbye        return reason == cb::mcbp::Status::AuthError;
195fe93eb50STrond Norbye    }
19686839fbeSTrond Norbye
197fe93eb50STrond Norbye    bool isNotSupported() const {
19845cbd889STrond Norbye        return reason == cb::mcbp::Status::NotSupported;
199fe93eb50STrond Norbye    }
200eee49ccfSTrond Norbye
201fe93eb50STrond Norbye    bool isLocked() const {
20245cbd889STrond Norbye        return reason == cb::mcbp::Status::Locked;
203fe93eb50STrond Norbye    }
204eee49ccfSTrond Norbye
205fe93eb50STrond Norbye    bool isTemporaryFailure() const {
20645cbd889STrond Norbye        return reason == cb::mcbp::Status::Etmpfail;
207fe93eb50STrond Norbye    }
20820284738STrond Norbye
2091ed4a1e8SSriram Ganesan    bool isTooBig() const {
21045cbd889STrond Norbye        return reason == cb::mcbp::Status::E2big;
2111ed4a1e8SSriram Ganesan    }
2121ed4a1e8SSriram Ganesan
213888aa3b7STrond Norbye    std::string getErrorContext() const;
214888aa3b7STrond Norbye
215f5071479STrond Norbye    nlohmann::json getErrorJsonContext() const;
216f5071479STrond Norbye
217fe93eb50STrond Norbyeprivate:
21845cbd889STrond Norbye    const cb::mcbp::Status reason;
219888aa3b7STrond Norbye    const std::string payload;
220a21009eeSTrond Norbye};
221dc57faf5STrond Norbye
2220d99b87aSDave Rigby/**
2230d99b87aSDave Rigby * Exception thrown when the received response deosn't match our expections.
2240d99b87aSDave Rigby */
2250d99b87aSDave Rigbystruct ValidationError : public std::runtime_error {
22696a7634eSTrond Norbye    explicit ValidationError(const std::string& msg) : std::runtime_error(msg) {
2270d99b87aSDave Rigby    }
2280d99b87aSDave Rigby};
2290d99b87aSDave Rigby
230e53770eeSTrond Norbye/**
231e53770eeSTrond Norbye * The execution mode represents the mode the server executes commands
232e53770eeSTrond Norbye * retrieved over the network. In an Ordered mode (that's the default mode
233e53770eeSTrond Norbye * and how things was defined in the initial implementation of the binary
234e53770eeSTrond Norbye * protocol) the server must not start executing the next command before
235e53770eeSTrond Norbye * the execution of the current command is completed. In Unordered mode
236e53770eeSTrond Norbye * the server may start executing (and report the result back to the client)
237e53770eeSTrond Norbye * whenever it feels like.
238e53770eeSTrond Norbye */
239e53770eeSTrond Norbyeenum class ExecutionMode { Ordered, Unordered };
240e53770eeSTrond Norbye
2417e10b0aaSTrond Norbye/**
2427e10b0aaSTrond Norbye * The MemcachedConnection class is an abstract class representing a
2437e10b0aaSTrond Norbye * connection to memcached. The concrete implementations of the class
2447e10b0aaSTrond Norbye * implements the Memcached binary protocol and Greenstack.
245a21009eeSTrond Norbye *
246a21009eeSTrond Norbye * By default a connection is set into a synchronous mode.
247a21009eeSTrond Norbye *
248a21009eeSTrond Norbye * All methods is expeted to work, and all failures is reported through
249a21009eeSTrond Norbye * exceptions. Unexpected packets / responses etc will use the ConnectionError,
250a21009eeSTrond Norbye * and other problems (like network error etc) use std::runtime_error.
251a21009eeSTrond Norbye *
2527e10b0aaSTrond Norbye */
2537e10b0aaSTrond Norbyeclass MemcachedConnection {
2547e10b0aaSTrond Norbyepublic:
2557e10b0aaSTrond Norbye    MemcachedConnection() = delete;
2567e10b0aaSTrond Norbye
2577e10b0aaSTrond Norbye    MemcachedConnection(const MemcachedConnection&) = delete;
2587e10b0aaSTrond Norbye
2598e198731STrond Norbye    /**
2608e198731STrond Norbye     * Create a new instance of the MemcachedConnection
2618e198731STrond Norbye     *
2628e198731STrond Norbye     * @param host the hostname to connect to (empty == localhost)
2638e198731STrond Norbye     * @param port the port number to connect to
2648e198731STrond Norbye     * @param family the socket family to connect as (AF_INET, AF_INET6
2658e198731STrond Norbye     *               or use AF_UNSPEC to just pick one)
2668e198731STrond Norbye     * @param ssl connect over SSL or not
2678e198731STrond Norbye     */
26896a7634eSTrond Norbye    MemcachedConnection(std::string host,
2698e198731STrond Norbye                        in_port_t port,
2708e198731STrond Norbye                        sa_family_t family,
2718e198731STrond Norbye                        bool ssl);
2728e198731STrond Norbye
2738e198731STrond Norbye    ~MemcachedConnection();
2747e10b0aaSTrond Norbye
275cbd8f4c6STrond Norbye    /**
276cbd8f4c6STrond Norbye     * Release the socket from this instance. The caller is required
277cbd8f4c6STrond Norbye     * to close the socket when it is no longer in use!
278cbd8f4c6STrond Norbye     *
279cbd8f4c6STrond Norbye     * @return the underlying socket
280cbd8f4c6STrond Norbye     */
281cbd8f4c6STrond Norbye    SOCKET releaseSocket();
282cbd8f4c6STrond Norbye
28326d24b39STrond Norbye    // Set a tag / label on this connection
28426d24b39STrond Norbye    void setTag(std::string tag) {
28526d24b39STrond Norbye        MemcachedConnection::tag = std::move(tag);
28626d24b39STrond Norbye    }
28726d24b39STrond Norbye
28826d24b39STrond Norbye    const std::string& getTag() const {
28926d24b39STrond Norbye        return tag;
29026d24b39STrond Norbye    }
29126d24b39STrond Norbye
29277a8f1ceSDave Rigby    // Creates clone (copy) of the given connection - i.e. a second independent
29377a8f1ceSDave Rigby    // channel to memcached. Used for multi-connection testing.
2948e198731STrond Norbye    std::unique_ptr<MemcachedConnection> clone();
29577a8f1ceSDave Rigby
2967e10b0aaSTrond Norbye    in_port_t getPort() const {
2977e10b0aaSTrond Norbye        return port;
2987e10b0aaSTrond Norbye    }
2997e10b0aaSTrond Norbye
3007e10b0aaSTrond Norbye    sa_family_t getFamily() const {
3017e10b0aaSTrond Norbye        return family;
3027e10b0aaSTrond Norbye    }
3037e10b0aaSTrond Norbye
3047e10b0aaSTrond Norbye    bool isSsl() const {
3057e10b0aaSTrond Norbye        return ssl;
3067e10b0aaSTrond Norbye    }
3077e10b0aaSTrond Norbye
3088fa0786cSTrond Norbye    /**
3098fa0786cSTrond Norbye     * Set the SSL Certificate file to use
3108fa0786cSTrond Norbye     *
3118fa0786cSTrond Norbye     * @throws std::system_error if the file doesn't exist
3128fa0786cSTrond Norbye     */
3138fa0786cSTrond Norbye    void setSslCertFile(const std::string& file);
3148fa0786cSTrond Norbye
3158fa0786cSTrond Norbye    /**
3168fa0786cSTrond Norbye     * Set the SSL private key file to use
3178fa0786cSTrond Norbye     *
3188fa0786cSTrond Norbye     * @throws std::system_error if the file doesn't exist
3198fa0786cSTrond Norbye     */
3208fa0786cSTrond Norbye    void setSslKeyFile(const std::string& file);
3218fa0786cSTrond Norbye
322b0daba34STrond Norbye    /// Set the TLS version to use
323b0daba34STrond Norbye    void setTlsProtocol(std::string protocol);
324b0daba34STrond Norbye    /// Set the ciphers to use for TLS < 1.3
325b0daba34STrond Norbye    void setTls12Ciphers(std::string ciphers);
326b0daba34STrond Norbye    /// Set the ciphers to use for TLS >= 1.3
327b0daba34STrond Norbye    void setTls13Ciphers(std::string ciphers);
328b0daba34STrond Norbye
32981f77e04STrond Norbye    /**
33081f77e04STrond Norbye     * Try to establish a connection to the server.
33181f77e04STrond Norbye     *
33281f77e04STrond Norbye     * @thows std::exception if an error occurs
33381f77e04STrond Norbye     */
33481f77e04STrond Norbye    void connect();
33581f77e04STrond Norbye
33681f77e04STrond Norbye    /**
33781f77e04STrond Norbye     * Close the connection to the server
33881f77e04STrond Norbye     */
3398e198731STrond Norbye    void close();
34081f77e04STrond Norbye
34181f77e04STrond Norbye    /**
34281f77e04STrond Norbye     * Drop the current connection to the server and re-establish the
34381f77e04STrond Norbye     * connection.
34481f77e04STrond Norbye     */
34581f77e04STrond Norbye    void reconnect() {
34681f77e04STrond Norbye        close();
34781f77e04STrond Norbye        connect();
34881f77e04STrond Norbye    }
34981f77e04STrond Norbye
3507e10b0aaSTrond Norbye    /**
3517e10b0aaSTrond Norbye     * Perform a SASL authentication to memcached
3527e10b0aaSTrond Norbye     *
3537e10b0aaSTrond Norbye     * @param username the username to use in authentication
3547e10b0aaSTrond Norbye     * @param password the password to use in authentication
3557e10b0aaSTrond Norbye     * @param mech the SASL mech to use
3567e10b0aaSTrond Norbye     */
3578e198731STrond Norbye    void authenticate(const std::string& username,
3588e198731STrond Norbye                      const std::string& password,
3598e198731STrond Norbye                      const std::string& mech);
3607e10b0aaSTrond Norbye
361a21009eeSTrond Norbye    /**
362a21009eeSTrond Norbye     * Create a bucket
363a21009eeSTrond Norbye     *
364a21009eeSTrond Norbye     * @param name the name of the bucket
365a21009eeSTrond Norbye     * @param config the buckets configuration attributes
366a21009eeSTrond Norbye     * @param type the kind of bucket to create
367a21009eeSTrond Norbye     */
3688e198731STrond Norbye    void createBucket(const std::string& name,
3698e198731STrond Norbye                      const std::string& config,
37096a7634eSTrond Norbye                      BucketType type);
371dc57faf5STrond Norbye
372a21009eeSTrond Norbye    /**
373a21009eeSTrond Norbye     * Delete the named bucket
374a21009eeSTrond Norbye     *
375a21009eeSTrond Norbye     * @param name the name of the bucket
376a21009eeSTrond Norbye     */
3778e198731STrond Norbye    void deleteBucket(const std::string& name);
378dc57faf5STrond Norbye
379d85212a6STrond Norbye    /**
380d85212a6STrond Norbye     * Select the named bucket
381d85212a6STrond Norbye     *
382d85212a6STrond Norbye     * @param name the name of the bucket to select
383d85212a6STrond Norbye     */
3848e198731STrond Norbye    void selectBucket(const std::string& name);
385d85212a6STrond Norbye
386a21009eeSTrond Norbye    /**
387a21009eeSTrond Norbye     * List all of the buckets on the server
388a21009eeSTrond Norbye     *
389a21009eeSTrond Norbye     * @return a vector containing all of the buckets
390a21009eeSTrond Norbye     */
39129f30f9dSTrond Norbye    std::vector<std::string> listBuckets(
39229f30f9dSTrond Norbye            GetFrameInfoFunction getFrameInfo = {});
393dc57faf5STrond Norbye
394a21009eeSTrond Norbye    /**
395a21009eeSTrond Norbye     * Fetch a document from the server
396a21009eeSTrond Norbye     *
397a21009eeSTrond Norbye     * @param id the name of the document
398a21009eeSTrond Norbye     * @param vbucket the vbucket the document resides in
399a21009eeSTrond Norbye     * @return a document object containg the information about the
400a21009eeSTrond Norbye     *         document.
401a21009eeSTrond Norbye     */
40229f30f9dSTrond Norbye    Document get(const std::string& id,
40329f30f9dSTrond Norbye                 Vbid vbucket,
40429f30f9dSTrond Norbye                 GetFrameInfoFunction getFrameInfo = {});
405a21009eeSTrond Norbye
406c73d8b3fSTrond Norbye    /**
407c73d8b3fSTrond Norbye     * Fetch multiple documents
408c73d8b3fSTrond Norbye     *
409c73d8b3fSTrond Norbye     * Send a pipeline of (quiet) get commands to the server and fire
410c73d8b3fSTrond Norbye     * the documentCallback with the documents found in the server.
411c73d8b3fSTrond Norbye     *
412c73d8b3fSTrond Norbye     * If the server returns with an error the provided error callback
413c73d8b3fSTrond Norbye     * will be called. (note that you won't receive a callback for
414c73d8b3fSTrond Norbye     * documents that don't exist on the server as we're using the
415c73d8b3fSTrond Norbye     * quiet commands.
416c73d8b3fSTrond Norbye     *
417c73d8b3fSTrond Norbye     * Use the getFrameInfo method if you'd like the server to perform
418c73d8b3fSTrond Norbye     * out of order requests (note: the connection must be set to
419c73d8b3fSTrond Norbye     * allow unordered execution).
420c73d8b3fSTrond Norbye     *
421c73d8b3fSTrond Norbye     * @param id The key and the vbucket the document resides in
422c73d8b3fSTrond Norbye     * @param documentCallback the callback with the document for an
423c73d8b3fSTrond Norbye     *                         operation
424c73d8b3fSTrond Norbye     * @param errorCallback the callback if the server returns an error
425c73d8b3fSTrond Norbye     * @param getFrameInfo Optional FrameInfo to inject to the commands
426c73d8b3fSTrond Norbye     * @return A vector containing all of the found documents
427c73d8b3fSTrond Norbye     */
428c73d8b3fSTrond Norbye    void mget(const std::vector<std::pair<const std::string, Vbid>>& id,
429c73d8b3fSTrond Norbye              std::function<void(std::unique_ptr<Document>&)> documentCallback,
430c73d8b3fSTrond Norbye              std::function<void(const std::string&, const cb::mcbp::Response&)>
431c73d8b3fSTrond Norbye                      errorCallback = {},
432c73d8b3fSTrond Norbye              GetFrameInfoFunction getFrameInfo = {});
433c73d8b3fSTrond Norbye
434eee49ccfSTrond Norbye    /**
435eee49ccfSTrond Norbye     * Fetch and lock a document from the server
436eee49ccfSTrond Norbye     *
437eee49ccfSTrond Norbye     * @param id the name of the document
438eee49ccfSTrond Norbye     * @param vbucket the vbucket the document resides in
439eee49ccfSTrond Norbye     * @param lock_timeout the timeout (in sec) for the lock. 0 means
440eee49ccfSTrond Norbye     *                     use the default lock timeout from the server
441eee49ccfSTrond Norbye     * @return a document object containing the information about the
442eee49ccfSTrond Norbye     *         document.
443eee49ccfSTrond Norbye     */
4448e198731STrond Norbye    Document get_and_lock(const std::string& id,
445f871d12bSChristopher Farman                          Vbid vbucket,
44629f30f9dSTrond Norbye                          uint32_t lock_timeout,
44729f30f9dSTrond Norbye                          GetFrameInfoFunction getFrameInfo = {});
448eee49ccfSTrond Norbye
449c19807c3SPaolo Cocchi    /**
450c19807c3SPaolo Cocchi     * Get the Failover Log for a given VBucket
451c19807c3SPaolo Cocchi     *
452c19807c3SPaolo Cocchi     * @param vbucket
453c19807c3SPaolo Cocchi     * @return the raw BinprotResponse
454c19807c3SPaolo Cocchi     */
45529f30f9dSTrond Norbye    BinprotResponse getFailoverLog(Vbid vbucket,
45629f30f9dSTrond Norbye                                   GetFrameInfoFunction getFrameInfo = {});
457c19807c3SPaolo Cocchi
458eee49ccfSTrond Norbye    /**
459eee49ccfSTrond Norbye     * Unlock a locked document
460eee49ccfSTrond Norbye     *
461eee49ccfSTrond Norbye     * @param id the name of the document
462eee49ccfSTrond Norbye     * @param vbucket the vbucket the document resides in
463eee49ccfSTrond Norbye     * @param cas the cas identifier of the locked document
464eee49ccfSTrond Norbye     */
46529f30f9dSTrond Norbye    void unlock(const std::string& id,
46629f30f9dSTrond Norbye                Vbid vbucket,
46729f30f9dSTrond Norbye                uint64_t cas,
46829f30f9dSTrond Norbye                GetFrameInfoFunction getFrameInfo = {});
469eee49ccfSTrond Norbye
47029f30f9dSTrond Norbye    void dropPrivilege(cb::rbac::Privilege privilege,
47129f30f9dSTrond Norbye                       GetFrameInfoFunction getFrameInfo = {});
472eee49ccfSTrond Norbye
47377a8f1ceSDave Rigby    /*
47477a8f1ceSDave Rigby     * Form a Frame representing a CMD_GET
47577a8f1ceSDave Rigby     */
47696a7634eSTrond Norbye    static Frame encodeCmdGet(const std::string& id, Vbid vbucket);
47777a8f1ceSDave Rigby
47829f30f9dSTrond Norbye    MutationInfo mutate(const Document& doc,
47929f30f9dSTrond Norbye                        Vbid vbucket,
48029f30f9dSTrond Norbye                        MutationType type,
48129f30f9dSTrond Norbye                        GetFrameInfoFunction getFrameInfo = {}) {
4820444680cSMark Nunberg        return mutate(doc.info,
4830444680cSMark Nunberg                      vbucket,
484037d3ff8SDave Rigby                      cb::const_byte_buffer(reinterpret_cast<const uint8_t*>(
485037d3ff8SDave Rigby                                                    doc.value.data()),
486037d3ff8SDave Rigby                                            doc.value.size()),
48729f30f9dSTrond Norbye                      type,
48829f30f9dSTrond Norbye                      getFrameInfo);
4890444680cSMark Nunberg    }
4900444680cSMark Nunberg
491a21009eeSTrond Norbye    /**
492a21009eeSTrond Norbye     * Perform the mutation on the attached document.
493a21009eeSTrond Norbye     *
494a21009eeSTrond Norbye     * The method throws an exception upon errors
495a21009eeSTrond Norbye     *
4960444680cSMark Nunberg     * @param info Document metadata
497a21009eeSTrond Norbye     * @param vbucket the vbucket to operate on
4980444680cSMark Nunberg     * @param value new value for the document
499a21009eeSTrond Norbye     * @param type the type of mutation to perform
500a21009eeSTrond Norbye     * @return the new cas value for success
501a21009eeSTrond Norbye     */
5028e198731STrond Norbye    MutationInfo mutate(const DocumentInfo& info,
503f871d12bSChristopher Farman                        Vbid vbucket,
5048e198731STrond Norbye                        cb::const_byte_buffer value,
50529f30f9dSTrond Norbye                        MutationType type,
50629f30f9dSTrond Norbye                        GetFrameInfoFunction getFrameInfo = {});
507a21009eeSTrond Norbye
508d6ec23d7SMark Nunberg    /**
509d6ec23d7SMark Nunberg     * Convenience method to store (aka "upsert") an item.
510d6ec23d7SMark Nunberg     * @param id The item's ID
511d6ec23d7SMark Nunberg     * @param vbucket vBucket
512037d3ff8SDave Rigby     * @param value Value of the item.
513d6ec23d7SMark Nunberg     * @return The mutation result.
514d6ec23d7SMark Nunberg     */
515037d3ff8SDave Rigby    MutationInfo store(const std::string& id,
516f871d12bSChristopher Farman                       Vbid vbucket,
517037d3ff8SDave Rigby                       std::string value,
51829f30f9dSTrond Norbye                       cb::mcbp::Datatype datatype = cb::mcbp::Datatype::Raw,
51929f30f9dSTrond Norbye                       GetFrameInfoFunction getFrameInfo = {});
520d49a32deSTrond Norbye
52123bbc0e3STrond Norbye    /**
52223bbc0e3STrond Norbye     * Get statistics from the server, and fire a callback with the key and
52323bbc0e3STrond Norbye     * value of each reported stat
52423bbc0e3STrond Norbye     *
52523bbc0e3STrond Norbye     * @param callback the callback to call for each stat
52623bbc0e3STrond Norbye     * @param group the stats group to request
52723bbc0e3STrond Norbye     */
52823bbc0e3STrond Norbye    void
52923bbc0e3STrond Norbye    stats(std::function<void(const std::string&, const std::string&)> callback,
53023bbc0e3STrond Norbye          const std::string& group = std::string{});
53123bbc0e3STrond Norbye
53269a59d92SMark Nunberg    /**
53369a59d92SMark Nunberg     * Get stats as a map
53469a59d92SMark Nunberg     * @param subcommand
53569a59d92SMark Nunberg     * @return
53669a59d92SMark Nunberg     */
5378e198731STrond Norbye    std::map<std::string, std::string> statsMap(const std::string& subcommand);
53869a59d92SMark Nunberg
5393c80b425SBen Huddleston    nlohmann::json stats(const std::string& subcommand);
540d49a32deSTrond Norbye
5415514a9ebSTrond Norbye    /**
5425514a9ebSTrond Norbye     * Instruct the audit daemon to reload the configuration
5435514a9ebSTrond Norbye     */
54429f30f9dSTrond Norbye    void reloadAuditConfiguration(GetFrameInfoFunction getFrameInfo = {});
5455514a9ebSTrond Norbye
5467e10b0aaSTrond Norbye    /**
5477e10b0aaSTrond Norbye     * Sent the given frame over this connection
548a21009eeSTrond Norbye     *
549a21009eeSTrond Norbye     * @param frame the frame to send to the server
5507e10b0aaSTrond Norbye     */
5518e198731STrond Norbye    void sendFrame(const Frame& frame);
5527e10b0aaSTrond Norbye
55377a8f1ceSDave Rigby    /** Send part of the given frame over this connection. Upon success,
55477a8f1ceSDave Rigby     * the frame's payload will be modified such that the sent bytes are
55577a8f1ceSDave Rigby     * deleted - i.e. after a successful call the frame object will only have
55677a8f1ceSDave Rigby     * the remaining, unsent bytes left.
55777a8f1ceSDave Rigby     *
55877a8f1ceSDave Rigby     * @param frame The frame to partially send.
55977a8f1ceSDave Rigby     * @param length The number of bytes to transmit. Must be less than or
56077a8f1ceSDave Rigby     *               equal to the size of the frame.
56177a8f1ceSDave Rigby     */
56277a8f1ceSDave Rigby    void sendPartialFrame(Frame& frame, Frame::size_type length);
56377a8f1ceSDave Rigby
564