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