1// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/states/state_change_queue.h"
6
7#include <base/logging.h>
8
9namespace weave {
10
11StateChangeQueue::StateChangeQueue(size_t max_queue_size)
12    : max_queue_size_(max_queue_size) {
13  CHECK_GT(max_queue_size_, 0U) << "Max queue size must not be zero";
14}
15
16bool StateChangeQueue::NotifyPropertiesUpdated(
17    base::Time timestamp,
18    const base::DictionaryValue& changed_properties) {
19  auto& stored_changes = state_changes_[timestamp];
20  // Merge the old property set.
21  if (stored_changes)
22    stored_changes->MergeDictionary(&changed_properties);
23  else
24    stored_changes.reset(changed_properties.DeepCopy());
25
26  while (state_changes_.size() > max_queue_size_) {
27    // Queue is full.
28    // Merge the two oldest records into one. The merge strategy is:
29    //  - Move non-existent properties from element [old] to [new].
30    //  - If both [old] and [new] specify the same property,
31    //    keep the value of [new].
32    //  - Keep the timestamp of [new].
33    auto element_old = state_changes_.begin();
34    auto element_new = std::next(element_old);
35    // This will skip elements that exist in both [old] and [new].
36    element_old->second->MergeDictionary(element_new->second.get());
37    std::swap(element_old->second, element_new->second);
38    state_changes_.erase(element_old);
39  }
40  return true;
41}
42
43std::vector<StateChange> StateChangeQueue::GetAndClearRecordedStateChanges() {
44  std::vector<StateChange> changes;
45  changes.reserve(state_changes_.size());
46  for (auto& pair : state_changes_) {
47    changes.push_back(StateChange{pair.first, std::move(pair.second)});
48  }
49  state_changes_.clear();
50  return changes;
51}
52
53}  // namespace weave
54