blob: 6ca95f49011ff61a6257a74af88c43eab829f6d3 [file] [log] [blame]
/*
*
* Copyright (c) 2016-2017 Nest Labs, Inc.
* 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.
*/
/**
* @file
* This file defines the generic Update Client for Weave
* Data Management (WDM) profile.
*
*/
#ifndef _WEAVE_DATA_MANAGEMENT_UPDATE_ENCODER_CURRENT_H
#define _WEAVE_DATA_MANAGEMENT_UPDATE_ENCODER_CURRENT_H
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif // __STDC_FORMAT_MACROS
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Profiles/data-management/MessageDef.h>
#include <Weave/Profiles/data-management/EventLoggingTypes.h>
#include <Weave/Profiles/data-management/TraitCatalog.h>
namespace nl {
namespace Weave {
namespace Profiles {
namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) {
TraitUpdatableDataSink *Locate(TraitDataHandle aTraitDataHandle, const TraitCatalogBase<TraitDataSink> * aDataSinkCatalog);
/**
* This object encodes WDM UpdateRequest and PartialUpdateRequest payloads.
* Note that both requests have the same format; they are differentiated only
* by the message type, which is outside the scope of this object.
*
* The encoding is done synchronously by the EncodeRequest method.
* The only other public method is InsertInProgressUpdateItem, which is
* called by the SchemaEngine when it needs to push a dictionary back to the queue.
*/
class UpdateEncoder
{
public:
UpdateEncoder() { }
~UpdateEncoder() { }
/**
* This structure holds the I/O arguments to the EncodeRequest method.
*/
struct Context
{
Context()
: mBuf(NULL), mMaxPayloadSize(0), mUpdateRequestIndex(0), mExpiryTimeMicroSecond(0),
mItemInProgress(0), mInProgressUpdateList(NULL), mNextDictionaryElementPathHandle(kNullPropertyPathHandle),
mDataSinkCatalog(NULL), mNumDataElementsAddedToPayload(0)
{ }
// Destination buffer
PacketBuffer *mBuf; /**< The output buffer. In case of failure the PacketBuffer's data length
is not updated, but the buffer contents are not preserved. */
uint32_t mMaxPayloadSize; /**< The maximum number of bytes to write. */
// Other fields of the payload
uint32_t mUpdateRequestIndex; /**< The value of the UpdateRequestIndex field for this request. */
utc_timestamp_t mExpiryTimeMicroSecond; /**< The value of the ExpiryTimeMicroSecond field for this request.
It is encoded only if different than 0 */
// What to encode
size_t mItemInProgress; /**< Input: the index of the item of mInProgressUpdateList to start
encoding from.
Output: Upon returning, if the whole path list fit in the payload,
this field equals mInProgressUpdateList->GetPathStoreSize().
Otherwise, the index of the item to start the next payload from.*/
TraitPathStore *mInProgressUpdateList; /**< The list of TraitPaths to encode. */
PropertyPathHandle mNextDictionaryElementPathHandle; /**< Input: if the encoding starts with a dictionary being
resumed, this field holds the property path of the next
dictionary item to encode. Otherwise, this field should be
kNullPropertyPathHandle.
Output: if the last DataElement encoded is a dictionary and
not all items fit in the payload, this field holds the property
path handle of the item to start from for the next payload. */
const TraitCatalogBase<TraitDataSink> * mDataSinkCatalog; /**< Input: The catalog of TraitDataSinks which the
TraitPaths refer to. */
// Other
size_t mNumDataElementsAddedToPayload; /**< Output: The number of items encoded in the payload. */
};
WEAVE_ERROR EncodeRequest(Context &aContext);
WEAVE_ERROR InsertInProgressUpdateItem(const TraitPath &aItem);
private:
/**
* The context used to encode the path of a DataElement.
*/
struct DataElementPathContext
{
DataElementPathContext()
: mProfileId(0), mResourceId(0), mInstanceId(0), mNumTags(0),
mTags(NULL), mSchemaVersionRange(NULL)
{ }
uint32_t mProfileId; /**< Profile ID of the data sink. */
ResourceIdentifier mResourceId; /**< Resource ID of the data sink; if 0 it is not encoded
and defaults to the resource ID of the publisher. */
uint64_t mInstanceId; /**< Instance ID of the data sink; if 0 it is not encoded
and defaults to the first instance of the trait in the publisher. */
uint32_t mNumTags; /**< Number of tags in the tags array mTags. */
uint64_t *mTags; /**< Array of tags to be encoded in the path. */
const SchemaVersionRange * mSchemaVersionRange; /**< Schema version range. */
};
/**
* The context used to encode the data of a DataElement.
*/
struct DataElementDataContext
{
DataElementDataContext() { memset(this, 0, sizeof(*this)); }
TraitPath mTraitPath; /**< The TraitPath to encode. */
DataVersion mUpdateRequiredVersion; /**< If the update is conditional, the version the update is based off. */
bool mForceMerge; /**< True if the property is a dictionary and should be encoded as a merge. */
TraitUpdatableDataSink *mDataSink; /**< DataSink the TraitPath refers to. */
const TraitSchemaEngine *mSchemaEngine; /**< The TraitSchemaEngine of the data sink. */
PropertyPathHandle mNextDictionaryElementPathHandle; /**< See @UpdateEncoder::Context */
};
WEAVE_ERROR EncodePreamble();
WEAVE_ERROR EncodeDataList(void);
WEAVE_ERROR EncodeDataElements();
WEAVE_ERROR EncodeDataElement();
static WEAVE_ERROR EncodeElementPath(const DataElementPathContext &aElementContext, TLV::TLVWriter &aWriter);
static WEAVE_ERROR EncodeElementData(DataElementDataContext &aElementContext, TLV::TLVWriter &aWriter);
WEAVE_ERROR EndUpdateRequest(void);
void Checkpoint(TLV::TLVWriter &aWriter) { aWriter = mWriter; }
void Rollback(TLV::TLVWriter &aWriter) { mWriter = aWriter; }
static void RemoveInProgressPrivateItemsAfter(TraitPathStore &aList, size_t aItemInProgress);
Context *mContext;
TLV::TLVWriter mWriter;
nl::Weave::TLV::TLVType mPayloadOuterContainerType, mDataListOuterContainerType, mDataElementOuterContainerType;
};
}; // namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
}; // namespace Profiles
}; // namespace Weave
}; // namespace nl
#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
#endif // _WEAVE_DATA_MANAGEMENT_UPDATE_ENCODER_CURRENT_H