소스 검색

Merge pull request #9688 from jakesmith/hpcc-17192

HPCC-17192 Refactor PTree to have atom and non-atom versions

Reviewed-By: Gavin Halliday <gavin.halliday@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 8 년 전
부모
커밋
b6a5c5a529
7개의 변경된 파일681개의 추가작업 그리고 693개의 파일을 삭제
  1. 12 12
      dali/base/dacsds.cpp
  2. 45 44
      dali/base/dacsds.ipp
  3. 3 3
      dali/base/dasds.cpp
  4. 8 15
      dali/base/dasds.ipp
  5. 321 435
      system/jlib/jptree.cpp
  6. 280 179
      system/jlib/jptree.ipp
  7. 12 5
      system/jlib/jsuperhash.hpp

+ 12 - 12
dali/base/dacsds.cpp

@@ -756,7 +756,7 @@ IPropertyTree *CClientRemoteTree::ownPTree(IPropertyTree *tree)
         return tree;
     }
     else
-        return PTree::ownPTree(tree);
+        return PARENT::ownPTree(tree);
 }
 
 IPropertyTree *CClientRemoteTree::create(const char *name, IPTArrayValue *value, ChildMap *children, bool existing)
@@ -797,7 +797,7 @@ void CClientRemoteTree::setLocal(size32_t size, const void *data, bool _binary)
 {
     clearState(CPS_PropAppend);
     mergeState(CPS_Changed);
-    PTree::setLocal(size, data, _binary);
+    PARENT::setLocal(size, data, _binary);
 }
 
 void CClientRemoteTree::appendLocal(size32_t size, const void *data, bool binary)
@@ -807,7 +807,7 @@ void CClientRemoteTree::appendLocal(size32_t size, const void *data, bool binary
     {
         if (0 != (CPS_PropAppend & state))
         {
-            PTree::appendLocal(size, data, binary);
+            PARENT::appendLocal(size, data, binary);
             return;
         }
         else if (0 == (CPS_Changed & state))
@@ -820,7 +820,7 @@ void CClientRemoteTree::appendLocal(size32_t size, const void *data, bool binary
                 {
                     mergeState(CPS_PropAppend);
                     registerPropAppend(sz);
-                    PTree::appendLocal(size, data, binary);
+                    PARENT::appendLocal(size, data, binary);
                     return;
                 }
             }
@@ -830,14 +830,14 @@ void CClientRemoteTree::appendLocal(size32_t size, const void *data, bool binary
                 {
                     mergeState(CPS_PropAppend);
                     registerPropAppend(0); // whole value on commit to be sent for external append.
-                    PTree::appendLocal(size, data, binary);
+                    PARENT::appendLocal(size, data, binary);
                     return;
                 }
             }
         }
     }
     mergeState(CPS_Changed);
-    PTree::appendLocal(size, data, binary);
+    PARENT::appendLocal(size, data, binary);
 }
 
 void CClientRemoteTree::addingNewElement(IPropertyTree &child, int pos)
@@ -847,26 +847,26 @@ void CClientRemoteTree::addingNewElement(IPropertyTree &child, int pos)
     if (pos >= 0)
         ((CRemoteTreeBase &)child).mergeState(CPS_InsPos);
 #endif
-    PTree::addingNewElement(child, pos);
+    PARENT::addingNewElement(child, pos);
 }
 
 void CClientRemoteTree::removingElement(IPropertyTree *tree, unsigned pos)
 {
     CRemoteTreeBase *child = QUERYINTERFACE(tree, CRemoteTreeBase); assertex(child);
     registerDeleted(child->queryName(), pos, child->queryServerId());
-    PTree::removingElement(tree, pos);
+    PARENT::removingElement(tree, pos);
 }
 
-void CClientRemoteTree::setAttr(const char *attr, const char *val)
+void CClientRemoteTree::setAttribute(const char *attr, const char *val)
 {
-    PTree::setAttr(attr, val);
+    PARENT::setAttribute(attr, val);
     mergeState(CPS_AttrChanges);
     registerAttrChange(attr);
 }
 
-bool CClientRemoteTree::removeAttr(const char *attr)
+bool CClientRemoteTree::removeAttribute(const char *attr)
 {
-    if (PTree::removeAttr(attr))
+    if (PARENT::removeAttribute(attr))
     {
         registerDeletedAttr(attr);
         return true;

+ 45 - 44
dali/base/dacsds.ipp

@@ -287,6 +287,8 @@ public:
 ////////////////////
 class CClientRemoteTree : implements ITrackChanges, public CRemoteTreeBase
 {
+    typedef CRemoteTreeBase PARENT;
+
     DECL_NAMEDCOUNT;
     IPropertyTree *_queryBranch(const char *xpath);
     ChildMap *_checkChildren();
@@ -307,12 +309,8 @@ public:
     virtual void Link() const;
     virtual bool Release() const;
 
-    virtual bool renameTree(IPropertyTree *tree, const char *newName);
-
-    virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, CClientRemoteTree)); }
-    
-    virtual void deserializeSelfRT(MemoryBuffer &mb);
-    virtual void deserializeChildrenRT(MemoryBuffer &src);
+    virtual void deserializeSelfRT(MemoryBuffer &mb) override;
+    virtual void deserializeChildrenRT(MemoryBuffer &src) override;
 
     inline void addServerTreeInfo(byte STIInfo) { serverTreeInfo += STIInfo; }
     inline bool queryLazyFetch() const { return connection.queryLazyFetch(); }
@@ -324,48 +322,51 @@ public:
     void checkExt() const;
 
     virtual bool setLazyFetch(bool fetch) { return connection.setLazyFetch(fetch); }
-    virtual ChildMap *checkChildren() const;
-    virtual IPropertyTree *create(const char *name, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false);
-    virtual IPropertyTree *create(MemoryBuffer &mb);
-    virtual void createChildMap();
-    virtual IPropertyTree *ownPTree(IPropertyTree *tree);
-    virtual void setLocal(size32_t size, const void *data, bool _binary);
-    virtual void appendLocal(size32_t size, const void *data, bool binary);
-    virtual void addingNewElement(IPropertyTree &child, int pos);
-    virtual void removingElement(IPropertyTree *tree, unsigned pos);
-    virtual void setAttr(const char *attr, const char *val);
-    virtual bool removeAttr(const char *attr);
+
+// PTree overrides
+    virtual bool isEquivalent(IPropertyTree *tree) const override { return (NULL != QUERYINTERFACE(tree, CClientRemoteTree)); }
+    virtual ChildMap *checkChildren() const override;
+    virtual IPropertyTree *create(const char *name, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false) override;
+    virtual IPropertyTree *create(MemoryBuffer &mb) override;
+    virtual void createChildMap() override;
+    virtual IPropertyTree *ownPTree(IPropertyTree *tree) override;
+    virtual void setLocal(size32_t size, const void *data, bool _binary) override;
+    virtual void appendLocal(size32_t size, const void *data, bool binary) override;
+    virtual void addingNewElement(IPropertyTree &child, int pos) override;
+    virtual void removingElement(IPropertyTree *tree, unsigned pos) override;
+    virtual void setAttribute(const char *attr, const char *val) override;
+    virtual bool removeAttribute(const char *attr) override;
 
 // IPropertyTree
-    virtual void addProp(const char *xpath, const char *val);
-    virtual void setProp(const char *xpath, const char *val);
-    virtual void addPropInt64(const char *xpath, __int64 val);
-    virtual void setPropInt64(const char *xpath, __int64 val);
-    virtual void setPropBin(const char *xpath, size32_t size, const void *data);
-    virtual IPropertyTree *setPropTree(const char *xpath, IPropertyTree *val);
-    virtual IPropertyTree *addPropTree(const char *xpath, IPropertyTree *val);
-    virtual bool removeProp(const char *xpath);
-    virtual bool removeTree(IPropertyTree *child);
-    virtual IPropertyTreeIterator *getElements(const char *xpath, IPTIteratorCodes flags = iptiter_null) const;
-    virtual bool isCompressed(const char *xpath=NULL) const;
-    virtual bool getProp(const char *xpath, StringBuffer &ret) const;
-    virtual const char *queryProp(const char * xpath) const;
-    virtual bool getPropBool(const char *xpath, bool dft=false) const;
-    virtual __int64 getPropInt64(const char *xpath, __int64 dft=0) const;
-    virtual bool getPropBin(const char *xpath, MemoryBuffer &ret) const;
-    virtual void localizeElements(const char *xpath, bool allTail=false);
-    virtual IPropertyTree *queryBranch(const char *xpath) const;
-    virtual bool hasChildren() const { return (children && children->count()) || (!children && 0 != (serverTreeInfo & STI_HaveChildren)); }
+    virtual bool renameTree(IPropertyTree *tree, const char *newName) override;
+    virtual void addProp(const char *xpath, const char *val) override;
+    virtual void setProp(const char *xpath, const char *val) override;
+    virtual void addPropInt64(const char *xpath, __int64 val) override;
+    virtual void setPropInt64(const char *xpath, __int64 val) override;
+    virtual void setPropBin(const char *xpath, size32_t size, const void *data) override;
+    virtual IPropertyTree *setPropTree(const char *xpath, IPropertyTree *val) override;
+    virtual IPropertyTree *addPropTree(const char *xpath, IPropertyTree *val) override;
+    virtual bool removeProp(const char *xpath) override;
+    virtual bool removeTree(IPropertyTree *child) override;
+    virtual IPropertyTreeIterator *getElements(const char *xpath, IPTIteratorCodes flags = iptiter_null) const override;
+    virtual bool isCompressed(const char *xpath=NULL) const override;
+    virtual bool getProp(const char *xpath, StringBuffer &ret) const override;
+    virtual const char *queryProp(const char * xpath) const override;
+    virtual bool getPropBool(const char *xpath, bool dft=false) const override;
+    virtual __int64 getPropInt64(const char *xpath, __int64 dft=0) const override;
+    virtual bool getPropBin(const char *xpath, MemoryBuffer &ret) const override;
+    virtual void localizeElements(const char *xpath, bool allTail=false) override;
+    virtual IPropertyTree *queryBranch(const char *xpath) const override;
+    virtual bool hasChildren() const override { return (children && children->count()) || (!children && 0 != (serverTreeInfo & STI_HaveChildren)); }
 
 // ITrackChanges
-    virtual ChangeInfo *queryChanges();
-    virtual void registerRenamed(const char *newName, const char *oldName, unsigned pos, __int64 id);
-    virtual void registerDeleted(const char *name, unsigned position, __int64 id);
-    virtual void registerDeletedAttr(const char *attr);
-    virtual void clearChanges();
-
-    virtual void registerAttrChange(const char *attr);
-    virtual void registerPropAppend(size32_t l);
+    virtual ChangeInfo *queryChanges() override;
+    virtual void registerRenamed(const char *newName, const char *oldName, unsigned pos, __int64 id) override;
+    virtual void registerDeleted(const char *name, unsigned position, __int64 id) override;
+    virtual void registerDeletedAttr(const char *attr) override;
+    virtual void clearChanges() override;
+    virtual void registerAttrChange(const char *attr) override;
+    virtual void registerPropAppend(size32_t l) override;
 
 private: // data
     unsigned state;

+ 3 - 3
dali/base/dasds.cpp

@@ -1624,7 +1624,7 @@ public:
     virtual void resetAsExternal(IPropertyTree &_tree)
     {
         PTree &tree = *QUERYINTERFACE(&_tree, PTree);
-        tree.clear();
+        ::Release(tree.detach());
     }
     virtual void readValue(const char *name, MemoryBuffer &mb)
     {
@@ -2265,7 +2265,7 @@ void CServerConnection::aborted(SessionId id)
 enum IncCmd { None, PropDelete, AttrDelete, PropChange, PropNew, PropExisting, ChildEndMarker, PropRename, AttrChange };
 
 CRemoteTreeBase::CRemoteTreeBase(const char *name, IPTArrayValue *value, ChildMap *children)
-    : PTree(name, ipt_none, value, children)
+    : SDS_PTREE(name, ipt_none, value, children)
 {
     serverId = 0;
 }
@@ -3010,7 +3010,7 @@ PDState CServerRemoteTree::checkChange(IPropertyTree &changeTree, CBranchChange
                         Owned<IAttributeIterator> iter = e.getAttributes();
                         ForEach(*iter)
                         {
-                            if (removeAttr(iter->queryName()))
+                            if (removeAttribute(iter->queryName()))
                                 mergePDState(res, PDS_Data);
                         }
                         break;

+ 8 - 15
dali/base/dasds.ipp

@@ -225,7 +225,9 @@ class CBranchChange;
 ///////////////////
 class CSubscriberContainerList;
 
-class CRemoteTreeBase : public PTree
+#define SDS_PTREE CAtomPTree
+
+class CRemoteTreeBase : public SDS_PTREE
 {
 public:
     CRemoteTreeBase(MemoryBuffer &mb);
@@ -238,24 +240,15 @@ public:
 
     void clearChildren();
     CRemoteTreeBase *createChild(int pos, const char *childName);
-    
+
     inline __int64 queryServerId() { return serverId; }
     virtual void setServerId(__int64 _serverId);
     virtual CSubscriberContainerList *getSubscribers(const char *xpath, CPTStack &stack) { UNIMPLEMENTED; return NULL; } // JCSMORE
 
-// PTree
-    virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, CRemoteTreeBase)); }
-    virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false) = 0;
-    virtual IPropertyTree *create(MemoryBuffer &mb) = 0;
-
-// ITrackChanges
-    virtual ChangeInfo *queryChanges() { assertex(false); return NULL; }
-    virtual void registerRenamed(const char *newName, const char *oldName, unsigned pos, __int64 id) { }
-    virtual void registerDeleted(const char *name, unsigned pos, __int64 id) { }
-    virtual void registerDeletedAttr(const char *attr) { }
-    virtual void clearChanges() { assertex(false); }
-    virtual void registerAttrChange(const char *attr) { }
-    virtual void registerPropAppend(size32_t l) { }
+// PTree overrides
+    virtual bool isEquivalent(IPropertyTree *tree) const override { return (NULL != QUERYINTERFACE(tree, CRemoteTreeBase)); }
+    virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false) override = 0;
+    virtual IPropertyTree *create(MemoryBuffer &mb) override = 0;
 
 protected: // data
     __int64 serverId;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 321 - 435
system/jlib/jptree.cpp


+ 280 - 179
system/jlib/jptree.ipp

@@ -47,26 +47,25 @@ class jlib_decl ChildMap : protected SuperHashTableOf<IPropertyTree, constcharpt
 {
 protected:
 // SuperHashTable definitions
-    virtual void onAdd(void *) {}
-
-    virtual void onRemove(void *e)
+    virtual void onAdd(void *) override {}
+    virtual void onRemove(void *e) override
     {
-        IPropertyTree &elem= *(IPropertyTree *)e;
+        IPropertyTree &elem = *(IPropertyTree *)e;
         elem.Release();
     }
-    virtual unsigned getHashFromElement(const void *e) const;
-    virtual unsigned getHashFromFindParam(const void *fp) const
+    virtual const void *getFindParam(const void *e) const override
     {
-        return hashc((const unsigned char *)fp, (size32_t)strlen((const char *)fp), 0);
+        const IPropertyTree &elem = *(const IPropertyTree *)e;
+        return elem.queryName();
     }
-    virtual const void *getFindParam(const void *e) const
+    virtual unsigned getHashFromElement(const void *e) const;
+    virtual unsigned getHashFromFindParam(const void *fp) const override
     {
-        const IPropertyTree &elem=*(const IPropertyTree *)e;
-        return (void *)elem.queryName();
+        return hashc((const unsigned char *)fp, (size32_t)strlen((const char *)fp), 0);
     }
-    virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const
+    virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const override
     {
-        return (0 == strcmp(((IPropertyTree *)e)->queryName(), (const char *)fp));
+        return streq(((IPropertyTree *)e)->queryName(), (const char *)fp);
     }
 public: 
     IMPLEMENT_IINTERFACE;
@@ -110,13 +109,13 @@ class jlib_decl ChildMapNC : public ChildMap
 {
 public:
 // SuperHashTable definitions
-    virtual unsigned getHashFromFindParam(const void *fp) const
+    virtual unsigned getHashFromFindParam(const void *fp) const override
     {
         return hashnc((const unsigned char *)fp, (size32_t)strlen((const char *)fp), 0);
     }
-    virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const
+    virtual bool matchesFindParam(const void *e, const void *fp, unsigned fphash) const override
     {
-        return (0 == stricmp(((IPropertyTree *)e)->queryName(), (const char *)fp));
+        return strieq(((IPropertyTree *)e)->queryName(), (const char *)fp);
     }
 };
 
@@ -232,68 +231,6 @@ struct AttrValue
     AttrStr *value;
 };
 
-#define AM_NOCASE_FLAG (0x8000)
-#define AM_NOCASE_MASK (0x7fff)
-
-#ifdef __64BIT__
-#pragma pack(push,1)
-// Byte-Pack AttrMap and PTree because very large numbers are created.  However, this may cause problems on systems that
-// require aligned pointer access.  Without overriding the packing the structure currently wastes 8 bytes.
-// Ideally the classes would be restructured to avoid this, but it would probably require AttrMap to move into PTree
-#endif
-
-class jlib_decl AttrMap
-{
-    AttrValue *attrs;
-    unsigned short numattrs;    // use top bit for nocase flag
-    static AttrValue **freelist; // entry 0 not used
-    static unsigned freelistmax; 
-    static CLargeMemoryAllocator freeallocator;
-
-    AttrValue *newArray(unsigned n);
-    void freeArray(AttrValue *a,unsigned n);
-
-public:
-    AttrMap()
-    { 
-        attrs = NULL;
-        numattrs = 0;
-    }
-    ~AttrMap() 
-    { 
-        kill();
-    }
-    inline unsigned count() const
-    { 
-        return numattrs&AM_NOCASE_MASK; 
-    }
-    inline AttrValue *item(unsigned i) const
-    { 
-        return attrs+i; 
-    }
-    void setNoCase(bool nc) 
-    { 
-        if (nc) 
-            numattrs |= AM_NOCASE_FLAG; 
-        else 
-            numattrs &= AM_NOCASE_MASK; 
-    }
-    inline bool isNoCase() const 
-    { 
-        return (numattrs&AM_NOCASE_FLAG)!=0; 
-    }
-    void kill();
-    void set(const char *key, const char *val);
-    const char *find(const char *key) const;
-    bool remove(const char *key);
-    void swap(AttrMap &other);
-    static inline void killfreelist()
-    {
-        free(freelist);
-        freelist = NULL;
-    }
-};
-
 
 class jlib_decl PTree : public CInterfaceOf<IPropertyTree>
 {
@@ -303,26 +240,25 @@ friend class PTIdMatchIterator;
 friend class ChildMap;
 
 public:
-    PTree(MemoryBuffer &mb);
-    PTree(const char *_name=NULL, byte _flags=0, IPTArrayValue *_value=NULL, ChildMap *_children=NULL);
+    PTree(byte _flags=ipt_none, IPTArrayValue *_value=nullptr, ChildMap *_children=nullptr);
     ~PTree();
+    virtual void beforeDispose() override { }
 
+    const char *queryName() const
+    {
+        return name?name->get():nullptr;
+    }
+    HashKeyElement *queryKey() const { return name; }
     IPropertyTree *queryParent() { return parent; }
     IPropertyTree *queryChild(unsigned index);
     ChildMap *queryChildren() { return children; }
     aindex_t findChild(IPropertyTree *child, bool remove=false);
     inline bool isnocase() const { return IptFlagTst(flags, ipt_caseInsensitive); }
     ipt_flags queryFlags() const { return (ipt_flags) flags; }
-public:
+    void serializeSelf(MemoryBuffer &tgt);
     void serializeCutOff(MemoryBuffer &tgt, int cutoff=-1, int depth=0);
+    void deserializeSelf(MemoryBuffer &src);
     void serializeAttributes(MemoryBuffer &tgt);
-    virtual void serializeSelf(MemoryBuffer &tgt);
-    virtual void deserializeSelf(MemoryBuffer &src);
-    virtual void createChildMap() { children = isnocase()?new ChildMapNC():new ChildMap(); }
-
-
-    HashKeyElement *queryKey() { return name; }
-    void setName(const char *_name);
     IPropertyTree *clone(IPropertyTree &srcTree, bool self=false, bool sub=true);
     void clone(IPropertyTree &srcTree, IPropertyTree &dstTree, bool sub=true);
     inline void setParent(IPropertyTree *_parent) { parent = _parent; }
@@ -332,107 +268,273 @@ public:
     IPTArrayValue *detachValue() { IPTArrayValue *v = value; value = NULL; return v; }
     void setValue(IPTArrayValue *_value, bool binary) { if (value) delete value; value = _value; if (binary) IptFlagSet(flags, ipt_binary); }
     bool checkPattern(const char *&xxpath) const;
-    void clear();
+    IPropertyTree *detach()
+    {
+        IPropertyTree *tree = create(queryName(), value, children, true);
+        PTree *_tree = QUERYINTERFACE(tree, PTree); assertex(_tree); _tree->setParent(this);
+
+        std::swap(numAttrs, _tree->numAttrs);
+        std::swap(attrs, _tree->attrs);
+
+        ::Release(children);
+        children = nullptr;
+        return tree;
+    }
+    virtual void createChildMap() { children = isnocase()?new ChildMapNC():new ChildMap(); }
+    virtual void setName(const char *name) = 0;
 
 // IPropertyTree impl.
-    virtual bool hasProp(const char * xpath) const;
-    virtual bool isBinary(const char *xpath=NULL) const;
-    virtual bool isCompressed(const char *xpath=NULL) const;
-    virtual bool renameProp(const char *xpath, const char *newName);
-    virtual bool renameTree(IPropertyTree *tree, const char *newName);
-    virtual const char *queryProp(const char *xpath) const;
-    virtual bool getProp(const char *xpath, StringBuffer &ret) const;
-    virtual void setProp(const char *xpath, const char *val);
-    virtual void addProp(const char *xpath, const char *val);
-    virtual void appendProp(const char *xpath, const char *val);
-    virtual bool getPropBool(const char *xpath, bool dft=false) const;
-    virtual void setPropBool(const char *xpath, bool val) { setPropInt(xpath, val); }
-    virtual void addPropBool(const char *xpath, bool val) { addPropInt(xpath, val); }
-    virtual __int64 getPropInt64(const char *xpath, __int64 dft=0) const;
-    virtual void setPropInt64(const char * xpath, __int64 val);
-    virtual void addPropInt64(const char *xpath, __int64 val);
-    virtual int getPropInt(const char *xpath, int dft=0) const;
-    virtual void setPropInt(const char *xpath, int val);
-    virtual void addPropInt(const char *xpath, int val);
-    virtual bool getPropBin(const char * xpath, MemoryBuffer &ret) const;
-    virtual void setPropBin(const char * xpath, size32_t size, const void *data);
-    virtual void appendPropBin(const char *xpath, size32_t size, const void *data);
-    virtual void addPropBin(const char *xpath, size32_t size, const void *data);
-    virtual IPropertyTree *getPropTree(const char *xpath) const;
-    virtual IPropertyTree *queryPropTree(const char *xpath) const;
-    virtual IPropertyTree *getBranch(const char *xpath) const { return LINK(queryBranch(xpath)); }
-    virtual IPropertyTree *queryBranch(const char *xpath) const { return queryPropTree(xpath); }
-    virtual IPropertyTree *setPropTree(const char *xpath, IPropertyTree *val);
-    virtual IPropertyTree *addPropTree(const char *xpath, IPropertyTree *val);
-    virtual bool removeTree(IPropertyTree *child);
-    virtual bool removeProp(const char *xpath);
-    virtual aindex_t queryChildIndex(IPropertyTree *child);
-    virtual const char *queryName() const;
-    virtual StringBuffer &getName(StringBuffer &ret) const;
-    virtual IAttributeIterator *getAttributes(bool sorted=false) const;
-    virtual IPropertyTreeIterator *getElements(const char *xpath, IPTIteratorCodes flags = iptiter_null) const;
-    virtual void localizeElements(const char *xpath, bool allTail=false);
-    virtual bool hasChildren() const { return children && children->count()?true:false; }
-    virtual unsigned numUniq() { return checkChildren()?children->count():0; }  
-    virtual unsigned numChildren();
-    virtual bool isCaseInsensitive() { return isnocase(); }
-    virtual unsigned getCount(const char *xpath);
+    virtual bool hasProp(const char * xpath) const override;
+    virtual bool isBinary(const char *xpath=NULL) const override;
+    virtual bool isCompressed(const char *xpath=NULL) const override;
+    virtual bool renameProp(const char *xpath, const char *newName) override;
+    virtual bool renameTree(IPropertyTree *tree, const char *newName) override;
+    virtual const char *queryProp(const char *xpath) const override;
+    virtual bool getProp(const char *xpath, StringBuffer &ret) const override;
+    virtual void setProp(const char *xpath, const char *val) override;
+    virtual void addProp(const char *xpath, const char *val) override;
+    virtual void appendProp(const char *xpath, const char *val) override;
+    virtual bool getPropBool(const char *xpath, bool dft=false) const override;
+    virtual void setPropBool(const char *xpath, bool val) override { setPropInt(xpath, val); }
+    virtual void addPropBool(const char *xpath, bool val) override { addPropInt(xpath, val); }
+    virtual __int64 getPropInt64(const char *xpath, __int64 dft=0) const override;
+    virtual void setPropInt64(const char * xpath, __int64 val) override;
+    virtual void addPropInt64(const char *xpath, __int64 val) override;
+    virtual int getPropInt(const char *xpath, int dft=0) const override;
+    virtual void setPropInt(const char *xpath, int val) override;
+    virtual void addPropInt(const char *xpath, int val) override;
+    virtual bool getPropBin(const char * xpath, MemoryBuffer &ret) const override;
+    virtual void setPropBin(const char * xpath, size32_t size, const void *data) override;
+    virtual void appendPropBin(const char *xpath, size32_t size, const void *data) override;
+    virtual void addPropBin(const char *xpath, size32_t size, const void *data) override;
+    virtual IPropertyTree *getPropTree(const char *xpath) const override;
+    virtual IPropertyTree *queryPropTree(const char *xpath) const override;
+    virtual IPropertyTree *getBranch(const char *xpath) const override { return LINK(queryBranch(xpath)); }
+    virtual IPropertyTree *queryBranch(const char *xpath) const override { return queryPropTree(xpath); }
+    virtual IPropertyTree *setPropTree(const char *xpath, IPropertyTree *val) override;
+    virtual IPropertyTree *addPropTree(const char *xpath, IPropertyTree *val) override;
+    virtual bool removeTree(IPropertyTree *child) override;
+    virtual bool removeProp(const char *xpath) override;
+    virtual aindex_t queryChildIndex(IPropertyTree *child) override;
+    virtual StringBuffer &getName(StringBuffer &ret) const override;
+    virtual IAttributeIterator *getAttributes(bool sorted=false) const override;
+    virtual IPropertyTreeIterator *getElements(const char *xpath, IPTIteratorCodes flags = iptiter_null) const override;
+    virtual void localizeElements(const char *xpath, bool allTail=false) override;
+    virtual bool hasChildren() const override { return children && children->count()?true:false; }
+    virtual unsigned numUniq() override { return checkChildren()?children->count():0; }
+    virtual unsigned numChildren() override;
+    virtual bool isCaseInsensitive() override { return isnocase(); }
+    virtual unsigned getCount(const char *xpath) override;
 // serializable impl.
-    virtual void serialize(MemoryBuffer &tgt);
-    virtual void deserialize(MemoryBuffer &src);
-    const AttrMap &queryAttributes() const { return attributes; }
-    
+    virtual void serialize(MemoryBuffer &tgt) override;
+    virtual void deserialize(MemoryBuffer &src) override;
+
 protected:
+    aindex_t getChildMatchPos(const char *xpath);
+
     virtual ChildMap *checkChildren() const;
-    virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, PTree)); }
+    virtual bool isEquivalent(IPropertyTree *tree) const { return (nullptr != QUERYINTERFACE(tree, PTree)); }
     virtual void setLocal(size32_t l, const void *data, bool binary=false);
     virtual void appendLocal(size32_t l, const void *data, bool binary=false);
-    virtual void setAttr(const char *attr, const char *val);
-    virtual bool removeAttr(const char *attr);
     virtual void addingNewElement(IPropertyTree &child, int pos) { }
     virtual void removingElement(IPropertyTree *tree, unsigned pos) { }
-    virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false) = 0;
+    virtual IPropertyTree *create(const char *name=nullptr, IPTArrayValue *value=nullptr, ChildMap *children=nullptr, bool existing=false) = 0;
     virtual IPropertyTree *create(MemoryBuffer &mb) = 0;
     virtual IPropertyTree *ownPTree(IPropertyTree *tree);
-    aindex_t getChildMatchPos(const char *xpath);
+
+    virtual void setAttribute(const char *attr, const char *val) = 0;
+    virtual bool removeAttribute(const char *k) = 0;
+
+    AttrValue *findAttribute(const char *k) const;
+    const char *getAttributeValue(const char *k) const;
+    unsigned getAttributeCount() const;
+    AttrValue *getNextAttribute(AttrValue *cur) const;
 
 private:
-    void init();
     void addLocal(size32_t l, const void *data, bool binary=false, int pos=-1);
     void resolveParentChild(const char *xpath, IPropertyTree *&parent, IPropertyTree *&child, StringAttr &path, StringAttr &qualifier);
     void replaceSelf(IPropertyTree *val);
 
 protected: // data
-    IPropertyTree *parent; // ! currently only used if tree embedded into array, used to locate position.
-    HashKeyElement *name;
-    ChildMap *children;
-    IPTArrayValue *value;
-    //The packing (#pragma pack) is overridden because very large numbers of these objects are created, and the
-    //following two members currently cause 8 bytes to be wasted.  Refactoring the contents of AttrMap into this
-    //class would allow the fields to pack cleanly.
-    AttrMap attributes;     // this has 2 "extra" bytes - which could pack into the space following the count
-    byte flags;             // this could also pack into the space following the count.
+    /* NB: the order of the members here is important to reduce the size of the objects, because very large numbers of these are created.
+     * The base CInterfaceOf contains it's VMT + a unsigned link count.
+     * Therefore the short+byte follows the 4 byte link count.
+     */
+
+    unsigned short numAttrs = 0;
+    byte flags;           // set by constructor
+    IPropertyTree *parent = nullptr; // ! currently only used if tree embedded into array, used to locate position.
+    ChildMap *children;   // set by constructor
+    IPTArrayValue *value; // set by constructor
+    HashKeyElement *name = nullptr;
+    AttrValue *attrs = nullptr;
 };
 
-#ifdef __64BIT__
-#pragma pack(pop)
-#endif
+
+struct AttrStrC : public AttrStr
+{
+    static inline unsigned getHash(const char *k)
+    {
+        return hashc((const byte *)k, strlen(k), 17);
+    }
+    inline bool eq(const char *k)
+    {
+        return streq(k,str);
+    }
+    static AttrStrC *create(const char *k)
+    {
+        size32_t kl = (k?strlen(k):0);
+        AttrStrC *ret = (AttrStrC *)malloc(sizeof(AttrStrC)+kl);
+        memcpy(ret->str, k, kl);
+        ret->str[kl] = 0;
+        ret->hash = hashc((const byte *)k, kl, 17);
+        ret->linkcount = 0;
+        return ret;
+    }
+    static void destroy(AttrStrC *a)
+    {
+        free(a);
+    }
+};
+
+struct AttrStrNC : public AttrStr
+{
+    static inline unsigned getHash(const char *k)
+    {
+        return hashnc((const byte *)k, strlen(k), 17);
+    }
+    inline bool eq(const char *k)
+    {
+        return strieq(k,str);
+    }
+    static AttrStrNC *create(const char *k)
+    {
+        size32_t kl = (k?strlen(k):0);
+        AttrStrNC *ret = (AttrStrNC *)malloc(sizeof(AttrStrNC)+kl);
+        memcpy(ret->str,k,kl);
+        ret->str[kl] = 0;
+        ret->hash = hashnc((const byte *)k, kl, 17);
+        ret->linkcount = 0;
+        return ret;
+    }
+    static void destroy(AttrStrNC *a)
+    {
+        free(a);
+    }
+};
+
+class CAttrValHashTable
+{
+    CMinHashTable<AttrStrC>  htc;
+    CMinHashTable<AttrStrNC> htnc;
+    CMinHashTable<AttrStrC>  htv;
+public:
+    inline AttrStr *addkey(const char *v,bool nc)
+    {
+        AttrStr * ret;
+        if (nc)
+            ret = htnc.find(v,true);
+        else
+            ret = htc.find(v,true);
+        if (ret->linkcount!=(unsigned short)-1)
+            ret->linkcount++;
+        return ret;
+    }
+    inline AttrStr *addval(const char *v)
+    {
+        AttrStr * ret = htv.find(v,true);
+        if (ret->linkcount!=(unsigned short)-1)
+            ret->linkcount++;
+        return ret;
+    }
+    inline void removekey(AttrStr *a,bool nc)
+    {
+        if (a->linkcount!=(unsigned short)-1)
+        {
+            if (--(a->linkcount)==0)
+            {
+                if (nc)
+                    htnc.remove((AttrStrNC *)a);
+                else
+                    htc.remove((AttrStrC *)a);
+            }
+        }
+    }
+    inline void removeval(AttrStr *a)
+    {
+        if (a->linkcount!=(unsigned short)-1)
+            if (--(a->linkcount)==0)
+                htv.remove((AttrStrC *)a);
+    }
+};
+
+
+class jlib_decl CAtomPTree : public PTree
+{
+    static AtomRefTable *keyTable, *keyTableNC;
+    static CriticalSection hashcrit;
+    static CAttrValHashTable *attrHT;
+    static AttrValue **freelist; // entry 0 not used
+    static unsigned freelistmax;
+    static CLargeMemoryAllocator freeallocator;
+
+    AttrValue *newAttrArray(unsigned n);
+    void freeAttrArray(AttrValue *a, unsigned n);
+
+protected:
+    virtual void setAttribute(const char *attr, const char *val) override;
+    virtual bool removeAttribute(const char *k) override;
+public:
+    static inline void init()
+    {
+        keyTable = new AtomRefTable;
+        keyTableNC = new AtomRefTable(true);
+        attrHT = new CAttrValHashTable;
+    }
+    static inline void kill()
+    {
+        delete attrHT;
+        keyTable->Release();
+        keyTableNC->Release();
+        free(freelist);
+        freelist = NULL;
+    }
+
+    CAtomPTree(const char *name=nullptr, byte flags=ipt_none, IPTArrayValue *value=nullptr, ChildMap *children=nullptr);
+    ~CAtomPTree();
+    virtual void setName(const char *_name) override;
+    virtual bool isEquivalent(IPropertyTree *tree) const override { return (nullptr != QUERYINTERFACE(tree, CAtomPTree)); }
+    virtual IPropertyTree *create(const char *name=nullptr, IPTArrayValue *value=nullptr, ChildMap *children=nullptr, bool existing=false)
+    {
+        return new CAtomPTree(name, flags, value, children);
+    }
+    virtual IPropertyTree *create(MemoryBuffer &mb) override
+    {
+        IPropertyTree *tree = new CAtomPTree();
+        tree->deserialize(mb);
+        return tree;
+    }
+};
 
 
 jlib_decl IPropertyTree *createPropBranch(IPropertyTree *tree, const char *xpath, bool createIntermediates=false, IPropertyTree **created=NULL, IPropertyTree **createdParent=NULL);
 
-class LocalPTree : public PTree
+class jlib_decl LocalPTree : public PTree
 {
+protected:
+    virtual void setAttribute(const char *attr, const char *val) override;
+    virtual bool removeAttribute(const char *k) override;
 public:
-    LocalPTree(const char *name=NULL, byte flags=ipt_none, IPTArrayValue *value=NULL, ChildMap *children=NULL)
-        : PTree(name, flags, value, children) { }
+    LocalPTree(const char *name=nullptr, byte flags=ipt_none, IPTArrayValue *value=nullptr, ChildMap *children=nullptr);
+    ~LocalPTree();
 
-    virtual bool isEquivalent(IPropertyTree *tree) { return (NULL != QUERYINTERFACE(tree, LocalPTree)); }
-    virtual IPropertyTree *create(const char *name=NULL, IPTArrayValue *value=NULL, ChildMap *children=NULL, bool existing=false)
+    virtual void setName(const char *_name) override;
+    virtual bool isEquivalent(IPropertyTree *tree) const override { return (nullptr != QUERYINTERFACE(tree, LocalPTree)); }
+    virtual IPropertyTree *create(const char *name=nullptr, IPTArrayValue *value=nullptr, ChildMap *children=nullptr, bool existing=false) override
     {
         return new LocalPTree(name, flags, value, children);
     }
-    virtual IPropertyTree *create(MemoryBuffer &mb)
+    virtual IPropertyTree *create(MemoryBuffer &mb) override
     {
         IPropertyTree *tree = new LocalPTree();
         tree->deserialize(mb);
@@ -440,7 +542,6 @@ public:
     }
 };
 
-class PTree;
 class SingleIdIterator : public CInterfaceOf<IPropertyTreeIterator>
 {
 public:
@@ -449,10 +550,10 @@ public:
     void setCurrent(unsigned pos);
 
 // IPropertyTreeIterator
-    virtual bool first();
-    virtual bool next();
-    virtual bool isValid();
-    virtual IPropertyTree & query() { return * current; }
+    virtual bool first() override;
+    virtual bool next() override;
+    virtual bool isValid() override;
+    virtual IPropertyTree & query() override { return * current; }
 
 private:
     unsigned many, count, whichNext, start;
@@ -470,10 +571,10 @@ public:
     virtual bool match() = 0;
 
 // IPropertyTreeIterator
-    virtual bool first();
-    virtual bool next();
-    virtual bool isValid();
-    virtual IPropertyTree & query() { return iter->query(); }
+    virtual bool first() override;
+    virtual bool next() override;
+    virtual bool isValid() override;
+    virtual IPropertyTree & query() override { return iter->query(); }
 
 protected:
     bool nocase, sort;  // pack with the link count
@@ -503,10 +604,10 @@ public:
     ~PTStackIterator();
 
 // IPropertyTreeIterator
-    virtual bool first();
-    virtual bool isValid();
-    virtual bool next();
-    virtual IPropertyTree & query();
+    virtual bool first() override;
+    virtual bool isValid() override;
+    virtual bool next() override;
+    virtual IPropertyTree & query() override;
 
 private:
     void setIterator(IPropertyTreeIterator *iter);
@@ -537,7 +638,7 @@ class CPTreeMaker : public CInterfaceOf<IPTreeMaker>
 
         CDefaultNodeCreator(byte _flags) : flags(_flags) { }
 
-        virtual IPropertyTree *create(const char *tag) { return createPTree(tag, flags); }
+        virtual IPropertyTree *create(const char *tag) override { return createPTree(tag, flags); }
     };
 protected:
     IPropertyTree *currentNode;
@@ -567,7 +668,7 @@ public:
     }
 
 // IPTreeMaker
-    virtual void beginNode(const char *tag, offset_t startOffset)
+    virtual void beginNode(const char *tag, offset_t startOffset) override
     {
         if (rootProvided)
         {
@@ -591,12 +692,12 @@ public:
         }
         ptreeStack.append(*currentNode);
     }
-    virtual void newAttribute(const char *name, const char *value)
+    virtual void newAttribute(const char *name, const char *value) override
     {
         currentNode->setProp(name, value);
     }
-    virtual void beginNodeContent(const char *name) { }
-    virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset)
+    virtual void beginNodeContent(const char *name) override { }
+    virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset) override
     {
         if (binary)
             currentNode->setPropBin(NULL, length, value);
@@ -608,9 +709,9 @@ public:
         ptreeStack.pop();
         currentNode = (c>1) ? &ptreeStack.tos() : NULL;
     }
-    virtual IPropertyTree *queryRoot() { return root; }
-    virtual IPropertyTree *queryCurrentNode() { return currentNode; }
-    virtual void reset()
+    virtual IPropertyTree *queryRoot() override { return root; }
+    virtual IPropertyTree *queryCurrentNode() override { return currentNode; }
+    virtual void reset() override
     {
         if (!rootProvided)
         {

+ 12 - 5
system/jlib/jsuperhash.hpp

@@ -478,11 +478,8 @@ friend class AtomRefTable;
 typedef const char constcharptr;
 class jlib_decl AtomRefTable : public SuperHashTableOf<HashKeyElement, constcharptr>
 {
-protected:
-    CriticalSection crit;
-    bool nocase;
-
-    inline HashKeyElement *createKeyElement(const char *key)
+public:
+    static HashKeyElement *createKeyElement(const char *key, bool nocase)
     {
         size32_t l = (size32_t)strlen(key);
         HashKeyElement *hke = (HashKeyElement *) checked_malloc(sizeof(HashKeyElement)+l+1,-605);
@@ -492,6 +489,16 @@ protected:
         else
             hke->hashValue = hashc((const unsigned char *)key, l, 0);
         hke->linkCount = 0;
+        return hke;
+    }
+
+protected:
+    CriticalSection crit;
+    bool nocase;
+
+    inline HashKeyElement *createKeyElement(const char *key)
+    {
+        HashKeyElement *hke = createKeyElement(key, nocase);
         verifyex(add(*hke));
         return hke;
     }