Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Bdd/Targets/FreeRtos/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ static volatile bool solidSyslogTeardown = false;
static const char STORE_PATH_PREFIX[] = "STORE";

static SolidSyslogFatFsFileStorage storeFileStorage;
static SolidSyslogBlockStoreStorage blockStoreStorage;

/* FATFS object lives in .bss because f_mount stores its address inside the
* FatFs volume registry — the object must outlive every f_open / f_stat /
Expand Down Expand Up @@ -604,7 +603,7 @@ static bool RebuildWithFileStore(void)
.OnThresholdCrossed = NULL,
.ThresholdContext = &pendingCapacityThreshold,
};
currentStore = SolidSyslogBlockStore_Create(&blockStoreStorage, &storeConfig);
currentStore = SolidSyslogBlockStore_Create(&storeConfig);
currentStoreIsFile = true;

solidSyslogConfig.Store = currentStore;
Expand Down
3 changes: 1 addition & 2 deletions Bdd/Targets/Linux/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,7 @@ static struct SolidSyslogStore* CreateStore(const struct BddTargetOptions* optio
storeConfig.OnThresholdCrossed = OnThresholdCrossed;
storeConfig.ThresholdContext = &capacityThreshold;

static SolidSyslogBlockStoreStorage storeStorage;
return SolidSyslogBlockStore_Create(&storeStorage, &storeConfig);
return SolidSyslogBlockStore_Create(&storeConfig);
}

return SolidSyslogNullStore_Get();
Expand Down
3 changes: 1 addition & 2 deletions Bdd/Targets/Windows/BddTargetWindows.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,7 @@ static struct SolidSyslogStore* CreateStore(const struct BddTargetWindowsOptions
storeConfig.OnThresholdCrossed = OnThresholdCrossed;
storeConfig.ThresholdContext = &capacityThreshold;

static SolidSyslogBlockStoreStorage storeStorage;
return SolidSyslogBlockStore_Create(&storeStorage, &storeConfig);
return SolidSyslogBlockStore_Create(&storeConfig);
}

return SolidSyslogNullStore_Get();
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ live under `Core/Interface/`; platform-specific helpers (the `SolidSyslogPosix*`
| `SolidSyslogNullBlockDevice.h` | Any code installing a no-op block device slot (every method returns `false` / `0` — disk doesn't exist) | `SolidSyslogNullBlockDevice_Get` |
| `SolidSyslogBlockDeviceDefinition.h` | BlockDevice implementors (extension point) | `SolidSyslogBlockDevice` vtable struct (`Acquire`, `Dispose`, `Exists`, `Read`, `Append`, `WriteAt`, `Size`) |
| `SolidSyslogFileBlockDevice.h` | System setup code wiring a file-backed block device | `SolidSyslogFileBlockDevice_Create(file, pathPrefix)` (sequence-numbered filenames `<prefix><NN>.log`, one cached file handle), `_Destroy(base)`. Instance struct lives in a library-internal static pool (E11); `_Destroy` takes the handle returned by `_Create`. Pool exhaustion resolves to the shared `SolidSyslogNullBlockDevice`. |
| `SolidSyslogBlockStore.h` | System setup code using a BlockDevice-backed store | `SolidSyslogBlockStoreStorage`, `SOLIDSYSLOG_BLOCKSTORE_STORAGE_SIZE`, `SolidSyslogBlockStoreConfig` (with `blockDevice`, `storeFullContext`, `getCapacityThreshold`, `onThresholdCrossed`, `thresholdContext`), `SolidSyslogBlockStore_Create(storage, config)`, `_Destroy(store)`, `SolidSyslogDiscardPolicy` (`SolidSyslogDiscardPolicy_Oldest` / `_Newest` / `_Halt`), `SolidSyslogStoreFullCallback(void* context)`, `SolidSyslogStoreThresholdFunction(void* context)` (returns threshold in bytes; 0 disables; queried each Write), `SolidSyslogStoreThresholdCallback(void* context)` (edge-triggered; PassthroughBuffer recursion gotcha — see header) |
| `SolidSyslogBlockStore.h` | System setup code using a BlockDevice-backed store | `SolidSyslogBlockStoreConfig` (with `blockDevice`, `storeFullContext`, `getCapacityThreshold`, `onThresholdCrossed`, `thresholdContext`), `SolidSyslogBlockStore_Create(config)`, `_Destroy(store)`, `SolidSyslogDiscardPolicy` (`SolidSyslogDiscardPolicy_Oldest` / `_Newest` / `_Halt`), `SolidSyslogStoreFullCallback(void* context)`, `SolidSyslogStoreThresholdFunction(void* context)` (returns threshold in bytes; 0 disables; queried each Write), `SolidSyslogStoreThresholdCallback(void* context)` (edge-triggered; PassthroughBuffer recursion gotcha — see header). Instance struct lives in a library-internal static pool (E11); each slot composes one inner RecordStore + BlockSequence drawn 1:1 from sibling pools sized off the same `SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE` tunable. Pool exhaustion (or either inner Create failing) resolves to the shared `SolidSyslogNullStore`. |
| `SolidSyslogSecurityPolicyDefinition.h` | SecurityPolicy implementors (extension point) | `SolidSyslogSecurityPolicy` vtable struct, `SOLIDSYSLOG_MAX_INTEGRITY_SIZE` |
| `SolidSyslogNullSecurityPolicy.h` | System setup code (no integrity checking) | `SolidSyslogNullSecurityPolicy_Get` |
| `SolidSyslogCrc16Policy.h` | System setup code using CRC-16 integrity | `SolidSyslogCrc16Policy_Create`, `_Destroy` |
Expand Down
20 changes: 2 additions & 18 deletions Core/Interface/SolidSyslogBlockStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
#define SOLIDSYSLOGBLOCKSTORE_H

#include <stddef.h>
#include <stdint.h>

#include "SolidSyslogSecurityPolicyDefinition.h"
#include "SolidSyslogTunables.h"
#include "ExternC.h"

struct SolidSyslogStore;

EXTERN_C_BEGIN

struct SolidSyslogBlockDevice;
struct SolidSyslogSecurityPolicy;

enum SolidSyslogDiscardPolicy
{
Expand Down Expand Up @@ -48,21 +46,7 @@ EXTERN_C_BEGIN
void* ThresholdContext;
};

enum
{
SOLIDSYSLOG_BLOCK_STORE_STORAGE_SIZE =
(sizeof(intptr_t) * 32U) + SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_MAX_INTEGRITY_SIZE + 16U
};

typedef struct
{
intptr_t slots[(SOLIDSYSLOG_BLOCK_STORE_STORAGE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)];
} SolidSyslogBlockStoreStorage;

struct SolidSyslogStore* SolidSyslogBlockStore_Create(
SolidSyslogBlockStoreStorage * storage,
const struct SolidSyslogBlockStoreConfig* config
);
struct SolidSyslogStore* SolidSyslogBlockStore_Create(const struct SolidSyslogBlockStoreConfig* config);
void SolidSyslogBlockStore_Destroy(struct SolidSyslogStore * base);

EXTERN_C_END
Expand Down
25 changes: 25 additions & 0 deletions Core/Interface/SolidSyslogTunablesDefaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,31 @@
#error "SOLIDSYSLOG_STREAM_SENDER_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogBlockStore instances the library's internal
* static pool can simultaneously hold. Sizes three pools 1:1 — the
* BlockStore slot itself, plus the TU-internal RecordStore and
* BlockSequence pools that each BlockStore composes. The 1:1
* invariant means a BlockStore slot is guaranteed a free RecordStore
* and BlockSequence on Create; if any inner Create returns its
* fallback under normal use, the BlockStore as a whole resolves to
* SolidSyslogNullStore.
*
* Default 1 — almost all integrators wire a single store-and-forward
* BlockStore. Bump via SOLIDSYSLOG_USER_TUNABLES_FILE if more than
* one is genuinely needed.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE 1U
#endif

#if SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE < 1
#error "SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogFileBlockDevice instances the library's internal
* static pool can simultaneously hold. Each instance carries the cached
Expand Down
19 changes: 17 additions & 2 deletions Core/Source/BlockSequence.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#include "BlockSequence.h"
#include "BlockSequencePrivate.h"

#include "SolidSyslogBlockDevice.h"
#include "SolidSyslogBlockStore.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

struct SolidSyslogBlockDevice;

enum
{
Expand Down Expand Up @@ -39,7 +46,7 @@ static inline size_t BlockSequence_ClampToRange(size_t value, size_t min, size_t
return result;
}

void BlockSequence_Init(struct BlockSequence* blockSequence, const struct BlockSequenceConfig* config)
void BlockSequence_Initialise(struct BlockSequence* blockSequence, const struct BlockSequenceConfig* config)
{
blockSequence->BlockDevice = config->BlockDevice;
blockSequence->MaxBlockSize = config->MaxBlockSize;
Expand All @@ -61,6 +68,14 @@ void BlockSequence_Init(struct BlockSequence* blockSequence, const struct BlockS
blockSequence->WriteBlockCorrupt = false;
}

void BlockSequence_Cleanup(struct BlockSequence* blockSequence)
{
/* No owned resources to release. The BlockDevice pointer is caller-owned
* (integrator-supplied via BlockSequenceConfig.BlockDevice); the next
* _Initialise overwrites every field, so clearing here would be churn. */
(void) blockSequence;
}

static bool BlockSequence_ScanForExistingBlocks(struct BlockSequence* blockSequence);
static inline void BlockSequence_NotifyThresholdCrossed(struct BlockSequence* blockSequence);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef SOLIDSYSLOG_BLOCKSEQUENCE_H
#define SOLIDSYSLOG_BLOCKSEQUENCE_H
#ifndef SOLIDSYSLOG_BLOCKSEQUENCEPRIVATE_H
#define SOLIDSYSLOG_BLOCKSEQUENCEPRIVATE_H

#include "SolidSyslogBlockStore.h"

Expand Down Expand Up @@ -44,7 +44,12 @@ struct BlockSequence
bool WriteBlockCorrupt;
};

void BlockSequence_Init(struct BlockSequence* blockSequence, const struct BlockSequenceConfig* config);
void BlockSequence_Initialise(struct BlockSequence* blockSequence, const struct BlockSequenceConfig* config);
void BlockSequence_Cleanup(struct BlockSequence* blockSequence);

struct BlockSequence* BlockSequence_Create(const struct BlockSequenceConfig* config);
void BlockSequence_Destroy(struct BlockSequence* blockSequence);

bool BlockSequence_Open(struct BlockSequence* blockSequence);

bool BlockSequence_PrepareForWrite(struct BlockSequence* blockSequence, size_t recordSize, bool* readBlockChanged);
Expand All @@ -65,4 +70,4 @@ bool BlockSequence_IsHalted(const struct BlockSequence* blockSequence);
size_t BlockSequence_TotalBytes(const struct BlockSequence* blockSequence);
size_t BlockSequence_UsedBytes(const struct BlockSequence* blockSequence);

#endif /* SOLIDSYSLOG_BLOCKSEQUENCE_H */
#endif /* SOLIDSYSLOG_BLOCKSEQUENCEPRIVATE_H */
60 changes: 60 additions & 0 deletions Core/Source/BlockSequenceStatic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <stdbool.h>
#include <stddef.h>

#include "BlockSequencePrivate.h"
#include "SolidSyslogPoolAllocator.h"
#include "SolidSyslogTunables.h"

static size_t BlockSequence_IndexFromHandle(const struct BlockSequence* blockSequence);
static void BlockSequence_CleanupAtIndex(size_t index, void* context);

static bool BlockSequence_InUse[SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE];
static struct BlockSequence BlockSequence_Pool[SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE];
static struct SolidSyslogPoolAllocator BlockSequence_Allocator = {
BlockSequence_InUse,
SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE
};

struct BlockSequence* BlockSequence_Create(const struct BlockSequenceConfig* config)
{
struct BlockSequence* result = NULL;
size_t index = SolidSyslogPoolAllocator_AcquireFirstFree(&BlockSequence_Allocator);
if (SolidSyslogPoolAllocator_IndexIsValid(&BlockSequence_Allocator, index))
{
BlockSequence_Initialise(&BlockSequence_Pool[index], config);
result = &BlockSequence_Pool[index];
}
return result;
}

void BlockSequence_Destroy(struct BlockSequence* blockSequence)
{
if (blockSequence != NULL)
{
size_t index = BlockSequence_IndexFromHandle(blockSequence);
if (SolidSyslogPoolAllocator_IndexIsValid(&BlockSequence_Allocator, index))
{
SolidSyslogPoolAllocator_FreeIfInUse(&BlockSequence_Allocator, index, BlockSequence_CleanupAtIndex, NULL);
}
}
}

static size_t BlockSequence_IndexFromHandle(const struct BlockSequence* blockSequence)
{
size_t result = SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE;
for (size_t poolIndex = 0; poolIndex < SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE; poolIndex++)
{
if (blockSequence == &BlockSequence_Pool[poolIndex])
{
result = poolIndex;
break;
}
}
return result;
}

static void BlockSequence_CleanupAtIndex(size_t index, void* context)
{
(void) context;
BlockSequence_Cleanup(&BlockSequence_Pool[index]);
}
3 changes: 3 additions & 0 deletions Core/Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ set(SOURCES
SolidSyslogOriginSdStatic.c
SolidSyslogFile.c
SolidSyslogBlockStore.c
SolidSyslogBlockStoreStatic.c
RecordStore.c
RecordStoreStatic.c
BlockSequence.c
BlockSequenceStatic.c
SolidSyslogBlockDevice.c
SolidSyslogFileBlockDevice.c
SolidSyslogFileBlockDeviceStatic.c
Expand Down
17 changes: 15 additions & 2 deletions Core/Source/RecordStore.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#include "RecordStore.h"
#include "RecordStorePrivate.h"

#include "SolidSyslogBlockDevice.h"
#include "SolidSyslogSecurityPolicyDefinition.h"
#include "SolidSyslogTunables.h"

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

struct SolidSyslogBlockDevice;

enum
{
MAGIC_SIZE = 2,
Expand Down Expand Up @@ -71,14 +76,22 @@ static inline size_t RecordStore_SentFlagOffset(
return RecordStore_IntegrityChecksumOffset(recordStart, dataLength) + recordStore->SecurityPolicy->IntegritySize;
}

void RecordStore_Init(struct RecordStore* recordStore, struct SolidSyslogSecurityPolicy* securityPolicy)
void RecordStore_Initialise(struct RecordStore* recordStore, struct SolidSyslogSecurityPolicy* securityPolicy)
{
recordStore->SecurityPolicy = securityPolicy;
recordStore->HasReadRecord = false;
recordStore->LastReadBlockIndex = 0;
recordStore->LastSentFlagOffset = 0;
}

void RecordStore_Cleanup(struct RecordStore* recordStore)
{
/* No owned resources to release. The next _Initialise overwrites every
* field, so leave the slot's bytes alone — clearing them would be
* write-then-overwrite churn. */
(void) recordStore;
}

size_t RecordStore_RecordSize(const struct RecordStore* recordStore, uint16_t dataLength)
{
return (size_t) MAGIC_SIZE + RECORD_LENGTH_SIZE + dataLength + recordStore->SecurityPolicy->IntegritySize +
Expand Down
12 changes: 8 additions & 4 deletions Core/Source/RecordStore.h → Core/Source/RecordStorePrivate.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef SOLIDSYSLOG_RECORDSTORE_H
#define SOLIDSYSLOG_RECORDSTORE_H
#ifndef SOLIDSYSLOG_RECORDSTOREPRIVATE_H
#define SOLIDSYSLOG_RECORDSTOREPRIVATE_H

#include "SolidSyslogSecurityPolicyDefinition.h"
#include "SolidSyslogTunables.h"
Expand All @@ -24,7 +24,11 @@ struct RecordStore
uint8_t Buffer[RECORD_BUFFER_SIZE];
};

void RecordStore_Init(struct RecordStore* recordStore, struct SolidSyslogSecurityPolicy* securityPolicy);
void RecordStore_Initialise(struct RecordStore* recordStore, struct SolidSyslogSecurityPolicy* securityPolicy);
void RecordStore_Cleanup(struct RecordStore* recordStore);

struct RecordStore* RecordStore_Create(struct SolidSyslogSecurityPolicy* securityPolicy);
void RecordStore_Destroy(struct RecordStore* recordStore);

size_t RecordStore_RecordSize(const struct RecordStore* recordStore, uint16_t dataLength);

Expand Down Expand Up @@ -62,4 +66,4 @@ size_t RecordStore_FindFirstUnsent(
bool* corrupt
);

#endif /* SOLIDSYSLOG_RECORDSTORE_H */
#endif /* SOLIDSYSLOG_RECORDSTOREPRIVATE_H */
59 changes: 59 additions & 0 deletions Core/Source/RecordStoreStatic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <stdbool.h>
#include <stddef.h>

#include "RecordStorePrivate.h"
#include "SolidSyslogPoolAllocator.h"
#include "SolidSyslogTunables.h"

struct SolidSyslogSecurityPolicy;

static size_t RecordStore_IndexFromHandle(const struct RecordStore* recordStore);
static void RecordStore_CleanupAtIndex(size_t index, void* context);

static bool RecordStore_InUse[SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE];
static struct RecordStore RecordStore_Pool[SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE];
static struct SolidSyslogPoolAllocator RecordStore_Allocator = {RecordStore_InUse, SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE};

struct RecordStore* RecordStore_Create(struct SolidSyslogSecurityPolicy* securityPolicy)
{
struct RecordStore* result = NULL;
size_t index = SolidSyslogPoolAllocator_AcquireFirstFree(&RecordStore_Allocator);
if (SolidSyslogPoolAllocator_IndexIsValid(&RecordStore_Allocator, index))
{
RecordStore_Initialise(&RecordStore_Pool[index], securityPolicy);
result = &RecordStore_Pool[index];
}
return result;
}

void RecordStore_Destroy(struct RecordStore* recordStore)
{
if (recordStore != NULL)
{
size_t index = RecordStore_IndexFromHandle(recordStore);
if (SolidSyslogPoolAllocator_IndexIsValid(&RecordStore_Allocator, index))
{
SolidSyslogPoolAllocator_FreeIfInUse(&RecordStore_Allocator, index, RecordStore_CleanupAtIndex, NULL);
}
}
}

static size_t RecordStore_IndexFromHandle(const struct RecordStore* recordStore)
{
size_t result = SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE;
for (size_t poolIndex = 0; poolIndex < SOLIDSYSLOG_BLOCK_STORE_POOL_SIZE; poolIndex++)
{
if (recordStore == &RecordStore_Pool[poolIndex])
{
result = poolIndex;
break;
}
}
return result;
}

static void RecordStore_CleanupAtIndex(size_t index, void* context)
{
(void) context;
RecordStore_Cleanup(&RecordStore_Pool[index]);
}
Loading
Loading