comparison src/org/tmatesoft/hg/internal/DataAccessProvider.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
27 import java.io.OutputStream; 27 import java.io.OutputStream;
28 import java.nio.ByteBuffer; 28 import java.nio.ByteBuffer;
29 import java.nio.MappedByteBuffer; 29 import java.nio.MappedByteBuffer;
30 import java.nio.channels.FileChannel; 30 import java.nio.channels.FileChannel;
31 31
32 import org.tmatesoft.hg.core.HgIOException;
32 import org.tmatesoft.hg.core.SessionContext; 33 import org.tmatesoft.hg.core.SessionContext;
33 import org.tmatesoft.hg.util.LogFacility; 34 import org.tmatesoft.hg.util.LogFacility;
34 35
35 /** 36 /**
36 * 37 *
78 public DataAccess createReader(File f, boolean shortRead) { 79 public DataAccess createReader(File f, boolean shortRead) {
79 if (!f.exists()) { 80 if (!f.exists()) {
80 return new DataAccess(); 81 return new DataAccess();
81 } 82 }
82 try { 83 try {
83 FileChannel fc = new FileInputStream(f).getChannel(); 84 FileChannel fc = new FileInputStream(f).getChannel(); // FIXME SHALL CLOSE FIS, not only channel
84 long flen = fc.size(); 85 long flen = fc.size();
85 if (!shortRead && flen > mapioMagicBoundary) { 86 if (!shortRead && flen > mapioMagicBoundary) {
86 // TESTS: bufLen of 1024 was used to test MemMapFileAccess 87 // TESTS: bufLen of 1024 was used to test MemMapFileAccess
87 return new MemoryMapFileAccess(fc, flen, mapioBufSize, context.getLog()); 88 return new MemoryMapFileAccess(fc, flen, mapioBufSize, context.getLog());
88 } else { 89 } else {
98 context.getLog().dump(getClass(), Error, ex, null); 99 context.getLog().dump(getClass(), Error, ex, null);
99 } 100 }
100 return new DataAccess(); // non-null, empty. 101 return new DataAccess(); // non-null, empty.
101 } 102 }
102 103
103 public DataSerializer createWriter(File f, boolean createNewIfDoesntExist) { 104 public DataSerializer createWriter(final Transaction tr, File f, boolean createNewIfDoesntExist) throws HgIOException {
104 if (!f.exists() && !createNewIfDoesntExist) { 105 if (!f.exists() && !createNewIfDoesntExist) {
105 return new DataSerializer(); 106 return new DataSerializer();
106 } 107 }
107 try { 108 try {
108 return new StreamDataSerializer(context.getLog(), new FileOutputStream(f, true)); 109 final File transactionFile = tr.prepare(f);
110 return new StreamDataSerializer(context.getLog(), new FileOutputStream(transactionFile, true)) {
111 @Override
112 public void done() {
113 super.done();
114 // FIXME invert RevlogStreamWriter to send DataSource here instead of grabbing DataSerializer
115 // besides, DataSerializer#done is invoked regardless of whether write was successful or not,
116 // while Transaction#done() assumes there's no error
117 try {
118 tr.done(transactionFile);
119 } catch (HgIOException ex) {
120 context.getLog().dump(DataAccessProvider.class, Error, ex, null);
121 }
122 }
123 };
109 } catch (final FileNotFoundException ex) { 124 } catch (final FileNotFoundException ex) {
110 context.getLog().dump(getClass(), Error, ex, null); 125 context.getLog().dump(getClass(), Error, ex, null);
111 return new DataSerializer() { 126 return new DataSerializer() {
112 public void write(byte[] data, int offset, int length) throws IOException { 127 public void write(byte[] data, int offset, int length) throws IOException {
113 throw ex; 128 throw ex;