Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / osdc / MemWriteback.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <errno.h>
5 #include <time.h>
6
7 #include <thread>
8 #include "common/debug.h"
9 #include "common/Cond.h"
10 #include "common/Finisher.h"
11 #include "common/Mutex.h"
12 #include "include/assert.h"
13 #include "common/ceph_time.h"
14
15 #include "MemWriteback.h"
16
17 #define dout_context g_ceph_context
18 #define dout_subsys ceph_subsys_objectcacher
19 #undef dout_prefix
20 #define dout_prefix *_dout << "MemWriteback(" << this << ") "
21
22 class C_DelayRead : public Context {
23   MemWriteback *wb;
24   CephContext *m_cct;
25   Context *m_con;
26   ceph::timespan m_delay;
27   Mutex *m_lock;
28   object_t m_oid;
29   uint64_t m_off;
30   uint64_t m_len;
31   bufferlist *m_bl;
32
33 public:
34   C_DelayRead(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
35               const object_t& oid, uint64_t off, uint64_t len, bufferlist *pbl,
36               uint64_t delay_ns=0)
37     : wb(mwb), m_cct(cct), m_con(c),
38       m_delay(delay_ns * std::chrono::nanoseconds(1)),
39       m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(pbl) {}
40   void finish(int r) override {
41     std::this_thread::sleep_for(m_delay);
42     m_lock->Lock();
43     r = wb->read_object_data(m_oid, m_off, m_len, m_bl);
44     if (m_con)
45       m_con->complete(r);
46     m_lock->Unlock();
47   }
48 };
49
50 class C_DelayWrite : public Context {
51   MemWriteback *wb;
52   CephContext *m_cct;
53   Context *m_con;
54   ceph::timespan m_delay;
55   Mutex *m_lock;
56   object_t m_oid;
57   uint64_t m_off;
58   uint64_t m_len;
59   const bufferlist& m_bl;
60
61 public:
62   C_DelayWrite(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
63                const object_t& oid, uint64_t off, uint64_t len,
64                const bufferlist& bl, uint64_t delay_ns=0)
65     : wb(mwb), m_cct(cct), m_con(c),
66       m_delay(delay_ns * std::chrono::nanoseconds(1)),
67       m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(bl) {}
68   void finish(int r) override {
69     std::this_thread::sleep_for(m_delay);
70     m_lock->Lock();
71     wb->write_object_data(m_oid, m_off, m_len, m_bl);
72     if (m_con)
73       m_con->complete(r);
74     m_lock->Unlock();
75   }
76 };
77
78 MemWriteback::MemWriteback(CephContext *cct, Mutex *lock, uint64_t delay_ns)
79   : m_cct(cct), m_lock(lock), m_delay_ns(delay_ns)
80 {
81   m_finisher = new Finisher(cct);
82   m_finisher->start();
83 }
84
85 MemWriteback::~MemWriteback()
86 {
87   m_finisher->stop();
88   delete m_finisher;
89 }
90
91 void MemWriteback::read(const object_t& oid, uint64_t object_no,
92                          const object_locator_t& oloc,
93                          uint64_t off, uint64_t len, snapid_t snapid,
94                          bufferlist *pbl, uint64_t trunc_size,
95                          __u32 trunc_seq, int op_flags,
96                          const ZTracer::Trace &parent_trace,
97                          Context *onfinish)
98 {
99   assert(snapid == CEPH_NOSNAP);
100   C_DelayRead *wrapper = new C_DelayRead(this, m_cct, onfinish, m_lock, oid,
101                                          off, len, pbl, m_delay_ns);
102   m_finisher->queue(wrapper, len);
103 }
104
105 ceph_tid_t MemWriteback::write(const object_t& oid,
106                                 const object_locator_t& oloc,
107                                 uint64_t off, uint64_t len,
108                                 const SnapContext& snapc,
109                                 const bufferlist &bl, ceph::real_time mtime,
110                                 uint64_t trunc_size, __u32 trunc_seq,
111                                 ceph_tid_t journal_tid,
112                                 const ZTracer::Trace &parent_trace,
113                                 Context *oncommit)
114 {
115   assert(snapc.seq == 0);
116   C_DelayWrite *wrapper = new C_DelayWrite(this, m_cct, oncommit, m_lock, oid,
117                                            off, len, bl, m_delay_ns);
118   m_finisher->queue(wrapper, 0);
119   return ++m_tid;
120 }
121
122 void MemWriteback::write_object_data(const object_t& oid, uint64_t off, uint64_t len,
123                                      const bufferlist& data_bl)
124 {
125   dout(1) << "writing " << oid << " " << off << "~" << len  << dendl;
126   assert(len == data_bl.length());
127   bufferlist& obj_bl = object_data[oid];
128   bufferlist new_obj_bl;
129   // ensure size, or set it if new object
130   if (off + len > obj_bl.length()) {
131     obj_bl.append_zero(off + len - obj_bl.length());
132   }
133
134   // beginning
135   new_obj_bl.substr_of(obj_bl, 0, off);
136   // overwritten bit
137   new_obj_bl.append(data_bl);
138   // tail bit
139   bufferlist tmp;
140   tmp.substr_of(obj_bl, off+len, obj_bl.length()-(off+len));
141   new_obj_bl.append(tmp);
142   obj_bl.swap(new_obj_bl);
143   dout(1) << oid << " final size " << obj_bl.length() << dendl;
144 }
145
146 int MemWriteback::read_object_data(const object_t& oid, uint64_t off, uint64_t len,
147                                    bufferlist *data_bl)
148 {
149   dout(1) << "reading " << oid << " " << off << "~" << len << dendl;
150   auto obj_i = object_data.find(oid);
151   if (obj_i == object_data.end()) {
152     dout(1) << oid << "DNE!" << dendl;
153     return -ENOENT;
154   }
155
156   const bufferlist& obj_bl = obj_i->second;
157   dout(1) << "reading " << oid << " from total size " << obj_bl.length() << dendl;
158
159   uint64_t read_len = MIN(len, obj_bl.length()-off);
160   data_bl->substr_of(obj_bl, off, read_len);
161   return 0;
162 }
163
164 bool MemWriteback::may_copy_on_write(const object_t&, uint64_t, uint64_t,
165                                       snapid_t)
166 {
167   return false;
168 }