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 } |