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