public StageTree(TreeObject base, int capacity) { this.shadow = base; this.capacity = capacity; reset(); }
/** * Commit the changes made on this stage to the repo, returning the reference for the TreeObject * we will save for this. * * @param rp * @param commitRef * @return @ */ public String commitStage( VersionedRepo rp, String commitRef, CommitCollector collector, Map<DocumentObject, String> savedDocRefs) { // We create a new tree TreeObject newTreeObject = new TreeObject(); // We need to work out a new document bag structure, by removing and // resaving any document bags that have had // items removed... We then add back any documents back into the bags // that have room Set<DocumentBagObject> needToSave = new HashSet<DocumentBagObject>(); Map<String, DocumentBagObject> maybeReuse = new HashMap<String, DocumentBagObject>(); Set<String> refsToSave = new HashSet<String>(); workOutCommitChanges(rp, needToSave, maybeReuse, refsToSave); applyNewSaves(newTreeObject, refsToSave); // For the ones in needToSave, we can use them to hopefully fill a gap Map<String, DocumentObject> combinedSet = rebalanceTree(); for (Map.Entry<String, DocumentObject> entries : combinedSet.entrySet()) { // If the document is already in the savedDocRefs, we don't need to // save it, we should simply get the reference // from that String reference = null; if (savedDocRefs.containsKey(entries.getValue())) { reference = savedDocRefs.get(entries.getValue()); } else { entries.getValue().setCommitRef(commitRef); reference = rp.getObjectDatabase().writeDocument(entries.getValue()); savedDocRefs.put(entries.getValue(), reference); } collector.addDocReference(reference); collector.addDocName(entries.getKey()); // Find a spot to put this reference in boolean done = false; for (DocumentBagObject d : needToSave) { if (d.getDocRefs().size() < capacity) { d.getDocRefs().put(entries.getKey(), reference); done = true; break; } } if (!done && maybeReuse.size() != 0) { Map.Entry<String, DocumentBagObject> d = maybeReuse.entrySet().iterator().next(); d.getValue().getDocRefs().put(entries.getKey(), reference); needToSave.add(d.getValue()); maybeReuse.remove(d.getKey()); done = true; } if (!done) { DocumentBagObject dNew = new DocumentBagObject(); dNew.getDocRefs().put(entries.getKey(), reference); needToSave.add(dNew); } } // Add back those we didn't use for (String k : maybeReuse.keySet()) { if (!removedDocuments.contains(k)) { DocumentBagReference dr = new DocumentBagReference(); dr.setBagRef(k); dr.setSize(maybeReuse.get(k).getDocRefs().size()); newTreeObject.getDocuments().add(dr); } } // Now we need to save the need to save for (DocumentBagObject d : needToSave) { String reference = rp.getObjectDatabase().writeDocumentBag(d); DocumentBagReference dr = new DocumentBagReference(); dr.setBagRef(reference); dr.setSize(d.getDocRefs().size()); newTreeObject.getDocuments().add(dr); } newTreeObject.getTrees().putAll(shadow.getTrees()); // Add the new ones, do the trees first for (Map.Entry<String, StageTree> entries : stagedTrees.entrySet()) { collector.enterFolder(entries.getKey()); String reference = entries.getValue().commitStage(rp, commitRef, collector, savedDocRefs); collector.addTreeReference(reference); collector.leaveFolder(); collector.addFolderName(entries.getKey()); newTreeObject.getTrees().put(entries.getKey(), reference); } shadow = newTreeObject; reset(); return rp.getObjectDatabase().writeTree(newTreeObject); }