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
24class 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 */
37class ScrubberTask {
38public:
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     */
68    bool isIdle() {
69        std::lock_guard<std::mutex> guard(lock);
70        return (workQueue.empty() && state == State::Idle);
71    }
72
73private:
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