<commit_before>#pragma once

#include "mctypes.h"
#include <glog/logging.h>
#include "likely.h"

namespace evmc {

class Command  : public std::enable_shared_from_this<Command> {
public:
    Command(evpp::EventLoop* evloop, uint16_t vbucket)
        : caller_loop_(evloop), id_(0)
        , vbucket_id_(vbucket) {
    }

    virtual ~Command() {}

    inline uint32_t id() const {
        return id_;
    }
    inline void set_id(uint32_t v) {
        id_ = v;
    }

    inline uint16_t vbucket_id() const {
        return vbucket_id_;
    }

     uint16_t server_id()  const; 
    inline void set_server_id(uint16_t sid) {
        server_id_history_.emplace_back(sid);
    }

    inline evpp::EventLoop* caller_loop() const {
        return caller_loop_;
    }

    virtual void Launch(MemcacheClientPtr memc_client);

    bool ShouldRetry() const;

    virtual void OnError(int code) = 0;
    virtual void OnSetCommandDone(int resp_code) {}
    virtual void OnRemoveCommandDone(int resp_code) {}
    virtual void OnGetCommandDone(int resp_code, const std::string& value) {}
    virtual void OnMultiGetCommandOneResponse(int resp_code, std::string& key, std::string& value) {}
    virtual void OnMultiGetCommandDone(int resp_code, std::string& key, std::string& value) {}
    virtual void OnPrefixGetCommandDone() {}
	virtual PrefixGetResultPtr& GetResultContainerByKey(const std::string& key) { return *((PrefixGetResultPtr *)0); }

private:
    virtual void RequestBuffer(std::string& str) = 0;
    evpp::EventLoop* caller_loop_;
    uint32_t id_;               // 并非全局id，只是各个memc_client内部的序号; mget的多个命令公用一个id
    uint16_t vbucket_id_;
    std::vector<uint16_t> server_id_history_;        // 执行时从多个备选server中所选定的server
};

typedef std::shared_ptr<Command> CommandPtr;

class SetCommand  : public Command {
public:
    SetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, const std::string& value,
               uint32_t flags, uint32_t expire, SetCallback callback)
        : Command(evloop, vbucket), key_(key), value_(value),
          flags_(flags), expire_(expire),
          set_callback_(callback) {
    }

    virtual void OnError(int err_code) {
        LOG_INFO << "SetCommand OnError id=" << id();
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(set_callback_,
                                               std::move(key_), err_code));
        } else {
            set_callback_(key_, err_code);
        }
    }
    virtual void OnSetCommandDone(int resp_code) {
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(set_callback_, std::move(key_), resp_code));
        } else {
            set_callback_(key_, resp_code);
        }
    }
private:
    std::string key_;
    std::string value_;
    uint32_t flags_;
    uint32_t expire_;
    SetCallback set_callback_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};

class GetCommand : public Command {
public:
    GetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, GetCallback callback)
        : Command(evloop, vbucket)
        , key_(key)
        , get_callback_(callback) {
    }

    virtual void OnError(int err_code) {
        LOG(WARNING) << "GetCommand OnError id=" << id();
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            caller_loop()->RunInLoop(std::bind(get_callback_, std::move(key_),
                                               std::move(GetResult(err_code, std::string()))));
        } else {
            get_callback_(key_, GetResult(err_code, std::string()));
        }
    }
    virtual void OnGetCommandDone(int resp_code, const std::string& value) {
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            caller_loop()->RunInLoop(std::bind(get_callback_, std::move(key_),
                                               std::move(GetResult(resp_code, value))));
        } else {
            get_callback_(key_, GetResult(resp_code, value));
        }
    }
private:
    std::string key_;
    GetCallback get_callback_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};

class PrefixGetCommand  : public Command {
public:
    PrefixGetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, PrefixGetCallback callback)
        : Command(evloop, vbucket), key_(key), mget_callback_(callback), mget_result_(std::make_shared<PrefixGetResult>()) {
    }

    virtual void OnError(int err_code) {
        LOG(WARNING) << "PrefixGetCommand OnError id=" << id();
        mget_result_->code = err_code;
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(mget_callback_, std::move(key_), std::move(mget_result_)));
        } else {
            mget_callback_(key_, mget_result_);
        }
    }
    virtual void OnPrefixGetCommandDone();
	virtual PrefixGetResultPtr& GetResultContainerByKey(const std::string& key) {return mget_result_;};
private:
    std::string key_;
    PrefixGetCallback mget_callback_;
    PrefixGetResultPtr mget_result_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};


template<class Result, class Callback>
class MultiKeyHandler {
	public:
		MultiKeyHandler(const Callback& callback, uint32_t finished_nums = 0) 
			:finished_vbucket_nums_(finished_nums), vbucket_size_(0),
			mget_callback_(callback) {
			}

		inline void set_vbucket_keys(std::map<uint16_t, std::vector<std::string> >& vbucket_keys) {
			vbucket_keys_.swap(vbucket_keys);
			vbucket_size_ = vbucket_keys_.size();
		}

		inline uint32_t finished_vbucket_nums() {
			return finished_vbucket_nums_;
		}

		inline const uint32_t  FinishedOne()  {
			return finished_vbucket_nums_++;
		}

		inline const std::size_t vbucket_size() const {
			return vbucket_size_;
		}

		std::vector<std::string>& FindKeysByid(const int16_t id) {
			auto it = vbucket_keys_.find(id);
			assert(it != vbucket_keys_.end());
			return it->second;
		}

		inline Callback& get_callback() {
			return mget_callback_;
		}

		inline Result& get_result() {<commit_msg>delete command.h  const<commit_after>#pragma once

#include "mctypes.h"
#include <glog/logging.h>
#include "likely.h"

namespace evmc {

class Command  : public std::enable_shared_from_this<Command> {
public:
    Command(evpp::EventLoop* evloop, uint16_t vbucket)
        : caller_loop_(evloop), id_(0)
        , vbucket_id_(vbucket) {
    }

    virtual ~Command() {}

    inline uint32_t id() const {
        return id_;
    }
    inline void set_id(uint32_t v) {
        id_ = v;
    }

    inline uint16_t vbucket_id() const {
        return vbucket_id_;
    }

     uint16_t server_id()  const; 
    inline void set_server_id(uint16_t sid) {
        server_id_history_.emplace_back(sid);
    }

    inline evpp::EventLoop* caller_loop() const {
        return caller_loop_;
    }

    virtual void Launch(MemcacheClientPtr memc_client);

    bool ShouldRetry() const;

    virtual void OnError(int code) = 0;
    virtual void OnSetCommandDone(int resp_code) {}
    virtual void OnRemoveCommandDone(int resp_code) {}
    virtual void OnGetCommandDone(int resp_code, const std::string& value) {}
    virtual void OnMultiGetCommandOneResponse(int resp_code, std::string& key, std::string& value) {}
    virtual void OnMultiGetCommandDone(int resp_code, std::string& key, std::string& value) {}
    virtual void OnPrefixGetCommandDone() {}
	virtual PrefixGetResultPtr& GetResultContainerByKey(const std::string& key) { return *((PrefixGetResultPtr *)0); }

private:
    virtual void RequestBuffer(std::string& str) = 0;
    evpp::EventLoop* caller_loop_;
    uint32_t id_;               // 并非全局id，只是各个memc_client内部的序号; mget的多个命令公用一个id
    uint16_t vbucket_id_;
    std::vector<uint16_t> server_id_history_;        // 执行时从多个备选server中所选定的server
};

typedef std::shared_ptr<Command> CommandPtr;

class SetCommand  : public Command {
public:
    SetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, const std::string& value,
               uint32_t flags, uint32_t expire, SetCallback callback)
        : Command(evloop, vbucket), key_(key), value_(value),
          flags_(flags), expire_(expire),
          set_callback_(callback) {
    }

    virtual void OnError(int err_code) {
        LOG_INFO << "SetCommand OnError id=" << id();
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(set_callback_,
                                               std::move(key_), err_code));
        } else {
            set_callback_(key_, err_code);
        }
    }
    virtual void OnSetCommandDone(int resp_code) {
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(set_callback_, std::move(key_), resp_code));
        } else {
            set_callback_(key_, resp_code);
        }
    }
private:
    std::string key_;
    std::string value_;
    uint32_t flags_;
    uint32_t expire_;
    SetCallback set_callback_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};

class GetCommand : public Command {
public:
    GetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, GetCallback callback)
        : Command(evloop, vbucket)
        , key_(key)
        , get_callback_(callback) {
    }

    virtual void OnError(int err_code) {
        LOG(WARNING) << "GetCommand OnError id=" << id();
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            caller_loop()->RunInLoop(std::bind(get_callback_, std::move(key_),
                                               std::move(GetResult(err_code, std::string()))));
        } else {
            get_callback_(key_, GetResult(err_code, std::string()));
        }
    }
    virtual void OnGetCommandDone(int resp_code, const std::string& value) {
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            caller_loop()->RunInLoop(std::bind(get_callback_, std::move(key_),
                                               std::move(GetResult(resp_code, value))));
        } else {
            get_callback_(key_, GetResult(resp_code, value));
        }
    }
private:
    std::string key_;
    GetCallback get_callback_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};

class PrefixGetCommand  : public Command {
public:
    PrefixGetCommand(evpp::EventLoop* evloop, uint16_t vbucket, const std::string& key, PrefixGetCallback callback)
        : Command(evloop, vbucket), key_(key), mget_callback_(callback), mget_result_(std::make_shared<PrefixGetResult>()) {
    }

    virtual void OnError(int err_code) {
        LOG(WARNING) << "PrefixGetCommand OnError id=" << id();
        mget_result_->code = err_code;
		auto loop = caller_loop(); 
        if (loop && !loop->IsInLoopThread()) {
            loop->RunInLoop(std::bind(mget_callback_, std::move(key_), std::move(mget_result_)));
        } else {
            mget_callback_(key_, mget_result_);
        }
    }
    virtual void OnPrefixGetCommandDone();
	virtual PrefixGetResultPtr& GetResultContainerByKey(const std::string& key) {return mget_result_;};
private:
    std::string key_;
    PrefixGetCallback mget_callback_;
    PrefixGetResultPtr mget_result_;
    static std::atomic_int next_thread_;
private:
    virtual void RequestBuffer(std::string& str);
};


template<class Result, class Callback>
class MultiKeyHandler {
	public:
		MultiKeyHandler(const Callback& callback, uint32_t finished_nums = 0) 
			:finished_vbucket_nums_(finished_nums), vbucket_size_(0),
			mget_callback_(callback) {
			}

		inline void set_vbucket_keys(std::map<uint16_t, std::vector<std::string> >& vbucket_keys) {
			vbucket_keys_.swap(vbucket_keys);
			vbucket_size_ = vbucket_keys_.size();
		}

		inline uint32_t finished_vbucket_nums() {
			return finished_vbucket_nums_;
		}

		inline uint32_t  FinishedOne()  {
			return finished_vbucket_nums_++;
		}

		inline  std::size_t vbucket_size() const {
			return vbucket_size_;
		}

		std::vector<std::string>& FindKeysByid(const int16_t id) {
			auto it = vbucket_keys_.find(id);
			assert(it != vbucket_keys_.end());
			return it->second;
		}

		inline Callback& get_callback() {
			return mget_callback_;
		}

		inline Result& get_result() {
{'fraction_non_alphanumeric': 0.11649639661043795, 'fraction_numerical': 0.007602755999049656, 'mean_word_length': 3.2347417840375585, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5130944', 'n_tokens_mistral': 4161, 'n_tokens_neox': 3980, 'n_words': 834}