From 2f3546f11a740e841efa307b131e3db85620552d Mon Sep 17 00:00:00 2001 From: Gavin Halliday Date: Wed, 20 Mar 2024 09:46:41 +0000 Subject: [PATCH] HPCC-31497 Improve error details if unexpected node type read from index Signed-off-by: Gavin Halliday --- system/jhtree/jhtree.cpp | 11 +++++++++-- system/jhtree/jhtree.hpp | 2 +- system/jhtree/jhtree.ipp | 7 +++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/system/jhtree/jhtree.cpp b/system/jhtree/jhtree.cpp index be4413d4356..084d0e9bff4 100644 --- a/system/jhtree/jhtree.cpp +++ b/system/jhtree/jhtree.cpp @@ -2441,7 +2441,7 @@ class CLazyKeyIndex : implements IKeyIndex, public CInterface virtual IKeyIndex *queryPart(unsigned idx) { return idx ? NULL : this; } virtual unsigned queryScans() { return realKey ? realKey->queryScans() : 0; } virtual unsigned querySeeks() { return realKey ? realKey->querySeeks() : 0; } - virtual const char *queryFileName() { return keyfile.get(); } + virtual const char *queryFileName() const { return keyfile.get(); } virtual offset_t queryBlobHead() { return checkOpen().queryBlobHead(); } virtual void resetCounts() { if (realKey) realKey->resetCounts(); } virtual offset_t queryLatestGetNodeOffset() const { return realKey ? realKey->queryLatestGetNodeOffset() : 0; } @@ -2659,7 +2659,14 @@ const CJHTreeNode *CNodeCache::getNode(const INodeLoader *keyIndex, unsigned iD, if (!ownedCacheEntry->isReady()) { const CJHTreeNode *node = keyIndex->loadNode(&fetchCycles, pos); - assertex(type == node->getNodeType()); + if (unlikely(type != node->getNodeType())) + { + //This should never happen, but if it does, report as much information as possible to diagnose the issue. + StringBuffer msg; + msg.appendf("Node type mismatch for node %s@%llx (expected %s, got %s)", keyIndex->queryFileName(), pos, cacheTypeText[type], cacheTypeText[node->getNodeType()]); + node->Release(); + throwUnexpectedX(msg); + } //Update the associated size of the entry in the hash table before setting isReady (never evicted until isReady is set) curCache.noteReady(*node); diff --git a/system/jhtree/jhtree.hpp b/system/jhtree/jhtree.hpp index d22531c3b70..8879696ef59 100644 --- a/system/jhtree/jhtree.hpp +++ b/system/jhtree/jhtree.hpp @@ -90,7 +90,7 @@ interface jhtree_decl IKeyIndex : public IKeyIndexBase virtual unsigned querySeeks() = 0; virtual size32_t keyedSize() = 0; virtual bool hasPayload() = 0; - virtual const char *queryFileName() = 0; + virtual const char *queryFileName() const = 0; virtual offset_t queryBlobHead() = 0; virtual void resetCounts() = 0; virtual offset_t queryLatestGetNodeOffset() const = 0; diff --git a/system/jhtree/jhtree.ipp b/system/jhtree/jhtree.ipp index 9280e967f40..93ae8013db7 100644 --- a/system/jhtree/jhtree.ipp +++ b/system/jhtree/jhtree.ipp @@ -78,6 +78,7 @@ interface INodeLoader virtual const CJHTreeNode *loadNode(cycle_t * fetchCycles, offset_t offset) const = 0; virtual const CJHSearchNode *locateFirstLeafNode(IContextLogger *ctx) const = 0; virtual const CJHSearchNode *locateLastLeafNode(IContextLogger *ctx) const = 0; + virtual const char *queryFileName() const = 0; }; class jhtree_decl CKeyIndex : implements IKeyIndex, implements INodeLoader, public CInterface @@ -161,6 +162,8 @@ public: virtual const CJHSearchNode *locateLastLeafNode(IContextLogger *ctx) const override; virtual void mergeStats(CRuntimeStatisticCollection & stats) const override {} + + virtual const char *queryFileName() const = 0; }; class jhtree_decl CMemKeyIndex : public CKeyIndex @@ -170,7 +173,7 @@ private: public: CMemKeyIndex(unsigned _iD, IMemoryMappedFile *_io, const char *_name, bool _isTLK); - virtual const char *queryFileName() { return name.get(); } + virtual const char *queryFileName() const { return name.get(); } virtual const IFileIO *queryFileIO() const override { return nullptr; } // INodeLoader impl. virtual const CJHTreeNode *loadNode(cycle_t * fetchCycles, offset_t offset) const override; @@ -186,7 +189,7 @@ private: public: CDiskKeyIndex(unsigned _iD, IFileIO *_io, const char *_name, bool _isTLK); - virtual const char *queryFileName() { return name.get(); } + virtual const char *queryFileName() const { return name.get(); } virtual const IFileIO *queryFileIO() const override { return io; } // INodeLoader impl. virtual const CJHTreeNode *loadNode(cycle_t * fetchCycles, offset_t offset) const override;