blob: c7b16e22d4b0a33ee134e963c0af0879a0e7a263 [file] [log] [blame]
/*
*
* Copyright (c) 2015-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
*
* @brief
* Management of the Weave Event Logging.
*
*/
#ifndef _WEAVE_DATA_MANAGEMENT_EVENT_LOGGING_MANAGEMENT_CURRENT_H
#define _WEAVE_DATA_MANAGEMENT_EVENT_LOGGING_MANAGEMENT_CURRENT_H
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Core/WeaveCircularTLVBuffer.h>
#if WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
#include <Weave/Profiles/time/WeaveTime.h>
#endif
#include <Weave/Support/PersistedCounter.h>
namespace nl {
namespace Weave {
namespace Profiles {
namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) {
/**
* @brief
* Internal event buffer, built around the #WeaveCircularTLVBuffer
*/
struct CircularEventBuffer
{
// for doxygen, see the CPP file
CircularEventBuffer(uint8_t *inBuffer, size_t inBufferLength, CircularEventBuffer *inPrev, CircularEventBuffer *inNext);
// for doxygen, see the CPP file
bool IsFinalDestinationForImportance(ImportanceType inImportance) const;
event_id_t VendEventID(void);
void RemoveEvent(void);
// for doxygen, see the CPP file
void AddEvent(timestamp_t inEventTimestamp);
#if WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
// for doxygen, see the CPP file
void AddEventUTC(utc_timestamp_t inEventTimestamp);
#endif
// for doxygen, see the CPP file
WEAVE_ERROR RegisterExternalEventsCallback(FetchExternalEventsFunct aFetchCallback, NotifyExternalEventsDeliveredFunct aNotifyCallback, size_t aNumEvents, ExternalEvents **aExternalEventsPtr);
// for doxygen, see the CPP file
void UnregisterExternalEventsCallback(ExternalEvents *ioPtr);
nl::Weave::TLV::WeaveCircularTLVBuffer mBuffer; //< The underlying TLV buffer storing the events in a TLV representation
CircularEventBuffer *mPrev; //< A pointer #CircularEventBuffer storing events less important events
CircularEventBuffer *mNext; //< A pointer #CircularEventBuffer storing events more important events
ImportanceType mImportance; //< The buffer is the final bucket for events of this importance. Events of lesser importance are dropped when they get bumped out of this buffer
event_id_t mFirstEventID; //< First event ID stored in the logging subsystem for this importance
event_id_t mLastEventID; //< Last event ID vended for this importance
timestamp_t mFirstEventTimestamp; //< The timestamp of the first event in this buffer
timestamp_t mLastEventTimestamp; //< The timestamp of the last event in this buffer
#if WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
utc_timestamp_t mFirstEventUTCTimestamp; //< The UTC timestamp of the first event in this buffer
utc_timestamp_t mLastEventUTCTimestamp; //< The UTC timestamp of the last event in this buffer
bool mUTCInitialized; //< Indicates whether UTC timestamps are initialized in this buffer
#endif
// The counter we're going to actually use.
nl::Weave::MonotonicallyIncreasingCounter *mEventIdCounter;
// The backup counter to use if no counter is provided for us.
nl::Weave::MonotonicallyIncreasingCounter mNonPersistedCounter;
#if WEAVE_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS
ExternalEvents mExternalEventsList[WEAVE_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS];
ExternalEvents *GetExternalEventsFromEventID(event_id_t aEventID);
ExternalEvents *GetNextAvailableExternalEvents(void);
#endif // WEAVE_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS
static WEAVE_ERROR GetNextBufferFunct(nl::Weave::TLV::TLVReader& ioReader, uintptr_t &inBufHandle, const uint8_t *&outBufStart, uint32_t &outBufLen);
};
/**
* @brief
* A TLVReader backed by CircularEventBuffer
*/
class CircularEventReader : public nl::Weave::TLV::TLVReader
{
friend struct CircularEventBuffer;
public:
void Init(CircularEventBuffer *inBuf);
};
/**
* @brief
* Internal structure for traversing event list.
*/
struct CopyAndAdjustDeltaTimeContext
{
CopyAndAdjustDeltaTimeContext(nl::Weave::TLV::TLVWriter *inWriter, EventLoadOutContext *inContext);
nl::Weave::TLV::TLVWriter *mWriter;
EventLoadOutContext *mContext;
};
/**
* @brief
* Internal structure for traversing events.
*/
struct EventEnvelopeContext
{
EventEnvelopeContext(void);
size_t mNumFieldsToRead;
int32_t mDeltaTime;
#if WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
int64_t mDeltaUtc;
#endif
ImportanceType mImportance;
};
enum LoggingManagementStates
{
kLoggingManagementState_Idle = 1, //< No log offload in progress, log offload can begin without any constraints
kLoggingManagementState_InProgress = 2, //< Log offload in progress
kLoggingManagementState_Holdoff = 3, //< Log offload has completed; we do not restart the log until the holdoff expires
kLoggingManagementState_Shutdown = 4 //< Not capable of performing any logging operation
};
// forward class declaration
class LogBDXUpload;
/**
* @brief
* A class for managing the in memory event logs.
*/
class LoggingManagement
{
friend class LogBDXUpload;
public:
LoggingManagement(nl::Weave::WeaveExchangeManager* inMgr,
size_t inNumBuffers, size_t *inBufferLengths, void **inBuffers,
nl::Weave::Platform::PersistedStorage::Key *inCounterKeys, const uint32_t *inCounterEpochs, nl::Weave::PersistedCounter **inCounterStorage);
LoggingManagement(nl::Weave::WeaveExchangeManager* inMgr,
size_t inNumBuffers, size_t *inBufferLengths, void **inBuffers,
nl::Weave::MonotonicallyIncreasingCounter **nWeaveCounter);
LoggingManagement(void);
static LoggingManagement &GetInstance(void);
static void CreateLoggingManagement(nl::Weave::WeaveExchangeManager *inMgr,
size_t inNumBuffers, size_t *inBufferLengths, void **inBuffers,
nl::Weave::Platform::PersistedStorage::Key *inCounterKeys, const uint32_t *inCounterEpochs, nl::Weave::PersistedCounter **inCounterStorage);
static void CreateLoggingManagement(nl::Weave::WeaveExchangeManager *inMgr,
size_t inNumBuffers, size_t *inBufferLengths, void **inBuffers,
nl::Weave::MonotonicallyIncreasingCounter **nWeaveCounter);
static void DestroyLoggingManagement(void);
WEAVE_ERROR SetExchangeManager(nl::Weave::WeaveExchangeManager *inMgr);
event_id_t LogEvent(const EventSchema &inSchema, EventWriterFunct inEventWriter, void *inAppData, const EventOptions *inOptions);
WEAVE_ERROR GetEventReader(nl::Weave::TLV::TLVReader &reader, ImportanceType inImportance);
WEAVE_ERROR FetchEventsSince(nl::Weave::TLV::TLVWriter &ioWriter, ImportanceType inImportance, event_id_t &ioEventID);
WEAVE_ERROR ScheduleFlushIfNeeded(bool inFlushRequested);
WEAVE_ERROR SetLoggingEndpoint(event_id_t *inEventEndpoints, size_t inNumImportanceLevels, size_t &outLoggingPosition);
uint32_t GetBytesWritten(void) const;
void NotifyEventsDelivered(ImportanceType inImportance, event_id_t inLastDeliveredEventID, uint64_t inRecipientNodeID) const;
/**
* @brief
* IsValid returns whether the LoggingManagement instance is valid
*
* @retval true if the instance is valid (initialized with the appropriate backing store)
* @retval false otherwise
*/
bool IsValid(void) { return (mEventBuffer != NULL); };
#if WEAVE_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS
bool IsEventExternal(ImportanceType inImportance, event_id_t inEventID) const;
event_id_t GetEndOfExternalEventRange(ImportanceType inImportance, event_id_t inEventID) const;
#endif // WEAVE_CONFIG_EVENT_LOGGING_NUM_EXTERNAL_CALLBACKS
event_id_t GetLastEventID(ImportanceType inImportance);
event_id_t GetFirstEventID(ImportanceType inImportance);
void ThrottleLogger(void);
void UnthrottleLogger(void);
void SetBDXUploader(LogBDXUpload *inUploader);
WEAVE_ERROR RegisterEventCallbackForImportance(ImportanceType inImportance, FetchExternalEventsFunct inFetchCallback, NotifyExternalEventsDeliveredFunct inNotifyCallback, size_t inNumEvents, ExternalEvents **aExternalEventsPtr);
WEAVE_ERROR RegisterEventCallbackForImportance(ImportanceType inImportance, FetchExternalEventsFunct inFetchCallback, size_t inNumEvents, ExternalEvents **aExternalEventsPtr);
void UnregisterEventCallbackForImportance(ImportanceType inImportance, ExternalEvents *inPtr);
WEAVE_ERROR BlitEvent(EventLoadOutContext *aContext,
const EventSchema &inSchema,
EventWriterFunct inEventWriter,
void *inAppData,
const EventOptions *inOptions);
#if WEAVE_CONFIG_EVENT_LOGGING_WDM_OFFLOAD
bool CheckShouldRunWDM(void);
#endif
private:
event_id_t LogEventPrivate(const EventSchema &inSchema, EventWriterFunct inEventWriter, void *inAppData, const EventOptions *inOptions);
void FlushHandler(System::Layer *inSystemLayer, INET_ERROR inErr);
void SignalUploadDone(void);
WEAVE_ERROR CopyToNextBuffer(CircularEventBuffer *inEventBuffer);
WEAVE_ERROR EnsureSpace(size_t inRequiredSpace);
static WEAVE_ERROR CopyEventsSince(const nl::Weave::TLV::TLVReader &aReader, size_t aDepth, void *aContext);
static WEAVE_ERROR FetchEventParameters(const nl::Weave::TLV::TLVReader &aReader, size_t aDepth, void *aContext);
static WEAVE_ERROR CopyAndAdjustDeltaTime(const nl::Weave::TLV::TLVReader &aReader, size_t aDepth, void *aContext);
static WEAVE_ERROR EvictEvent(nl::Weave::TLV::WeaveCircularTLVBuffer &inBuffer, void * inAppData, nl::Weave::TLV::TLVReader & inReader);
static WEAVE_ERROR AlwaysFail(nl::Weave::TLV::WeaveCircularTLVBuffer &inBuffer, void * inAppData, nl::Weave::TLV::TLVReader & inReader);
static WEAVE_ERROR CopyEvent(const nl::Weave::TLV::TLVReader & aReader, nl::Weave::TLV::TLVWriter & aWriter, EventLoadOutContext *aContext);
static void LoggingFlushHandler(System::Layer *systemLayer, void *appState, INET_ERROR err);
#if WEAVE_CONFIG_EVENT_LOGGING_BDX_OFFLOAD
bool CheckShouldRunBDX(void);
#endif
ImportanceType GetMaxImportance(void);
ImportanceType GetCurrentImportance(uint32_t profileId);
private:
CircularEventBuffer *GetImportanceBuffer(ImportanceType inImportance) const;
CircularEventBuffer *mEventBuffer;
WeaveExchangeManager *mExchangeMgr;
LoggingManagementStates mState;
LogBDXUpload *mBDXUploader;
uint32_t mBytesWritten;
uint32_t mThrottled;
ImportanceType mMaxImportanceBuffer;
bool mUploadRequested;
};
namespace Platform
{
extern void CriticalSectionEnter(void);
extern void CriticalSectionExit(void);
} // Platform
} // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
} // Profiles
} // Weave
} //nl
#endif //_WEAVE_DATA_MANAGEMENT_EVENT_LOGGING_MANAGEMENT_CURRENT_H