1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 * Copyright (C) 2012 CohortFS, LLC.
7 * This is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License version 2.1, as published by the Free Software
10 * Foundation. See file COPYING.
14 #if defined(__FreeBSD__)
15 #include <sys/param.h>
18 #include "include/Context.h"
21 #include "include/assert.h"
24 #define dout_prefix *_dout << "client." << whoami << " "
26 #define dout_subsys ceph_subsys_client
28 #define cldout(cl, v) dout_impl((cl)->cct, dout_subsys, v) \
29 *_dout << "client." << cl->whoami << " "
32 class C_Block_Sync : public Context {
37 enum CBlockSync_State state;
39 int *rval; /* see Cond.h */
42 boost::intrusive::list_member_hook<> intervals_hook;
43 C_Block_Sync(Client *c, uint64_t i, barrier_interval iv, int *r);
44 void finish(int rval);
47 friend class BarrierContext;
50 C_Block_Sync::C_Block_Sync(Client *c, uint64_t i, barrier_interval iv,
52 cl(c), ino(i), iv(iv), rval(r)
54 state = CBlockSync_State_None;
57 cldout(cl, 1) << "C_Block_Sync for " << ino << dendl;
59 if (!cl->barriers[ino]) {
60 cl->barriers[ino] = new BarrierContext(cl, ino);
62 /* XXX current semantics aren't commit-ordered */
63 cl->barriers[ino]->write_nobarrier(*this);
66 void C_Block_Sync::finish(int r) {
67 cldout(cl, 1) << "C_Block_Sync::finish() for " << ino << " "
68 << iv << " r==" << r << dendl;
71 cl->barriers[ino]->complete(*this);
82 BarrierContext::BarrierContext(Client *c, uint64_t ino) :
83 cl(c), ino(ino), lock("BarrierContext")
86 void BarrierContext::write_nobarrier(C_Block_Sync &cbs)
88 Mutex::Locker locker(lock);
89 cbs.state = CBlockSync_State_Unclaimed;
90 outstanding_writes.push_back(cbs);
93 void BarrierContext::write_barrier(C_Block_Sync &cbs)
95 Mutex::Locker locker(lock);
96 barrier_interval &iv = cbs.iv;
98 { /* find blocking commit--intrusive no help here */
99 BarrierList::iterator iter;
101 for (iter = active_commits.begin();
102 !done && (iter != active_commits.end());
104 Barrier &barrier = *iter;
105 while (boost::icl::intersects(barrier.span, iv)) {
107 barrier.cond.Wait(lock);
113 cbs.state = CBlockSync_State_Unclaimed;
114 outstanding_writes.push_back(cbs);
116 } /* write_barrier */
118 void BarrierContext::commit_barrier(barrier_interval &civ)
120 Mutex::Locker locker(lock);
122 /* we commit outstanding writes--if none exist, we don't care */
123 if (outstanding_writes.size() == 0)
126 boost::icl::interval_set<uint64_t> cvs;
129 Barrier *barrier = NULL;
130 BlockSyncList::iterator iter, iter2;
132 iter = outstanding_writes.begin();
133 while (iter != outstanding_writes.end()) {
134 barrier_interval &iv = iter->iv;
135 if (boost::icl::intersects(cvs, iv)) {
136 C_Block_Sync &a_write = *iter;
138 barrier = new Barrier();
139 /* mark the callback */
140 a_write.state = CBlockSync_State_Committing;
141 a_write.barrier = barrier;
143 outstanding_writes.erase(iter2);
144 barrier->write_list.push_back(a_write);
145 barrier->span.insert(iv);
146 /* avoid iter invalidate */
153 active_commits.push_back(*barrier);
154 /* and wait on this */
155 barrier->cond.Wait(lock);
158 } /* commit_barrier */
160 void BarrierContext::complete(C_Block_Sync &cbs)
162 Mutex::Locker locker(lock);
163 BlockSyncList::iterator iter =
164 BlockSyncList::s_iterator_to(cbs);
167 case CBlockSync_State_Unclaimed:
168 /* cool, no waiting */
169 outstanding_writes.erase(iter);
171 case CBlockSync_State_Committing:
173 Barrier *barrier = iter->barrier;
174 barrier->write_list.erase(iter);
176 barrier->cond.Signal();
177 /* dispose cleared barrier */
178 if (barrier->write_list.size() == 0) {
179 BarrierList::iterator iter2 =
180 BarrierList::s_iterator_to(*barrier);
181 active_commits.erase(iter2);
191 cbs.state = CBlockSync_State_Completed;
195 BarrierContext::~BarrierContext()