TensorFlow Serving C++ API Documentation
dynamic_source_router.h
1 /* Copyright 2016 Google Inc. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7  http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_SERVING_CORE_DYNAMIC_SOURCE_ROUTER_H_
17 #define TENSORFLOW_SERVING_CORE_DYNAMIC_SOURCE_ROUTER_H_
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "tensorflow/core/platform/macros.h"
24 #include "tensorflow_serving/core/source_router.h"
25 
26 namespace tensorflow {
27 namespace serving {
28 
29 // A SourceRouter with a fixed set of N output ports, and a dynamically
30 // reconfigurable map from servable name to port. The route map can only
31 // reference the first N-1 ports; the Nth port is reserved for servables not
32 // found in the route map.
33 template <typename T>
34 class DynamicSourceRouter final : public SourceRouter<T> {
35  public:
36  // A servable name -> output port map.
37  using Routes = std::map<string, int>;
38 
39  // Creates a DynamicSourceRouter with 'num_output_ports' output ports and an
40  // (initial) route map given by 'routes'.
41  static Status Create(int num_output_ports, const Routes& routes,
42  std::unique_ptr<DynamicSourceRouter<T>>* result);
43  ~DynamicSourceRouter() override;
44 
45  // Gets the current route map.
46  Routes GetRoutes() const;
47 
48  // Sets the route map to 'routes'.
49  Status UpdateRoutes(const Routes& routes);
50 
51  protected:
52  int num_output_ports() const override { return num_output_ports_; }
53 
54  int Route(const StringPiece servable_name,
55  const std::vector<ServableData<T>>& versions) override;
56 
57  private:
58  DynamicSourceRouter(int num_output_ports, const Routes& routes);
59 
60  // Returns an error if 'routes' is invalid, given 'num_output_ports'.
61  static Status ValidateRoutes(int num_output_ports, const Routes& routes);
62 
63  const int num_output_ports_;
64 
65  mutable mutex routes_mu_;
66  Routes routes_ TF_GUARDED_BY(routes_mu_);
67 
68  TF_DISALLOW_COPY_AND_ASSIGN(DynamicSourceRouter);
69 };
70 
72 // Implementation details follow. API users need not read.
73 
74 template <typename T>
76  int num_output_ports, const Routes& routes,
77  std::unique_ptr<DynamicSourceRouter<T>>* result) {
78  TF_RETURN_IF_ERROR(ValidateRoutes(num_output_ports, routes));
79  result->reset(new DynamicSourceRouter<T>(num_output_ports, routes));
80  return Status();
81 }
82 
83 template <typename T>
84 DynamicSourceRouter<T>::~DynamicSourceRouter() {
85  TargetBase<T>::Detach();
86 }
87 
88 template <typename T>
89 typename DynamicSourceRouter<T>::Routes DynamicSourceRouter<T>::GetRoutes()
90  const {
91  mutex_lock l(routes_mu_);
92  return routes_;
93 }
94 
95 template <typename T>
96 Status DynamicSourceRouter<T>::UpdateRoutes(const Routes& routes) {
97  TF_RETURN_IF_ERROR(ValidateRoutes(num_output_ports_, routes));
98  {
99  mutex_lock l(routes_mu_);
100  routes_ = routes;
101  }
102  return Status();
103 }
104 
105 template <typename T>
106 int DynamicSourceRouter<T>::Route(
107  const StringPiece servable_name,
108  const std::vector<ServableData<T>>& versions) {
109  mutex_lock l(routes_mu_);
110  auto it = routes_.find(string(servable_name));
111  if (it == routes_.end()) {
112  LOG(INFO) << "Routing servable(s) from stream " << servable_name
113  << " to default output port " << num_output_ports_ - 1;
114  return num_output_ports_ - 1;
115  } else {
116  return it->second;
117  }
118 }
119 
120 template <typename T>
121 DynamicSourceRouter<T>::DynamicSourceRouter(int num_output_ports,
122  const Routes& routes)
123  : num_output_ports_(num_output_ports), routes_(routes) {}
124 
125 template <typename T>
126 Status DynamicSourceRouter<T>::ValidateRoutes(int num_output_ports,
127  const Routes& routes) {
128  for (const auto& entry : routes) {
129  const int port = entry.second;
130  if (port < 0 || port >= num_output_ports) {
131  return errors::InvalidArgument(
132  strings::StrCat("Port number out of range: ", port));
133  }
134  if (port == num_output_ports - 1) {
135  return errors::InvalidArgument(
136  "Last port cannot be used in route map, since it's reserved for the "
137  "default route");
138  }
139  }
140  return Status();
141 }
142 
143 } // namespace serving
144 } // namespace tensorflow
145 
146 #endif // TENSORFLOW_SERVING_CORE_DYNAMIC_SOURCE_ROUTER_H_