Reload from memory example of using 51Degrees device detection.This example shows how to:
This example illustrates how to use a single reference to the resource manager to use device detection and invoke the reload functionality instead of maintaining a reference to the dataset directly.
Important** : unlike the reload from file example you need to decide if the 51Degrees API should dispose of the allocated memory when the resources are deallocated or if you wish to retain the allocated memory for later use. To instruct the API to free the continuous memory space set the fiftyoneDegreesConfigBase.freeMemory option to true.
Please keep in mind that even if the current dataset was constructed with all available properties this does not guarantee that the new dataset will be initialized with the same set of properties. If the new data file contains properties that were not part of the original data file, the new extra property(ies) will not be initialized. If the new data file does not contain one or more property that were previously available, then these property(ies) will not be initialized.
Each successful data file reload should be accompanied by the integrity check to verify that the properties you want have indeed been loaded. This can be achieved by simply comparing the number of properties before and after the reload as the number can not go up but it can go down.
The reload functionality works both with the single threaded as well as the multi threaded modes. To try the reload functionality in single threaded mode build with FIFTYONE_DEGREES_NO_THREADING defined. Or build without FIFTYONE_DEGREES_NO_THREADING for multi threaded example.
In a single threaded environment the reload function is executed as part of the normal flow of the program execution and will prevent any other actions until the reload is complete. The reload itself takes less than half a second even for Enterprise dataset. For more information see: https://51degrees.com/Support/Documentation/APIs/C-V32/Benchmarks
#include <stdio.h>
#include <stdlib.h>
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 5105)
#include <windows.h>
#pragma warning (default: 5105)
#pragma warning (pop)
#else
#include <unistd.h>
#endif
#include "ExampleBase.h"
#include "../../../src/common-cxx/textfile.h"
#include "../../../src/hash/hash.h"
#include "../../../src/hash/fiftyone.h"
#define THREAD_COUNT 4
static const char *dataDir = "device-detection-data";
static const char *dataFileName = "51Degrees-LiteV4.1.hash";
static const char *userAgentFileName = "20000 User Agents.csv";
#define CONFIG fiftyoneDegreesHashInMemoryConfig
typedef struct shared_state_t {
const char *userAgentFilePath;
volatile long threadsFinished;
typedef struct thread_state_t {
int hashCode;
static unsigned long generateHash(unsigned char* value) {
unsigned long hashCode = 5381;
while (*value != '\0') {
hashCode = ((hashCode << 5) + hashCode) + (unsigned long)*value;
value++;
}
return hashCode;
}
static unsigned long getHashCode(
ResultsHash *results) {
unsigned long hashCode = 0;
uint32_t requiredPropertyIndex;
const char* valueName;
for (requiredPropertyIndex = 0;
requiredPropertyIndex++) {
results,
requiredPropertyIndex,
exception) == true) {
results,
requiredPropertyIndex,
exception);
hashCode ^= generateHash((unsigned char*)(valueName));
}
}
return hashCode;
}
static void executeTest(const char *userAgent, void *state) {
1,
0);
"User-Agent",
userAgent);
thread->
hashCode ^= getHashCode(results);
}
char userAgent[500] = "";
userAgent,
sizeof(userAgent),
&thread,
executeTest);
printf(
"Finished with hashcode '%i'\r\n", thread.
hashCode);
}
static void runRequestsMulti(void *state) {
runRequestsSingle(shared);
}
int thread;
for (thread = 0; thread < THREAD_COUNT; thread++) {
state);
}
}
int thread;
for (thread = 0; thread < THREAD_COUNT; thread++) {
}
}
static void reportStatus(
const char* fileName) {
printf("%s\n", message);
}
static void run(
const char *userAgentFilePath,
int numberOfReloads = 0;
int numberOfReloadFails = 0;
printf("** Multi Threaded Reload Example **\r\n");
startThreads(&state);
manager,
exception);
numberOfReloads++;
}
else {
numberOfReloadFails++;
}
#ifdef _MSC_VER
Sleep(50);
#else
usleep(500000);
#endif
}
joinThreads(&state);
}
else {
printf("** Single Threaded Reload Example **\r\n");
runRequestsSingle(&state);
manager,
exception);
numberOfReloads++;
}
else {
numberOfReloadFails++;
}
runRequestsSingle(&state);
}
printf("Reloaded '%i' times.\r\n", numberOfReloads);
printf("Failed to reload '%i' times.\r\n", numberOfReloadFails);
printf("Program execution complete. Press Return to exit.");
}
void fiftyoneDegreesHashReloadFromMemoryRun(
const char *dataFilePath,
const char *userAgentFilePath,
const char *requiredProperties,
reportStatus(status, dataFilePath);
return;
}
reqProps.
string = requiredProperties;
&manager,
&config,
&reqProps,
exception);
reportStatus(status, dataFilePath);
}
else {
run(&manager, userAgentFilePath, &reader);
}
}
void fiftyoneDegreesExampleCReloadFromMemoryRun(ExampleParameters *params) {
fiftyoneDegreesHashReloadFromMemoryRun(
params->dataFilePath,
params->evidenceFilePath,
params->propertiesString,
*params->config);
}
#ifndef TEST
int main(int argc, char* argv[]) {
if (argc > 1) {
strcpy(dataFilePath, argv[1]);
}
else {
dataDir,
dataFileName,
dataFilePath,
sizeof(dataFilePath));
}
reportStatus(status, dataFileName);
fgetc(stdin);
return 1;
}
if (argc > 2) {
strcpy(userAgentFilePath, argv[2]);
}
else {
dataDir,
userAgentFileName,
userAgentFilePath,
sizeof(userAgentFilePath));
}
reportStatus(status, userAgentFilePath);
fgetc(stdin);
return 1;
}
ExampleParameters params;
params.dataFilePath = dataFilePath;
params.evidenceFilePath = userAgentFilePath;
params.propertiesString =
argc > 3 ? argv[3] : "IsMobile,BrowserName,DeviceType";
params.config = &config;
fiftyoneDegreesExampleMemCheck(
¶ms,
fiftyoneDegreesExampleCReloadFromMemoryRun);
fgetc(stdin);
return 0;
}
#endif