Removing unused nodes from JackRabbit versionStorage - jackrabbit

I have a scenario where a repository contains several version nodes that don't reference any mix:versionable nodes. This is because those versionable nodes have been removed from repository but not their corresponding versions.
This is causing that the JackRabbit Garbage collector cannot remove some files from datastore, because there are versions that still reference them, and consequently the disk space is not properly freed.
I tried to manually remove those versions with the following algorithm:
Obtain a version by its path, let's say: /jcr:system/jcr:versionStorage/40/05/a9/4005a9b2-51d1-4ed1-8c30-934409e05f86/1.14/jcr:frozenNode
Get the jcr:frozenUuid property from the obtained node
Get the node by identifier, using the frozenUuid from step 2
If no such node exists, remove the version
But in the last step I get the following exception:
javax.jcr.nodetype.ConstraintViolationException: Unable to perform operation. Node is protected.
So, my question is. How can I remove the version nodes that are unused?
I'm using jackrabbit-2.2.13.

This is how I remove my versions...
String nodePath...
String versionName...
Session session...
VersionManager versionManager = session.getWorkspace().getVersionManager()
VersionHistory versionHistory = versionManager.getVersionHistory(nodePath);
versionHistory.removeVersion(versionName);

I think this will help you to traverse all the versions so that you can remove or restore.
Node vs = session.getRootNode().getNode("jcr:system").getNode("jcr:versionStorage");
Version v = traverseVersionStorage(vs, 0);
private static Version traverseVersionStorage(Node n, int level)
throws Exception {
Version v = null;
for (NodeIterator it = n.getNodes(); it.hasNext();) {
Node n2 = it.nextNode();
if (n2 instanceof Version && !n2.getName().startsWith("jcr:")) {
v = (Version) n2;
System.out.println("version " + n2.getName() + " of node "+ n2.getParent().getName() + ":");
Node n3 = n2.getNode("jcr:frozenNode");
VersionManager vman=session.getWorkspace().getVersionManager();
Node parent=n3.getParent();
System.out.println(parent.getName());
vman.restore("/any/path/where/to/restore", v, true);
session.save();
}
Version v2 = traverseVersionStorage(n2, level + 1);
v = v == null ? v2 : v;
}
return v;
}
below code is to traverse all versions of a node and remove by versionName
VersionManager versionManager=jcrsession.getWorkspace().getVersionManager();
VersionHistory vHistory=versionManager.getVersionHistory("/absolute/path/of/node/which/versions/to/be/removed");
for (VersionIterator pt = vHistory.getAllVersions(); pt.hasNext();)
{
Version p = pt.nextVersion();
if(p.getName()!="jcr:rootVersion")
{
vHistory.removeVersion(p.getName());
}
}

Related

Pooling and children removal

I try to use pooling with my qx.application, because it gives me a significant performance boost on mobile devices (especially Android devices).
For structuring (and for setting huge widget selections to “excluded” with one command) I use many widgets including qx.ui.core.MChildrenHandling.
After leaving a menu I iterate through all containers recursively and add them and their children to a pool.
For object creation I try to get an instance from the pool.
This is working really fine but after some time I get the following error (on Chrome for Android):
“Uncaught HierarchyRequestError: Failed to execute 'appendChild' on 'Node': The new child element contains the parent”
With disposal of the objects, everything runs fine.
This leads me to the conclusion that the objects aren’t always removed from their DOM parent which leads to recursion (a node is added to an old child node of itself).
Can someone point me in right direction how to ensure the removal of the child nodes before pooling them?
Below is the code I use for pooling:
function getPoolElement(type) {
var elem = pool.getObject(type);
//console.log(type.toString() + " " + elem.$$hash + " " + elem.classname);
return elem;
}
function poolElements(container) {
var children = container.removeAll();
for(var i = 0; i < children.length; i++) {
if(children[i].classname == "guibuilder.group"
|| children[i].classname == "guibuilder.picgroup"
|| children[i].classname == "guibuilder.tablegroup"
|| children[i].classname == "guibuilder.bordergroup") {
poolElements(children[i]);
} else if(children[i].classname == "guibuilder.smallchoice"
|| children[i].classname == "guibuilder.choice") {
var opts = children[i].removeAll();
for(var j = 0; j < opts.length; j++) {
pool.poolObject(opts[j]);
//opts[j].dispose();
}
}
pool.poolObject(children[i]);
//children[i].dispose();
}
}
Regards, Johannes

Fetching recent version of a file from Jackrabbit repository

I am very new in Jack Rabbit repository.! So please guide me for fetching recent version of a file from Jackrabbit repository.
My code is :
try{
session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
Node root = session.getRootNode();
if (!root.hasNode(nodeName)) {
root.addNode(nodeName, "nt:unstructured");
session.save();
}
String extention = FilenameUtils.getExtension(originalFileName);
InputStream stream = new BufferedInputStream(new FileInputStream(file));
Node roseNode = session.getRootNode().getNode(nodeName);
VersionManager vm = session.getWorkspace().getVersionManager();
Node fileNode = null;
if(roseNode.hasNode(fileName.toString()+"."+extention)){
fileNode = roseNode.getNode(fileName.toString()+"."+extention);
vm.checkout(fileNode.getPath());
} else {
fileNode = roseNode.addNode(fileName.toString()+"."+extention, "nt:unstructured");
fileNode.addMixin("mix:versionable");
fileNode.setProperty(extention, fileName.toString());
session.save();
}
Node content = fileNode.addNode("jcr:content", "nt:resource");
Binary binary = session.getValueFactory().createBinary(stream);
content.setProperty("jcr:data", binary);
stream.close();
session.save();
vm.checkin(fileNode.getPath());
I tried this.. But I am getting the older file while fetching..
Please help me on this...
Thanks in advance..
Finally I got it in this way, I tried following query as:
String expression = "select * from [nt:base] as b where name(b)= '"+fileName+"' ";
Query query = queryManager.createQuery(expression, Query.JCR_SQL2);
QueryResult result = query.execute();
NodeIterator iterator = result.getNodes();
VersionManager vm = session.getWorkspace().getVersionManager();
if(iterator.getSize() > 0){
Node node = iterator.nextNode();
Node recentVersionNode = null;
NodeIterator versionIterator = node.getNodes();
/*
A node has multiple content nodes with ("jcr:content", "nt:resource")
these are of different versions, so the file with name abc.pdf
will have multiple versions/content so that we can get
the recent version of content node of the same file.
*/
while(versionIterator.hasNext()){
recentVersionNode = versionIterator.nextNode();
}
finally I got the file node that is uploaded recently in to the Jackrabbit repository.
And we can fetch any version of the file by specifying the index of "jcr:content"

Behavior of initial.min.cluster.size

Is Hazelcast always blocking in case initial.min.cluster.size is not reached? If not, under which situations is it not?
Details:
I use the following code to initialize hazelcast:
Config cfg = new Config();
cfg.setProperty("hazelcast.initial.min.cluster.size",Integer.
toString(minimumInitialMembersInHazelCluster)); //2 in this case
cfg.getGroupConfig().setName(clusterName);
NetworkConfig network = cfg.getNetworkConfig();
JoinConfig join = network.getJoin();
join.getMulticastConfig().setEnabled(false);
join.getTcpIpConfig().addMember("192.168.0.1").addMember("192.168.0.2").
addMember("192.168.0.3").addMember("192.168.0.4").
addMember("192.168.0.5").addMember("192.168.0.6").
addMember("192.168.0.7").setRequiredMember(null).setEnabled(true);
network.getInterfaces().setEnabled(true).addInterface("192.168.0.*");
join.getMulticastConfig().setMulticastTimeoutSeconds(MCSOCK_TIMEOUT/100);
hazelInst = Hazelcast.newHazelcastInstance(cfg);
distrDischargedTTGs = hazelInst.getList(clusterName);
and get log messages like
debug: starting Hazel pullExternal from Hazelcluster with 1 members.
Does that definitely mean there was another member that has joined and left already? It does not look like that would be the case from the log files of the other instance. Hence I wonder whether there are situtations where hazelInst = Hazelcast.newHazelcastInstance(cfg); does not block even though it is the only instance in the hazelcast cluster.
The newHazelcastInstance blocks till the clusters has the required number of members.
See the code below for how it is implemented:
private static void awaitMinimalClusterSize(HazelcastInstanceImpl hazelcastInstance, Node node, boolean firstMember)
throws InterruptedException {
final int initialMinClusterSize = node.groupProperties.INITIAL_MIN_CLUSTER_SIZE.getInteger();
while (node.getClusterService().getSize() < initialMinClusterSize) {
try {
hazelcastInstance.logger.info("HazelcastInstance waiting for cluster size of " + initialMinClusterSize);
//noinspection BusyWait
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException ignored) {
}
}
if (initialMinClusterSize > 1) {
if (firstMember) {
node.partitionService.firstArrangement();
} else {
Thread.sleep(TimeUnit.SECONDS.toMillis(3));
}
hazelcastInstance.logger.info("HazelcastInstance starting after waiting for cluster size of "
+ initialMinClusterSize);
}
}
If you set the logging on debug then perhaps you can see better what is happening. Member joining and leaving should already be visible under info.

How to check if a node exists in CQ extjs?

Is there a way to check if a node exist and then get the fetch the property value of it?
Use CQ.Util.eval function and pass the node path followed by the .json extension as a single arugment:
var node = CQ.Util.eval('/content/geometrixx/en/jcr:content.json');
If the node doesn't exists you'll get null. Otherwise you can get properties using brackets:
if (node != null) {
console.log(node['jcr:title']);
}

OrientDB - Trouble storing data from a java application

I am trying to store triplets inside of OrientDB as Vertex-Edge-Vertex relationships inside of a Java application that I am working on. My understanding of using OrientDB is that I can use the Tinkerpop API and instantiate a graph like this:
OrientGraph graph = new OrientGraph("local:/tmp/orient/test_db");
That is really all I do to instantiate the graph, then I try to connect vertices with edges in a loop like this: (Note that a Statement is a triplet consisting of subject-relationship-object.)
for (Statement s : statements) {
Vertex a = graph.addVertex(null);
Vertex b = graph.addVertex(null);
a.setProperty("Subject", s.getSubject().toBELShortForm());
RelationshipType r = s.getRelationshipType();
if (s.getObject() != null) {
b.setProperty("Object", s.getObject().toBELShortForm());
Edge e = graph.addEdge(null, a, b, r.toString());
}
else {
b.setProperty("Object", "null");
Edge e = graph.addEdge(null, a, b, "no-relationship");
}
}
I then loop through the vertices of the graph and print them out like this:
for (Vertex v : graph.getVertices()) {
out.println("Vertex: " +v.toString());
}
It does print a lot of vertices, but when I log into the server via the command line, using server.sh, all I see are the 3 records for ORole and 4 records for OUser. What am I missing here? Because it seems like although my java program runs and completes, the data is not being put into the database.
The answer, at least for now, seems to be not to use the Tinkerpop API but rather the Orient API directly. This is the same thing I was doing with Tinkerpop, but using the OrientDB API. This actually does store my data into the database:
for (Statement s : statements) {
ODocument sNode = db.createVertex();
sNode.field("Subject", s.getSubject().toBELShortForm());
sNode.save();
ODocument oNode = db.createVertex();
if (s.getObject() != null) {
oNode.field("Object", s.getObject().toBELShortForm());
oNode.save();
}
else {
oNode.field("Object", "null");
oNode.save();
}
RelationshipType r = s.getRelationshipType();
ODocument edge = db.createEdge(sNode, oNode);
if (r != null) {
edge.field(r.toString());
edge.save();
}
else {
edge.field("no relationship");
edge.save();
}
}
Create the Graph under the Server's databases directory. Below an example assuming OrientDB has been installed under "/usr/local/orient":
OrientGraph graph = new OrientGraph("local:/usr/local/orient/databases/test_db");
When you start the server.sh you should find this database correctly populated.
Lvc#

Resources