* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef BOOST_SS_FRESH_BINARY_H
#define BOOST_SS_FRESH_BINARY_H
#include <iostream>
#include "binary/key/key.h"
#include "binary/value/value.h"
#include "boost/node_type.h"
#include "common/bss_def.h"
#include "value/value_type.h"
namespace ock {
namespace bss {
#pragma pack(1)
* The data structure of the key in the memory of the fresh table
*/
struct FreshIndexNode {
private:
uint32_t mKeyHashCode;
uint32_t mKeyNodeOffset;
uint32_t mValueNodeOffset;
uint32_t mNextIndexNodeOffset;
public:
* Key hash code.
* @return
*/
inline uint32_t KeyHashCode() const
{
return mKeyHashCode;
}
* Key node offset from segment start.
* @return
*/
inline uint32_t KeyNodeOffset() const
{
return mKeyNodeOffset;
}
* Value node offset from segment start.
* @return
*/
inline uint32_t ValueNodeOffset() const
{
return mValueNodeOffset;
}
* Next index node offset from segment start.
* @return
*/
inline uint32_t NextIndexNodeOffset() const
{
return mNextIndexNodeOffset;
}
};
struct FreshSglKeyData {
uint32_t mHashCode;
uint16_t mStateId;
uint8_t mKey[0];
};
using FreshPriKeyData = FreshSglKeyData;
struct FreshSecKeyData {
uint32_t mHashCode;
uint8_t mKey[0];
};
struct FreshKeyNode;
using FreshKeyNodePtr = FreshKeyNode *;
struct FreshKeyNode {
private:
uint32_t mKeyLen;
union {
* for single key.
*/
FreshSglKeyData mSglKey;
* for dual key.
*/
FreshPriKeyData mPriKey;
FreshSecKeyData mSecKey;
};
public:
static FreshKeyNodePtr FromBuffer(uint8_t *buffer)
{
return reinterpret_cast<FreshKeyNode *>(buffer);
}
* DUAL KEY BEGIN.
*/
* Primary key data length, exclude HashCode(4) and StateId(2)
* @return
*/
inline uint32_t PriKeyDataLen() const
{
return mKeyLen - NO_6;
}
* Primary key data
* @return
*/
inline const uint8_t *PriKeyData() const
{
return mPriKey.mKey;
}
* Primary key hash code, calculated by keyHashCode ^ NameSpaceHashCode(if it has name space), else it is the same
* with keyHashCode.
* @return
*/
inline uint32_t PriKeyHashCode() const
{
return mPriKey.mHashCode;
}
* Primary key state id, include table type and key group information.
* @return
*/
inline uint16_t PriKeyStateId() const
{
return mPriKey.mStateId;
}
* Key length exclude HashCode(4), the length of key data.
* @return
*/
inline uint32_t SecKeyDataLen() const
{
return mKeyLen - NO_4;
}
* Secondary key data
* @return
*/
inline const uint8_t *SecKeyData() const
{
return mSecKey.mKey;
}
* Secondary hash code, calculated by HashCode::Hash()
* keyHashCode.
* @return
*/
inline uint32_t SecKeyHashCode() const
{
return mSecKey.mHashCode;
}
* Equal lookup primary key
*/
inline bool Equal(const PriKeyNode &other) const
{
return (PriKeyStateId() == other.StateId() && (PriKeyHashCode() == other.HashCode()) &&
(PriKeyDataLen() == other.KeyLen()) && (memcmp(PriKeyData(), other.KeyData(), other.KeyLen()) == 0));
}
inline bool Equal(const SecKeyNode &other) const
{
return (SecKeyHashCode() == other.HashCode()) && (SecKeyDataLen() == other.KeyLen()) &&
(memcmp(SecKeyData(), other.KeyData(), other.KeyLen()) == 0);
}
* DUAL KEY END
*/
* SINGLE KEY BEGIN
*/
* Single key data length, exclude HashCode(4) and StateId(2)
* @return
*/
inline uint32_t SglKeyDataLen() const
{
return mKeyLen - NO_6;
}
* Single key data
* @return
*/
inline const uint8_t *SglKeyData() const
{
return mSglKey.mKey;
}
* Single key hash code, calculated by keyHashCode ^ NameSpaceHashCode(if it has name space), else it is the same
* with keyHashCode.
* @return
*/
inline uint32_t SglKeyHashCode() const
{
return mSglKey.mHashCode;
}
* Single key state id, include table type and key group information.
* @return
*/
inline uint16_t SglKeyStateId() const
{
return mSglKey.mStateId;
}
* SINGLE KEY END
*/
* To single key or primary key node.
* @param priKeyNode primary key node.
*/
inline void ToPriKeyNode(PriKeyNode &priKeyNode) const
{
priKeyNode.Init(PriKeyStateId(), PriKeyHashCode(), PriKeyData(), PriKeyDataLen());
}
* To secondary key.
* @param secKeyNode secondary key node.
*/
inline void ToSecKeyNode(SecKeyNode &secKeyNode) const
{
secKeyNode.Init(SecKeyHashCode(), SecKeyData(), SecKeyDataLen());
}
};
struct FreshValueNode;
using FreshValueNodePtr = FreshValueNode *;
struct FreshValueNode {
private:
uint32_t mValueLen;
NodeType mNodeType;
union {
uint8_t mBase[0];
struct {
uint64_t mSeqId;
ValueType mValueType;
uint8_t mValue[0];
} mValue;
struct {
uint32_t mIndexNodeSize;
uint32_t mBucketCount;
uint32_t mSectionIndexBase;
} mMap;
struct {
uint64_t mSeqId;
ValueType mValueType;
uint8_t mValue[0];
} mList;
};
public:
static FreshValueNodePtr FromBuffer(uint8_t *buffer)
{
return reinterpret_cast<FreshValueNode *>(buffer);
}
FreshValueNode() = default;
FreshValueNode(NodeType bType, uint32_t valLen, ValueType valType, uint64_t seqId)
: mValueLen(valLen), mNodeType(bType), mList{ seqId, valType, {} }
{
}
* Binary type, see @NodeType
* @return
*/
inline NodeType NodeType() const
{
return mNodeType;
}
* Value length, exclude GValueType and SeqId.
* @return
*/
inline uint32_t ValueDataLen() const
{
return mValueLen - NO_9;
}
* Value type, @ValueType
* @return
*/
inline ValueType ValueType() const
{
return mValue.mValueType;
}
* Value seq id, used for putting multiple times with the same key.
* @return
*/
inline uint64_t ValueSeqId() const
{
return mValue.mSeqId;
}
* Value data.
* @return
*/
inline const uint8_t *Value() const
{
return mValue.mValue;
}
inline const uint8_t *MapData() const
{
return mBase;
}
* Value data base address.
* @return
*/
inline const uint8_t *ValueDataBase() const
{
return mBase;
}
* @Visitor f 签名为:bool(FreshValueNode &),当停止遍历时返回false
*/
template <class VisitorF> void VisitAsList(const MemorySegment &freshSegment, VisitorF f)
{
bool continueVisit = true;
if (mNodeType == NodeType::SERIALIZED) {
continueVisit = f(*this);
return;
}
auto curNode = this;
while (continueVisit && curNode->mNodeType == NodeType::COMPOSITE) {
continueVisit = f(*curNode);
auto curPos = *reinterpret_cast<uint32_t *>(curNode->mBase + curNode->mValueLen);
curNode = FreshValueNode::FromBuffer(freshSegment.GetSegment() + curPos);
}
if (continueVisit && curNode->mNodeType == NodeType::SERIALIZED) {
f(*curNode);
}
}
inline std::string ToString() const
{
std::ostringstream oss;
oss << "ValueType: " << static_cast<int>(mValue.mValueType) << ", ValueLen: " << mValueLen
<< ", seqId: " << mValue.mSeqId << ", ValueData: [";
if (UNLIKELY(mValue.mValue != nullptr)) {
uint32_t printLen = std::min(NO_10, mValueLen);
for (uint32_t i = 0; i < printLen; i++) {
oss << std::hex << std::uppercase << std::setw(NO_2) << std::setfill('0')
<< static_cast<int>(mValue.mValue[i]);
}
} else {
oss << "null";
}
oss << "]";
return oss.str();
}
};
struct FreshNode {
private:
const FreshIndexNode *mIndexNode{ nullptr };
const FreshKeyNode *mKeyNode{ nullptr };
const FreshValueNode *mValueNode{ nullptr };
const FreshIndexNode *mNextIndexNode{ nullptr };
public:
* Unpack in-memory data into a data node data structure
* @param buffer memory data.
* @param offset memory start position offset
*/
FreshNode(const uint8_t *data, uint32_t offset)
{
mIndexNode = reinterpret_cast<const FreshIndexNode *>(data + offset);
mKeyNode = reinterpret_cast<const FreshKeyNode *>(data + mIndexNode->KeyNodeOffset());
mValueNode = reinterpret_cast<const FreshValueNode *>(data + mIndexNode->ValueNodeOffset());
mNextIndexNode = reinterpret_cast<const FreshIndexNode *>(data + mIndexNode->NextIndexNodeOffset());
}
* Get index node.
* @return
*/
inline const FreshIndexNode *IndexNode() const
{
return mIndexNode;
}
inline const FreshKeyNode *KeyNode() const
{
return mKeyNode;
}
inline const FreshValueNode *ValueNode() const
{
return mValueNode;
}
};
#pragma pack()
}
}
#endif