1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2017 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #include "vbucketdeletiontask.h"
19 #include "ep_engine.h"
20 #include "ep_vb.h"
21 #include "executorpool.h"
22 #include "kvshard.h"
23 
24 #include <phosphor/phosphor.h>
25 #include <platform/processclock.h>
26 
VBucketMemoryDeletionTask( EventuallyPersistentEngine& eng, VBucket* vb, TaskId tid)27 VBucketMemoryDeletionTask::VBucketMemoryDeletionTask(
28         EventuallyPersistentEngine& eng, VBucket* vb, TaskId tid)
29     : GlobalTask(&eng, tid, 0.0, true), vbucket(vb) {
30     if (!vbucket) {
31         throw std::logic_error(
32                 "VBucketMemoryDeletionTask::VBucketMemoryDeletionTask no "
33                 "vbucket");
34     }
35     description = "Removing (dead) vb:" + std::to_string(vbucket->getId()) +
36                   " from memory";
37 }
38 
getDescription()39 std::string VBucketMemoryDeletionTask::getDescription() {
40     return description;
41 }
42 
maxExpectedDuration()43 std::chrono::microseconds VBucketMemoryDeletionTask::maxExpectedDuration() {
44     // p99.9 typically around 50ms.
45     return std::chrono::milliseconds(100);
46 }
47 
run()48 bool VBucketMemoryDeletionTask::run() {
49     TRACE_EVENT1("ep-engine/task",
50                  "VBucketMemoryDeletionTask",
51                  "vb",
52                  vbucket->getId());
53 
54     notifyAllPendingConnsFailed(true);
55 
56     return false;
57 }
58 
notifyAllPendingConnsFailed( bool notifyIfCookieSet)59 void VBucketMemoryDeletionTask::notifyAllPendingConnsFailed(
60         bool notifyIfCookieSet) {
61     vbucket->notifyAllPendingConnsFailed(*engine);
62 
63     if (notifyIfCookieSet && vbucket->getDeferredDeletionCookie()) {
64         engine->notifyIOComplete(vbucket->getDeferredDeletionCookie(),
65                                  ENGINE_SUCCESS);
66     }
67 }
68 
VBucketMemoryAndDiskDeletionTask( EventuallyPersistentEngine& eng, KVShard& shard, EPVBucket* vb)69 VBucketMemoryAndDiskDeletionTask::VBucketMemoryAndDiskDeletionTask(
70         EventuallyPersistentEngine& eng, KVShard& shard, EPVBucket* vb)
71     : VBucketMemoryDeletionTask(eng,
72                                 static_cast<VBucket*>(vb),
73                                 TaskId::VBucketMemoryAndDiskDeletionTask),
74       shard(shard),
75       vbDeleteRevision(vb->getDeferredDeletionFileRevision()) {
76     description += " and disk";
77 }
78 
run()79 bool VBucketMemoryAndDiskDeletionTask::run() {
80     TRACE_EVENT1("ep-engine/task",
81                  "VBucketMemoryAndDiskDeletionTask",
82                  "vb",
83                  vbucket->getId());
84     notifyAllPendingConnsFailed(false);
85 
86     auto start = ProcessClock::now();
87     shard.getRWUnderlying()->delVBucket(vbucket->getId(), vbDeleteRevision);
88     auto elapsed = ProcessClock::now() - start;
89     auto wallTime =
90             std::chrono::duration_cast<std::chrono::microseconds>(elapsed);
91 
92     engine->getEpStats().vbucketDeletions++;
93     BlockTimer::log(elapsed, "disk_vb_del", engine->getEpStats().timingLog);
94     engine->getEpStats().diskVBDelHisto.add(wallTime);
95     atomic_setIfBigger(engine->getEpStats().vbucketDelMaxWalltime,
96                        hrtime_t(wallTime.count()));
97     engine->getEpStats().vbucketDelTotWalltime.fetch_add(wallTime.count());
98 
99     if (vbucket->getDeferredDeletionCookie()) {
100         engine->notifyIOComplete(vbucket->getDeferredDeletionCookie(),
101                                  ENGINE_SUCCESS);
102     }
103 
104     return false;
105 }
106