blob: effe7f3f8ff940942fef1917cd1d0d820c32b009 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenko57123b22014-10-28 13:50:16 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/states/state_change_queue.h"
Alex Vakulenko57123b22014-10-28 13:50:16 -07006
Alex Deymof6cbe322014-11-10 19:55:35 -08007#include <base/logging.h>
8
Vitaly Bukab6f015a2015-07-09 14:59:23 -07009namespace weave {
Alex Vakulenko57123b22014-10-28 13:50:16 -070010
11StateChangeQueue::StateChangeQueue(size_t max_queue_size)
12 : max_queue_size_(max_queue_size) {
Mike Frysinger42e3a722014-11-15 06:48:08 -050013 CHECK_GT(max_queue_size_, 0U) << "Max queue size must not be zero";
Alex Vakulenko57123b22014-10-28 13:50:16 -070014}
15
Alex Vakulenko7d669212015-11-23 16:05:24 -080016bool StateChangeQueue::NotifyPropertiesUpdated(
17 base::Time timestamp,
Alex Vakulenko6869ed72015-12-04 13:59:23 -080018 const base::DictionaryValue& changed_properties) {
Vitaly Buka70b697f2015-07-28 14:36:29 -070019 auto& stored_changes = state_changes_[timestamp];
20 // Merge the old property set.
Alex Vakulenko7d669212015-11-23 16:05:24 -080021 if (stored_changes)
Alex Vakulenko6869ed72015-12-04 13:59:23 -080022 stored_changes->MergeDictionary(&changed_properties);
Alex Vakulenko7d669212015-11-23 16:05:24 -080023 else
Alex Vakulenko6869ed72015-12-04 13:59:23 -080024 stored_changes.reset(changed_properties.DeepCopy());
Vitaly Buka70b697f2015-07-28 14:36:29 -070025
Alex Vakulenko57123b22014-10-28 13:50:16 -070026 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].
Alex Vakulenko7d669212015-11-23 16:05:24 -080036 element_old->second->MergeDictionary(element_new->second.get());
37 std::swap(element_old->second, element_new->second);
Alex Vakulenko57123b22014-10-28 13:50:16 -070038 state_changes_.erase(element_old);
39 }
40 return true;
41}
42
43std::vector<StateChange> StateChangeQueue::GetAndClearRecordedStateChanges() {
Alex Vakulenkoff73cf22014-10-29 09:53:52 -070044 std::vector<StateChange> changes;
45 changes.reserve(state_changes_.size());
Alex Vakulenko7d669212015-11-23 16:05:24 -080046 for (auto& pair : state_changes_) {
47 changes.push_back(StateChange{pair.first, std::move(pair.second)});
Alex Vakulenkoff73cf22014-10-29 09:53:52 -070048 }
49 state_changes_.clear();
50 return changes;
Alex Vakulenko57123b22014-10-28 13:50:16 -070051}
52
Vitaly Bukab6f015a2015-07-09 14:59:23 -070053} // namespace weave