1 /**
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef ANDROID_AUTOMOTIVE_COMPUTEPIPE_ROUTER_REGISTRY
17 #define ANDROID_AUTOMOTIVE_COMPUTEPIPE_ROUTER_REGISTRY
18
19 #include <list>
20 #include <memory>
21 #include <mutex>
22 #include <string>
23 #include <unordered_map>
24 #include <utility>
25
26 #include "PipeContext.h"
27
28 namespace android {
29 namespace automotive {
30 namespace computepipe {
31 namespace router {
32
33 enum Error {
34 // Operation successful
35 OK = 0,
36 // Unable to find pipe
37 PIPE_NOT_FOUND = -1,
38 // Duplicate pipe
39 DUPLICATE_PIPE = -2,
40 // Runner unavailable
41 RUNNER_BUSY = -3,
42 // Runner dead
43 RUNNER_DEAD = -4,
44 // Permission error
45 BAD_PERMISSION = -5,
46 // Bad args
47 BAD_ARGUMENTS = -6,
48 // no memory
49 NOMEM = -7,
50 // Internal error
51 INTERNAL_ERR = -8,
52 };
53
54 /**
55 * PipeRegistry
56 *
57 * Class that represents the current database of graphs and their associated
58 * runners.
59 */
60 template <typename T>
61 class PipeRegistry {
62 public:
63 /**
64 * Returns the runner for a particular graph
65 * If a runner dies, the discovery is made lazily at the point of
66 * attempted retrieval by a client, and the correct result is returned.
67 */
getClientPipeHandle(const std::string & name,std::unique_ptr<ClientHandle> clientHandle)68 std::unique_ptr<PipeHandle<T>> getClientPipeHandle(const std::string& name,
69 std::unique_ptr<ClientHandle> clientHandle) {
70 if (!clientHandle || !clientHandle->startClientMonitor()) {
71 return nullptr;
72 }
73 return getPipeHandle(name, std::move(clientHandle));
74 }
75 /**
76 * Returns list of registered graphs.
77 */
78 std::list<std::string> getPipeList();
79 /**
80 * Registers a graph and the associated runner
81 * if a restarted runner attempts to reregister, the existing entry is checked
82 * and updated if the old entry is found to be invalid.
83 */
RegisterPipe(std::unique_ptr<PipeHandle<T>> h,const std::string & name)84 Error RegisterPipe(std::unique_ptr<PipeHandle<T>> h, const std::string& name) {
85 std::lock_guard<std::mutex> lock(mPipeDbLock);
86 if (mPipeRunnerDb.find(name) == mPipeRunnerDb.end()) {
87 if (!h->startPipeMonitor()) {
88 return RUNNER_DEAD;
89 }
90 mPipeRunnerDb.emplace(
91 name, std::unique_ptr<PipeContext<T>>(new PipeContext<T>(std::move(h), name)));
92 return OK;
93 }
94 if (!mPipeRunnerDb[name]->isAlive()) {
95 mPipeRunnerDb.erase(name);
96 if (!h->startPipeMonitor()) {
97 return RUNNER_DEAD;
98 }
99 mPipeRunnerDb.emplace(
100 name, std::unique_ptr<PipeContext<T>>(new PipeContext<T>(std::move(h), name)));
101 return OK;
102 }
103 return DUPLICATE_PIPE;
104 }
105
106 PipeRegistry() = default;
107
~PipeRegistry()108 ~PipeRegistry() {
109 mPipeRunnerDb.clear();
110 }
111
112 protected:
113 /**
114 * The retrieval of the pipe handle for debug purposes is controlled by the
115 * instantiator of the pipe registry. This is not exposed to the users of
116 * the pipe registry.
117 */
getPipeHandle(const std::string & name,std::unique_ptr<ClientHandle> clientHandle)118 std::unique_ptr<PipeHandle<T>> getPipeHandle(const std::string& name,
119 std::unique_ptr<ClientHandle> clientHandle) {
120 std::lock_guard<std::mutex> lock(mPipeDbLock);
121 if (mPipeRunnerDb.find(name) == mPipeRunnerDb.end()) {
122 return nullptr;
123 }
124
125 if (!clientHandle) {
126 return mPipeRunnerDb[name]->isAlive() ? mPipeRunnerDb[name]->dupPipeHandle() : nullptr;
127 }
128
129 if (mPipeRunnerDb[name]->isAvailable()) {
130 if (mPipeRunnerDb[name]->isAlive()) {
131 mPipeRunnerDb[name]->setClient(std::move(clientHandle));
132 return mPipeRunnerDb[name]->dupPipeHandle();
133 } else {
134 mPipeRunnerDb.erase(name);
135 return nullptr;
136 }
137 }
138 return nullptr;
139 }
140 /**
141 * The deletion of specific entries is protected and can be performed by
142 * only the instantiator
143 */
DeletePipeHandle(const std::string & name)144 Error DeletePipeHandle(const std::string& name) {
145 std::lock_guard<std::mutex> lock(mPipeDbLock);
146 if (mPipeRunnerDb.find(name) == mPipeRunnerDb.end()) {
147 return PIPE_NOT_FOUND;
148 }
149 mPipeRunnerDb.erase(name);
150 return OK;
151 }
152
153 private:
154 std::mutex mPipeDbLock;
155 std::unordered_map<std::string, std::unique_ptr<PipeContext<T>>> mPipeRunnerDb;
156 }; // namespace router
157
158 template <typename T>
getPipeList()159 std::list<std::string> PipeRegistry<T>::getPipeList() {
160 std::list<std::string> pNames;
161
162 std::lock_guard<std::mutex> lock(mPipeDbLock);
163 for (auto const& kv : mPipeRunnerDb) {
164 pNames.push_back(kv.first);
165 }
166 return pNames;
167 }
168 } // namespace router
169 } // namespace computepipe
170 } // namespace automotive
171 } // namespace android
172 #endif
173