Esempio n. 1
0
  private FSInputStream(SVNDeltaCombiner combiner, FSRepresentation representation, FSFS owner)
      throws SVNException {
    myCombiner = combiner;
    myChunkIndex = 0;
    isChecksumFinalized = false;
    myHexChecksum = representation.getMD5HexDigest();
    myOffset = 0;
    myLength = representation.getExpandedSize();
    try {
      myDigest = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException nsae) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.IO_ERROR,
              "MD5 implementation not found: {0}",
              nsae.getLocalizedMessage());
      SVNErrorManager.error(err, nsae, SVNLogType.FSFS);
    }

    try {
      buildRepresentationList(representation, myRepStateList, owner);
    } catch (SVNException svne) {
      /*
       * Something terrible has happened while building rep list, need to
       * close any files still opened
       */
      close();
      throw svne;
    }
  }
 private static boolean areRepresentationsEqual(
     FSRevisionNode revNode1, FSRevisionNode revNode2, boolean forProperties) {
   if (revNode1 == revNode2) {
     return true;
   } else if (revNode1 == null || revNode2 == null) {
     return false;
   }
   return FSRepresentation.compareRepresentations(
       forProperties ? revNode1.getPropsRepresentation() : revNode1.getTextRepresentation(),
       forProperties ? revNode2.getPropsRepresentation() : revNode2.getTextRepresentation());
 }
Esempio n. 3
0
  private FSRepresentationState buildRepresentationList(
      FSRepresentation firstRep, LinkedList result, FSFS owner) throws SVNException {
    FSFile file = null;
    FSRepresentation rep = new FSRepresentation(firstRep);
    ByteBuffer buffer = ByteBuffer.allocate(4);
    try {
      while (true) {
        file = owner.openAndSeekRepresentation(rep);
        FSRepresentationState repState = readRepresentationLine(file);
        repState.myFile = file;
        repState.myStart = file.position();
        repState.myOffset = repState.myStart;
        repState.myEnd = repState.myStart + rep.getSize();
        if (!repState.myIsDelta) {
          return repState;
        }
        buffer.clear();
        int r = file.read(buffer);

        byte[] header = buffer.array();
        if (!(header[0] == 'S' && header[1] == 'V' && header[2] == 'N' && r == 4)) {
          SVNErrorMessage err =
              SVNErrorMessage.create(
                  SVNErrorCode.FS_CORRUPT, "Malformed svndiff data in representation");
          SVNErrorManager.error(err, SVNLogType.FSFS);
        }
        repState.myVersion = header[3];
        repState.myChunkIndex = 0;
        repState.myOffset += 4;
        /*
         * Push this rep onto the list. If it's self-compressed, we're
         * done.
         */
        result.addLast(repState);
        if (repState.myIsDeltaVsEmpty) {
          return null;
        }
        rep.setRevision(repState.myBaseRevision);
        rep.setOffset(repState.myBaseOffset);
        rep.setSize(repState.myBaseLength);
        rep.setTxnId(null);
      }
    } catch (IOException ioe) {
      file.close();
      SVNErrorMessage err =
          SVNErrorMessage.create(SVNErrorCode.IO_ERROR, ioe.getLocalizedMessage());
      SVNErrorManager.error(err, ioe, SVNLogType.FSFS);
    } catch (SVNException svne) {
      file.close();
      throw svne;
    }
    return null;
  }
Esempio n. 4
0
  private static long merge(
      FSFS owner,
      String targetPath,
      FSRevisionNode target,
      FSRevisionNode source,
      FSRevisionNode ancestor,
      FSTransactionRoot txnRoot,
      StringBuffer conflictPath)
      throws SVNException {
    FSID sourceId = source.getId();
    FSID targetId = target.getId();
    FSID ancestorId = ancestor.getId();
    long mergeInfoIncrement = 0;

    if (ancestorId.equals(targetId)) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_GENERAL,
              "Bad merge; target ''{0}'' has id ''{1}'', same as ancestor",
              new Object[] {targetPath, targetId});
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (ancestorId.equals(sourceId) || sourceId.equals(targetId)) {
      return mergeInfoIncrement;
    }

    if (source.getType() != SVNNodeKind.DIR
        || target.getType() != SVNNodeKind.DIR
        || ancestor.getType() != SVNNodeKind.DIR) {
      SVNErrorManager.error(FSErrors.errorConflict(targetPath, conflictPath), SVNLogType.FSFS);
    }

    if (!FSRepresentation.compareRepresentations(
        target.getPropsRepresentation(), ancestor.getPropsRepresentation())) {
      SVNErrorManager.error(FSErrors.errorConflict(targetPath, conflictPath), SVNLogType.FSFS);
    }

    Map sourceEntries = source.getDirEntries(owner);
    Map targetEntries = target.getDirEntries(owner);
    Map ancestorEntries = ancestor.getDirEntries(owner);
    Set removedEntries = new SVNHashSet();
    for (Iterator ancestorEntryNames = ancestorEntries.keySet().iterator();
        ancestorEntryNames.hasNext(); ) {
      String ancestorEntryName = (String) ancestorEntryNames.next();
      FSEntry ancestorEntry = (FSEntry) ancestorEntries.get(ancestorEntryName);
      FSEntry sourceEntry =
          removedEntries.contains(ancestorEntryName)
              ? null
              : (FSEntry) sourceEntries.get(ancestorEntryName);
      FSEntry targetEntry = (FSEntry) targetEntries.get(ancestorEntryName);
      if (sourceEntry != null && ancestorEntry.getId().equals(sourceEntry.getId())) {
        /*
         * No changes were made to this entry while the transaction was
         * in progress, so do nothing to the target.
         */
      } else if (targetEntry != null && ancestorEntry.getId().equals(targetEntry.getId())) {
        if (owner.supportsMergeInfo()) {
          FSRevisionNode targetEntryNode = owner.getRevisionNode(targetEntry.getId());
          long mergeInfoStart = targetEntryNode.getMergeInfoCount();
          mergeInfoIncrement -= mergeInfoStart;
        }
        if (sourceEntry != null) {
          if (owner.supportsMergeInfo()) {
            FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
            long mergeInfoEnd = sourceEntryNode.getMergeInfoCount();
            mergeInfoIncrement += mergeInfoEnd;
          }
          txnRoot.setEntry(target, ancestorEntryName, sourceEntry.getId(), sourceEntry.getType());
        } else {
          txnRoot.deleteEntry(target, ancestorEntryName);
        }
      } else {

        if (sourceEntry == null || targetEntry == null) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        if (sourceEntry.getType() == SVNNodeKind.FILE
            || targetEntry.getType() == SVNNodeKind.FILE
            || ancestorEntry.getType() == SVNNodeKind.FILE) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        if (!sourceEntry.getId().getNodeID().equals(ancestorEntry.getId().getNodeID())
            || !sourceEntry.getId().getCopyID().equals(ancestorEntry.getId().getCopyID())
            || !targetEntry.getId().getNodeID().equals(ancestorEntry.getId().getNodeID())
            || !targetEntry.getId().getCopyID().equals(ancestorEntry.getId().getCopyID())) {
          SVNErrorManager.error(
              FSErrors.errorConflict(
                  SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, ancestorEntryName)),
                  conflictPath),
              SVNLogType.FSFS);
        }

        FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
        FSRevisionNode targetEntryNode = owner.getRevisionNode(targetEntry.getId());
        FSRevisionNode ancestorEntryNode = owner.getRevisionNode(ancestorEntry.getId());
        String childTargetPath =
            SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, targetEntry.getName()));
        long subMergeInfoIncrement =
            merge(
                owner,
                childTargetPath,
                targetEntryNode,
                sourceEntryNode,
                ancestorEntryNode,
                txnRoot,
                conflictPath);
        if (owner.supportsMergeInfo()) {
          mergeInfoIncrement += subMergeInfoIncrement;
        }
      }

      removedEntries.add(ancestorEntryName);
    }

    for (Iterator sourceEntryNames = sourceEntries.keySet().iterator();
        sourceEntryNames.hasNext(); ) {
      String sourceEntryName = (String) sourceEntryNames.next();
      if (removedEntries.contains(sourceEntryName)) {
        continue;
      }
      FSEntry sourceEntry = (FSEntry) sourceEntries.get(sourceEntryName);
      FSEntry targetEntry = (FSEntry) targetEntries.get(sourceEntryName);
      if (targetEntry != null) {
        SVNErrorManager.error(
            FSErrors.errorConflict(
                SVNPathUtil.getAbsolutePath(SVNPathUtil.append(targetPath, targetEntry.getName())),
                conflictPath),
            SVNLogType.FSFS);
      }
      if (owner.supportsMergeInfo()) {
        FSRevisionNode sourceEntryNode = owner.getRevisionNode(sourceEntry.getId());
        long mergeInfoCount = sourceEntryNode.getMergeInfoCount();
        mergeInfoIncrement += mergeInfoCount;
      }
      txnRoot.setEntry(target, sourceEntry.getName(), sourceEntry.getId(), sourceEntry.getType());
    }
    long sourceCount = source.getCount();
    updateAncestry(owner, sourceId, targetId, targetPath, sourceCount);
    if (owner.supportsMergeInfo()) {
      txnRoot.incrementMergeInfoCount(target, mergeInfoIncrement);
    }
    return mergeInfoIncrement;
  }
Esempio n. 5
0
  public void close() throws IOException {
    if (myIsClosed) {
      return;
    }
    myIsClosed = true;
    final long truncateToSize[] = new long[] {-1};
    try {
      ByteArrayInputStream target = new ByteArrayInputStream(myTextBuffer.toByteArray());
      myDeltaGenerator.sendDelta(null, mySourceStream, mySourceOffset, target, this, false);

      final FSRepresentation rep = new FSRepresentation();
      rep.setOffset(myRepOffset);

      long offset = myTargetFileOS.getPosition();

      rep.setSize(offset - myDeltaStart);
      rep.setExpandedSize(myRepSize);
      rep.setTxnId(myRevNode.getId().getTxnID());
      String uniqueSuffix = myTxnRoot.getNewTxnNodeId();
      String uniquifier = rep.getTxnId() + '/' + uniqueSuffix;
      rep.setUniquifier(uniquifier);
      rep.setRevision(SVNRepository.INVALID_REVISION);

      rep.setMD5HexDigest(SVNFileUtil.toHexDigest(myMD5Digest));
      rep.setSHA1HexDigest(SVNFileUtil.toHexDigest(mySHA1Digest));

      FSFS fsfs = myTxnRoot.getOwner();
      final IFSRepresentationCacheManager reposCacheManager = fsfs.getRepositoryCacheManager();
      if (reposCacheManager != null) {
        try {
          reposCacheManager.runReadTransaction(
              new IFSSqlJetTransaction() {
                public void run() throws SVNException {
                  final FSRepresentation oldRep =
                      reposCacheManager.getRepresentationByHash(rep.getSHA1HexDigest());
                  if (oldRep != null) {
                    oldRep.setUniquifier(rep.getUniquifier());
                    oldRep.setMD5HexDigest(rep.getMD5HexDigest());
                    truncateToSize[0] = myRepOffset;
                    myRevNode.setTextRepresentation(oldRep);
                  }
                }
              });
        } catch (SVNException e) {
          // explicitly ignore.
          SVNDebugLog.getDefaultLog().logError(SVNLogType.FSFS, e);
        }
      }
      if (truncateToSize[0] < 0) {
        myTargetFileOS.write("ENDREP\n".getBytes("UTF-8"));
        myRevNode.setTextRepresentation(rep);
      }
      myRevNode.setIsFreshTxnRoot(false);
      fsfs.putTxnRevisionNode(myRevNode.getId(), myRevNode);
    } catch (SVNException svne) {
      throw new IOException(svne.getMessage());
    } finally {
      closeStreams(truncateToSize[0]);
      try {
        myTxnLock.unlock();
      } catch (SVNException e) {
        //
      }
      FSWriteLock.release(myTxnLock);
    }
  }
Esempio n. 6
0
  public static OutputStream createStream(
      FSRevisionNode revNode, FSTransactionRoot txnRoot, OutputStream dstStream, boolean compress)
      throws SVNException {
    if (revNode.getType() != SVNNodeKind.FILE) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_FILE, "Attempted to set textual contents of a *non*-file node");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    if (!revNode.getId().isTxn()) {
      SVNErrorMessage err =
          SVNErrorMessage.create(
              SVNErrorCode.FS_NOT_MUTABLE,
              "Attempted to set textual contents of an immutable node");
      SVNErrorManager.error(err, SVNLogType.FSFS);
    }

    OutputStream targetOS = null;
    InputStream sourceStream = null;
    long offset = -1;
    long deltaStart = -1;
    FSWriteLock txnLock = null;
    try {
      txnLock = FSWriteLock.getWriteLockForTxn(txnRoot.getTxnID(), txnRoot.getOwner());
      txnLock.lock();

      File targetFile = txnRoot.getTransactionProtoRevFile();
      offset = targetFile.length();
      targetOS = SVNFileUtil.openFileForWriting(targetFile, true);
      CountingOutputStream revWriter = new CountingOutputStream(targetOS, offset);

      FSRepresentation baseRep = revNode.chooseDeltaBase(txnRoot.getOwner());
      sourceStream =
          FSInputStream.createDeltaStream(new SVNDeltaCombiner(), baseRep, txnRoot.getOwner());
      String header;

      if (baseRep != null) {
        header =
            FSRepresentation.REP_DELTA
                + " "
                + baseRep.getRevision()
                + " "
                + baseRep.getOffset()
                + " "
                + baseRep.getSize()
                + "\n";
      } else {
        header = FSRepresentation.REP_DELTA + "\n";
      }

      revWriter.write(header.getBytes("UTF-8"));
      deltaStart = revWriter.getPosition();

      if (dstStream instanceof FSOutputStream) {
        FSOutputStream fsOS = (FSOutputStream) dstStream;
        fsOS.reset(
            revNode, revWriter, targetFile, sourceStream, deltaStart, 0, offset, txnRoot, txnLock);
        return dstStream;
      }

      return new FSOutputStream(
          revNode,
          revWriter,
          targetFile,
          sourceStream,
          deltaStart,
          0,
          offset,
          txnRoot,
          compress,
          txnLock);

    } catch (IOException ioe) {
      SVNFileUtil.closeFile(targetOS);
      SVNFileUtil.closeFile(sourceStream);
      txnLock.unlock();
      FSWriteLock.release(txnLock);
      SVNErrorMessage err =
          SVNErrorMessage.create(SVNErrorCode.IO_ERROR, ioe.getLocalizedMessage());
      SVNErrorManager.error(err, ioe, SVNLogType.FSFS);
    } catch (SVNException svne) {
      if (txnLock != null) {
        txnLock.unlock();
        FSWriteLock.release(txnLock);
      }
      SVNFileUtil.closeFile(targetOS);
      SVNFileUtil.closeFile(sourceStream);
      throw svne;
    }
    return null;
  }