2025-08-10 01:34:16 +02:00

147 lines
4.4 KiB
C

#ifndef STRIPEPATTERN_H_
#define STRIPEPATTERN_H_
/**
* Note: Do not instantiate this "class" directly (it contains pure virtual functions)
*/
#include <common/Common.h>
#include <common/storage/StoragePoolId.h>
#include <common/toolkit/SerializationTypes.h>
#include <common/toolkit/vector/UInt16Vec.h>
// pattern types
#define STRIPEPATTERN_Invalid 0
#define STRIPEPATTERN_Raid0 1
#define STRIPEPATTERN_Raid10 2
#define STRIPEPATTERN_BuddyMirror 3
// minimum allowed stripe pattern chunk size (in bytes)
#define STRIPEPATTERN_MIN_CHUNKSIZE (1024*64)
// pattern serialization defs
#define STRIPEPATTERN_HEADER_LENGTH \
(sizeof(unsigned) + sizeof(unsigned) + sizeof(unsigned))
/* length + type + chunkSize*/
struct StripePatternHeader
{
// everything in this struct is in host byte order!
unsigned patternLength; // in bytes
unsigned patternType; // the type of pattern, defined as STRIPEPATTERN_x
unsigned chunkSize;
// storagePoolId is unused in the client at the moment; however we deserialize it to avoid human
// errors later
StoragePoolId storagePoolId;
};
struct StripePattern;
typedef struct StripePattern StripePattern;
static inline void StripePattern_initFromPatternType(StripePattern* this,
unsigned patternType, unsigned chunkSize);
extern void StripePattern_virtualDestruct(struct StripePattern* this);
extern bool StripePattern_deserializePatternPreprocess(DeserializeCtx* ctx,
const char** outPatternStart, uint32_t* outPatternLength);
extern bool __StripePattern_deserializeHeader(DeserializeCtx* ctx,
struct StripePatternHeader* outPatternHeader);
// static functions
extern StripePattern* StripePattern_createFromBuf(const char* patternStart,
uint32_t patternLength);
// virtual functions
extern UInt16Vec* StripePattern_getMirrorTargetIDs(StripePattern* this);
// getters & setters
static inline int StripePattern_getPatternType(StripePattern* this);
static inline unsigned StripePattern_getChunkSize(StripePattern* this);
static inline int64_t StripePattern_getChunkStart(StripePattern* this, int64_t pos);
static inline int64_t StripePattern_getNextChunkStart(StripePattern* this, int64_t pos);
static inline int64_t StripePattern_getChunkEnd(StripePattern* this, int64_t pos);
struct StripePattern
{
unsigned patternType; // STRIPEPATTERN_...
unsigned chunkSize; // must be a power of two (optimizations rely on it)
unsigned serialPatternLength; // for (de)serialization
// virtual functions
void (*uninit) (StripePattern* this);
// (de)serialization
bool (*deserializePattern) (StripePattern* this, DeserializeCtx* ctx);
size_t (*getStripeTargetIndex) (StripePattern* this, int64_t pos);
uint16_t (*getStripeTargetID) (StripePattern* this, int64_t pos);
void (*getStripeTargetIDsCopy) (StripePattern* this, UInt16Vec* outTargetIDs);
UInt16Vec* (*getStripeTargetIDs) (StripePattern* this);
UInt16Vec* (*getMirrorTargetIDs) (StripePattern* this);
unsigned (*getMinNumTargets) (StripePattern* this);
unsigned (*getDefaultNumTargets) (StripePattern* this);
};
void StripePattern_initFromPatternType(StripePattern* this, unsigned patternType,
unsigned chunkSize)
{
this->patternType = patternType;
this->chunkSize = chunkSize;
this->serialPatternLength = 0;
// pre-defined virtual methods
this->getMirrorTargetIDs = StripePattern_getMirrorTargetIDs;
}
int StripePattern_getPatternType(StripePattern* this)
{
return this->patternType;
}
unsigned StripePattern_getChunkSize(StripePattern* this)
{
return this->chunkSize;
}
int64_t StripePattern_getChunkStart(StripePattern* this, int64_t pos)
{
// the code below is an optimization (wrt division) for the following line:
// int64_t chunkStart = pos - (pos % this->chunkSize);
// "& chunkSize -1" instead of "%", because chunkSize is a power of two
unsigned posModChunkSize = pos & (this->chunkSize - 1);
int64_t chunkStart = pos - posModChunkSize;
return chunkStart;
}
/**
* Get the exact file position where the next chunk starts
*/
int64_t StripePattern_getNextChunkStart(StripePattern* this, int64_t pos)
{
return StripePattern_getChunkStart(this, pos) + this->chunkSize;
}
/**
* Get the exact file position where the current chunk ends
*/
int64_t StripePattern_getChunkEnd(StripePattern* this, int64_t pos)
{
return StripePattern_getNextChunkStart(this, pos) - 1;
}
#endif /*STRIPEPATTERN_H_*/