示例#1
0
 private void mergeStageTree(VersionedRepo rp, String cRef, Map.Entry<String, String> t) {
   // They are different, we need to merge them
   StageTree st =
       new StageTree(rp.getObjectDatabase().getTree(shadow.getTrees().get(t.getKey())), capacity);
   st.apply(rp, rp.getObjectDatabase().getTree(t.getValue()), cRef);
   stagedTrees.put(t.getKey(), st);
 }
示例#2
0
 private void applyToBag(VersionedRepo rp, String cRef, DocumentBagObject dObj) {
   for (Map.Entry<String, String> d : dObj.getDocRefs().entrySet()) {
     boolean found = false;
     for (DocumentBagReference bagRef2 : shadow.getDocuments()) {
       DocumentBagObject dObj2 = rp.getObjectDatabase().getDocumentBag(bagRef2.getBagRef());
       if (dObj2.getDocRefs().containsKey(d.getKey())) {
         if (!dObj2.getDocRefs().get(d.getKey()).equals(d.getValue())) {
           // Here we have to see what we prefer - the target
           // could
           // have moved this document forward and
           // that is why they are different. OR we could have
           // moved it forward. Who wins? How do we know
           // whether
           // this document was modified here? - perhaps we add
           // the
           // commit to the BaseObject
           found = true;
           DocumentObject dob = rp.getObjectDatabase().getDocument(d.getValue());
           if (cRef.equals(dob.getCommitRef())) {
             stagedDocuments.put(d.getKey(), rp.getObjectDatabase().getDocument(d.getValue()));
           }
         }
       }
     }
     if (!found) {
       stagedDocuments.put(d.getKey(), rp.getObjectDatabase().getDocument(d.getValue()));
     }
   }
 }
示例#3
0
 /**
  * Add this document to this tree
  *
  * <p>If parts is of length 1, add it to this tree, otherwise either resolve (shadow) an existing
  * tree in the shadow tree as a StagedTree and add the document to that (removing one from the
  * list)
  *
  * @param parts
  * @param doc
  * @param mustBeNew
  * @throws Exception
  */
 public void addDocumentToStage(
     VersionedRepo rp, List<String> parts, DocumentObject doc, boolean mustBeNew) {
   if (parts.size() == 1) {
     if (mustBeNew) {
       newStagedDocuments.put(parts.get(0), doc);
     } else {
       stagedDocuments.put(parts.get(0), doc);
     }
   } else {
     String currentLevel = parts.remove(0);
     if (stagedTrees.containsKey(currentLevel)) {
       stagedTrees.get(currentLevel).addDocumentToStage(rp, parts, doc, mustBeNew);
     } else {
       if (shadow.getTrees().containsKey(currentLevel)) {
         TreeObject to = rp.getObjectDatabase().getTree(shadow.getTrees().get(currentLevel));
         StageTree newStage = new StageTree(to, capacity);
         stagedTrees.put(currentLevel, newStage);
       } else {
         StageTree newStage = new StageTree(new TreeObject(), capacity);
         stagedTrees.put(currentLevel, newStage);
       }
       stagedTrees.get(currentLevel).addDocumentToStage(rp, parts, doc, mustBeNew);
     }
   }
 }
示例#4
0
 private void workOutCommitChanges(
     VersionedRepo rp,
     Set<DocumentBagObject> needToSave,
     Map<String, DocumentBagObject> maybeReuse,
     Set<String> refsToSave) {
   for (DocumentBagReference docRef : shadow.getDocuments()) {
     refsToSave.add(docRef.getBagRef());
     DocumentBagObject dbo = rp.getObjectDatabase().getDocumentBag(docRef.getBagRef());
     boolean changed = false;
     for (String key : stagedDocuments.keySet()) {
       if (dbo.getDocRefs().containsKey(key)) {
         // We need to be saving this back
         dbo.getDocRefs().remove(key);
         needToSave.add(dbo);
         refsToSave.remove(docRef.getBagRef());
         changed = true;
         break;
       }
     }
     for (String rem : removedDocuments) {
       if (dbo.getDocRefs().containsKey(rem)) {
         dbo.getDocRefs().remove(rem);
         refsToSave.remove(docRef.getBagRef());
         needToSave.add(dbo);
         changed = true;
       }
     }
     if (!changed) {
       if (dbo.getDocRefs().size() < capacity) {
         maybeReuse.put(docRef.getBagRef(), dbo);
         refsToSave.remove(docRef.getBagRef());
       }
     }
   }
 }
示例#5
0
 private void applyDocuments(VersionedRepo rp, TreeObject apply, String cRef) {
   // Documents is a bit easier, simply overwrite for now...
   for (DocumentBagReference bagRef : apply.getDocuments()) {
     DocumentBagObject dObj = rp.getObjectDatabase().getDocumentBag(bagRef.getBagRef());
     applyToBag(rp, cRef, dObj);
   }
 }
示例#6
0
  public boolean removeFromStage(VersionedRepo rp, LinkedList<String> parts) {
    // Find the staged tree associated with this part and remove the
    // document reference from it

    String currentLevel = parts.remove();
    boolean removed = false;

    if (!parts.isEmpty()) {
      if (stagedTrees.containsKey(currentLevel)) {
        stagedTrees.get(currentLevel).removeFromStage(rp, parts);
      } else if (shadow.getTrees().containsKey(currentLevel)) {
        TreeObject to = rp.getObjectDatabase().getTree(shadow.getTrees().get(currentLevel));
        StageTree newStage = new StageTree(to, capacity);
        stagedTrees.put(currentLevel, newStage);
        removed = newStage.removeFromStage(rp, parts);
      }
    } else {
      removedDocuments.add(currentLevel);
      removed = true;
    }
    return removed;
  }
示例#7
0
  /**
   * 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);
  }
示例#8
0
 private void addStageTree(VersionedRepo rp, Map.Entry<String, String> t) {
   StageTree st = new StageTree(rp.getObjectDatabase().getTree(t.getValue()), capacity);
   stagedTrees.put(t.getKey(), st);
 }