From 366b477052eadae35dc578e864d1961ca01a33c6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 18 Nov 2012 17:13:19 -0800 Subject: [PATCH] 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. --- src/cpp/ripple/FieldNames.cpp | 10 ++++- src/cpp/ripple/FieldNames.h | 22 ++++++++--- src/cpp/ripple/LedgerEntrySet.cpp | 63 ++++++++++++++++++------------- src/cpp/ripple/LedgerFormats.cpp | 1 + src/cpp/ripple/SerializeProto.h | 1 + 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/cpp/ripple/FieldNames.cpp b/src/cpp/ripple/FieldNames.cpp index d51adf8ad0..0d7617ae41 100644 --- a/src/cpp/ripple/FieldNames.cpp +++ b/src/cpp/ripple/FieldNames.cpp @@ -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(); diff --git a/src/cpp/ripple/FieldNames.h b/src/cpp/ripple/FieldNames.h index db118ad8b4..507a2bd7f3 100644 --- a/src/cpp/ripple/FieldNames.h +++ b/src/cpp/ripple/FieldNames.h @@ -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 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(); @@ -86,8 +96,10 @@ public: bool isBinary() const { return fieldValue < 256; } bool isDiscardable() const { return fieldValue > 256; } - bool isSigningField() const { return signingField; } - void notSigningField() { signingField = false; } + 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); } diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index ab40fb2de7..1ff883fb52 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -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::iterator it = newMod.begin(), end = newMod.end(); - it != end; ++it) - entryModify(it->second); + typedef std::pair 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(); } } diff --git a/src/cpp/ripple/LedgerFormats.cpp b/src/cpp/ripple/LedgerFormats.cpp index ea1240bc5c..5605cd0413 100644 --- a/src/cpp/ripple/LedgerFormats.cpp +++ b/src/cpp/ripple/LedgerFormats.cpp @@ -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) ; diff --git a/src/cpp/ripple/SerializeProto.h b/src/cpp/ripple/SerializeProto.h index 542451f1ae..8b5920f644 100644 --- a/src/cpp/ripple/SerializeProto.h +++ b/src/cpp/ripple/SerializeProto.h @@ -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)