175 lines
4.3 KiB
C++
175 lines
4.3 KiB
C++
#include "examples/memcached/server/MemcacheServer.h"
|
|
|
|
#include "muduo/base/Atomic.h"
|
|
#include "muduo/base/Logging.h"
|
|
#include "muduo/net/EventLoop.h"
|
|
|
|
using namespace muduo;
|
|
using namespace muduo::net;
|
|
|
|
muduo::AtomicInt64 g_cas;
|
|
|
|
MemcacheServer::Options::Options()
|
|
{
|
|
memZero(this, sizeof(*this));
|
|
}
|
|
|
|
struct MemcacheServer::Stats
|
|
{
|
|
};
|
|
|
|
MemcacheServer::MemcacheServer(muduo::net::EventLoop* loop, const Options& options)
|
|
: loop_(loop),
|
|
options_(options),
|
|
startTime_(::time(NULL)-1),
|
|
server_(loop, InetAddress(options.tcpport), "muduo-memcached"),
|
|
stats_(new Stats)
|
|
{
|
|
server_.setConnectionCallback(
|
|
std::bind(&MemcacheServer::onConnection, this, _1));
|
|
}
|
|
|
|
MemcacheServer::~MemcacheServer() = default;
|
|
|
|
void MemcacheServer::start()
|
|
{
|
|
server_.start();
|
|
}
|
|
|
|
void MemcacheServer::stop()
|
|
{
|
|
loop_->runAfter(3.0, std::bind(&EventLoop::quit, loop_));
|
|
}
|
|
|
|
bool MemcacheServer::storeItem(const ItemPtr& item, const Item::UpdatePolicy policy, bool* exists)
|
|
{
|
|
assert(item->neededBytes() == 0);
|
|
MutexLock& mutex = shards_[item->hash() % kShards].mutex;
|
|
ItemMap& items = shards_[item->hash() % kShards].items;
|
|
MutexLockGuard lock(mutex);
|
|
ItemMap::const_iterator it = items.find(item);
|
|
*exists = it != items.end();
|
|
if (policy == Item::kSet)
|
|
{
|
|
item->setCas(g_cas.incrementAndGet());
|
|
if (*exists)
|
|
{
|
|
items.erase(it);
|
|
}
|
|
items.insert(item);
|
|
}
|
|
else
|
|
{
|
|
if (policy == Item::kAdd)
|
|
{
|
|
if (*exists)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
item->setCas(g_cas.incrementAndGet());
|
|
items.insert(item);
|
|
}
|
|
}
|
|
else if (policy == Item::kReplace)
|
|
{
|
|
if (*exists)
|
|
{
|
|
item->setCas(g_cas.incrementAndGet());
|
|
items.erase(it);
|
|
items.insert(item);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (policy == Item::kAppend || policy == Item::kPrepend)
|
|
{
|
|
if (*exists)
|
|
{
|
|
const ConstItemPtr& oldItem = *it;
|
|
int newLen = static_cast<int>(item->valueLength() + oldItem->valueLength() - 2);
|
|
ItemPtr newItem(Item::makeItem(item->key(),
|
|
oldItem->flags(),
|
|
oldItem->rel_exptime(),
|
|
newLen,
|
|
g_cas.incrementAndGet()));
|
|
if (policy == Item::kAppend)
|
|
{
|
|
newItem->append(oldItem->value(), oldItem->valueLength() - 2);
|
|
newItem->append(item->value(), item->valueLength());
|
|
}
|
|
else
|
|
{
|
|
newItem->append(item->value(), item->valueLength() - 2);
|
|
newItem->append(oldItem->value(), oldItem->valueLength());
|
|
}
|
|
assert(newItem->neededBytes() == 0);
|
|
assert(newItem->endsWithCRLF());
|
|
items.erase(it);
|
|
items.insert(newItem);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (policy == Item::kCas)
|
|
{
|
|
if (*exists && (*it)->cas() == item->cas())
|
|
{
|
|
item->setCas(g_cas.incrementAndGet());
|
|
items.erase(it);
|
|
items.insert(item);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ConstItemPtr MemcacheServer::getItem(const ConstItemPtr& key) const
|
|
{
|
|
MutexLock& mutex = shards_[key->hash() % kShards].mutex;
|
|
const ItemMap& items = shards_[key->hash() % kShards].items;
|
|
MutexLockGuard lock(mutex);
|
|
ItemMap::const_iterator it = items.find(key);
|
|
return it != items.end() ? *it : ConstItemPtr();
|
|
}
|
|
|
|
bool MemcacheServer::deleteItem(const ConstItemPtr& key)
|
|
{
|
|
MutexLock& mutex = shards_[key->hash() % kShards].mutex;
|
|
ItemMap& items = shards_[key->hash() % kShards].items;
|
|
MutexLockGuard lock(mutex);
|
|
return items.erase(key) == 1;
|
|
}
|
|
|
|
void MemcacheServer::onConnection(const TcpConnectionPtr& conn)
|
|
{
|
|
if (conn->connected())
|
|
{
|
|
SessionPtr session(new Session(this, conn));
|
|
MutexLockGuard lock(mutex_);
|
|
assert(sessions_.find(conn->name()) == sessions_.end());
|
|
sessions_[conn->name()] = session;
|
|
// assert(sessions_.size() == stats_.current_conns);
|
|
}
|
|
else
|
|
{
|
|
MutexLockGuard lock(mutex_);
|
|
assert(sessions_.find(conn->name()) != sessions_.end());
|
|
sessions_.erase(conn->name());
|
|
// assert(sessions_.size() == stats_.current_conns);
|
|
}
|
|
}
|