Metadata rework to make it possible to watch things like order books or

directories.

1) Some fields are never put in metadata, like Indexes, PreviousTxnID, and
others that are useless/redundant

2) Directory nodes now contain a RootIndex field so you can tell which
directory they're part of.

3) Some fields are always put in metdata, even if they don't change, like
RootIndex. So if a directory entry node is touched, you can tell what
directory it was part of.

Note that this change will cause ledger divergence. Also, existing directory
nodes will not be fully metadata indexed but newly-created nodes will be.
This commit is contained in:
JoelKatz
2012-11-18 17:13:19 -08:00
parent b9bdcceecf
commit 366b477052
5 changed files with 64 additions and 33 deletions

View File

@@ -28,8 +28,16 @@ SField sfIndex(STI_HASH256, 258, "index");
static int initFields()
{
sfTxnSignature.notSigningField(); sfTxnSignatures.notSigningField();
sfTxnSignature.notSigningField();
sfTxnSignatures.notSigningField();
sfSignature.notSigningField();
sfIndexes.setMeta(SField::sMD_Never);
sfPreviousTxnID.setMeta(SField::sMD_Never);
sfPreviousTxnLgrSeq.setMeta(SField::sMD_Never);
sfLedgerEntryType.setMeta(SField::sMD_Never);
sfRootIndex.setMeta(SField::sMD_Always);
return 0;
}
static const int f = initFields();

View File

@@ -40,6 +40,14 @@ public:
typedef const SField& ref;
typedef SField const * ptr;
static const int sMD_Never = 0x00;
static const int sMD_ChangeOrig = 0x01; // original value when it changes
static const int sMD_ChangeNew = 0x02; // new value when it changes
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
static const int sMD_Create = 0x08; // value when it's created
static const int sMD_Always = 0x10; // value when node containing it is affected at all
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal;
protected:
static std::map<int, ptr> codeToField;
static boost::mutex mapMutex;
@@ -52,23 +60,25 @@ public:
const SerializedTypeID fieldType; // STI_*
const int fieldValue; // Code number for protocol
std::string fieldName;
int fieldMeta;
bool signingField;
SField(int fc, SerializedTypeID tid, int fv, const char* fn) :
fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true)
fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), fieldMeta(sMD_Default), signingField(true)
{
boost::mutex::scoped_lock sl(mapMutex);
codeToField[fieldCode] = this;
}
SField(SerializedTypeID tid, int fv, const char *fn) :
fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true)
fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn),
fieldMeta(sMD_Default), signingField(true)
{
boost::mutex::scoped_lock sl(mapMutex);
codeToField[fieldCode] = this;
}
SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0) { ; }
SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0), fieldMeta(sMD_Never) { ; }
~SField();
@@ -88,6 +98,8 @@ public:
bool isSigningField() const { return signingField; }
void notSigningField() { signingField = false; }
bool shouldMeta(int c) const { return (fieldMeta & c) != 0; }
void setMeta(int c) { fieldMeta = c; }
bool shouldInclude(bool withSigningField) const
{ return (fieldValue < 256) && (withSigningField || signingField); }

View File

@@ -407,59 +407,66 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
mSet.setAffectedNode(it.first, *type, nodeType);
if (type == &sfDeletedNode)
{
{ // nodes was deleted
assert(origNode);
assert(curNode);
threadOwners(origNode, mLedger, newMod);
threadOwners(origNode, mLedger, newMod); // thread transaction to owners
STObject mods(sfPreviousFields);
STObject finals(sfFinalFields);
BOOST_FOREACH(const SerializedType& obj, *curNode)
{ // save non-default values
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType))
finals.addObject(obj);
}
if (!finals.empty())
mSet.getAffectedNode(it.first, *type).addObject(finals);
}
if ((type == &sfDeletedNode || type == &sfModifiedNode))
{
STObject mods(sfPreviousFields);
BOOST_FOREACH(const SerializedType& obj, *origNode)
{ // search the original node for values saved on modify
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType) && !curNode->hasMatchingEntry(obj))
if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj))
mods.addObject(obj);
if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_DeleteFinal))
finals.addObject(obj);
}
if (!mods.empty())
mSet.getAffectedNode(it.first, *type).addObject(mods);
if (!finals.empty())
mSet.getAffectedNode(it.first, *type).addObject(finals);
}
else if (type == &sfModifiedNode)
{
if (curNode->isThreadedType()) // thread transaction to node it modified
threadTx(curNode, mLedger, newMod);
if (type == &sfCreatedNode) // if created, thread to owner(s)
STObject mods(sfPreviousFields);
STObject finals(sfFinalFields);
BOOST_FOREACH(const SerializedType& obj, *origNode)
{ // search the original node for values saved on modify
if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj))
mods.addObject(obj);
if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_ChangeNew))
finals.addObject(obj);
}
if (!mods.empty())
mSet.getAffectedNode(it.first, *type).addObject(mods);
if (!finals.empty())
mSet.getAffectedNode(it.first, *type).addObject(finals);
}
else if (type == &sfCreatedNode) // if created, thread to owner(s)
{
assert(!origNode);
threadOwners(curNode, mLedger, newMod);
if (curNode->isThreadedType()) // always thread to self
threadTx(curNode, mLedger, newMod);
STObject news(sfNewFields);
BOOST_FOREACH(const SerializedType& obj, *curNode)
{ // save non-default values
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType))
if (!obj.isDefault() && obj.getFName().shouldMeta(SField::sMD_Create | SField::sMD_Always))
news.addObject(obj);
}
if (!news.empty())
mSet.getAffectedNode(it.first, *type).addObject(news);
}
if ((type == &sfCreatedNode) || (type == &sfModifiedNode))
{
if (curNode->isThreadedType()) // always thread to self
threadTx(curNode, mLedger, newMod);
}
}
// add any new modified nodes to the modification set
for (boost::unordered_map<uint256, SLE::pointer>::iterator it = newMod.begin(), end = newMod.end();
it != end; ++it)
entryModify(it->second);
typedef std::pair<const uint256, SLE::pointer> u256_sle_pair;
BOOST_FOREACH(u256_sle_pair& it, newMod)
entryModify(it.second);
mSet.addRaw(s, result);
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
@@ -483,6 +490,7 @@ TER LedgerEntrySet::dirAdd(
{
// No root, make it.
sleRoot = entryCreate(ltDIR_NODE, uRootIndex);
sleRoot->setFieldH256(sfRootIndex, uRootIndex);
sleNode = sleRoot;
uNodeDir = 0;
@@ -543,6 +551,7 @@ TER LedgerEntrySet::dirAdd(
// Create the new node.
sleNode = entryCreate(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
sleNode->setFieldH256(sfRootIndex, uRootIndex);
svIndexes = STVector256();
}
}

View File

@@ -47,6 +47,7 @@ static bool LEFInit()
DECLARE_LEF(DirectoryNode, ltDIR_NODE)
<< SOElement(sfIndexes, SOE_REQUIRED)
<< SOElement(sfRootIndex, SOE_REQUIRED)
<< SOElement(sfIndexNext, SOE_OPTIONAL)
<< SOElement(sfIndexPrevious, SOE_OPTIONAL)
;

View File

@@ -76,6 +76,7 @@
FIELD(PreviousTxnID, HASH256, 5)
FIELD(LedgerIndex, HASH256, 6)
FIELD(WalletLocator, HASH256, 7)
FIELD(RootIndex, HASH256, 8)
// 256-bit (uncommon)
FIELD(BookDirectory, HASH256, 16)