Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/RevlogStreamWriter.java @ 617:65c01508f002
Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 15 May 2013 20:10:09 +0200 |
| parents | e1b29756f901 |
| children | 7c0d2ce340b8 |
comparison
equal
deleted
inserted
replaced
| 616:5e0313485eef | 617:65c01508f002 |
|---|---|
| 17 package org.tmatesoft.hg.internal; | 17 package org.tmatesoft.hg.internal; |
| 18 | 18 |
| 19 import static org.tmatesoft.hg.internal.Internals.REVLOGV1_RECORD_SIZE; | 19 import static org.tmatesoft.hg.internal.Internals.REVLOGV1_RECORD_SIZE; |
| 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; | 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; |
| 21 | 21 |
| 22 import java.io.File; | |
| 22 import java.io.IOException; | 23 import java.io.IOException; |
| 23 import java.nio.ByteBuffer; | 24 import java.nio.ByteBuffer; |
| 24 | 25 |
| 26 import org.tmatesoft.hg.core.HgIOException; | |
| 25 import org.tmatesoft.hg.core.Nodeid; | 27 import org.tmatesoft.hg.core.Nodeid; |
| 26 import org.tmatesoft.hg.core.SessionContext; | 28 import org.tmatesoft.hg.core.SessionContext; |
| 27 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | 29 import org.tmatesoft.hg.repo.HgInvalidControlFileException; |
| 28 import org.tmatesoft.hg.repo.HgInvalidStateException; | 30 import org.tmatesoft.hg.repo.HgInvalidStateException; |
| 29 | 31 |
| 36 */ | 38 */ |
| 37 public class RevlogStreamWriter { | 39 public class RevlogStreamWriter { |
| 38 | 40 |
| 39 private final DigestHelper dh = new DigestHelper(); | 41 private final DigestHelper dh = new DigestHelper(); |
| 40 private final RevlogCompressor revlogDataZip; | 42 private final RevlogCompressor revlogDataZip; |
| 43 private final Transaction transaction; | |
| 41 private int lastEntryBase, lastEntryIndex; | 44 private int lastEntryBase, lastEntryIndex; |
| 42 private byte[] lastEntryContent; | 45 private byte[] lastEntryContent; |
| 43 private Nodeid lastEntryRevision; | 46 private Nodeid lastEntryRevision; |
| 44 private IntMap<Nodeid> revisionCache = new IntMap<Nodeid>(32); | 47 private IntMap<Nodeid> revisionCache = new IntMap<Nodeid>(32); |
| 45 private RevlogStream revlogStream; | 48 private RevlogStream revlogStream; |
| 46 | 49 |
| 47 public RevlogStreamWriter(SessionContext.Source ctxSource, RevlogStream stream) { | 50 public RevlogStreamWriter(SessionContext.Source ctxSource, RevlogStream stream, Transaction tr) { |
| 48 assert ctxSource != null; | 51 assert ctxSource != null; |
| 49 assert stream != null; | 52 assert stream != null; |
| 53 assert tr != null; | |
| 50 | 54 |
| 51 revlogDataZip = new RevlogCompressor(ctxSource.getSessionContext()); | 55 revlogDataZip = new RevlogCompressor(ctxSource.getSessionContext()); |
| 52 revlogStream = stream; | 56 revlogStream = stream; |
| 57 transaction = tr; | |
| 53 } | 58 } |
| 54 | 59 |
| 55 /** | 60 /** |
| 56 * @return nodeid of added revision | 61 * @return nodeid of added revision |
| 57 */ | 62 */ |
| 58 public Nodeid addRevision(byte[] content, int linkRevision, int p1, int p2) { | 63 public Nodeid addRevision(byte[] content, int linkRevision, int p1, int p2) throws HgIOException { |
| 59 lastEntryRevision = Nodeid.NULL; | 64 lastEntryRevision = Nodeid.NULL; |
| 60 int revCount = revlogStream.revisionCount(); | 65 int revCount = revlogStream.revisionCount(); |
| 61 lastEntryIndex = revCount == 0 ? NO_REVISION : revCount - 1; | 66 lastEntryIndex = revCount == 0 ? NO_REVISION : revCount - 1; |
| 62 populateLastEntry(); | 67 populateLastEntry(); |
| 63 // | 68 // |
| 83 | 88 |
| 84 DataSerializer indexFile, dataFile, activeFile; | 89 DataSerializer indexFile, dataFile, activeFile; |
| 85 indexFile = dataFile = activeFile = null; | 90 indexFile = dataFile = activeFile = null; |
| 86 try { | 91 try { |
| 87 // | 92 // |
| 88 activeFile = indexFile = revlogStream.getIndexStreamWriter(); | 93 activeFile = indexFile = revlogStream.getIndexStreamWriter(transaction); |
| 89 final boolean isInlineData = revlogStream.isInlineData(); | 94 final boolean isInlineData = revlogStream.isInlineData(); |
| 90 HeaderWriter revlogHeader = new HeaderWriter(isInlineData); | 95 HeaderWriter revlogHeader = new HeaderWriter(isInlineData); |
| 91 revlogHeader.length(content.length, compressedLen); | 96 revlogHeader.length(content.length, compressedLen); |
| 92 revlogHeader.nodeid(revisionNodeidBytes); | 97 revlogHeader.nodeid(revisionNodeidBytes); |
| 93 revlogHeader.linkRevision(linkRevision); | 98 revlogHeader.linkRevision(linkRevision); |
| 99 revlogHeader.serialize(indexFile); | 104 revlogHeader.serialize(indexFile); |
| 100 | 105 |
| 101 if (isInlineData) { | 106 if (isInlineData) { |
| 102 dataFile = indexFile; | 107 dataFile = indexFile; |
| 103 } else { | 108 } else { |
| 104 dataFile = revlogStream.getDataStreamWriter(); | 109 dataFile = revlogStream.getDataStreamWriter(transaction); |
| 105 } | 110 } |
| 106 activeFile = dataFile; | 111 activeFile = dataFile; |
| 107 if (useCompressedData) { | 112 if (useCompressedData) { |
| 108 int actualCompressedLenWritten = revlogDataZip.writeCompressedData(dataFile); | 113 int actualCompressedLenWritten = revlogDataZip.writeCompressedData(dataFile); |
| 109 if (actualCompressedLenWritten != compressedLen) { | 114 if (actualCompressedLenWritten != compressedLen) { |
| 122 revisionCache.put(lastEntryIndex, lastEntryRevision); | 127 revisionCache.put(lastEntryIndex, lastEntryRevision); |
| 123 | 128 |
| 124 revlogStream.revisionAdded(lastEntryIndex, lastEntryRevision, lastEntryBase, lastEntryOffset); | 129 revlogStream.revisionAdded(lastEntryIndex, lastEntryRevision, lastEntryBase, lastEntryOffset); |
| 125 } catch (IOException ex) { | 130 } catch (IOException ex) { |
| 126 String m = String.format("Failed to write revision %d", lastEntryIndex+1, null); | 131 String m = String.format("Failed to write revision %d", lastEntryIndex+1, null); |
| 127 HgInvalidControlFileException t = new HgInvalidControlFileException(m, ex, null); | 132 // FIXME proper file in the exception based on activeFile == dataFile || indexFile |
| 128 if (activeFile == dataFile) { | 133 throw new HgIOException(m, ex, new File(revlogStream.getDataFileName())); |
| 129 throw revlogStream.initWithDataFile(t); | |
| 130 } else { | |
| 131 throw revlogStream.initWithIndexFile(t); | |
| 132 } | |
| 133 } finally { | 134 } finally { |
| 134 indexFile.done(); | 135 indexFile.done(); |
| 135 if (dataFile != null && dataFile != indexFile) { | 136 if (dataFile != null && dataFile != indexFile) { |
| 136 dataFile.done(); | 137 dataFile.done(); |
| 137 } | 138 } |
