comparison src/org/tmatesoft/hg/internal/DataAccessProvider.java @ 456:909306e412e2

Refactor LogFacility and SessionContext, better API for both
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 18 Jun 2012 16:54:00 +0200
parents 299870249a28
children 2743641f2f12
comparison
equal deleted inserted replaced
454:36fd1fd06492 456:909306e412e2
1 /* 1 /*
2 * Copyright (c) 2010-2011 TMate Software Ltd 2 * Copyright (c) 2010-2012 TMate Software Ltd
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License. 6 * the Free Software Foundation; version 2 of the License.
7 * 7 *
13 * For information on how to redistribute this software under 13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License 14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18
19 import static org.tmatesoft.hg.util.LogFacility.Severity.Error;
20 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn;
18 21
19 import java.io.File; 22 import java.io.File;
20 import java.io.FileInputStream; 23 import java.io.FileInputStream;
21 import java.io.IOException; 24 import java.io.IOException;
22 import java.nio.ByteBuffer; 25 import java.nio.ByteBuffer;
44 private static final int DEFAULT_MAPIO_LIMIT = 100 * 1024; // 100 kB 47 private static final int DEFAULT_MAPIO_LIMIT = 100 * 1024; // 100 kB
45 private static final int DEFAULT_FILE_BUFFER = 8 * 1024; // 8 kB 48 private static final int DEFAULT_FILE_BUFFER = 8 * 1024; // 8 kB
46 private static final int DEFAULT_MAPIO_BUFFER = DEFAULT_MAPIO_LIMIT; // same as default boundary 49 private static final int DEFAULT_MAPIO_BUFFER = DEFAULT_MAPIO_LIMIT; // same as default boundary
47 50
48 private final int mapioMagicBoundary; 51 private final int mapioMagicBoundary;
49 private final int bufferSize; 52 private final int bufferSize, mapioBufSize;
50 private final SessionContext context; 53 private final SessionContext context;
51 54
52 public DataAccessProvider(SessionContext ctx) { 55 public DataAccessProvider(SessionContext ctx) {
53 this(ctx, getConfigOption(ctx, CFG_PROPERTY_MAPIO_LIMIT, DEFAULT_MAPIO_LIMIT), getConfigOption(ctx, CFG_PROPERTY_FILE_BUFFER_SIZE, DEFAULT_FILE_BUFFER)); 56 context = ctx;
57 PropertyMarshal pm = new PropertyMarshal(ctx);
58 mapioMagicBoundary = pm.getInt(CFG_PROPERTY_MAPIO_LIMIT, DEFAULT_MAPIO_LIMIT);
59 bufferSize = pm.getInt(CFG_PROPERTY_FILE_BUFFER_SIZE, DEFAULT_FILE_BUFFER);
60 mapioBufSize = pm.getInt(CFG_PROPERTY_MAPIO_BUFFER_SIZE, DEFAULT_MAPIO_BUFFER);
54 } 61 }
55 62
56 private static int getConfigOption(SessionContext ctx, String optName, int defaultValue) { 63 public DataAccessProvider(SessionContext ctx, int mapioBoundary, int regularBufferSize, int mapioBufferSize) {
57 Object v = ctx.getProperty(optName, defaultValue);
58 if (false == v instanceof Number) {
59 v = Integer.parseInt(v.toString());
60 }
61 return ((Number) v).intValue();
62 }
63
64 public DataAccessProvider(SessionContext ctx, int mapioBoundary, int regularBufferSize) {
65 context = ctx; 64 context = ctx;
66 mapioMagicBoundary = mapioBoundary == 0 ? Integer.MAX_VALUE : mapioBoundary; 65 mapioMagicBoundary = mapioBoundary == 0 ? Integer.MAX_VALUE : mapioBoundary;
67 bufferSize = regularBufferSize; 66 bufferSize = regularBufferSize;
67 mapioBufSize = mapioBufferSize;
68 } 68 }
69 69
70 public DataAccess create(File f) { 70 public DataAccess create(File f) {
71 if (!f.exists()) { 71 if (!f.exists()) {
72 return new DataAccess(); 72 return new DataAccess();
74 try { 74 try {
75 FileChannel fc = new FileInputStream(f).getChannel(); 75 FileChannel fc = new FileInputStream(f).getChannel();
76 long flen = fc.size(); 76 long flen = fc.size();
77 if (flen > mapioMagicBoundary) { 77 if (flen > mapioMagicBoundary) {
78 // TESTS: bufLen of 1024 was used to test MemMapFileAccess 78 // TESTS: bufLen of 1024 was used to test MemMapFileAccess
79 int mapioBufSize = getConfigOption(context, CFG_PROPERTY_MAPIO_BUFFER_SIZE, DEFAULT_MAPIO_BUFFER);
80 return new MemoryMapFileAccess(fc, flen, mapioBufSize, context.getLog()); 79 return new MemoryMapFileAccess(fc, flen, mapioBufSize, context.getLog());
81 } else { 80 } else {
82 // XXX once implementation is more or less stable, 81 // XXX once implementation is more or less stable,
83 // may want to try ByteBuffer.allocateDirect() to see 82 // may want to try ByteBuffer.allocateDirect() to see
84 // if there's any performance gain. 83 // if there's any performance gain.
86 // TESTS: bufferSize of 100 was used to check buffer underflow states when readBytes reads chunks bigger than bufSize 85 // TESTS: bufferSize of 100 was used to check buffer underflow states when readBytes reads chunks bigger than bufSize
87 return new FileAccess(fc, flen, bufferSize, useDirectBuffer, context.getLog()); 86 return new FileAccess(fc, flen, bufferSize, useDirectBuffer, context.getLog());
88 } 87 }
89 } catch (IOException ex) { 88 } catch (IOException ex) {
90 // unlikely to happen, we've made sure file exists. 89 // unlikely to happen, we've made sure file exists.
91 context.getLog().error(getClass(), ex, null); 90 context.getLog().dump(getClass(), Error, ex, null);
92 } 91 }
93 return new DataAccess(); // non-null, empty. 92 return new DataAccess(); // non-null, empty.
94 } 93 }
95 94
96 private static class MemoryMapFileAccess extends DataAccess { 95 private static class MemoryMapFileAccess extends DataAccess {
175 if (i == 2) { 174 if (i == 2) {
176 throw ex; 175 throw ex;
177 } 176 }
178 if (i == 0) { 177 if (i == 0) {
179 // if first attempt failed, try to free some virtual memory, see Issue 30 for details 178 // if first attempt failed, try to free some virtual memory, see Issue 30 for details
180 logFacility.warn(getClass(), ex, "Memory-map failed, gonna try gc() to free virtual memory"); 179 logFacility.dump(getClass(), Warn, ex, "Memory-map failed, gonna try gc() to free virtual memory");
181 } 180 }
182 try { 181 try {
183 buffer = null; 182 buffer = null;
184 System.gc(); 183 System.gc();
185 Thread.sleep((1+i) * 1000); 184 Thread.sleep((1+i) * 1000);
186 } catch (Throwable t) { 185 } catch (Throwable t) {
187 logFacility.error(getClass(), t, "Bad luck"); 186 logFacility.dump(getClass(), Error, t, "Bad luck");
188 } 187 }
189 } 188 }
190 } 189 }
191 } 190 }
192 191
228 buffer = null; 227 buffer = null;
229 if (fileChannel != null) { 228 if (fileChannel != null) {
230 try { 229 try {
231 fileChannel.close(); 230 fileChannel.close();
232 } catch (IOException ex) { 231 } catch (IOException ex) {
233 logFacility.debug(getClass(), ex, null); 232 logFacility.dump(getClass(), Warn, ex, null);
234 } 233 }
235 fileChannel = null; 234 fileChannel = null;
236 } 235 }
237 } 236 }
238 } 237 }
362 } 361 }
363 if (fileChannel != null) { 362 if (fileChannel != null) {
364 try { 363 try {
365 fileChannel.close(); 364 fileChannel.close();
366 } catch (IOException ex) { 365 } catch (IOException ex) {
367 logFacility.debug(getClass(), ex, null); 366 logFacility.dump(getClass(), Warn, ex, null);
368 } 367 }
369 fileChannel = null; 368 fileChannel = null;
370 } 369 }
371 } 370 }
372 } 371 }