Skip to content

Commit

Permalink
Add initial cluster data version support
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google committed Jan 9, 2022
1 parent 6d8589f commit 20dad18
Show file tree
Hide file tree
Showing 26 changed files with 366 additions and 69 deletions.
6 changes: 3 additions & 3 deletions src/app/AttributeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ void AttributeCache::OnReportEnd(const ReadClient * apReadClient)
mCallback.OnReportEnd(apReadClient);
}

void AttributeCache::OnAttributeData(const ReadClient * apReadClient, const ConcreteDataAttributePath & aPath,
TLV::TLVReader * apData, const StatusIB & aStatus)
void AttributeCache::OnAttributeData(const ReadClient * apReadClient, DataVersion * apVersion,
const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus)
{
//
// Since the cache itself is a ReadClient::Callback, it may be incorrectly passed in directly when registering with the
Expand All @@ -121,7 +121,7 @@ void AttributeCache::OnAttributeData(const ReadClient * apReadClient, const Conc
//
// Forward the call through.
//
mCallback.OnAttributeData(apReadClient, aPath, apData, aStatus);
mCallback.OnAttributeData(apReadClient, apVersion, aPath, apData, aStatus);
}

CHIP_ERROR AttributeCache::Get(const ConcreteAttributePath & path, TLV::TLVReader & reader)
Expand Down
4 changes: 2 additions & 2 deletions src/app/AttributeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,8 @@ class AttributeCache : protected ReadClient::Callback
//
void OnReportBegin(const ReadClient * apReadClient) override;
void OnReportEnd(const ReadClient * apReadClient) override;
void OnAttributeData(const ReadClient * apReadClient, const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData,
const StatusIB & aStatus) override;
void OnAttributeData(const ReadClient * apReadClient, DataVersion * apVersion, const ConcreteDataAttributePath & aPath,
TLV::TLVReader * apData, const StatusIB & aStatus) override;
void OnError(const ReadClient * apReadClient, CHIP_ERROR aError) override { return mCallback.OnError(apReadClient, aError); }
void OnEventData(const ReadClient * apReadClient, const EventHeader & aEventHeader, TLV::TLVReader * apData,
const StatusIB * apStatus) override
Expand Down
3 changes: 3 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ static_library("app") {
"CASEClientPool.h",
"CASESessionManager.cpp",
"CASESessionManager.h",
"ClusterDataVersionPersistenceProvider.h",
"CommandHandler.cpp",
"CommandSender.cpp",
"DefaultAttributePersistenceProvider.cpp",
"DefaultClusterDataVersionPersistenceProvider.cpp",
"DefaultClusterDataVersionPersistenceProvider.h",
"DeviceProxy.cpp",
"DeviceProxy.h",
"EventManagement.cpp",
Expand Down
11 changes: 7 additions & 4 deletions src/app/BufferedReadCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,21 @@ CHIP_ERROR BufferedReadCallback::DispatchBufferedData(const ReadClient * apReadC
//
ReturnErrorOnFailure(reader.Next());

mCallback.OnAttributeData(apReadClient, mBufferedPath, &reader, statusIB);
mCallback.OnAttributeData(apReadClient, mpDataVersion, mBufferedPath, &reader, statusIB);

//
// Clear out our buffered contents to free up allocated buffers, and reset the buffered path.
//
mBufferedList.clear();
mBufferedPath = ConcreteDataAttributePath();
mpDataVersion = nullptr;

return CHIP_NO_ERROR;
}

void BufferedReadCallback::OnAttributeData(const ReadClient * apReadClient, const ConcreteDataAttributePath & aPath,
TLV::TLVReader * apData, const StatusIB & aStatus)
void BufferedReadCallback::OnAttributeData(const ReadClient * apReadClient, DataVersion * apVersion,
const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData,
const StatusIB & aStatus)
{
CHIP_ERROR err;

Expand All @@ -247,13 +249,14 @@ void BufferedReadCallback::OnAttributeData(const ReadClient * apReadClient, cons
}
else
{
mCallback.OnAttributeData(apReadClient, aPath, apData, aStatus);
mCallback.OnAttributeData(apReadClient, apVersion, aPath, apData, aStatus);
}

//
// Update our latched buffered path.
//
mBufferedPath = aPath;
mpDataVersion = apVersion;

exit:
if (err != CHIP_NO_ERROR)
Expand Down
5 changes: 3 additions & 2 deletions src/app/BufferedReadCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class BufferedReadCallback : public ReadClient::Callback
//
void OnReportBegin(const ReadClient * apReadClient) override;
void OnReportEnd(const ReadClient * apReadClient) override;
void OnAttributeData(const ReadClient * apReadClient, const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData,
const StatusIB & aStatus) override;
void OnAttributeData(const ReadClient * apReadClient, DataVersion * apVersion, const ConcreteDataAttributePath & aPath,
TLV::TLVReader * apData, const StatusIB & aStatus) override;
void OnError(const ReadClient * apReadClient, CHIP_ERROR aError) override { return mCallback.OnError(apReadClient, aError); }
void OnEventData(const ReadClient * apReadClient, const EventHeader & aEventHeader, TLV::TLVReader * apData,
const StatusIB * apStatus) override
Expand All @@ -93,6 +93,7 @@ class BufferedReadCallback : public ReadClient::Callback
CHIP_ERROR BufferListItem(TLV::TLVReader & reader);

ConcreteDataAttributePath mBufferedPath;
DataVersion * mpDataVersion = nullptr;
std::vector<System::PacketBufferHandle> mBufferedList;
Callback & mCallback;
};
Expand Down
76 changes: 76 additions & 0 deletions src/app/ClusterDataVersionPersistenceProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <app/ConcreteClusterPath.h>
#include <app/util/basic-types.h>
#include <lib/support/CodeUtils.h>

namespace chip {
namespace app {

/**
* Interface for persisting cluster data version value.
*/

class ClusterDataVersionPersistenceProvider
{
public:
virtual ~ClusterDataVersionPersistenceProvider() = default;
ClusterDataVersionPersistenceProvider() = default;

/**
* Write a version value from the attribute store to non-volatile memory.
*
* @param [in] aPath the cluster path for the version being written.
* @param [in] aValue the data to write. Integer is
* represented in native endianness. The length is
* stored as little-endian.
*/
virtual CHIP_ERROR WriteValue(const ConcreteClusterPath & aPath, const chip::DataVersion & aValue) = 0;

/**
* Read an attribute value from non-volatile memory.
*
* @param [in] aPath the cluster path for the version being persisted.
* @param [inout] aValue where to place the data.
*
* The data is expected to be in native endianness for integer.
*/
virtual CHIP_ERROR ReadValue(const ConcreteClusterPath & aPath, chip::DataVersion & aValue) = 0;
};

/**
* Instance getter for the global ClusterDataVersionPersistenceProvider.
*
* Callers have to externally synchronize usage of this function.
*
* @return The global ClusterDataVersionPersistenceProvider. This must never be null.
*/
ClusterDataVersionPersistenceProvider * GetClusterDataVersionPersistenceProvider();

/**
* Instance setter for the global ClusterDataVersionPersistenceProvider.
*
* Callers have to externally synchronize usage of this function.
*
* If the `provider` is nullptr, the value is not changed.
*
* @param[in] provider the ClusterDataVersionPersistenceProvider implementation to use.
*/
void SetClusterDataVersionPersistenceProvider(ClusterDataVersionPersistenceProvider * aProvider);

} // namespace app
} // namespace chip
35 changes: 35 additions & 0 deletions src/app/ConcreteClusterPath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <app/util/basic-types.h>

namespace chip {
namespace app {
struct ConcreteClusterPath
{
ConcreteClusterPath(EndpointId aEndpointId, ClusterId aClusterId) : mEndpointId(aEndpointId), mClusterId(aClusterId) {}

ConcreteClusterPath() {}

EndpointId mEndpointId = 0;
ClusterId mClusterId = 0;
};
} // namespace app
} // namespace chip
63 changes: 63 additions & 0 deletions src/app/DefaultClusterDataVersionPersistenceProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <app/DefaultClusterDataVersionPersistenceProvider.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>

namespace chip {
namespace app {

CHIP_ERROR DefaultClusterDataVersionPersistenceProvider::WriteValue(const ConcreteClusterPath & aPath,
const chip::DataVersion & aValue)
{
// TODO: we may want to have a small cache for values that change a lot, so
// we only write them once a bunch of changes happen or on timer or
// shutdown.
DefaultStorageKeyAllocator key;
return mStorage.SyncSetKeyValue(key.ClusterValue(aPath), &aValue, sizeof(aValue));
}

CHIP_ERROR DefaultClusterDataVersionPersistenceProvider::ReadValue(const ConcreteClusterPath & aPath, chip::DataVersion & aValue)
{
DefaultStorageKeyAllocator key;
uint16_t size = sizeof(aValue);
ReturnErrorOnFailure(mStorage.SyncGetKeyValue(key.ClusterValue(aPath), &aValue, size));
return CHIP_NO_ERROR;
}

namespace {

ClusterDataVersionPersistenceProvider * gDataVersionSaver = nullptr;

} // anonymous namespace

ClusterDataVersionPersistenceProvider * GetClusterDataVersionPersistenceProvider()
{
return gDataVersionSaver;
}

void SetClusterDataVersionPersistenceProvider(ClusterDataVersionPersistenceProvider * aProvider)
{
if (aProvider != nullptr)
{
gDataVersionSaver = aProvider;
}
}

} // namespace app
} // namespace chip
48 changes: 48 additions & 0 deletions src/app/DefaultClusterDataVersionPersistenceProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once

#include <app/ClusterDataVersionPersistenceProvider.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/support/DefaultStorageKeyAllocator.h>

namespace chip {
namespace app {

/**
* Default implementation of ClusterDataVersionPersistenceProvider. This uses
* PersistentStorageDelegate to store the version.
*
* NOTE: SetAttributePersistenceProvider must still be called with an instance
* of this class, since it can't be constructed automatically without knowing
* what PersistentStorageDelegate is to be used.
*/
class DefaultClusterDataVersionPersistenceProvider : public ClusterDataVersionPersistenceProvider
{
public:
// aStorage must outlive this object.
DefaultClusterDataVersionPersistenceProvider(PersistentStorageDelegate & aStorage) : mStorage(aStorage) {}

// AttributePersistenceProvider implementation.
CHIP_ERROR WriteValue(const ConcreteClusterPath & aPath, const chip::DataVersion & aValue) override;
CHIP_ERROR ReadValue(const ConcreteClusterPath & aPath, chip::DataVersion & aValue) override;

private:
PersistentStorageDelegate & mStorage;
};

} // namespace app
} // namespace chip
6 changes: 4 additions & 2 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo
AttributePathIB::Parser path;
ConcreteDataAttributePath attributePath;
StatusIB statusIB;
DataVersion version = 0;

TLV::TLVReader reader = aAttributeReportIBsReader;
ReturnErrorOnFailure(report.Init(reader));
Expand All @@ -511,13 +512,14 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo
ReturnErrorOnFailure(ProcessAttributePath(path, attributePath));
ReturnErrorOnFailure(status.GetErrorStatus(&errorStatus));
ReturnErrorOnFailure(errorStatus.DecodeStatusIB(statusIB));
mpCallback.OnAttributeData(this, attributePath, nullptr, statusIB);
mpCallback.OnAttributeData(this, nullptr, attributePath, nullptr, statusIB);
}
else if (CHIP_END_OF_TLV == err)
{
ReturnErrorOnFailure(report.GetAttributeData(&data));
ReturnErrorOnFailure(data.GetPath(&path));
ReturnErrorOnFailure(ProcessAttributePath(path, attributePath));
ReturnErrorOnFailure(data.GetDataVersion(&version));
ReturnErrorOnFailure(data.GetData(&dataReader));

// The element in an array may be another array -- so we should only set the list operation when we are handling the
Expand All @@ -527,7 +529,7 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo
attributePath.mListOp = ConcreteDataAttributePath::ListOperation::ReplaceAll;
}

mpCallback.OnAttributeData(this, attributePath, &dataReader, statusIB);
mpCallback.OnAttributeData(this, &version, attributePath, &dataReader, statusIB);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/app/ReadClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,14 @@ class ReadClient : public Messaging::ExchangeDelegate
* receives an OnDone call to destroy the object.
*
* @param[in] apReadClient The read client object that initiated the read or subscribe transaction.
* @param[in] apVersion The cluster version in report response.
* @param[in] aPath The attribute path field in report response.
* @param[in] apData The attribute data of the given path, will be a nullptr if status is not Success.
* @param[in] aStatus Attribute-specific status, containing an InteractionModel::Status code as well as an
* optional cluster-specific status code.
*/
virtual void OnAttributeData(const ReadClient * apReadClient, const ConcreteDataAttributePath & aPath,
TLV::TLVReader * apData, const StatusIB & aStatus)
virtual void OnAttributeData(const ReadClient * apReadClient, DataVersion * apVersion,
const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus)
{}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/app/reporting/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*/

#include <app/AppBuildConfig.h>
#include <app/ConcreteClusterPath.h>
#include <app/DefaultClusterDataVersionPersistenceProvider.h>
#include <app/InteractionModelEngine.h>
#include <app/reporting/Engine.h>
#include <app/util/MatterCallbacks.h>
Expand Down
Loading

0 comments on commit 20dad18

Please sign in to comment.