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

140 lines
3.5 KiB
C

#include <common/toolkit/Serialization.h>
#include "BuddyMirrorPattern.h"
#include "Raid0Pattern.h"
#include "Raid10Pattern.h"
#include "SimplePattern.h"
#include "StripePattern.h"
#define HAS_NO_POOL_FLAG (1 << 24)
/**
* Calls the virtual uninit method and kfrees the object.
*/
void StripePattern_virtualDestruct(StripePattern* this)
{
this->uninit(this);
kfree(this);
}
bool StripePattern_deserializePatternPreprocess(DeserializeCtx* ctx,
const char** outPatternStart, uint32_t* outPatternLength)
{
DeserializeCtx temp = *ctx;
if(!Serialization_deserializeUInt(&temp, outPatternLength))
return false;
*outPatternStart = ctx->data;
if (*outPatternLength > ctx->length)
return false;
ctx->data += *outPatternLength;
ctx->length -= *outPatternLength;
return true;
}
/**
* @return outPattern; outPattern->patternType is STRIPEPATTERN_Invalid on error
*/
StripePattern* StripePattern_createFromBuf(const char* patternStart,
uint32_t patternLength)
{
struct StripePatternHeader patternHeader;
StripePattern* pattern;
DeserializeCtx ctx = {
.data = patternStart,
.length = patternLength,
};
bool deserRes;
if (!__StripePattern_deserializeHeader(&ctx, &patternHeader))
return (StripePattern*)SimplePattern_construct(STRIPEPATTERN_Invalid, 0);
switch (patternHeader.patternType)
{
case STRIPEPATTERN_Raid0:
{
pattern = (StripePattern*)Raid0Pattern_constructFromChunkSize(patternHeader.chunkSize);
} break;
case STRIPEPATTERN_Raid10:
{
pattern = (StripePattern*)Raid10Pattern_constructFromChunkSize(patternHeader.chunkSize);
} break;
case STRIPEPATTERN_BuddyMirror:
{
pattern = (StripePattern*)BuddyMirrorPattern_constructFromChunkSize(
patternHeader.chunkSize);
} break;
default:
{
pattern = (StripePattern*)SimplePattern_construct(STRIPEPATTERN_Invalid, 0);
return pattern;
} break;
}
deserRes = pattern->deserializePattern(pattern, &ctx);
if(unlikely(!deserRes) )
{ // deserialization failed => discard half-initialized pattern and create new invalid pattern
StripePattern_virtualDestruct(pattern);
pattern = (StripePattern*)SimplePattern_construct(STRIPEPATTERN_Invalid, 0);
return pattern;
}
return pattern;
}
bool __StripePattern_deserializeHeader(DeserializeCtx* ctx,
struct StripePatternHeader* outPatternHeader)
{
// pattern length
if(!Serialization_deserializeUInt(ctx, &outPatternHeader->patternLength) )
return false;
// pattern type
if(!Serialization_deserializeUInt(ctx, &outPatternHeader->patternType) )
return false;
// chunkSize
if(!Serialization_deserializeUInt(ctx, &outPatternHeader->chunkSize) )
return false;
// storagePoolId
if (!(outPatternHeader->patternType & HAS_NO_POOL_FLAG)) {
if(!StoragePoolId_deserialize(ctx, &outPatternHeader->storagePoolId) )
return false;
}
outPatternHeader->patternType &= ~HAS_NO_POOL_FLAG;
// check length field
if(outPatternHeader->patternLength < STRIPEPATTERN_HEADER_LENGTH)
return false;
// check chunkSize
if(!outPatternHeader->chunkSize)
return false;
return true;
}
/**
* Predefined virtual method returning NULL. Will be overridden by StripePatterns (e.g. Raid10)
* that actually do have mirror targets.
*
* @return NULL for patterns that don't have mirror targets.
*/
UInt16Vec* StripePattern_getMirrorTargetIDs(StripePattern* this)
{
return NULL;
}