Line data Source code
1 : /* 2 : * Copyright (c) 2022 Project CHIP Authors 3 : * 4 : * Licensed under the Apache License, Version 2.0 (the "License"); 5 : * you may not use this file except in compliance with the License. 6 : * You may obtain a copy of the License at 7 : * 8 : * http://www.apache.org/licenses/LICENSE-2.0 9 : * 10 : * Unless required by applicable law or agreed to in writing, software 11 : * distributed under the License is distributed on an "AS IS" BASIS, 12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 : * See the License for the specific language governing permissions and 14 : * limitations under the License. 15 : */ 16 : 17 : #include <app/DeferredAttributePersistenceProvider.h> 18 : 19 : #include <platform/CHIPDeviceLayer.h> 20 : 21 : namespace chip { 22 : namespace app { 23 : 24 0 : CHIP_ERROR DeferredAttribute::PrepareWrite(System::Clock::Timestamp flushTime, const ByteSpan & value) 25 : { 26 0 : mFlushTime = flushTime; 27 : 28 0 : if (mValue.AllocatedSize() != value.size()) 29 : { 30 0 : mValue.Alloc(value.size()); 31 0 : ReturnErrorCodeIf(!mValue, CHIP_ERROR_NO_MEMORY); 32 : } 33 : 34 0 : memcpy(mValue.Get(), value.data(), value.size()); 35 0 : return CHIP_NO_ERROR; 36 : } 37 : 38 0 : void DeferredAttribute::Flush(AttributePersistenceProvider & persister) 39 : { 40 0 : VerifyOrReturn(IsArmed()); 41 0 : persister.WriteValue(mPath, ByteSpan(mValue.Get(), mValue.AllocatedSize())); 42 0 : mValue.Free(); 43 : } 44 : 45 0 : CHIP_ERROR DeferredAttributePersistenceProvider::WriteValue(const ConcreteAttributePath & aPath, const ByteSpan & aValue) 46 : { 47 0 : for (DeferredAttribute & da : mDeferredAttributes) 48 : { 49 0 : if (da.Matches(aPath)) 50 : { 51 0 : ReturnErrorOnFailure(da.PrepareWrite(System::SystemClock().GetMonotonicTimestamp() + mWriteDelay, aValue)); 52 0 : FlushAndScheduleNext(); 53 0 : return CHIP_NO_ERROR; 54 : } 55 : } 56 : 57 0 : return mPersister.WriteValue(aPath, aValue); 58 : } 59 : 60 0 : CHIP_ERROR DeferredAttributePersistenceProvider::ReadValue(const ConcreteAttributePath & aPath, 61 : const EmberAfAttributeMetadata * aMetadata, MutableByteSpan & aValue) 62 : { 63 0 : return mPersister.ReadValue(aPath, aMetadata, aValue); 64 : } 65 : 66 0 : void DeferredAttributePersistenceProvider::FlushAndScheduleNext() 67 : { 68 0 : const System::Clock::Timestamp now = System::SystemClock().GetMonotonicTimestamp(); 69 0 : System::Clock::Timestamp nextFlushTime = System::Clock::Timestamp::max(); 70 : 71 0 : for (DeferredAttribute & da : mDeferredAttributes) 72 : { 73 0 : if (!da.IsArmed()) 74 : { 75 0 : continue; 76 : } 77 : 78 0 : if (da.GetFlushTime() <= now) 79 : { 80 0 : da.Flush(mPersister); 81 : } 82 : else 83 : { 84 0 : nextFlushTime = chip::min(nextFlushTime, da.GetFlushTime()); 85 : } 86 : } 87 : 88 0 : if (nextFlushTime != System::Clock::Timestamp::max()) 89 : { 90 0 : DeviceLayer::SystemLayer().StartTimer( 91 0 : nextFlushTime - now, 92 0 : [](System::Layer *, void * me) { static_cast<DeferredAttributePersistenceProvider *>(me)->FlushAndScheduleNext(); }, 93 : this); 94 : } 95 0 : } 96 : 97 : } // namespace app 98 : } // namespace chip