| /* |
| * |
| * 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 |