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
18/**
19 * Engine manager provides a C API for the managment of default_engine
20 * 'handles'. Creation / Deletion and the item scrubber thread are all
21 * managed by this module.
22 */
23
24#ifdef __cplusplus
25#include <condition_variable>
26#include <mutex>
27#include <unordered_set>
28
29#include "scrubber_task.h"
30
31class EngineManager {
32public:
33
34    EngineManager();
35    ~EngineManager();
36
37    /**
38     * Create a new instance of the default_engine
39     *
40     * @return the newly created instance or nullptr if we ran out of
41     *         resources (memory _or_ bucket id's)
42     */
43    struct default_engine* createEngine();
44
45    /**
46     * Request that the scrubber destroy's this engine.
47     * Scrubber will delete the object.
48     */
49    void requestDestroyEngine(struct default_engine* engine);
50
51    /**
52     *  Request that the engine is scrubbed.
53     */
54    void scrubEngine(struct default_engine* engine);
55
56    /**
57     * Set the shutdown flag so that we can clean up
58     *    1) no new engine's can be created.
59     *    2) the scrubber can be notified to exit and joined.
60     */
61    void shutdown();
62
63    /**
64     * When the scrubber is done running the requested scrub task it
65     * will call this callback notifying that it is done.
66     *
67     * @param engine the requested engine
68     * @param destroy set to true if the engine should be destroyed
69     */
70    void notifyScrubComplete(struct default_engine* engine, bool destroy);
71
72protected:
73    /**
74     * Wait for the scrubber task to be idle. You <b>must</b> hold the
75     * mutex while calling this function.
76     */
77    void waitForScrubberToBeIdle(std::unique_lock<std::mutex>& lck);
78
79private:
80    /** single mutex protects all members */
81    std::mutex lock;
82
83    /** condition variable used from the scrubber to notify the engine */
84    std::condition_variable cond;
85
86    /** Handle to the scrubber task being used to preform the operations */
87    ScrubberTask scrubberTask;
88
89    /** Are we currently shutting down? (Note: We should refactor the clients
90     * using the class to ensure that this isn't a problem. Given that we can't
91     * restart the task it doesn't really make any sense if we have a race
92     * with one client trying to delete a bucket, and another one trying to
93     * shut down the object...
94     */
95    bool shuttingdown;
96
97    /** Handle of all of the instances created of default engine */
98    std::unordered_set<struct default_engine*> engines;
99};
100
101extern "C" {
102#endif
103
104/*
105 * Create a new engine instance.
106 * Returns NULL for failure.
107 */
108struct default_engine* engine_manager_create_engine();
109
110/*
111 * Delete the engine instance.
112 * Deletion is performed by a background thread.
113 * On return from this method the caller must not use the pointer as
114 * it will be deleted at any time.
115 */
116void engine_manager_delete_engine(struct default_engine* engine);
117
118/*
119 * Request that a scrub of the engine is performed.
120 * Scrub is perfromed by a background thread.
121 */
122void engine_manager_scrub_engine(struct default_engine* engine);
123
124/*
125 * Perform global shutdown in prepration for unloading of the shared object.
126 * This method will block until background threads are joined.
127 */
128void engine_manager_shutdown();
129
130#ifdef __cplusplus
131}
132#endif
133