1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include "tensorflow/core/distributed_runtime/recent_request_ids.h"
17
18#include "tensorflow/core/lib/core/errors.h"
19#include "tensorflow/core/lib/strings/strcat.h"
20#include "tensorflow/core/platform/logging.h"
21
22namespace tensorflow {
23
24RecentRequestIds::RecentRequestIds(int num_tracked_request_ids)
25    : circular_buffer_(num_tracked_request_ids) {
26  set_.reserve(num_tracked_request_ids);
27}
28
29Status RecentRequestIds::TrackUnique(int64 request_id,
30                                     const string& method_name,
31                                     const protobuf::Message& request) {
32  mutex_lock l(mu_);
33  if (request_id == 0) {
34    // For backwards compatibility, allow all requests with request_id 0.
35    return Status::OK();
36  }
37  if (set_.count(request_id) > 0) {
38    // Note: RecentRequestIds is not strict LRU because we don't update
39    // request_id's age in the circular_buffer_ if it's tracked again. Strict
40    // LRU is not useful here because returning this error will close the
41    // current Session.
42    return errors::Aborted("The same ", method_name,
43                           " request was received twice. ",
44                           request.ShortDebugString());
45  }
46
47  // Remove the oldest request_id from the set_. circular_buffer_ is
48  // zero-initialized, and zero is never tracked, so it's safe to do this even
49  // when the buffer is not yet full.
50  set_.erase(circular_buffer_[next_index_]);
51  circular_buffer_[next_index_] = request_id;
52  set_.insert(request_id);
53  next_index_ = (next_index_ + 1) % circular_buffer_.size();
54  return Status::OK();
55}
56
57}  // namespace tensorflow
58