Skip to content

Commit

Permalink
Merge branch 'wip-rgw-refcount'
Browse files Browse the repository at this point in the history
  • Loading branch information
yehudasa committed Sep 15, 2012
2 parents 0bf7723 + a150cf3 commit a16fa04
Show file tree
Hide file tree
Showing 12 changed files with 950 additions and 67 deletions.
26 changes: 24 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ librgw_a_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS}
noinst_LIBRARIES += librgw.a

my_radosgw_ldadd = \
libglobal.la librgw.a librados.la libcls_rgw_client.a libcls_lock_client.a -lcurl -lexpat \
libglobal.la librgw.a librados.la libcls_rgw_client.a \
libcls_lock_client.a libcls_refcount_client.a -lcurl -lexpat \
$(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS)

radosgw_SOURCES = \
Expand Down Expand Up @@ -444,7 +445,7 @@ radoslibdir = $(libdir)/rados-classes
radoslib_LTLIBRARIES = libcls_rbd.la


# rbd: rados block device class
# lock class
libcls_lock_la_SOURCES = cls/lock/cls_lock.cc
libcls_lock_la_CFLAGS = ${AM_CFLAGS}
libcls_lock_la_CXXFLAGS= ${AM_CXXFLAGS}
Expand All @@ -453,6 +454,15 @@ libcls_lock_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex

radoslib_LTLIBRARIES += libcls_lock.la

# refcount class
libcls_refcount_la_SOURCES = cls/refcount/cls_refcount.cc
libcls_refcount_la_CFLAGS = ${AM_CFLAGS}
libcls_refcount_la_CXXFLAGS= ${AM_CXXFLAGS}
libcls_refcount_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
libcls_refcount_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex '.*__cls_.*'

radoslib_LTLIBRARIES += libcls_refcount.la


if WITH_RADOSGW
# rgw: rados gateway
Expand All @@ -471,6 +481,10 @@ libcls_lock_client_a_SOURCES = \
cls/lock/cls_lock_ops.cc
noinst_LIBRARIES += libcls_lock_client.a

libcls_refcount_client_a_SOURCES = \
cls/refcount/cls_refcount_client.cc
noinst_LIBRARIES += libcls_refcount_client.a

libcls_rgw_client_a_SOURCES = \
cls/rgw/cls_rgw_client.cc \
cls/rgw/cls_rgw_types.cc \
Expand Down Expand Up @@ -759,6 +773,12 @@ test_cls_rbd_LDADD = librados.la ${UNITTEST_STATIC_LDADD}
test_cls_rbd_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
bin_DEBUGPROGRAMS += test_cls_rbd

test_cls_refcount_SOURCES = test/cls_refcount/test_cls_refcount.cc \
test/rados-api/test.cc
test_cls_refcount_LDADD = librados.la libcls_refcount_client.a ${UNITTEST_STATIC_LDADD}
test_cls_refcount_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
bin_DEBUGPROGRAMS += test_cls_refcount

if WITH_RADOSGW

test_cls_rgw_SOURCES = test/rgw/test_cls_rgw.cc \
Expand Down Expand Up @@ -1314,6 +1334,8 @@ noinst_HEADERS = \
cls/lock/cls_lock_types.h\
cls/lock/cls_lock_ops.h\
cls/lock/cls_lock_client.h\
cls/refcount/cls_refcount_ops.h\
cls/refcount/cls_refcount_client.h\
cls/rgw/cls_rgw_client.h\
cls/rgw/cls_rgw_ops.h\
cls/rgw/cls_rgw_types.h\
Expand Down
243 changes: 243 additions & 0 deletions src/cls/refcount/cls_refcount.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include <iostream>

#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "include/types.h"
#include "include/utime.h"
#include "objclass/objclass.h"
#include "cls/refcount/cls_refcount_ops.h"
#include "common/Clock.h"

#include "global/global_context.h"

CLS_VER(1,0)
CLS_NAME(refcount)

cls_handle_t h_class;
cls_method_handle_t h_refcount_get;
cls_method_handle_t h_refcount_put;
cls_method_handle_t h_refcount_set;
cls_method_handle_t h_refcount_read;


#define REFCOUNT_ATTR "refcount"

struct obj_refcount {
map<string, bool> refs;

obj_refcount() {}

void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
::encode(refs, bl);
ENCODE_FINISH(bl);
}

void decode(bufferlist::iterator& bl) {
DECODE_START(1, bl);
::decode(refs, bl);
DECODE_FINISH(bl);
}
};
WRITE_CLASS_ENCODER(obj_refcount)

static string wildcard_tag;

static int read_refcount(cls_method_context_t hctx, bool implicit_ref, obj_refcount *objr)
{
bufferlist bl;
objr->refs.clear();
int ret = cls_cxx_getxattr(hctx, REFCOUNT_ATTR, &bl);
if (ret == -ENOENT || ret == -ENODATA) {
if (implicit_ref) {
objr->refs[wildcard_tag] = true;
}
return 0;
}
if (ret < 0)
return ret;

try {
bufferlist::iterator iter = bl.begin();
::decode(*objr, iter);
} catch (buffer::error& err) {
CLS_LOG(0, "ERROR: read_refcount(): failed to decode refcount entry\n");
return -EIO;
}

return 0;
}

static int set_refcount(cls_method_context_t hctx, map<string, bool>& refs)
{
bufferlist bl;
struct obj_refcount objr;

objr.refs = refs;

::encode(objr, bl);

int ret = cls_cxx_setxattr(hctx, REFCOUNT_ATTR, &bl);
if (ret < 0)
return ret;

return 0;
}

static int cls_rc_refcount_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
bufferlist::iterator in_iter = in->begin();

cls_refcount_get_op op;
try {
::decode(op, in_iter);
} catch (buffer::error& err) {
CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
return -EINVAL;
}

obj_refcount objr;
int ret = read_refcount(hctx, op.implicit_ref, &objr);
if (ret < 0)
return ret;

CLS_LOG(10, "cls_rc_refcount_get() tag=%s\n", op.tag.c_str());

objr.refs[op.tag] = true;

ret = set_refcount(hctx, objr.refs);
if (ret < 0)
return ret;

return 0;
}

static int cls_rc_refcount_put(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
bufferlist::iterator in_iter = in->begin();

cls_refcount_put_op op;
try {
::decode(op, in_iter);
} catch (buffer::error& err) {
CLS_LOG(1, "ERROR: cls_rc_refcount_put(): failed to decode entry\n");
return -EINVAL;
}

obj_refcount objr;
int ret = read_refcount(hctx, op.implicit_ref, &objr);
if (ret < 0)
return ret;

if (!objr.refs.size()) {// shouldn't happen!
CLS_LOG(0, "ERROR: cls_rc_refcount_put() was called without any references!\n");
return -EINVAL;
}

CLS_LOG(10, "cls_rc_refcount_put() tag=%s\n", op.tag.c_str());

bool found = false;
map<string, bool>::iterator iter = objr.refs.find(op.tag);
if (iter != objr.refs.end()) {
found = true;
} else if (op.implicit_ref) {
iter = objr.refs.find(wildcard_tag);
if (iter != objr.refs.end()) {
found = true;
}
}

if (!found)
return 0;

objr.refs.erase(iter);

if (!objr.refs.size()) {
return cls_cxx_remove(hctx);
}

ret = set_refcount(hctx, objr.refs);
if (ret < 0)
return ret;

return 0;
}

static int cls_rc_refcount_set(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
bufferlist::iterator in_iter = in->begin();

cls_refcount_set_op op;
try {
::decode(op, in_iter);
} catch (buffer::error& err) {
CLS_LOG(1, "ERROR: cls_refcount_set(): failed to decode entry\n");
return -EINVAL;
}

if (!op.refs.size()) {
return cls_cxx_remove(hctx);
}

obj_refcount objr;
list<string>::iterator iter;
for (iter = op.refs.begin(); iter != op.refs.end(); ++iter) {
objr.refs[*iter] = true;
}

int ret = set_refcount(hctx, objr.refs);
if (ret < 0)
return ret;

return 0;
}

static int cls_rc_refcount_read(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
bufferlist::iterator in_iter = in->begin();

cls_refcount_read_op op;
try {
::decode(op, in_iter);
} catch (buffer::error& err) {
CLS_LOG(1, "ERROR: cls_rc_refcount_read(): failed to decode entry\n");
return -EINVAL;
}

obj_refcount objr;

cls_refcount_read_ret read_ret;
int ret = read_refcount(hctx, op.implicit_ref, &objr);
if (ret < 0)
return ret;

map<string, bool>::iterator iter;
for (iter = objr.refs.begin(); iter != objr.refs.end(); ++iter) {
read_ret.refs.push_back(iter->first);
}

::encode(read_ret, *out);

return 0;
}

void __cls_init()
{
CLS_LOG(1, "Loaded refcount class!");

cls_register("refcount", &h_class);

/* refcount */
cls_register_cxx_method(h_class, "get", CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PUBLIC, cls_rc_refcount_get, &h_refcount_get);
cls_register_cxx_method(h_class, "put", CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PUBLIC, cls_rc_refcount_put, &h_refcount_put);
cls_register_cxx_method(h_class, "set", CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PUBLIC, cls_rc_refcount_set, &h_refcount_set);
cls_register_cxx_method(h_class, "read", CLS_METHOD_RD | CLS_METHOD_PUBLIC, cls_rc_refcount_read, &h_refcount_read);

return;
}

60 changes: 60 additions & 0 deletions src/cls/refcount/cls_refcount_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <errno.h>

#include "include/types.h"
#include "cls/refcount/cls_refcount_ops.h"
#include "include/rados/librados.hpp"

using namespace librados;


void cls_refcount_get(librados::ObjectWriteOperation& op, const string& tag, bool implicit_ref)
{
bufferlist in;
cls_refcount_get_op call;
call.tag = tag;
call.implicit_ref = implicit_ref;
::encode(call, in);
op.exec("refcount", "get", in);
}

void cls_refcount_put(librados::ObjectWriteOperation& op, const string& tag, bool implicit_ref)
{
bufferlist in;
cls_refcount_put_op call;
call.tag = tag;
call.implicit_ref = implicit_ref;
::encode(call, in);
op.exec("refcount", "put", in);
}

void cls_refcount_set(librados::ObjectWriteOperation& op, list<string>& refs)
{
bufferlist in;
cls_refcount_set_op call;
call.refs = refs;
::encode(call, in);
op.exec("refcount", "set", in);
}

int cls_refcount_read(librados::IoCtx& io_ctx, string& oid, list<string> *refs, bool implicit_ref)
{
bufferlist in, out;
cls_refcount_read_op call;
call.implicit_ref = implicit_ref;
::encode(call, in);
int r = io_ctx.exec(oid, "refcount", "read", in, out);
if (r < 0)
return r;

cls_refcount_read_ret ret;
try {
bufferlist::iterator iter = out.begin();
::decode(ret, iter);
} catch (buffer::error& err) {
return -EIO;
}

*refs = ret.refs;

return r;
}
Loading

0 comments on commit a16fa04

Please sign in to comment.