238 lines
9.2 KiB
C++
238 lines
9.2 KiB
C++
#pragma once
|
|
|
|
#include <glog/logging.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "types.h"
|
|
|
|
namespace mooncake {
|
|
|
|
/*
|
|
* @brief A helper class for etcd operations.
|
|
* This class is used to handle the requests to the etcd cluster.
|
|
* All methods of this class are thread-safe.
|
|
*/
|
|
class EtcdHelper {
|
|
public:
|
|
/*
|
|
* @brief Connect to the etcd store client. There is a global etcd client in
|
|
* libetcd. It is used for all the etcd operations for mooncake-store. This
|
|
* function ensures the client is only connected once.
|
|
* @param etcd_endpoints: The endpoints of the etcd store client.
|
|
* Multiple endpoints are separated by semicolons.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode ConnectToEtcdStoreClient(
|
|
const std::string& etcd_endpoints);
|
|
|
|
/*
|
|
* @brief Get the value of a key from the etcd.
|
|
* @param key: The key to get the value of.
|
|
* @param key_size: The size of the key in bytes.
|
|
* @param value: Output param, the value of the key.
|
|
* @param revision_id: Output param, the create revision id of the key.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode Get(const char* key, const size_t key_size,
|
|
std::string& value, EtcdRevisionId& revision_id);
|
|
|
|
/*
|
|
* @brief Create a key-value pair that binds to a given lease.
|
|
* @param key: The key to create.
|
|
* @param key_size: The size of the key in bytes.
|
|
* @param value: The value to create.
|
|
* @param value_size: The size of the value in bytes.
|
|
* @param lease_id: The lease id to bind to the key.
|
|
* @param revision_id: Output param, the create revision id of the key.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode CreateWithLease(const char* key, const size_t key_size,
|
|
const char* value, const size_t value_size,
|
|
EtcdLeaseId lease_id,
|
|
EtcdRevisionId& revision_id);
|
|
|
|
/*
|
|
* @brief Batch create key-value pairs in a single transaction.
|
|
* Fails if any key already exists.
|
|
* @param keys: The vector of keys.
|
|
* @param values: The vector of values.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode BatchCreate(const std::vector<std::string>& keys,
|
|
const std::vector<std::string>& values);
|
|
|
|
/*
|
|
* @brief Grant a lease from the etcd.
|
|
* @param lease_ttl: The ttl of the lease, in seconds.
|
|
* @param lease_id: Output param, the lease id.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode GrantLease(int64_t lease_ttl, EtcdLeaseId& lease_id);
|
|
|
|
/*
|
|
* @brief Revoke a lease in etcd immediately.
|
|
* @param lease_id: The lease id to revoke.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode RevokeLease(EtcdLeaseId lease_id);
|
|
|
|
/*
|
|
* @brief Watch a key until it is deleted. This is a blocking function.
|
|
* @param key: The key to watch.
|
|
* @param key_size: The size of the key in bytes.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode WatchUntilDeleted(const char* key, const size_t key_size);
|
|
|
|
/*
|
|
* @brief Cancel watching a key
|
|
* @param key: The key to cancel watch.
|
|
* @param key_size: The size of the key in bytes.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode CancelWatch(const char* key, const size_t key_size);
|
|
|
|
/*
|
|
* @brief Keep a lease alive. This is a blocking function.
|
|
* @param lease_id: The lease id to keep alive.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode KeepAlive(EtcdLeaseId lease_id);
|
|
|
|
/*
|
|
* @brief Cancel a lease keep alive. Returning error means
|
|
* the lease id does not exist or the goroutine to
|
|
* keep the lease alive is already closed.
|
|
* @param lease_id: The lease id to cancel keep alive.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode CancelKeepAlive(EtcdLeaseId lease_id);
|
|
|
|
/*
|
|
* @brief Wait until a keep alive context is registered and cancellable.
|
|
* @param lease_id: The lease id to wait for.
|
|
* @param timeout_ms: Wait timeout in milliseconds.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode WaitKeepAliveReady(EtcdLeaseId lease_id, int timeout_ms);
|
|
|
|
/*
|
|
* @brief Put a key-value pair to etcd.
|
|
* @param key: The key to put.
|
|
* @param key_size: The size of the key in bytes.
|
|
* @param value: The value to put.
|
|
* @param value_size: The size of the value in bytes.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode Put(const char* key, const size_t key_size,
|
|
const char* value, const size_t value_size);
|
|
|
|
/*
|
|
* @brief Create a key-value pair in etcd if the key does not already exist.
|
|
* This is implemented via etcd transaction (CreateRevision == 0).
|
|
* @return: OK on success; ETCD_TRANSACTION_FAIL if key already exists.
|
|
*/
|
|
static ErrorCode Create(const char* key, const size_t key_size,
|
|
const char* value, const size_t value_size);
|
|
|
|
/*
|
|
* @brief Range get in etcd and return result as a JSON array string.
|
|
* This avoids complex cross-language memory management for key/value
|
|
* arrays.
|
|
* @param start_key: Start key (inclusive).
|
|
* @param start_key_size: Size in bytes.
|
|
* @param end_key: End key (exclusive).
|
|
* @param end_key_size: Size in bytes.
|
|
* @param limit: Maximum number of kvs to return (0 means no limit).
|
|
* @param json: Output JSON string, format: [{"key":"...","value":"..."}]
|
|
* @param revision_id: Output etcd revision of this read
|
|
* (resp.Header.Revision).
|
|
*/
|
|
static ErrorCode GetRangeAsJson(const char* start_key,
|
|
const size_t start_key_size,
|
|
const char* end_key,
|
|
const size_t end_key_size, size_t limit,
|
|
std::string& json,
|
|
EtcdRevisionId& revision_id);
|
|
|
|
/*
|
|
* @brief Get the first key with a given prefix (sorted by key).
|
|
* @param prefix: The prefix to search for.
|
|
* @param prefix_size: The size of the prefix in bytes.
|
|
* @param first_key: Output param, the first key found.
|
|
* @return: Error code. ETCD_KEY_NOT_EXIST if no key found.
|
|
*/
|
|
static ErrorCode GetFirstKeyWithPrefix(const char* prefix,
|
|
const size_t prefix_size,
|
|
std::string& first_key);
|
|
|
|
/*
|
|
* @brief Get the last key with a given prefix (sorted by key descending).
|
|
* @param prefix: The prefix to search for.
|
|
* @param prefix_size: The size of the prefix in bytes.
|
|
* @param last_key: Output param, the last key found.
|
|
* @return: Error code. ETCD_KEY_NOT_EXIST if no key found.
|
|
*/
|
|
static ErrorCode GetLastKeyWithPrefix(const char* prefix,
|
|
const size_t prefix_size,
|
|
std::string& last_key);
|
|
|
|
/*
|
|
* @brief Delete a range of keys from etcd.
|
|
* @param start_key: The start key (inclusive).
|
|
* @param start_key_size: The size of the start key in bytes.
|
|
* @param end_key: The end key (exclusive).
|
|
* @param end_key_size: The size of the end key in bytes.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode DeleteRange(const char* start_key,
|
|
const size_t start_key_size,
|
|
const char* end_key,
|
|
const size_t end_key_size);
|
|
|
|
/*
|
|
* @brief Watch all keys with a given prefix from a specific etcd revision.
|
|
* Callback includes `mod_revision` for precise resume.
|
|
* (Implementation may pass max(event.ModRevision,
|
|
* watchResp.Header.Revision).)
|
|
* @param callback_func: void cb(void* ctx, const char* key, size_t
|
|
* key_size, const char* value, size_t value_size, int event_type, int64_t
|
|
* mod_revision) event_type: 0=PUT, 1=DELETE, 2=WATCH_BROKEN (watch ended;
|
|
* reconnect)
|
|
*/
|
|
static ErrorCode WatchWithPrefixFromRevision(
|
|
const char* prefix, const size_t prefix_size,
|
|
EtcdRevisionId start_revision, void* callback_context,
|
|
void (*callback_func)(void*, const char*, size_t, const char*, size_t,
|
|
int, int64_t));
|
|
|
|
/*
|
|
* @brief Cancel watching a prefix.
|
|
* @param prefix: The prefix to stop watching.
|
|
* @param prefix_size: The size of the prefix in bytes.
|
|
* @return: Error code.
|
|
*/
|
|
static ErrorCode CancelWatchWithPrefix(const char* prefix,
|
|
const size_t prefix_size);
|
|
|
|
/*
|
|
* @brief Wait until a prefix watch goroutine fully exits (no more
|
|
* callbacks). This should be used after CancelWatchWithPrefix to avoid
|
|
* shutdown races.
|
|
* @param timeout_ms: Wait timeout in milliseconds.
|
|
*/
|
|
static ErrorCode WaitWatchWithPrefixStopped(const char* prefix,
|
|
const size_t prefix_size,
|
|
int timeout_ms);
|
|
|
|
private:
|
|
// Variables that are used to ensure the etcd client
|
|
// is only connected once.
|
|
static std::string connected_endpoints_;
|
|
static std::mutex etcd_mutex_;
|
|
static bool etcd_connected_;
|
|
};
|
|
|
|
} // namespace mooncake
|