TensorFlow Serving C++ API Documentation
loader_harness.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_LOADER_HARNESS_H_
17 #define TENSORFLOW_SERVING_CORE_LOADER_HARNESS_H_
18 
19 #include <memory>
20 
21 #include "absl/status/status.h"
22 #include "absl/types/optional.h"
23 #include "tensorflow/core/lib/core/status.h"
24 #include "tensorflow/core/platform/macros.h"
25 #include "tensorflow/core/platform/mutex.h"
26 #include "tensorflow/core/platform/thread_annotations.h"
27 #include "tensorflow/core/platform/types.h"
28 #include "tensorflow_serving/core/loader.h"
29 #include "tensorflow_serving/core/servable_id.h"
30 
31 namespace tensorflow {
32 namespace serving {
33 
34 // START_SKIP_DOXYGEN
35 // Forward-declaration for the use in LoaderHarness.
36 template <typename T>
37 struct ServableStateSnapshot;
38 // END_SKIP_DOXYGEN
39 
49 class LoaderHarness final {
50  public:
59  enum class State {
61  kNew,
62 
65 
69 
71  kLoading,
72 
74  kReady,
75 
78 
80  kQuiescing,
81 
83  kQuiesced,
84 
86  kUnloading,
87 
89  kDisabled,
90 
93  kError
94  };
95 
97  struct Options {
98  Options() {}
99 
103 
106 
108  std::function<void(const ServableId& id, const Status& error)>
110  };
111 
112  LoaderHarness(const ServableId& id, std::unique_ptr<Loader> loader,
113  const Options& options = Options());
114 
117  template <typename T>
118  LoaderHarness(const ServableId& id, std::unique_ptr<Loader> loader,
119  std::unique_ptr<T> additional_state,
120  const Options& options = Options())
121  : id_(id),
122  loader_(std::move(loader)),
123  additional_state_(std::move(additional_state)),
124  options_(options),
125  should_retry_([&](absl::Status status) { return true; }) {}
126 
129  ~LoaderHarness();
130 
132  ServableId id() const { return id_; }
133 
135  State state() const TF_LOCKS_EXCLUDED(mu_);
136 
139  Loader* loader() const { return loader_.get(); }
140 
142  template <typename T = std::nullptr_t>
143  ServableStateSnapshot<T> loader_state_snapshot() const TF_LOCKS_EXCLUDED(mu_);
144 
148  Status LoadRequested() TF_LOCKS_EXCLUDED(mu_);
149 
154  Status LoadApproved() TF_LOCKS_EXCLUDED(mu_);
155 
166  Status Load() TF_LOCKS_EXCLUDED(mu_);
167 
171  Status UnloadRequested() TF_LOCKS_EXCLUDED(mu_);
172 
181  void set_should_retry(std::function<bool(absl::Status)> should_retry)
182  TF_LOCKS_EXCLUDED(mu_);
183 
185  bool should_retry(absl::Status status) TF_LOCKS_EXCLUDED(mu_);
186 
192  Status Unload() TF_LOCKS_EXCLUDED(mu_);
193 
199  Status StartQuiescing() TF_LOCKS_EXCLUDED(mu_);
200 
207  Status DoneQuiescing() TF_LOCKS_EXCLUDED(mu_);
208 
210  void Error(const Status& status) TF_LOCKS_EXCLUDED(mu_);
211 
217  Status status() const TF_LOCKS_EXCLUDED(mu_);
218 
221  template <typename T>
223  return additional_state_.get<T>();
224  }
225 
226  static string StateDebugString(State state);
227 
228  private:
229  // Transitions the state to kError and invokes 'options_.error_callback'.
230  // Private method to be used when we want to set an error from another method
231  // in this class, where mu_ is already held.
232  void ErrorInternal(const Status& status) TF_EXCLUSIVE_LOCKS_REQUIRED(mu_);
233 
234  // Expects 'state_' to equal 'from', and if so transitions it to 'to'. If not,
235  // DCHECK-fails, calls ErrorInternal() with a suitable error and returns the
236  // same error.
237  Status TransitionState(State from, State to) TF_EXCLUSIVE_LOCKS_REQUIRED(mu_);
238 
239  Status UnloadInternal(State from_state) TF_LOCKS_EXCLUDED(mu_);
240  Status UnloadDueToCancelledLoad() TF_LOCKS_EXCLUDED(mu_);
241 
242  const ServableId id_;
243  const std::unique_ptr<Loader> loader_;
244  // Additional state that the manager uses.
245  const UniqueAnyPtr additional_state_;
246  const Options options_;
247  mutable mutex mu_;
248  State state_ TF_GUARDED_BY(mu_) = State::kNew;
249  // If state_ is kError, this will be non-OK.
250  Status status_ TF_GUARDED_BY(mu_);
251  // The retry policy for the servable. If the function returns false, we cancel
252  // the next retry. This does not affect the current load action already
253  // running.
254  // There is no retry if the last action was successful.
255  std::function<bool(absl::Status)> should_retry_ TF_GUARDED_BY(mu_);
256 
257  TF_DISALLOW_COPY_AND_ASSIGN(LoaderHarness);
258 };
259 
260 // START_SKIP_DOXYGEN
261 
262 // A snapshot of a servable's state and aspiredness, from the LoaderHarness's
263 // perspective.
264 template <typename T = std::nullptr_t>
265 struct ServableStateSnapshot final {
266  ServableId id;
268  absl::optional<T> additional_state;
269 };
270 
271 template <typename T>
272 inline bool operator==(const ServableStateSnapshot<T>& a,
273  const ServableStateSnapshot<T>& b) {
274  return a.id == b.id && a.state == b.state &&
275  a.additional_state == b.additional_state;
276 }
277 
278 template <typename T>
279 inline bool operator!=(const ServableStateSnapshot<T>& a,
280  const ServableStateSnapshot<T>& b) {
281  return !(a == b);
282 }
283 
284 inline std::ostream& operator<<(std::ostream& os, LoaderHarness::State state) {
285  os << LoaderHarness::StateDebugString(state);
286  return os;
287 }
288 
290 // Implementation details. API readers may skip.
292 
293 template <typename T>
295  mutex_lock l(mu_);
296  if (additional_state_.get<T>() == nullptr) {
297  return {id_, state_, {}};
298  } else {
299  return {id_, state_, {*additional_state_.get<T>()}};
300  }
301 }
302 
303 // Specialization for std::nullptr_t.
304 //
305 // We mark this inline to follow ODR.
306 template <>
309  mutex_lock l(mu_);
310  return {id_, state_, {}};
311 }
312 
313 // END_SKIP_DOXYGEN
314 
315 } // namespace serving
316 } // namespace tensorflow
317 
318 #endif // TENSORFLOW_SERVING_CORE_LOADER_HARNESS_H_
void set_should_retry(std::function< bool(absl::Status)> should_retry) TF_LOCKS_EXCLUDED(mu_)
Status DoneQuiescing() TF_LOCKS_EXCLUDED(mu_)
State state() const TF_LOCKS_EXCLUDED(mu_)
Returns the current state of underlying Servable.
Status Unload() TF_LOCKS_EXCLUDED(mu_)
Status UnloadRequested() TF_LOCKS_EXCLUDED(mu_)
LoaderHarness(const ServableId &id, std::unique_ptr< Loader > loader, std::unique_ptr< T > additional_state, const Options &options=Options())
Status StartQuiescing() TF_LOCKS_EXCLUDED(mu_)
@ kLoadRequested
The manager has been requested to load this servable.
@ kReady
'loader_->Load()' has succeeded.
@ kUnloadRequested
The manager has been requested to unload this servable.
@ kDisabled
'loader_->Unload()' has finished.
@ kLoading
'loader_->Load()' has been called.
@ kQuiesced
The servable has been made unavailable for serving.
@ kQuiescing
The servable is going to be made unavailable for serving.
@ kUnloading
'loader_->Unload()' has been called.
void Error(const Status &status) TF_LOCKS_EXCLUDED(mu_)
Transitions the state to kError and invokes 'options_.error_callback'.
Status LoadApproved() TF_LOCKS_EXCLUDED(mu_)
ServableId id() const
Returns the identifier of underlying Servable.
bool should_retry(absl::Status status) TF_LOCKS_EXCLUDED(mu_)
Returns true if the servable should be retried.
Status LoadRequested() TF_LOCKS_EXCLUDED(mu_)
ServableStateSnapshot< T > loader_state_snapshot() const TF_LOCKS_EXCLUDED(mu_)
Returns the current overall state snapshot of the underlying Servable.
Status Load() TF_LOCKS_EXCLUDED(mu_)
Status status() const TF_LOCKS_EXCLUDED(mu_)
T * get() const
Accessor for the underlying pointer if it is of type T, otherwise null.
Definition: any_ptr.h:136
Options to configure a LoaderHarness.
std::function< void(const ServableId &id, const Status &error)> error_callback
An (optional) function to call upon transitioning to state kError.
uint64_t load_retry_interval_micros
The interval, in microseconds, between each servable load retry.