123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- #ifndef BACKEND_H
- #define BACKEND_H
- #include <open62541/plugin/historydata/history_data_backend.h>
- struct tupel {
- size_t index;
- UA_DataValue value;
- };
- // null terminated array
- struct context_randomindextest {
- // null terminated array
- struct tupel *tupels;
- size_t tupelSize;
- };
- static size_t
- indexByIndex_randomindextest(struct context_randomindextest *context, size_t index)
- {
- for (size_t i = 0; i < context->tupelSize; ++i) {
- if (context->tupels[i].index == index)
- return i;
- }
- return context->tupelSize;
- }
- // last value should be NULL, all values must be sorted
- static struct context_randomindextest*
- generateTestContext_randomindextest(const UA_DateTime *data) {
- size_t count = 0;
- while(data[count++]);
- struct context_randomindextest* ret = (struct context_randomindextest*)UA_calloc(1, sizeof(struct context_randomindextest));
- ret->tupels = (struct tupel*)UA_calloc(count, sizeof(struct tupel));
- ret->tupelSize = count;
- UA_DateTime *sortData;
- UA_StatusCode retval = UA_Array_copy(data, count, (void**)&sortData, &UA_TYPES[UA_TYPES_DATETIME]);
- if (retval != UA_STATUSCODE_GOOD)
- return NULL;
- for (size_t i = 0; i < count; ++i) {
- size_t current = 0;
- for (size_t j = 1; j < count-1; ++j){
- UA_DateTime currentDate = sortData[current];
- UA_DateTime jDate = sortData[j];
- if (currentDate > jDate) {
- current = j;
- }
- }
- UA_DateTime nextValue = i == count-1 ? 0 : sortData[current];
- sortData[current] = LLONG_MAX;
- bool unique;
- do {
- unique = true;
- ret->tupels[i].index = UA_UInt32_random();
- for (size_t j = 0; j < i; ++j)
- if (i != j && ret->tupels[i].index == ret->tupels[j].index)
- unique = false;
- } while (!unique);
- UA_DataValue_init(&ret->tupels[i].value);
- ret->tupels[i].value.hasValue = true;
- UA_Variant_setScalarCopy(&ret->tupels[i].value.value, &nextValue, &UA_TYPES[UA_TYPES_INT64]);
- ret->tupels[i].value.hasStatus = true;
- ret->tupels[i].value.status = UA_STATUSCODE_GOOD;
- ret->tupels[i].value.hasServerTimestamp = true;
- ret->tupels[i].value.serverTimestamp = nextValue;
- ret->tupels[i].value.hasSourceTimestamp = true;
- ret->tupels[i].value.sourceTimestamp = nextValue;
- }
- UA_free(sortData);
- return ret;
- }
- static void
- deleteMembers_randomindextest(UA_HistoryDataBackend *backend)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)backend->context;
- for (size_t i = 0; i < context->tupelSize; ++i) {
- UA_DataValue_deleteMembers(&context->tupels[i].value);
- }
- UA_free(context->tupels);
- UA_free(context);
- }
- static UA_StatusCode
- serverSetHistoryData_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- UA_Boolean historizing,
- const UA_DataValue *value)
- {
- // we do not add data to the test data
- return UA_STATUSCODE_GOOD;
- }
- static size_t
- getEnd_private(struct context_randomindextest* context)
- {
- return context->tupels[context->tupelSize-1].index;
- }
- static size_t
- getEnd_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- return getEnd_private(context);
- }
- static size_t
- lastIndex_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- return context->tupels[context->tupelSize-2].index;
- }
- static size_t
- firstIndex_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- return context->tupels[0].index;
- }
- static UA_Boolean
- search_randomindextest(struct context_randomindextest* ctx,
- const UA_DateTime timestamp,
- size_t *index) {
- for (size_t i = 0; i < ctx->tupelSize; ++i) {
- if (ctx->tupels[i].value.sourceTimestamp == timestamp) {
- *index = i;
- return true;
- }
- if (ctx->tupels[i].value.sourceTimestamp > timestamp) {
- *index = i;
- return false;
- }
- }
- *index = ctx->tupelSize-1;
- return false;
- }
- static size_t
- getDateTimeMatch_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- const UA_DateTime timestamp,
- const MatchStrategy strategy)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- size_t current;
- UA_Boolean retval = search_randomindextest(context, timestamp, ¤t);
- if ((strategy == MATCH_EQUAL
- || strategy == MATCH_EQUAL_OR_AFTER
- || strategy == MATCH_EQUAL_OR_BEFORE)
- && retval)
- return context->tupels[current].index;
- switch (strategy) {
- case MATCH_AFTER:
- if (retval)
- return context->tupels[current+1].index;
- return context->tupels[current].index;
- case MATCH_EQUAL_OR_AFTER:
- return context->tupels[current].index;
- case MATCH_EQUAL_OR_BEFORE:
- // retval == true aka "equal" is handled before
- // Fall through if !retval
- case MATCH_BEFORE:
- if (current > 0)
- return context->tupels[current-1].index;
- else
- return context->tupels[context->tupelSize-1].index;
- default:
- break;
- }
- return context->tupels[context->tupelSize-1].index;
- }
- #define MYABSSUB(a,b) ((a)<(b)?((b)-(a)):(a)-(b))
- static size_t
- resultSize_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- size_t startIndex,
- size_t endIndex)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- if (startIndex == getEnd_private(context)
- || endIndex == getEnd_private(context))
- return 0;
- size_t realEndIndex = indexByIndex_randomindextest(context, endIndex);
- size_t realStartIndex = indexByIndex_randomindextest(context, startIndex);
- size_t result = MYABSSUB(realEndIndex,realStartIndex);
- return result+1;
- }
- static UA_StatusCode
- copyDataValues_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- size_t startIndex,
- size_t endIndex,
- UA_Boolean reverse,
- size_t maxValues,
- UA_NumericRange range,
- UA_Boolean releaseContinuationPoints,
- const UA_ByteString *continuationPoint,
- UA_ByteString *outContinuationPoint,
- size_t *providedValues,
- UA_DataValue *values)
- {
- size_t skip = 0;
- if (continuationPoint->length > 0) {
- if (continuationPoint->length == sizeof(size_t)) {
- skip = *((size_t*)(continuationPoint->data));
- } else {
- return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
- }
- }
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- size_t index = indexByIndex_randomindextest(context,startIndex);
- size_t counter = 0;
- size_t skipedValues = 0;
- if (reverse) {
- while (index >= indexByIndex_randomindextest(context,endIndex)
- && index < context->tupelSize-1
- && counter < maxValues) {
- if (skipedValues++ >= skip) {
- UA_DataValue_copy(&context->tupels[index].value, &values[counter]);
- ++counter;
- }
- --index;
- }
- } else {
- while (index <= indexByIndex_randomindextest(context,endIndex) && counter < maxValues) {
- if (skipedValues++ >= skip) {
- UA_DataValue_copy(&context->tupels[index].value, &values[counter]);
- ++counter;
- }
- ++index;
- }
- }
- if (providedValues)
- *providedValues = counter;
- if ((!reverse && (indexByIndex_randomindextest(context,endIndex)-indexByIndex_randomindextest(context,startIndex)-skip+1) > counter)
- || (reverse && (indexByIndex_randomindextest(context,startIndex)-indexByIndex_randomindextest(context,endIndex)-skip+1) > counter)) {
- outContinuationPoint->length = sizeof(size_t);
- size_t t = sizeof(size_t);
- outContinuationPoint->data = (UA_Byte*)UA_malloc(t);
- *((size_t*)(outContinuationPoint->data)) = skip + counter;
- }
- return UA_STATUSCODE_GOOD;
- }
- static const UA_DataValue*
- getDataValue_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- size_t index)
- {
- struct context_randomindextest* context = (struct context_randomindextest*)hdbContext;
- size_t realIndex = indexByIndex_randomindextest(context, index);
- return &context->tupels[realIndex].value;
- }
- static UA_Boolean
- boundSupported_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId)
- {
- return true;
- }
- static UA_Boolean
- timestampsToReturnSupported_randomindextest(UA_Server *server,
- void *hdbContext,
- const UA_NodeId *sessionId,
- void *sessionContext,
- const UA_NodeId *nodeId,
- const UA_TimestampsToReturn timestampsToReturn)
- {
- return true;
- }
- UA_HistoryDataBackend
- UA_HistoryDataBackend_randomindextest(UA_DateTime *data);
- UA_HistoryDataBackend
- UA_HistoryDataBackend_randomindextest(UA_DateTime *data)
- {
- UA_HistoryDataBackend result;
- memset(&result, 0, sizeof(UA_HistoryDataBackend));
- result.serverSetHistoryData = &serverSetHistoryData_randomindextest;
- result.resultSize = &resultSize_randomindextest;
- result.getEnd = &getEnd_randomindextest;
- result.lastIndex = &lastIndex_randomindextest;
- result.firstIndex = &firstIndex_randomindextest;
- result.getDateTimeMatch = &getDateTimeMatch_randomindextest;
- result.copyDataValues = ©DataValues_randomindextest;
- result.getDataValue = &getDataValue_randomindextest;
- result.boundSupported = &boundSupported_randomindextest;
- result.timestampsToReturnSupported = ×tampsToReturnSupported_randomindextest;
- result.deleteMembers = &deleteMembers_randomindextest;
- result.getHistoryData = NULL;
- result.context = generateTestContext_randomindextest(data);
- return result;
- }
- void
- UA_HistoryDataBackend_randomindextest_deleteMembers(UA_HistoryDataBackend *backend);
- void
- UA_HistoryDataBackend_randomindextest_deleteMembers(UA_HistoryDataBackend *backend)
- {
- deleteMembers_randomindextest(backend);
- }
- #endif // BACKEND_H
|