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 }