private long commit() throws SVNException { long oldRev = myFSFS.getYoungestRevision(); if (myTxn.getBaseRevision() != oldRev) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.FS_TXN_OUT_OF_DATE, "Transaction out of date"); SVNErrorManager.error(err, SVNLogType.FSFS); } verifyLocks(); final String startNodeId; final String startCopyId; if (myFSFS.getDBFormat() < FSFS.MIN_NO_GLOBAL_IDS_FORMAT) { String[] ids = myFSFS.getNextRevisionIDs(); startNodeId = ids[0]; startCopyId = ids[1]; } else { startNodeId = null; startCopyId = null; } final long newRevision = oldRev + 1; final OutputStream protoFileOS = null; final FSID newRootId = null; final FSTransactionRoot txnRoot = getTxnRoot(); FSWriteLock txnWriteLock = FSWriteLock.getWriteLockForTxn(myTxn.getTxnId(), myFSFS); synchronized (txnWriteLock) { try { // start transaction. txnWriteLock.lock(); final File revisionPrototypeFile = txnRoot.getTransactionProtoRevFile(); final long offset = revisionPrototypeFile.length(); if (myFSFS.getRepositoryCacheManager() != null) { myFSFS .getRepositoryCacheManager() .runWriteTransaction( new IFSSqlJetTransaction() { public void run() throws SVNException { commit( startNodeId, startCopyId, newRevision, protoFileOS, newRootId, txnRoot, revisionPrototypeFile, offset); } }); } else { commit( startNodeId, startCopyId, newRevision, protoFileOS, newRootId, txnRoot, revisionPrototypeFile, offset); } File dstRevFile = myFSFS.getNewRevisionFile(newRevision); SVNFileUtil.rename(revisionPrototypeFile, dstRevFile); } finally { txnWriteLock.unlock(); FSWriteLock.release(txnWriteLock); } } String commitTime = SVNDate.formatDate(new Date(System.currentTimeMillis())); SVNProperties presetRevisionProperties = myFSFS.getTransactionProperties(myTxn.getTxnId()); if (presetRevisionProperties == null || !presetRevisionProperties.containsName(SVNRevisionProperty.DATE)) { myFSFS.setTransactionProperty( myTxn.getTxnId(), SVNRevisionProperty.DATE, SVNPropertyValue.create(commitTime)); } File txnPropsFile = myFSFS.getTransactionPropertiesFile(myTxn.getTxnId()); if (myFSFS.getDBFormat() < FSFS.MIN_PACKED_REVPROP_FORMAT || newRevision >= myFSFS.getMinUnpackedRevProp()) { File dstRevPropsFile = myFSFS.getNewRevisionPropertiesFile(newRevision); SVNFileUtil.rename(txnPropsFile, dstRevPropsFile); } else { /* Read the revprops, and commit them to the permenant sqlite db. */ FSFile fsfProps = new FSFile(txnPropsFile); try { final SVNProperties revProperties = fsfProps.readProperties(false, true); final SVNSqlJetStatement stmt = myFSFS.getRevisionProperitesDb().getStatement(SVNWCDbStatements.FSFS_SET_REVPROP); try { stmt.insert( new Object[] {newRevision, SVNSkel.createPropList(revProperties.asMap()).getData()}); } finally { stmt.reset(); } } finally { fsfProps.close(); } } try { txnRoot.writeFinalCurrentFile(newRevision, startNodeId, startCopyId); } catch (IOException ioe) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.IO_ERROR, ioe.getLocalizedMessage()); SVNErrorManager.error(err, ioe, SVNLogType.FSFS); } myFSFS.setYoungestRevisionCache(newRevision); myFSFS.purgeTxn(myTxn.getTxnId()); return newRevision; }
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; }