@Override public OMVRBTreeEntry<K, V> getParent() { if (dataProvider == null) return null; if (parent == null && dataProvider.getParent().isValid()) { // LAZY LOADING OF THE PARENT NODE parent = pTree.loadEntry(null, dataProvider.getParent()); checkEntryStructure(); if (parent != null) { // TRY TO ASSIGN IT FOLLOWING THE RID if (parent.dataProvider.getLeft().isValid() && parent.dataProvider.getLeft().equals(dataProvider.getIdentity())) parent.left = this; else if (parent.dataProvider.getRight().isValid() && parent.dataProvider.getRight().equals(dataProvider.getIdentity())) parent.right = this; else { OLogManager.instance() .error( this, "getParent: Cannot assign node %s to parent. Nodes parent-left=%s, parent-right=%s", dataProvider.getParent(), parent.dataProvider.getLeft(), parent.dataProvider.getRight()); } } } return parent; }
public void checkEntryStructure() { if (!tree.isRuntimeCheckEnabled()) return; if (dataProvider.getParent() == null) OLogManager.instance() .error(this, "checkEntryStructure: Node %s has parentRid null!\n", this); if (dataProvider.getLeft() == null) OLogManager.instance().error(this, "checkEntryStructure: Node %s has leftRid null!\n", this); if (dataProvider.getRight() == null) OLogManager.instance().error(this, "checkEntryStructure: Node %s has rightRid null!\n", this); if (this == left || dataProvider.getIdentity().isValid() && dataProvider.getIdentity().equals(dataProvider.getLeft())) OLogManager.instance() .error(this, "checkEntryStructure: Node %s has left that points to itself!\n", this); if (this == right || dataProvider.getIdentity().isValid() && dataProvider.getIdentity().equals(dataProvider.getRight())) OLogManager.instance() .error(this, "checkEntryStructure: Node %s has right that points to itself!\n", this); if (left != null && left == right) OLogManager.instance() .error(this, "checkEntryStructure: Node %s has left and right equals!\n", this); if (left != null) { if (!left.dataProvider.getIdentity().equals(dataProvider.getLeft())) OLogManager.instance() .error(this, "checkEntryStructure: Wrong left node loaded: " + dataProvider.getLeft()); if (left.parent != this) OLogManager.instance() .error( this, "checkEntryStructure: Left node is not correctly connected to the parent" + dataProvider.getLeft()); } if (right != null) { if (!right.dataProvider.getIdentity().equals(dataProvider.getRight())) OLogManager.instance() .error( this, "checkEntryStructure: Wrong right node loaded: " + dataProvider.getRight()); if (right.parent != this) OLogManager.instance() .error( this, "checkEntryStructure: Right node is not correctly connected to the parent" + dataProvider.getRight()); } }
@Override public OMVRBTreeEntry<K, V> setParent(final OMVRBTreeEntry<K, V> iParent) { if (iParent != parent) { OMVRBTreeEntryPersistent<K, V> newParent = (OMVRBTreeEntryPersistent<K, V>) iParent; ORID newParentId = iParent == null ? ORecordId.EMPTY_RECORD_ID : newParent.dataProvider.getIdentity(); parent = newParent; if (dataProvider.setParent(newParentId)) markDirty(); if (parent != null) { ORID thisRid = dataProvider.getIdentity(); if (parent.left == this && !parent.dataProvider.getLeft().equals(thisRid)) if (parent.dataProvider.setLeft(thisRid)) parent.markDirty(); if (parent.left != this && parent.dataProvider.getLeft().isValid() && parent.dataProvider.getLeft().equals(thisRid)) parent.left = this; if (parent.right == this && !parent.dataProvider.getRight().equals(thisRid)) if (parent.dataProvider.setRight(thisRid)) parent.markDirty(); if (parent.right != this && parent.dataProvider.getRight().isValid() && parent.dataProvider.getRight().equals(thisRid)) parent.right = this; } } return iParent; }
/** Assures that all the links versus parent, left and right are consistent. */ public OMVRBTreeEntryPersistent<K, V> save() throws OSerializationException { if (!dataProvider.isEntryDirty()) return this; final boolean isNew = dataProvider.getIdentity().isNew(); // FOR EACH NEW LINK, SAVE BEFORE if (left != null && left.dataProvider.getIdentity().isNew()) { if (isNew) { // TEMPORARY INCORRECT SAVE FOR GETTING AN ID. WILL BE SET DIRTY AGAIN JUST AFTER left.dataProvider.save(); } else left.save(); } if (right != null && right.dataProvider.getIdentity().isNew()) { if (isNew) { // TEMPORARY INCORRECT SAVE FOR GETTING AN ID. WILL BE SET DIRTY AGAIN JUST AFTER right.dataProvider.save(); } else right.save(); } if (parent != null && parent.dataProvider.getIdentity().isNew()) { if (isNew) { // TEMPORARY INCORRECT SAVE FOR GETTING AN ID. WILL BE SET DIRTY AGAIN JUST AFTER parent.dataProvider.save(); } else parent.save(); } dataProvider.save(); // if (parent != null) // if (!parent.record.getIdentity().equals(parentRid)) // OLogManager.instance().error(this, // "[save]: Tree node %s has parentRid '%s' different by the rid of the assigned parent node: // %s", record.getIdentity(), // parentRid, parent.record.getIdentity()); checkEntryStructure(); if (pTree.searchNodeInCache(dataProvider.getIdentity()) != this) { // UPDATE THE CACHE pTree.addNodeInMemory(this); } return this; }
/** * Delete all the nodes recursively. IF they are not loaded in memory, load all the tree. * * @throws IOException */ public OMVRBTreeEntryPersistent<K, V> delete() throws IOException { if (dataProvider != null) { pTree.removeNodeFromMemory(this); pTree.removeEntry(dataProvider.getIdentity()); // EARLY LOAD LEFT AND DELETE IT RECURSIVELY if (getLeft() != null) ((OMVRBTreeEntryPersistent<K, V>) getLeft()).delete(); // EARLY LOAD RIGHT AND DELETE IT RECURSIVELY if (getRight() != null) ((OMVRBTreeEntryPersistent<K, V>) getRight()).delete(); // DELETE MYSELF dataProvider.removeIdentityChangedListener(this); dataProvider.delete(); clear(); } return this; }
private boolean canDisconnectFrom(OMVRBTreeEntryPersistent<K, V> entry) { return dataProvider == null || !dataProvider.getIdentity().isNew() && !entry.dataProvider.getIdentity().isNew(); }
/** * Disconnect the current node from others. * * @param iForceDirty Force disconnection also if the record it's dirty * @param iLevel * @return count of nodes that has been disconnected */ protected int disconnect(final boolean iForceDirty, final int iLevel) { if (dataProvider == null) // DIRTY NODE, JUST REMOVE IT return 1; int totalDisconnected = 0; final ORID rid = dataProvider.getIdentity(); boolean disconnectedFromParent = false; if (parent != null) { // DISCONNECT RECURSIVELY THE PARENT NODE if (canDisconnectFrom(parent) || iForceDirty) { if (parent.left == this) { parent.left = null; } else if (parent.right == this) { parent.right = null; } else OLogManager.instance() .warn( this, "Node " + rid + " has the parent (" + parent + ") unlinked to itself. It links to " + parent); totalDisconnected += parent.disconnect(iForceDirty, iLevel + 1); parent = null; disconnectedFromParent = true; } } else { disconnectedFromParent = true; } boolean disconnectedFromLeft = false; if (left != null) { // DISCONNECT RECURSIVELY THE LEFT NODE if (canDisconnectFrom(left) || iForceDirty) { if (left.parent == this) left.parent = null; else OLogManager.instance() .warn( this, "Node " + rid + " has the left (" + left + ") unlinked to itself. It links to " + left.parent); totalDisconnected += left.disconnect(iForceDirty, iLevel + 1); left = null; disconnectedFromLeft = true; } } else { disconnectedFromLeft = true; } boolean disconnectedFromRight = false; if (right != null) { // DISCONNECT RECURSIVELY THE RIGHT NODE if (canDisconnectFrom(right) || iForceDirty) { if (right.parent == this) right.parent = null; else OLogManager.instance() .warn( this, "Node " + rid + " has the right (" + right + ") unlinked to itself. It links to " + right.parent); totalDisconnected += right.disconnect(iForceDirty, iLevel + 1); right = null; disconnectedFromRight = true; } } else { disconnectedFromLeft = true; } if (disconnectedFromParent && disconnectedFromLeft && disconnectedFromRight) if ((!dataProvider.isEntryDirty() && !dataProvider.getIdentity().isTemporary() || iForceDirty) && !pTree.isNodeEntryPoint(this)) { totalDisconnected++; pTree.removeNodeFromMemory(this); clear(); } return totalDisconnected; }