| /* |
| * |
| * 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 forms the crux of the TDM layer (trait data management), providing |
| * various classes that manage and process data as it applies to traits and their |
| * associated schemas. |
| * |
| */ |
| |
| |
| #ifndef _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H |
| #define _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H |
| |
| #include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h> |
| |
| #include <Weave/Core/WeaveCore.h> |
| #include <Weave/Core/WeaveMessageLayer.h> |
| #include <Weave/Profiles/ProfileCommon.h> |
| #include <Weave/Support/CodeUtils.h> |
| #include <Weave/Profiles/data-management/MessageDef.h> |
| |
| namespace nl { |
| namespace Weave { |
| namespace Profiles { |
| namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) { |
| |
| /* |
| * A PropertyPathHandle is a unique 32-bit numerical hash of a WDM path relative to the root of a trait instance. It has two parts to it: |
| * - A lower 16-bit number that maps to the static portion of the schema. |
| * - Where the lower 16-bits refer to a path within a dictionary element, an upper 16-bit number is present that represents the dictionary key associated with that element. |
| * If the lower 16-bits refer to a non dictionary element, then the upper 16-bits should be 0. |
| * |
| * Some characteristics: |
| * - Every trait has its own property path handle space. |
| * - Every unique WDM sub-path path will have a similarly unique PropertyPathHandle. |
| * - PropertyPathHandles are auto-generated (done by hand for now) by a trait compiler from IDL and is represented as an enumerant list in the corresponding trait's header file. |
| * - With this construct, application logic never has to deal with WDM paths directly. Rather, their interactions with WDM are conducted exclusively through these handles. |
| * - There are two reserved values for path handles that have specific meaning: |
| * - 0 indicates a 'NULL' handle |
| * - 1 indicates a handle that points to the root of the trait instance. |
| * |
| */ |
| typedef uint32_t PropertyPathHandle; |
| typedef uint16_t PropertySchemaHandle; |
| typedef uint16_t PropertyDictionaryKey; |
| |
| /* Reserved property path handles that have special meaning */ |
| enum { |
| kNullPropertyPathHandle = 0, |
| kRootPropertyPathHandle = 1 |
| }; |
| |
| inline PropertyPathHandle CreatePropertyPathHandle(PropertySchemaHandle aPropertyPathSchemaId, PropertyDictionaryKey aPropertyPathDictionaryKey = 0) { |
| return (((uint32_t)aPropertyPathDictionaryKey << 16) | aPropertyPathSchemaId); |
| } |
| |
| inline PropertySchemaHandle GetPropertySchemaHandle(PropertyPathHandle aHandle) { |
| return (aHandle & 0xffff); |
| } |
| |
| inline PropertyDictionaryKey GetPropertyDictionaryKey(PropertyPathHandle aHandle) { |
| return (aHandle >> 16); |
| } |
| |
| inline bool IsRootPropertyPathHandle(PropertyPathHandle aHandle) { |
| return (aHandle == kRootPropertyPathHandle); |
| } |
| |
| inline bool IsNullPropertyPathHandle(PropertyPathHandle aHandle) { |
| return (aHandle == kNullPropertyPathHandle); |
| } |
| |
| /* |
| * @class TraitSchemaEngine |
| * |
| * @brief The schema engine takes schema information associated with a particular trait and provides facilities to parse and translate that into a form usable by the WDM machinery. |
| * This includes converting from PathHandles to WDM paths (and vice versa), methods to interpret/query the schema itself and methods to help read/write out data to/from TLV given a handle. |
| * |
| * The schema itself is stored in tabular form, sufficiently described to allow for generic parsing/composition of WDM paths/data for any given trait. These tables are what will be the |
| * eventual output of 'code-gen' (The term itself being somewhat misleading given the absence of any generated code :P) |
| */ |
| class TraitSchemaEngine |
| { |
| public: |
| /* Provides information about a particular path handle including its parent property schema handle, |
| * its context tag and its name. |
| */ |
| struct PropertyInfo { |
| PropertySchemaHandle mParentHandle; |
| uint8_t mContextTag; |
| }; |
| |
| /** |
| * @brief |
| * The main schema structure that houses the schema information. |
| */ |
| struct Schema { |
| uint32_t mProfileId; //< The ID of the trait profile. |
| const PropertyInfo *mSchemaHandleTbl; //< A pointer to the schema handle table, which provides parent info and context tags for each schema handle. |
| uint32_t mNumSchemaHandleEntries; //< The number of schema handles in this trait. |
| uint32_t mTreeDepth; //< The max depth of this schema. |
| uint8_t *mIsDictionaryBitfield; //< A bitfield indicating whether each schema handle is a dictionary or not. |
| uint8_t *mIsOptionalBitfield; //< A bitfield indicating whether each schema handle is optional or not. |
| uint8_t *mIsImplementedBitfield; //< A bitfield indicating whether each optional schema handle is implemented or not. |
| uint8_t *mIsNullableBitfield; //< A bitfield indicating whether each schema handle is nullable or not. |
| uint8_t *mIsEphemeralBitfield; //< A bitfield indicating whether each schema handle is ephemeral or not. |
| }; |
| |
| /* While traits can have deep nested structures (which can include dictionaries), application logic is only expected to provide getters/setters for 'leaf' nodes in the schema. If one can visualize a |
| * schema as a tree (a directed graph where you can have at most one parent for any given node) where branches indicate the presence of a nested structure, then this analogy fits in quite nicely. |
| */ |
| class IDataSinkDelegate |
| { |
| public: |
| enum DataSinkEventType { |
| /* Start of replacement of an entire dictionary */ |
| kDataSinkEvent_DictionaryReplaceBegin, |
| |
| /* End of replacement of an entire dictionary */ |
| kDataSinkEvent_DictionaryReplaceEnd, |
| |
| /* Start of modification or addition of a dictionary item */ |
| kDataSinkEvent_DictionaryItemModifyBegin, |
| |
| /* End of modification or addition of a dictionary item */ |
| kDataSinkEvent_DictionaryItemModifyEnd, |
| }; |
| |
| /** |
| * Given a path handle to a leaf node and a TLV reader, set the leaf data in the callee. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Was unable to read out data from the reader. |
| */ |
| virtual WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) = 0; |
| |
| /** |
| * Given a path handle to a node, a TLV reader, and an indication |
| * of whether a null type was received, set the data in the callee. |
| * TDM will only call this function for handles that are nullable, |
| * optional, ephemeral, or leafs. If aHandle is a non-leaf node |
| * and is nullified, TDM will not call SetData for its children. |
| * |
| * @param[in] aHandle The PropertyPathHandle in question. |
| * |
| * @param[inout] aReader The TLV reader to read from. |
| * |
| * @param[out] aIsNull Is aHandle nullified? |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Was unable to read out data from the reader. |
| */ |
| virtual WEAVE_ERROR SetData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader &aReader, bool aIsNull) = 0; |
| |
| /** |
| * Signals to delegates when notable events occur while parsing dictionaries. In all cases, a property path handle is provided that provides more context on what this event applies to. |
| * |
| * For dictionary replace begin/ends, these handles are purely schema handles. |
| * For dictionary item added/modififed events, these handles are property path handles as they contain the dictionary key as well. |
| */ |
| virtual void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) = 0; |
| }; |
| |
| class IDataSourceDelegate |
| { |
| public: |
| /** |
| * Given a path handle to a leaf node and a TLV writer, get the data from the callee. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Was unable to retrieve data and write it into the writer. |
| */ |
| virtual WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) = 0; |
| |
| /** |
| * Given a path handle to a node, a TLV writer, and booleans indicating whether the |
| * value is null or not present, get the data from the trait source that will build a |
| * notify. If the path handle is not a leaf node, TDM will handle writing values to |
| * the writer (like opening containers, nullifying the struct, etc). If a non-leaf |
| * node is null or not present, TDM will not call GetData for its children. |
| * |
| * This function will only be called for handles that are nullable, optional, |
| * ephemeral, or leafs. The expectation is that any traits with handles that |
| * have those options enabled will implement appropriate logic to populate |
| * aIsNull and aIsPresent. |
| * |
| * @param[in] aHandle The PropertyPathHandle in question. |
| * |
| * @param[in] aTagToWrite The tag to write for the aHandle. |
| * |
| * @param[inout] aWriter The writer to write TLV elements to. |
| * |
| * @param[out] aIsNull Is aHandle nullified? If yes, TDM will write |
| * a null element. If aHandle is not a leaf, |
| * TDM will skip over its children. |
| * |
| * @param[out] aIsPresent Is aHandle present? If no and if aHandle |
| * is not a leaf, TDM will skip over the |
| * path and its children. |
| * |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Was unable to retrieve data and write it into the writer. |
| */ |
| virtual WEAVE_ERROR GetData(PropertyPathHandle aHandle, |
| uint64_t aTagToWrite, |
| nl::Weave::TLV::TLVWriter &aWriter, |
| bool &aIsNull, |
| bool &aIsPresent) = 0; |
| |
| #if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT |
| /** |
| * Given a handle to a particular dictionary and some context (that is usable by the delegate to track state between invocations), return |
| * the next dictionary item key. |
| * |
| * The context is initially set to 0 on the first call. There-after, the application is allowed to store any data |
| * (up to width of a pointer) within that variable and it will be passed in un-modified on successive invocations. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval #WEAVE_END_OF_INPUT if there are no more keys to iterate over in the dictionary. |
| * |
| */ |
| virtual WEAVE_ERROR GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey) = 0; |
| #endif |
| }; |
| |
| |
| /** |
| * Given a reader positioned at the root of a WDM path element, read out the relevant tags and provide |
| * the equivalent path handle. |
| * |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval #WEAVE_ERROR_TLV_TAG_NOT_FOUND If a matching handle could not be found due to a |
| * malformed/incorrectly specified path. |
| */ |
| WEAVE_ERROR MapPathToHandle(nl::Weave::TLV::TLVReader &aPathReader, PropertyPathHandle &aHandle) const; |
| |
| /** |
| * Convert the path handle to a TLV path. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Was unable to convert the handle to a TLV path |
| */ |
| WEAVE_ERROR MapHandleToPath(PropertyPathHandle aHandle, nl::Weave::TLV::TLVWriter &aPathWriter) const; |
| |
| /** |
| * Given a path handle and a reader positioned on the corresponding data element, process the data buffer pointed to by the reader and |
| * store it into the sink by invoking the SetLeafData call whenever a leaf data item is encountered. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Encountered errors parsing/processing the data. |
| */ |
| WEAVE_ERROR StoreData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader &aReader, IDataSinkDelegate *aDelegate) const; |
| |
| /** |
| * Given a path handle and a writer position on the corresponding data element, retrieve leaf data from the source and write it into the buffer |
| * pointed to by the writer in a schema compliant manner. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Encountered errors writing out the data. |
| */ |
| WEAVE_ERROR RetrieveData(PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter, IDataSourceDelegate *aDelegate) const; |
| |
| /********** |
| * |
| * Schema Query Functions |
| * |
| *********/ |
| |
| /* Offset from the value of a path that provides the index into the table for that handle |
| * It is 2 since the 0 and 1 are special handles. |
| */ |
| static const uint32_t kHandleTableOffset = 2; |
| |
| /* Returns the property path handle of the child of a parent given the parent handle and the child's context tag. |
| * If the parent happens to be in a dictionary, the key is preserved in the child. |
| */ |
| PropertyPathHandle GetChildHandle(PropertyPathHandle aParentHandle, uint8_t aContextTag) const; |
| |
| /* Returns the property path handle of the dictionary item given its parent dictionary handle and an item |
| * key. |
| */ |
| PropertyPathHandle GetDictionaryItemHandle(PropertyPathHandle aParentHandle, uint16_t aDictionaryKey) const; |
| |
| /** |
| * Returns true if the handle refers to a leaf node in the schema tree. |
| * |
| * @retval bool |
| */ |
| bool IsLeaf(PropertyPathHandle aPropertyHandle) const; |
| |
| /** |
| * Returns a pointer to the PropertyInfo structure describing a particular path handle. |
| * |
| * @retval PropertyInfo* |
| */ |
| const PropertyInfo *GetMap(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Returns the tag associated with a path handle. If it's a dictionary element, this function returns the ProfileTag. Otherwise, it returns |
| * context tags. |
| * |
| * @retval uint64_t |
| */ |
| uint64_t GetTag(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Returns the parent handle of a given child path handle. Dictionary keys in the handle are preserved in the case where the parent |
| * handle is also a dictionary element. |
| * |
| * @retval PropertyPathHandle Handle of the parent. |
| */ |
| PropertyPathHandle GetParent(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Returns the first child handle associated with a particular parent. |
| * |
| * @retval PropertyPathHandle Handle of the first child. |
| */ |
| PropertyPathHandle GetFirstChild(PropertyPathHandle aParentHandle) const; |
| |
| /** |
| * Given a handle to an existing child, returns the next child handle associated with a particular parent. |
| * |
| * @retval PropertyPathHandle Handle of the next child. |
| */ |
| PropertyPathHandle GetNextChild(PropertyPathHandle aParentId, PropertyPathHandle aChildHandle) const; |
| |
| /** |
| * Calculate the depth in the schema tree for a given handle. |
| * |
| * @retval int32_t The depth in the tree |
| */ |
| int32_t GetDepth(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Given two property handles, calculate the lowest handle that serves as a parent to both of these handles. Additionally, return the two child branches that contain each of the two handles (even |
| * if they are the same). |
| * |
| * @retval PropertyPathHandle Handle to the lowest parent. |
| */ |
| PropertyPathHandle FindLowestCommonAncestor(PropertyPathHandle aHandle1, PropertyPathHandle aHandle2, PropertyPathHandle *aHandle1BranchChild, PropertyPathHandle *aHandle2BranchChild) const; |
| |
| /** |
| * Returns true if the passed in profileId matches that stored in the schema. |
| * |
| * @retval bool |
| */ |
| bool MatchesProfileId(uint32_t aProfileId) const; |
| |
| /** |
| * Returns the profile id of the associated trait. |
| * |
| * @retval Trait profile id |
| */ |
| uint32_t GetProfileId(void) const; |
| |
| /** |
| * Returns true if the handle is a dictionary (and not in a dictionary - see method below). |
| * |
| * @retval bool |
| */ |
| bool IsDictionary(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Returns true if the handle is *inside* a dictionary (a dictionary element). A user passed in handle (aDictionaryItemHandle) is updated to |
| * point to the top-most dictionary element handle within the dictionary. |
| * |
| * @retval bool |
| */ |
| bool IsInDictionary(PropertyPathHandle aHandle, PropertyPathHandle &aDictionaryItemHandle) const; |
| |
| bool IsNullable(PropertyPathHandle aHandle) const; |
| bool IsEphemeral(PropertyPathHandle aHandle) const; |
| bool IsOptional(PropertyPathHandle aHandle) const; |
| |
| /** |
| * Checks if a given handle is a child of another handle. This can be an in-direct parent. |
| * |
| * @retval bool |
| */ |
| bool IsParent(PropertyPathHandle aChildHandle, PropertyPathHandle aParentHandle) const; |
| |
| /** |
| * Given a version range, this function checks to see if there is a compatibility intersection between that |
| * and what is supported by schema that is backing this schema engine. If there is an intersection, the function will |
| * return true and update the aIntersection argument passed in to reflect that results of that intersection test. |
| */ |
| bool GetVersionIntersection(SchemaVersionRange &aVersion, SchemaVersionRange &aIntersection) const; |
| |
| /** |
| * Given a provided data schema version, this will return the highest forward compatible schema version. |
| */ |
| SchemaVersion GetHighestForwardVersion(SchemaVersion aVersion) const; |
| |
| /** |
| * Given a provided data schema version, this will return the minimum compatible schema version |
| */ |
| SchemaVersion GetLowestCompatibleVersion(SchemaVersion aVersion) const; |
| |
| private: |
| PropertyPathHandle _GetChildHandle(PropertyPathHandle aParentHandle, uint8_t aContextTag) const; |
| bool GetBitFromPathHandleBitfield(uint8_t *aBitfield, PropertyPathHandle aPathHandle) const; |
| |
| public: |
| const Schema mSchema; |
| }; |
| |
| /* |
| * @class TraitDataSink |
| * |
| * @brief Base abstract class that represents a particular instance of a trait on a specific external resource (client). Application |
| * developers are expected to subclass this to make a concrete sink that ingests data received from publishers. |
| * |
| * It takes in a pointer to a schema that it then uses to help decipher incoming TLV data from a publisher and invoke the |
| * relevant data setter calls to pass the data up to subclasses. |
| */ |
| class TraitDataSink : private TraitSchemaEngine::IDataSinkDelegate |
| { |
| public: |
| TraitDataSink(const TraitSchemaEngine *aEngine); |
| const TraitSchemaEngine *GetSchemaEngine(void) const { return mSchemaEngine; } |
| |
| typedef WEAVE_ERROR (*OnChangeRejection)(uint16_t aRejectionStatusCode, uint64_t aVersion, void *aContext); |
| |
| enum ChangeFlags { |
| kFirstElementInChange = (1 << 0), |
| kLastElementInChange = (1 << 1) |
| }; |
| |
| /** |
| * Given a reader that points to a data element conformant to a schema bound to this object, this method processes that data and |
| * invokes the relevant SetLeafData call below for all leaf items in the buffer. |
| * |
| * A change rejection function can be passed in as well that will be invoked if the sink chooses to reject this data for any reason. |
| * |
| * @retval #WEAVE_NO_ERROR On success. |
| * @retval other Encountered errors writing out the data. |
| */ |
| WEAVE_ERROR StoreDataElement(PropertyPathHandle aHandle, TLV::TLVReader &aReader, uint8_t aFlags, OnChangeRejection aFunc, void *aContext); |
| |
| /** |
| * Retrieves the current version of the data that resides in this sink. |
| */ |
| uint64_t GetVersion(void) const { return mVersion; } |
| |
| /** |
| * Returns a boolean value that determines whether the version is valid. |
| */ |
| bool IsVersionValid(void) const { return mHasValidVersion; } |
| |
| /** |
| * Convenience function for data sinks to handle unknown leaf handles with |
| * a system level tolerance for mismatched schema as defined by |
| * TDM_DISABLE_STRICT_SCHEMA_COMPILANCE. |
| */ |
| WEAVE_ERROR HandleUnknownLeafHandle(void) |
| { |
| #if TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE |
| return WEAVE_NO_ERROR; |
| #else |
| return WEAVE_ERROR_TLV_TAG_NOT_FOUND; |
| #endif |
| } |
| |
| enum EventType { |
| /* Signals the beginning of a change record which in certain scenarios can span multiple data elements over multiple notifies |
| * (the latter only a possibility if the data being transmitted is unable to fit within a single packet) |
| */ |
| kEventChangeBegin, |
| |
| /* Start of a data element */ |
| kEventDataElementBegin, |
| |
| /* End of a data element */ |
| kEventDataElementEnd, |
| |
| /* End of a change record */ |
| kEventChangeEnd, |
| |
| /* Start of replacement of an entire dictionary */ |
| kEventDictionaryReplaceBegin, |
| |
| /* End of replacement of an entire dictionary */ |
| kEventDictionaryReplaceEnd, |
| |
| /* Start of modification or addition of a dictionary item */ |
| kEventDictionaryItemModifyBegin, |
| |
| /* End of modification or addition of a dictionary item */ |
| kEventDictionaryItemModifyEnd, |
| |
| /* Deletion of a dictionary item */ |
| kEventDictionaryItemDelete, |
| |
| /* Signals the start of the processing of a notify packet |
| */ |
| kEventNotifyRequestBegin, |
| |
| /* Signals the end of the processing of a notify packet |
| */ |
| kEventNotifyRequestEnd, |
| |
| /* Signals the start of the processing of a view response |
| * TODO: I'm not entirely convinced of the need to have this event. |
| */ |
| kEventViewResponseBegin, |
| |
| /* Signals the end of the processing of a view response |
| * TODO: I'm not entirely convinced of the need to have this event. |
| */ |
| kEventViewResponseEnd, |
| |
| /* Signals the termination of a subscription either due to an error, or the subscription was cancelled */ |
| kEventSubscriptionTerminated |
| }; |
| |
| union InEventParam { |
| struct { |
| PropertyPathHandle mTargetHandle; |
| } mDictionaryReplaceBegin; |
| |
| struct { |
| PropertyPathHandle mTargetHandle; |
| } mDictionaryReplaceEnd; |
| |
| struct { |
| PropertyPathHandle mTargetHandle; |
| } mDictionaryItemModifyBegin; |
| |
| struct { |
| PropertyPathHandle mTargetHandle; |
| } mDictionaryItemModifyEnd; |
| |
| struct { |
| PropertyPathHandle mTargetHandle; |
| } mDictionaryItemDelete; |
| }; |
| |
| /* |
| * Invoked either by the base class or by an external agent (like the subscription engine) to signal the occurence of an event (of type EventType). |
| * Sub-classes are expected to over-ride this if they desire to be made known of these events. |
| */ |
| virtual WEAVE_ERROR OnEvent(uint16_t aType, void *aInEventParam) { return WEAVE_NO_ERROR; } |
| |
| protected: // IDataSinkDelegate |
| virtual WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE = 0; |
| |
| /* |
| * Defaults to calling SetLeafData if aHandle is a leaf. DataSinks |
| * can optionally implement this if they need to support nullable, |
| * ephemeral, or optional properties. |
| * |
| * TODO: make this the defacto API, moving all the logic from |
| * SetLeafData into this function. |
| */ |
| virtual WEAVE_ERROR SetData(PropertyPathHandle aHandle, |
| nl::Weave::TLV::TLVReader &aReader, |
| bool aIsNull) __OVERRIDE; |
| |
| /* Subclass can invoke this if they desire to reject a particular data change */ |
| void RejectChange(uint16_t aRejectionStatusCode); |
| |
| /* Subclass can invoke this to clear out their version */ |
| void ClearVersion(void) { mHasValidVersion = false; } |
| |
| const TraitSchemaEngine *mSchemaEngine; |
| private: |
| void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) __OVERRIDE; |
| |
| uint64_t mVersion; |
| bool mHasValidVersion; |
| static OnChangeRejection sChangeRejectionCb; |
| static void *sChangeRejectionContext; |
| }; |
| |
| class Command; |
| |
| class TraitDataSource : private TraitSchemaEngine::IDataSourceDelegate |
| { |
| public: |
| TraitDataSource(const TraitSchemaEngine *aEngine); |
| const TraitSchemaEngine *GetSchemaEngine(void) const { return mSchemaEngine; } |
| |
| uint64_t GetVersion(void) const { return mVersion; } |
| |
| WEAVE_ERROR ReadData(PropertyPathHandle aHandle, uint64_t aTagToWrite, TLV::TLVWriter &aWriter); |
| |
| /* Interactions with the underlying data has to always be done within a locked context. This applies to both the app logic (e.g a publisher when modifying its source data) |
| * as well as to the core WDM logic (when trying to access that published data). This is required of both publishers and clients. |
| */ |
| WEAVE_ERROR Lock(void); |
| WEAVE_ERROR Unlock(void); |
| |
| void SetDirty(PropertyPathHandle aPropertyHandle); |
| |
| #if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT |
| void DeleteKey(PropertyPathHandle aPropertyHandle); |
| #endif |
| |
| virtual void OnCustomCommand(Command * aCommand, |
| const nl::Weave::WeaveMessageInfo * aMsgInfo, |
| nl::Weave::PacketBuffer * aPayload, |
| const uint64_t & aCommandType, |
| const bool aIsExpiryTimeValid, |
| const int64_t & aExpiryTimeMicroSecond, |
| const bool aIsMustBeVersionValid, |
| const uint64_t & aMustBeVersion, |
| nl::Weave::TLV::TLVReader & aArgumentReader); |
| |
| /* |
| * Invoked either by the base class or by an external agent (like the subscription engine) to signal the occurrence of an event (of type EventType). |
| * Sub-classes are expected to over-ride this if they desire to be made known of these events. |
| */ |
| virtual WEAVE_ERROR OnEvent(uint16_t aType, void *aInEventParam) { return WEAVE_NO_ERROR; } |
| |
| #if (WEAVE_CONFIG_WDM_PUBLISHER_GRAPH_SOLVER == IntermediateGraphSolver) |
| /* Set of functions to be called by the intermediate graph solver on the notification engine for marking/clearing this entire data source as dirty */ |
| void SetRootDirty(void) { mRootIsDirty = true; } |
| void ClearRootDirty(void) { mRootIsDirty = false; } |
| bool IsRootDirty(void) const { return mRootIsDirty; } |
| bool mRootIsDirty; |
| #endif |
| |
| protected: // IDataSourceDelegate |
| /* |
| * Defaults to calling GetLeafData if aHandle is a leaf. DataSources |
| * can optionally implement this if they need to support nullable, |
| * ephemeral, or optional properties. |
| * |
| * TODO: make this the defacto API, moving all the logic from |
| * GetLeafData into this function. |
| */ |
| virtual WEAVE_ERROR GetData(PropertyPathHandle aHandle, |
| uint64_t aTagToWrite, |
| nl::Weave::TLV::TLVWriter &aWriter, |
| bool &aIsNull, |
| bool &aIsPresent) __OVERRIDE; |
| |
| virtual WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE = 0 ; |
| |
| #if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT |
| virtual WEAVE_ERROR GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey) __OVERRIDE { return WEAVE_ERROR_INVALID_ARGUMENT; } |
| #endif |
| |
| void IncrementVersion(void) { mVersion++; } |
| uint64_t mVersion; |
| |
| // Controls whether mVersion is incremented automatically or not. |
| bool mManagedVersion; |
| |
| const TraitSchemaEngine *mSchemaEngine; |
| private: |
| |
| // Tracks whether SetDirty was called within a Lock/Unlock 'session' |
| bool mSetDirtyCalled; |
| }; |
| |
| }; // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) |
| }; // Profiles |
| }; // Weave |
| }; // nl |
| |
| #endif // _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H |