diff options
author | Greg Farnum <greg@inktank.com> | 2013-06-17 17:32:29 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-20 14:10:35 -0700 |
commit | e4ef5c6f9667890dde6d72b6878887fd78335447 (patch) | |
tree | f514ae075c82ce753eddd6097f36f98e3cfa723c | |
parent | 22a02e95aecd33c008b5592628300fbde6e5f0a8 (diff) | |
download | ceph-e4ef5c6f9667890dde6d72b6878887fd78335447.tar.gz |
cls_replica_log: add the actual class
This class can be applied to any object, and will keep track of
the bounds, matching times, and matching sets of in-progress items.
We're about to add a cls_replica_log_client that will provide a friendly
user interface and provide more documentation.
Signed-off-by: Greg Farnum <greg@inktank.com>
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/cls/replica_log/cls_replica_log.cc | 151 |
2 files changed, 159 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index df61ca6d780..b497d6605b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -581,6 +581,14 @@ libcls_statelog_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-r radoslib_LTLIBRARIES += libcls_statelog.la +# replica log class +libcls_replica_log_la_SOURCES = cls/replica_log/cls_replica_log.cc +libcls_replica_log_la_CFLAGS = ${AM_CFLAGS} +libcls_replica_log_la_CXXFLAGS= ${AM_CXXFLAGS} +libcls_replica_log_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS) +libcls_replica_log_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex '.*__cls_.*' + +radoslib_LTLIBRARIES += libcls_replica_log.la if WITH_RADOSGW # rgw: rados gateway diff --git a/src/cls/replica_log/cls_replica_log.cc b/src/cls/replica_log/cls_replica_log.cc new file mode 100644 index 00000000000..1083b8adc38 --- /dev/null +++ b/src/cls/replica_log/cls_replica_log.cc @@ -0,0 +1,151 @@ +/* + * Ceph - scalable distributed file system + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + * Copyright Inktank 2013 + */ + +#include "objclass/objclass.h" +#include "global/global_context.h" + +#include "cls_replica_log_types.h" +#include "cls_replica_log_ops.h" + +CLS_VER(1, 0) +CLS_NAME(replica_log) + +cls_handle_t h_class; +cls_method_handle_t h_replica_log_set; +cls_method_handle_t h_replica_log_delete; +cls_method_handle_t h_replica_log_get; + +static const string replica_log_prefix = "rl_"; +static const string replica_log_bounds = replica_log_prefix + "bounds"; + +static int get_bounds(cls_method_context_t hctx, cls_replica_log_bound& bound) +{ + bufferlist bounds_bl; + int rc = cls_cxx_map_get_val(hctx, replica_log_bounds, &bounds_bl); + if (rc < 0) { + return rc; + } + + try { + bufferlist::iterator bounds_bl_i = bounds_bl.begin(); + ::decode(bound, bounds_bl_i); + } catch (buffer::error& err) { + bound = cls_replica_log_bound(); + CLS_LOG(0, "ERROR: get_bounds(): failed to decode on-disk bounds object"); + return -EIO; + } + + return 0; +} + +static int write_bounds(cls_method_context_t hctx, + const cls_replica_log_bound& bound) +{ + bufferlist bounds_bl; + ::encode(bound, bounds_bl); + return cls_cxx_map_set_val(hctx, replica_log_bounds, &bounds_bl); +} + +static int cls_replica_log_set(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_replica_log_set_marker_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(0, "ERROR: cls_replica_log_set(): failed to decode op"); + return -EINVAL; + } + + cls_replica_log_bound bound; + int rc = get_bounds(hctx, bound); + if (rc < 0 && rc != -ENOENT) { + return rc; + } + + rc = bound.update_marker(op.marker); + if (rc < 0) { + return rc; + } + + return write_bounds(hctx, bound); +} + +static int cls_replica_log_delete(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_replica_log_delete_marker_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(0, "ERROR: cls_replica_log_delete(): failed to decode op"); + return -EINVAL; + } + + cls_replica_log_bound bound; + int rc = get_bounds(hctx, bound); + if (rc < 0 && rc != -ENOENT) { + return rc; + } + + rc = bound.delete_marker(op.entity_id); + if (rc < 0) { + return rc; + } + + return write_bounds(hctx, bound); +} + +static int cls_replica_log_get(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_replica_log_get_bounds_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(0, "ERROR: cls_replica_log_get(): failed to decode op"); + return -EINVAL; + } + + cls_replica_log_bound bound; + int rc = get_bounds(hctx, bound); + if (rc < 0) { + return rc; + } + + cls_replica_log_get_bounds_ret ret; + ret.oldest_time = bound.get_oldest_time(); + ret.position_marker = bound.get_lowest_marker_bound(); + bound.get_markers(ret.markers); + + ::encode(ret, *out); + return 0; +} + +void __cls_init() +{ + CLS_LOG(1, "Loaded replica log class!"); + + cls_register("replica_log", &h_class); + + cls_register_cxx_method(h_class, "set", CLS_METHOD_RD | CLS_METHOD_WR, + cls_replica_log_set, &h_replica_log_set); + cls_register_cxx_method(h_class, "get", CLS_METHOD_RD, + cls_replica_log_get, &h_replica_log_get); + cls_register_cxx_method(h_class, "delete", CLS_METHOD_RD | CLS_METHOD_WR, + cls_replica_log_delete, &h_replica_log_delete); +} |