io.sirix.index.path.summary.PathSummaryWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sirix-core Show documentation
Show all versions of sirix-core Show documentation
SirixDB is a hybrid on-disk and in-memory document oriented, versioned database system. It has a lightweight buffer manager, stores everything in a huge persistent and durable tree and allows efficient reconstruction of every revision. Furthermore, SirixDB implements change tracking, diffing and supports time travel queries.
package io.sirix.index.path.summary;
import io.sirix.access.Utils;
import io.sirix.access.trx.node.NodeFactory;
import io.sirix.api.*;
import io.sirix.api.json.JsonNodeReadOnlyTrx;
import io.sirix.api.xml.XmlNodeReadOnlyTrx;
import io.sirix.axis.*;
import io.sirix.axis.filter.FilterAxis;
import io.sirix.axis.filter.PathKindFilter;
import io.sirix.axis.filter.PathNameFilter;
import io.sirix.exception.SirixException;
import io.sirix.exception.SirixIOException;
import io.sirix.index.IndexType;
import io.sirix.node.NodeKind;
import io.sirix.node.immutable.json.ImmutableArrayNode;
import io.sirix.node.immutable.json.ImmutableObjectKeyNode;
import io.sirix.node.immutable.xml.ImmutableElement;
import io.sirix.node.interfaces.NameNode;
import io.sirix.node.interfaces.Node;
import io.sirix.node.interfaces.StructNode;
import io.sirix.node.interfaces.immutable.ImmutableNameNode;
import io.sirix.node.interfaces.immutable.ImmutableNode;
import io.sirix.node.json.ObjectKeyNode;
import io.sirix.settings.Fixed;
import io.brackit.query.atomic.QNm;
import org.checkerframework.checker.index.qual.NonNegative;
import javax.xml.namespace.QName;
import static java.util.Objects.requireNonNull;
/**
* Path summary writer organizing the path classes of a resource.
*
* @author Johannes Lichtenberger, University of Konstanz
*/
public final class PathSummaryWriter
extends AbstractForwardingPathSummaryReader {
/**
* Operation type to determine behavior of path summary updates during {@code setQName(QName)} and
* the move-operations.
*/
public enum OPType {
/**
* Move from and to is on the same level (before and after the move, the node has the same parent).
*/
MOVED_ON_SAME_LEVEL,
/**
* Move from and to is not on the same level (before and after the move, the node has a different
* parent).
*/
MOVED,
/**
* A new {@link QName} is set.
*/
SETNAME,
}
/**
* Determines if a path subtree must be deleted or not.
*/
private enum RemoveSubtreePath {
/**
* Yes, it must be deleted.
*/
YES,
/**
* No, it must not be deleted.
*/
NO
}
/**
* Sirix {@link PageTrx}.
*/
private final PageTrx pageTrx;
/**
* Sirix {@link PathSummaryReader}.
*/
private final PathSummaryReader pathSummaryReader;
/**
* Sirix {@link NodeFactory} to create new nodes.
*/
private final NodeFactory nodeFactory;
/**
* The read-only trx.
*/
private final R nodeRtx;
/**
* Determines if number of children is stored or not.
*/
private final boolean storeChildCount;
/**
* Constructor.
*
* @param pageTrx Sirix {@link PageTrx}
* @param resMgr The resource manager
* @param nodeFactory The node factory to create path nodes
* @param rtx the read-only trx
*/
public PathSummaryWriter(final PageTrx pageTrx, final ResourceSession resMgr,
final NodeFactory nodeFactory, final R rtx) {
this.pageTrx = requireNonNull(pageTrx);
pathSummaryReader = PathSummaryReader.getInstance(pageTrx, resMgr);
nodeRtx = requireNonNull(rtx);
this.nodeFactory = requireNonNull(nodeFactory);
storeChildCount = resMgr.getResourceConfig().storeChildCount();
}
/**
* Get the path summary reader.
*
* @return {@link PathSummaryReader} instance
*/
public PathSummaryReader getPathSummary() {
return pathSummaryReader;
}
/**
* Insert a new path node or increment the counter of an existing node and return the path node key.
*
* @param name the name of the path node to search for
* @param pathKind the kind of the path node to search for
* @return a path node key of the found node, or the path node key of a new inserted node
* @throws SirixException if anything went wrong
*/
public long getPathNodeKey(final QNm name, final NodeKind pathKind) {
final NodeKind kind = nodeRtx.getNode().getKind();
int level = 0;
if (kind == NodeKind.XML_DOCUMENT || kind == NodeKind.JSON_DOCUMENT) {
pathSummaryReader.moveTo(Fixed.DOCUMENT_NODE_KEY.getStandardProperty());
} else {
movePathSummary();
level = pathSummaryReader.getLevel();
}
final long nodeKey = pathSummaryReader.getNodeKey();
final Axis axis = new FilterAxis<>(new ChildAxis(pathSummaryReader),
new PathNameFilter(pathSummaryReader,
pathKind == NodeKind.NAMESPACE
? name.getPrefix()
: Utils.buildName(name)),
new PathKindFilter(pathSummaryReader, pathKind));
long retVal;
if (axis.hasNext()) {
retVal = axis.nextLong();
final PathNode pathNode = pageTrx.prepareRecordForModification(retVal, IndexType.PATH_SUMMARY, 0);
pathNode.incrementReferenceCount();
pathSummaryReader.putMapping(pathNode.getNodeKey(), pathNode);
} else {
assert nodeKey == pathSummaryReader.getNodeKey();
insertPathAsFirstChild(name, pathKind, level + 1);
retVal = pathSummaryReader.getNodeKey();
}
return retVal;
}
/**
* Move path summary cursor to the path node which is references by the current node.
*/
private void movePathSummary() {
if (nodeRtx.getKind() == NodeKind.OBJECT) {
nodeRtx.moveToParent();
}
if (nodeRtx.getKind() == NodeKind.OBJECT_KEY) {
pathSummaryReader.moveTo(((ImmutableObjectKeyNode) nodeRtx.getNode()).getPathNodeKey());
} else if (nodeRtx.getKind() == NodeKind.ARRAY) {
pathSummaryReader.moveTo(((ImmutableArrayNode) nodeRtx.getNode()).getPathNodeKey());
} else if (nodeRtx.getNode() instanceof ImmutableNameNode) {
pathSummaryReader.moveTo(((ImmutableNameNode) nodeRtx.getNode()).getPathNodeKey());
} else {
throw new IllegalStateException();
}
}
/**
* Insert a path node as first child.
*
* @param name {@link QNm} of the path node (not stored) twice
* @param pathKind kind of node to index
* @param level level in the path summary
* @return this path writer instance
* @throws SirixException if an I/O error occurs
*/
public PathSummaryWriter insertPathAsFirstChild(final QNm name, final NodeKind pathKind, final int level) {
final long parentKey = pathSummaryReader.getNodeKey();
final long leftSibKey = Fixed.NULL_NODE_KEY.getStandardProperty();
final long rightSibKey = pathSummaryReader.getFirstChildKey();
final PathNode node = nodeFactory.createPathNode(parentKey, leftSibKey, rightSibKey, name, pathKind, level);
pathSummaryReader.removeFromCache(name);
pathSummaryReader.putMapping(node.getNodeKey(), node);
pathSummaryReader.moveTo(node.getNodeKey());
adaptForInsert(node);
pathSummaryReader.moveTo(node.getNodeKey());
pathSummaryReader.putQNameMapping(node, name);
return this;
}
/**
* Adapting everything for insert operations.
*
* @param newNode pointer of the new node to be inserted
* @throws SirixIOException if anything weird happens
*/
private void adaptForInsert(final Node newNode) {
assert newNode != null;
if (newNode instanceof StructNode strucNode) {
final StructNode parent = pageTrx.prepareRecordForModification(newNode.getParentKey(), IndexType.PATH_SUMMARY, 0);
if (storeChildCount) {
parent.incrementChildCount();
}
parent.setFirstChildKey(newNode.getNodeKey());
pathSummaryReader.putMapping(parent.getNodeKey(), parent);
if (strucNode.hasRightSibling()) {
final StructNode rightSiblingNode =
pageTrx.prepareRecordForModification(strucNode.getRightSiblingKey(), IndexType.PATH_SUMMARY, 0);
rightSiblingNode.setLeftSiblingKey(newNode.getNodeKey());
pathSummaryReader.putMapping(rightSiblingNode.getNodeKey(), rightSiblingNode);
}
if (strucNode.hasLeftSibling()) {
final StructNode leftSiblingNode =
pageTrx.prepareRecordForModification(strucNode.getLeftSiblingKey(), IndexType.PATH_SUMMARY, 0);
leftSiblingNode.setRightSiblingKey(newNode.getNodeKey());
pathSummaryReader.putMapping(leftSiblingNode.getNodeKey(), leftSiblingNode);
}
}
}
/**
* Adapt path summary either for moves or {@code setQName(QName)}.
*
* @param node the node for which the path node needs to be adapted
* @param name the new {@link QName} in case of a new one is set, the old {@link QName} otherwise
* @param uriKey uriKey of the new node
* @throws SirixException if a Sirix operation fails
* @throws NullPointerException if {@code pNode} or {@code pQName} is null
*/
public void adaptPathForChangedNode(final ImmutableNameNode node, final QNm name, final int uriKey,
final int prefixKey, final int localNameKey, final OPType type) {
// Possibly either reset a path node or decrement its reference counter
// and search for the new path node or insert it.
movePathSummary();
final long oldPathNodeKey = pathSummaryReader.getNodeKey();
// Only one path node is referenced (after a setQName(QName) the
// reference-counter would be 0).
if (type == OPType.SETNAME && pathSummaryReader.getReferences() == 1) {
moveSummaryGetLevel(node);
// Search for new path entry.
final Axis axis = new FilterAxis<>(new ChildAxis(pathSummaryReader),
new PathNameFilter(pathSummaryReader, Utils.buildName(name)),
new PathKindFilter(pathSummaryReader, node.getKind()));
if (axis.hasNext()) {
axis.nextLong();
long nodeKey = decrementReferenceCountOrRemove(node);
pathSummaryReader.moveTo(nodeKey);
// Found node.
processFoundPathNode(oldPathNodeKey,
pathSummaryReader.getNodeKey(),
node.getNodeKey(),
name,
uriKey,
prefixKey,
localNameKey);
} else {
if (pathSummaryReader.getKind() == NodeKind.XML_DOCUMENT
|| pathSummaryReader.getKind() == NodeKind.JSON_DOCUMENT) {
insertPathAsFirstChild(name, node.getKind(), 1);
} else {
/* The path summary just needs to be updated for the new renamed node. */
pathSummaryReader.moveTo(oldPathNodeKey);
final PathNode pathNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
pathNode.setPrefixKey(prefixKey);
pathNode.setLocalNameKey(localNameKey);
pathNode.setURIKey(uriKey);
pathNode.setName(name);
pathSummaryReader.putMapping(pathNode.getNodeKey(), pathNode);
pathSummaryReader.putQNameMapping(pathNode, name);
}
}
} else {
int level = moveSummaryGetLevel(node);
// TODO: Johannes: Optimize? (either use this or use the name-mapping,
// depending on the number of child nodes or nodes with a certain name).
// Search for new path entry.
final Axis axis = new FilterAxis<>(new ChildAxis(pathSummaryReader),
new PathNameFilter(pathSummaryReader, Utils.buildName(name)),
new PathKindFilter(pathSummaryReader, node.getKind()));
if (axis.hasNext()) {
axis.nextLong();
long nodeKey = decrementReferenceCountOrRemove(node);
pathSummaryReader.moveTo(nodeKey);
// Found node.
processFoundPathNode(oldPathNodeKey,
pathSummaryReader.getNodeKey(),
node.getNodeKey(),
name,
uriKey,
prefixKey,
localNameKey);
} else {
long nodeKey = decrementReferenceCountOrRemove(node);
pathSummaryReader.moveTo(nodeKey);
// Not found => create new path nodes for the whole subtree.
boolean firstRun = true;
for (final Axis descendants = new DescendantAxis(nodeRtx, IncludeSelf.YES); descendants.hasNext(); ) {
descendants.nextLong();
if (nodeRtx.getKind() == NodeKind.ELEMENT || nodeRtx.getKind() == NodeKind.OBJECT_KEY) {
// Path Summary : New mapping.
if (firstRun) {
insertPathAsFirstChild(name, nodeRtx.getKind(), ++level);
nodeKey = pathSummaryReader.getNodeKey();
} else {
insertPathAsFirstChild(nodeRtx.getName(), nodeRtx.getKind(), ++level);
}
resetPathNodeKey(nodeRtx.getNodeKey(), nodeRtx.getKind());
if (nodeRtx instanceof XmlNodeReadOnlyTrx rtx) {
// Namespaces.
for (int i = 0, nsps = rtx.getNamespaceCount(); i < nsps; i++) {
rtx.moveToNamespace(i);
// Path Summary : New mapping.
insertPathAsFirstChild(rtx.getName(), NodeKind.NAMESPACE, level + 1);
resetPathNodeKey(rtx.getNodeKey(), NodeKind.NAMESPACE);
rtx.moveToParent();
pathSummaryReader.moveToParent();
}
// Attributes.
for (int i = 0, atts = rtx.getAttributeCount(); i < atts; i++) {
rtx.moveToAttribute(i);
// Path Summary : New mapping.
insertPathAsFirstChild(rtx.getName(), NodeKind.ATTRIBUTE, level + 1);
resetPathNodeKey(rtx.getNodeKey(), NodeKind.ATTRIBUTE);
rtx.moveToParent();
pathSummaryReader.moveToParent();
}
}
if (firstRun) {
firstRun = false;
} else {
pathSummaryReader.moveToParent();
level--;
}
}
}
// /*
// * Remove path nodes with zero node references.
// *
// * (TODO: Johannes: might not be necessary, as it's likely that future
// * updates will reinsert the path).
// */
// for (final long key : nodesToDelete) {
// if (mPathSummaryReader.moveTo(key).hasMoved()) {
// removePathSummaryNode(Remove.NO);
// }
// }
pathSummaryReader.moveTo(nodeKey);
}
}
}
// Decrement reference count or remove path summary node.
private long decrementReferenceCountOrRemove(final ImmutableNameNode node) {
long nodeKey = pathSummaryReader.getNodeKey();
nodeRtx.moveTo(node.getNodeKey());
for (final Axis descendants = new PostOrderAxis(nodeRtx, IncludeSelf.YES); descendants.hasNext(); ) {
descendants.nextLong();
if (nodeRtx.getKind() == NodeKind.ELEMENT) {
final XmlNodeReadOnlyTrx rtx = (XmlNodeReadOnlyTrx) nodeRtx;
final ImmutableElement element = (ImmutableElement) rtx.getNode();
// Namespaces.
for (int i = 0, nsps = element.getNamespaceCount(); i < nsps; i++) {
rtx.moveToNamespace(i);
deleteOrDecrement();
rtx.moveToParent();
}
// Attributes.
for (int i = 0, atts = element.getAttributeCount(); i < atts; i++) {
rtx.moveToAttribute(i);
deleteOrDecrement();
rtx.moveToParent();
}
}
deleteOrDecrement();
}
return nodeKey;
}
/**
* Process a found path node.
*
* @param oldPathNodeKey key of old path node
* @param newPathNodeKey key of new path node
* @param oldNodeKey key of old node
* @param uriKey key of URI
* @param prefixKey key of prefix
* @param localNameKey key of local name
* @throws SirixException if Sirix fails to do so
*/
private void processFoundPathNode(final @NonNegative long oldPathNodeKey, final @NonNegative long newPathNodeKey,
final @NonNegative long oldNodeKey, final QNm name, final int uriKey, final int prefixKey,
final int localNameKey) {
nodeRtx.moveTo(oldNodeKey);
// Set new reference count of the root.
final PathNode currNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
currNode.setReferenceCount(currNode.getReferences() + 1);
currNode.setLocalNameKey(localNameKey);
currNode.setPrefixKey(prefixKey);
currNode.setURIKey(uriKey);
currNode.setName(name);
pathSummaryReader.putMapping(currNode.getNodeKey(), currNode);
pathSummaryReader.putQNameMapping(currNode, name);
final long pathNodeKey = currNode.getNodeKey();
processElementNonStructuralNodes(pathNodeKey, 0);
// For all old path nodes: Merge paths and adapt reference counts.
final boolean movedNodeCursorToFirstChild = nodeRtx.moveToFirstChild();
final boolean movedPathSummaryToFirstChild = pathSummaryReader.moveToFirstChild();
if (movedNodeCursorToFirstChild && movedPathSummaryToFirstChild) {
final long pathRootNodeKey = pathSummaryReader.getNodeKey();
for (final LevelOrderAxis levelOrderAxis =
new LevelOrderAxis.Builder(nodeRtx).includeSelf().build(); levelOrderAxis.hasNext(); ) {
levelOrderAxis.nextLong();
if (nodeRtx.getNode() instanceof ImmutableNameNode) {
adaptPathSummary(levelOrderAxis.getCurrentLevel(), pathRootNodeKey);
processElementNonStructuralNodes(pathRootNodeKey, levelOrderAxis.getCurrentLevel());
}
}
} else if (movedNodeCursorToFirstChild) {
for (final LevelOrderAxis levelOrderAxis =
new LevelOrderAxis.Builder(nodeRtx).includeSelf().build(); levelOrderAxis.hasNext(); ) {
levelOrderAxis.nextLong();
if (nodeRtx.getNode() instanceof ImmutableNameNode) {
adaptForNewPathNode();
processElementNonStructuralNodes(pathSummaryReader.getNodeKey(), levelOrderAxis.getCurrentLevel());
}
}
} else if (movedPathSummaryToFirstChild) {
// Only move back.
pathSummaryReader.moveToParent();
}
pathSummaryReader.moveTo(pathNodeKey);
}
private void processElementNonStructuralNodes(final long pathRootNodeKey, final int level) {
if (nodeRtx.getNode().getKind() == NodeKind.ELEMENT) {
final XmlNodeReadOnlyTrx rtx = (XmlNodeReadOnlyTrx) nodeRtx;
final ImmutableElement element = (ImmutableElement) rtx.getNode();
for (int i = 0, nspCount = element.getNamespaceCount(); i < nspCount; i++) {
rtx.moveToNamespace(i);
adaptPathSummary(level, pathRootNodeKey);
rtx.moveToParent();
}
for (int i = 0, attCount = element.getAttributeCount(); i < attCount; i++) {
rtx.moveToAttribute(i);
adaptPathSummary(level, pathRootNodeKey);
rtx.moveToParent();
}
}
}
private void adaptPathSummary(int level, long newPathNodeKey) {
// Search for new path entry.
final Axis axis =
new FilterAxis<>(new LevelOrderAxis.Builder(pathSummaryReader).filterLevel(level).includeSelf().build(),
new PathNameFilter(pathSummaryReader, Utils.buildName(nodeRtx.getName())),
new PathKindFilter(pathSummaryReader, nodeRtx.getKind()));
if (axis.hasNext()) {
axis.nextLong();
adaptForFoundPathNode();
} else {
adaptForNewPathNode();
}
pathSummaryReader.moveTo(newPathNodeKey);
}
private void adaptForNewPathNode() {
// Move to parent path node.
moveToPathNodeOfParentNode();
// Insert new node.
insertPathAsFirstChild(nodeRtx.getName(), nodeRtx.getKind(), pathSummaryReader.getLevel() + 1);
// Set reference count to one.
setReferenceCountToOne();
// Set new path node key.
setNewPathNodeKey();
}
private void moveToPathNodeOfParentNode() {
final long nodeKey = nodeRtx.getNodeKey();
final long pathNodeKey;
if (nodeRtx instanceof XmlNodeReadOnlyTrx xmlNodeReadOnlyTrx) {
xmlNodeReadOnlyTrx.moveToParent();
pathNodeKey = xmlNodeReadOnlyTrx.getPathNodeKey();
} else if (nodeRtx instanceof JsonNodeReadOnlyTrx jsonNodeReadOnlyTrx) {
jsonNodeReadOnlyTrx.moveToParent();
pathNodeKey = jsonNodeReadOnlyTrx.getPathNodeKey();
} else {
throw new IllegalStateException("Node transaction kind not known.");
}
pathSummaryReader.moveTo(pathNodeKey);
nodeRtx.moveTo(nodeKey);
}
private void adaptForFoundPathNode() {
// Increase reference count.
increaseReferenceCount();
// Set new path node.
resetPathNodeKey(nodeRtx.getNodeKey(), nodeRtx.getKind());
}
private void setNewPathNodeKey() {
final NameNode node = pageTrx.prepareRecordForModification(nodeRtx.getNodeKey(), IndexType.DOCUMENT, -1);
node.setPathNodeKey(pathSummaryReader.getNodeKey());
}
private void setReferenceCountToOne() {
final PathNode currNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
currNode.setReferenceCount(1);
pathSummaryReader.putMapping(currNode.getNodeKey(), currNode);
}
private void increaseReferenceCount() {
// Set new reference count.
final PathNode currNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
currNode.setReferenceCount(currNode.getReferences() + 1);
pathSummaryReader.putMapping(currNode.getNodeKey(), currNode);
}
/**
* Move path summary to the associated {@code parent} {@link PathNode} and get the level of the
* node.
*
* @param node the node to lookup for it's {@link PathNode}
* @return level of the path node
*/
private int moveSummaryGetLevel(final ImmutableNode node) {
assert node != null;
// Get parent path node and level.
nodeRtx.moveToParent();
if (nodeRtx.getKind() == NodeKind.OBJECT)
nodeRtx.moveToParent();
int level = 0;
if (nodeRtx.getKind() == NodeKind.XML_DOCUMENT || nodeRtx.getKind() == NodeKind.JSON_DOCUMENT) {
pathSummaryReader.moveToDocumentRoot();
} else {
movePathSummary();
level = pathSummaryReader.getLevel();
}
nodeRtx.moveTo(node.getNodeKey());
return level;
}
/**
* Reset a path node key.
*
* @param nodeKey the nodeKey of the node to adapt
* @param nodeKind the kind of the node to adapt
* @throws SirixException if anything fails
*/
private void resetPathNodeKey(final @NonNegative long nodeKey, final NodeKind nodeKind) {
if (nodeKind == NodeKind.ATTRIBUTE || nodeKind == NodeKind.ELEMENT || nodeKind == NodeKind.NAMESPACE) {
final NameNode currNode = pageTrx.prepareRecordForModification(nodeKey, IndexType.DOCUMENT, -1);
currNode.setPathNodeKey(pathSummaryReader.getNodeKey());
} else {
final ObjectKeyNode currNode = pageTrx.prepareRecordForModification(nodeKey, IndexType.DOCUMENT, -1);
currNode.setPathNodeKey(pathSummaryReader.getNodeKey());
}
}
/**
* Remove a path summary node with the specified PCR.
*
* @throws SirixException if Sirix fails to remove the path node
*/
private void removePathSummaryNode(final RemoveSubtreePath remove) {
pathSummaryReader.clearCache();
// Remove all descendant nodes.
if (remove == RemoveSubtreePath.YES) {
for (final Axis axis = new PostOrderAxis(pathSummaryReader); axis.hasNext(); ) {
axis.nextLong();
pathSummaryReader.removeMapping(pathSummaryReader.getNodeKey());
pathSummaryReader.removeQNameMapping(pathSummaryReader.getPathNode(), pathSummaryReader.getName());
pageTrx.removeRecord(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
}
}
// Adapt left sibling node if there is one.
if (pathSummaryReader.hasLeftSibling()) {
final StructNode leftSibling =
pageTrx.prepareRecordForModification(pathSummaryReader.getLeftSiblingKey(), IndexType.PATH_SUMMARY, 0);
leftSibling.setRightSiblingKey(pathSummaryReader.getRightSiblingKey());
pathSummaryReader.putMapping(leftSibling.getNodeKey(), leftSibling);
}
// Adapt right sibling node if there is one.
if (pathSummaryReader.hasRightSibling()) {
final StructNode rightSibling =
pageTrx.prepareRecordForModification(pathSummaryReader.getRightSiblingKey(), IndexType.PATH_SUMMARY, 0);
rightSibling.setLeftSiblingKey(pathSummaryReader.getLeftSiblingKey());
pathSummaryReader.putMapping(rightSibling.getNodeKey(), rightSibling);
}
// Adapt parent. If node has no left sibling it is a first child.
StructNode parent =
pageTrx.prepareRecordForModification(pathSummaryReader.getParentKey(), IndexType.PATH_SUMMARY, 0);
if (!pathSummaryReader.hasLeftSibling()) {
parent.setFirstChildKey(pathSummaryReader.getRightSiblingKey());
}
if (storeChildCount) {
parent.decrementChildCount();
}
pathSummaryReader.putMapping(parent.getNodeKey(), parent);
// Remove node.
pathSummaryReader.removeMapping(pathSummaryReader.getNodeKey());
pathSummaryReader.removeQNameMapping(pathSummaryReader.getPathNode(), pathSummaryReader.getName());
pageTrx.removeRecord(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
// pathSummaryReader.moveToDocumentRoot();
//
// System.out.println("removed: =====================");
//
// for (final var descendantAxis = new DescendantAxis(pathSummaryReader); descendantAxis.hasNext(); ) {
// descendantAxis.nextLong();
// System.out.println("path: " + pathSummaryReader.getPath());
// System.out.println("nodeKey: " + pathSummaryReader.getNodeKey());
// System.out.println("rightSiblingKey: " + pathSummaryReader.getRightSiblingKey());
// System.out.println("references: " + pathSummaryReader.getReferences());
// }
}
private void deleteOrDecrement() {
if (nodeRtx.getNode() instanceof ImmutableNameNode) {
movePathSummary();
if (pathSummaryReader.getReferences() == 1) {
removePathSummaryNode(RemoveSubtreePath.NO);
} else {
final PathNode pathNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
pathNode.decrementReferenceCount();
pathSummaryReader.putMapping(pathNode.getNodeKey(), pathNode);
}
}
}
/**
* Decrements the reference-counter of the node or removes the path node if the reference-counter
* would be zero otherwise.
*
* @param node node which is going to be removed from the storage
* @throws SirixException if anything went wrong
*/
public void remove(final ImmutableNameNode node) {
if (pathSummaryReader.moveTo(node.getPathNodeKey())) {
if (pathSummaryReader.getReferences() == 1) {
removePathSummaryNode(RemoveSubtreePath.YES);
} else {
assert pathSummaryReader.getReferences() > 1;
final PathNode pathNode =
pageTrx.prepareRecordForModification(pathSummaryReader.getNodeKey(), IndexType.PATH_SUMMARY, 0);
pathNode.decrementReferenceCount();
pathSummaryReader.putMapping(pathNode.getNodeKey(), pathNode);
}
}
}
@Override
protected PathSummaryReader delegate() {
return pathSummaryReader;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy