summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Farnum <greg@inktank.com>2013-06-17 17:32:29 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-06-20 14:10:35 -0700
commite4ef5c6f9667890dde6d72b6878887fd78335447 (patch)
treef514ae075c82ce753eddd6097f36f98e3cfa723c
parent22a02e95aecd33c008b5592628300fbde6e5f0a8 (diff)
downloadceph-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.am8
-rw-r--r--src/cls/replica_log/cls_replica_log.cc151
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);
+}