1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 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 #pragma once
18 
19 #include <condition_variable>
20 #include <deque>
21 #include <mutex>
22 #include <platform/platform.h>
23 
24 class EngineManager;
25 
26 /**
27  * The scrubber task is charged with
28  *   1. removing items from memory
29  *   2. deleting engine structs
30  *
31  * The common use-case is for bucket deletion performing tasks 1 and 2.
32  * The start_scrub command only performs 1.
33  *
34  * Global destruction can safely join the task and allow the engine to
35  * safely unload the shared object.
36  */
37 class ScrubberTask {
38 public:
39     ScrubberTask(EngineManager& manager);
40 
41     /**
42      *  Shutdown the task
43      */
44     void shutdown();
45 
46     /**
47      *  Join the thread running the scrubber (to be called after shutdown).
48      */
49     void joinThread();
50 
51     /**
52      *  Place the engine on the threads work queue for item scrubbing.
53      *  bool destroy indicates if the engine should be deleted once scrubbed.
54      */
55     void placeOnWorkQueue(struct default_engine* engine, bool destroy);
56 
57     /**
58      * Task's run loop method. This is not a public function and should only
59      * be called from the tasks constructor.
60      */
61     void run();
62 
63     /**
64      * Is the scrubber idle and have no pending work scheduled
65      *
66      * @return true if no work has been scheduled and its work queue is empty
67      */
isIdle()68     bool isIdle() {
69         std::lock_guard<std::mutex> guard(lock);
70         return (workQueue.empty() && state == State::Idle);
71     }
72 
73 private:
74     enum class State {
75         /// The scrubber is currently in the waiting state
76         Idle,
77         /// The scrubber is currently scrubbing a list
78         Scrubbing,
79         /// The scrubber task is stopped (returning from main)
80         Stopped
81     };
82 
83     /** What is the scrubber currently doing */
84     State state;
85 
86     /*
87      * A queue of engine's to work on.
88      * The second bool indicates if the engine is to be deleted when done.
89      */
90     std::deque<std::pair<struct default_engine*, bool> > workQueue;
91 
92     /** Is the task being requested to shut down? */
93     bool shuttingdown;
94 
95     /** The manager owning us */
96     EngineManager& engineManager;
97 
98     /** All internal state is protected by this mutex */
99     std::mutex lock;
100 
101     /**
102      * The condition variable used to notify the task that it has work
103      * to do.
104      */
105     std::condition_variable cvar;
106 
107     /**
108      * The identifier to the thread handle
109      */
110     cb_thread_t scrubberThread;
111 };
112