Merge lp:~pbeaman/akiban-persistit/buffer-pool-warmup-sorted into lp:akiban-persistit

Proposed by Peter Beaman
Status: Superseded
Proposed branch: lp:~pbeaman/akiban-persistit/buffer-pool-warmup-sorted
Merge into: lp:akiban-persistit
Prerequisite: lp:~pbeaman/akiban-persistit/eclipse-canonical-format
Diff against target: 1315 lines (+654/-247)
15 files modified
doc/Configuration.rst (+13/-1)
src/main/java/com/persistit/BufferPool.java (+144/-109)
src/main/java/com/persistit/CheckpointManager.java (+2/-1)
src/main/java/com/persistit/Configuration.java (+72/-72)
src/main/java/com/persistit/JournalManager.java (+45/-22)
src/main/java/com/persistit/MediatedFileChannel.java (+1/-1)
src/main/java/com/persistit/Persistit.java (+22/-9)
src/main/java/com/persistit/logging/LogBase.java (+9/-0)
src/test/java/com/persistit/IOFailureTest.java (+1/-1)
src/test/java/com/persistit/StressRunner.java (+2/-0)
src/test/java/com/persistit/TrackingFileChannel.java (+175/-0)
src/test/java/com/persistit/WarmupTest.java (+84/-29)
src/test/java/com/persistit/stress/PreloadMixtureTxn1.java (+82/-0)
src/test/java/com/persistit/unit/PersistitUnitTestCase.java (+2/-1)
src/test/java/com/persistit/unit/UnitTestProperties.java (+0/-1)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/buffer-pool-warmup-sorted
Reviewer Review Type Date Requested Status
Akiban Technologies Pending
Review via email: mp+121091@code.launchpad.net

This proposal has been superseded by a proposal from 2012-08-24.

Description of the change

This proposal is a re-work of the original buffer pool warm-up code. Instead of creating a text file, this version stores the inventory in the system volume. It also loads pages in file-address order to reduce I/O time. There is a new stress test that pushes this into a medium-sized buffer pool (25K pages) but we still need to test it with a 1M page pool in TPCC or some other big test.

There are two config options, one to turn on inventory recording and the other to enable pre-loading pages. They are separate so that a server can start up without waiting for the pre-load but still be set to perform the inventory function.

Other changes include Configuration, Configuration.rst (documentation), etc.

To post a comment you must log in.
383. By Peter Beaman

Merge from release-notes-3.16

384. By Peter Beaman

Fix failures in WarmupTest

385. By Peter Beaman

Fix WarmupTest (again)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'doc/Configuration.rst'
--- doc/Configuration.rst 2012-06-11 21:25:37 +0000
+++ doc/Configuration.rst 2012-08-23 21:28:19 +0000
@@ -221,7 +221,7 @@
221 ``serialOverride``, ``constructorOverride``: (``com.persistit.Configuration#setSerialOverride`` ``com.persistit.Configuration#setConstructorOverride``) 221 ``serialOverride``, ``constructorOverride``: (``com.persistit.Configuration#setSerialOverride`` ``com.persistit.Configuration#setConstructorOverride``)
222 Control aspects of object serialization. See :ref:`Serialization`.222 Control aspects of object serialization. See :ref:`Serialization`.
223223
224 ``showgui``: (``com.persistit.Configuration#setShowGUI``), True of False. 224 ``showgui``: (``com.persistit.Configuration#setShowGUI``), True or False (default).
225 If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM. 225 If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM.
226 Alternatively, AdminUI uses RMI and can be launched and run remotely if ``rmiport`` or ``rmihost`` has been 226 Alternatively, AdminUI uses RMI and can be launched and run remotely if ``rmiport`` or ``rmihost`` has been
227 specified.227 specified.
@@ -231,6 +231,18 @@
231 install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The ``logfile`` property is used 231 install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The ``logfile`` property is used
232 only when no adapter has been installed.232 only when no adapter has been installed.
233233
234 ``bufferinventory``: (``com.persistit.Configuration#setBufferInventoryEnabled``), True or False (default).
235 If true, Persistit periodically records an inventory of all the buffes in the buffers pools to the System Volume. The inventory
236 enables Persistit to preload the buffer pools then next time it starts up with approximately the same pages that were present
237 before shutdown. To enable buffer preloading, the bufferpreload property must also be true.
238
239 ``bufferpreload``: (``com.persistit.Configuration#setBufferPreloadEnabled``), True or False (default).
240 If true, and if a buffer pool inventory was previously recorded, Persistit attempts to "warm up" the buffer pool
241 by preloading pages that were present in the buffer pool when Persistit last shut down. This may allow a freshly started
242 Persistit instance to begin service a workload similar to what it had previously been processing without incurring the
243 cost of many random disk reads to load pages.
244
245
234For all integer-valued properties, the suffix “K” may be used to represent kilo, “M” for mega, “G” for giga and “T” for tera. For example, “2M” represents the value 2,097,152.246For all integer-valued properties, the suffix “K” may be used to represent kilo, “M” for mega, “G” for giga and “T” for tera. For example, “2M” represents the value 2,097,152.
235247
236A Configuration Example248A Configuration Example
237249
=== modified file 'src/main/java/com/persistit/BufferPool.java'
--- src/main/java/com/persistit/BufferPool.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/BufferPool.java 2012-08-23 21:28:19 +0000
@@ -15,16 +15,14 @@
1515
16package com.persistit;16package com.persistit;
1717
18import java.io.BufferedReader;
19import java.io.BufferedWriter;
20import java.io.DataOutputStream;18import java.io.DataOutputStream;
21import java.io.File;
22import java.io.FileReader;
23import java.io.FileWriter;
24import java.io.IOException;19import java.io.IOException;
25import java.nio.ByteBuffer;20import java.nio.ByteBuffer;
21import java.util.ArrayList;
26import java.util.Arrays;22import java.util.Arrays;
23import java.util.Collections;
27import java.util.HashSet;24import java.util.HashSet;
25import java.util.List;
28import java.util.Set;26import java.util.Set;
29import java.util.concurrent.atomic.AtomicBoolean;27import java.util.concurrent.atomic.AtomicBoolean;
30import java.util.concurrent.atomic.AtomicInteger;28import java.util.concurrent.atomic.AtomicInteger;
@@ -32,6 +30,7 @@
32import java.util.concurrent.atomic.AtomicLongArray;30import java.util.concurrent.atomic.AtomicLongArray;
33import java.util.concurrent.locks.ReentrantLock;31import java.util.concurrent.locks.ReentrantLock;
3432
33import com.persistit.JournalManager.PageNode;
35import com.persistit.exception.InUseException;34import com.persistit.exception.InUseException;
36import com.persistit.exception.InvalidPageAddressException;35import com.persistit.exception.InvalidPageAddressException;
37import com.persistit.exception.InvalidPageStructureException;36import com.persistit.exception.InvalidPageStructureException;
@@ -92,6 +91,17 @@
92 */91 */
93 private final static int WRITE_AGE_THRESHOLD_RATIO = 4;92 private final static int WRITE_AGE_THRESHOLD_RATIO = 4;
9493
94 private final static String INVENTORY_TREE_NAME = "_buffers";
95 /**
96 * Maximum number of buffer inventory versions to retain
97 */
98 private final static int INVENTORY_VERSIONS = 3;
99
100 /**
101 * Preload log multiple
102 */
103 private final static int INVENTORY_PRELOAD_LOG_MESSAGE_MULTIPLE = 10000;
104
95 /**105 /**
96 * The Persistit instance that references this BufferPool.106 * The Persistit instance that references this BufferPool.
97 */107 */
@@ -203,23 +213,11 @@
203 private volatile int _pageWriterTrancheSize = PAGE_WRITER_TRANCHE_SIZE;213 private volatile int _pageWriterTrancheSize = PAGE_WRITER_TRANCHE_SIZE;
204214
205 /**215 /**
206 * Polling interval for PageCacher
207 */
208 private volatile long _cacherPollInterval;
209
210 /**
211 * The PAGE_WRITER IOTaskRunnable216 * The PAGE_WRITER IOTaskRunnable
212 */217 */
213 private PageWriter _writer;218 private PageWriter _writer;
214219
215 /**220 /**
216 * The PAGE_CACHER IOTaskRunnable
217 */
218 private PageCacher _cacher;
219
220 private String _defaultLogPath;
221
222 /**
223 * Construct a BufferPool with the specified count of <code>Buffer</code>s221 * Construct a BufferPool with the specified count of <code>Buffer</code>s
224 * of the specified size.222 * of the specified size.
225 * 223 *
@@ -289,37 +287,6 @@
289 throw e;287 throw e;
290 }288 }
291 _writer = new PageWriter();289 _writer = new PageWriter();
292 _cacher = new PageCacher();
293 }
294
295 void warmupBufferPool(final String pathName, final String fname) throws PersistitException {
296 final File file = new File(pathName, fname + ".log");
297 _defaultLogPath = file.getAbsolutePath();
298
299 try {
300 if (!file.exists()) {
301 file.createNewFile();
302 }
303
304 final BufferedReader reader = new BufferedReader(new FileReader(file));
305 String currLine;
306 while ((currLine = reader.readLine()) != null) {
307 final String[] info = currLine.split(" ");
308 if (info.length == 2) {
309 final Volume vol = _persistit.getVolume(info[1]);
310 if (vol != null) {
311 final long page = Long.parseLong(info[0]);
312 final Buffer buff = get(vol, page, false, true);
313 buff.release();
314 }
315 }
316 }
317 reader.close();
318 _cacherPollInterval = _persistit.getConfiguration().getBufferInventoryPollingInterval();
319 _cacher.start();
320 } catch (final IOException e) {
321 throw new PersistitException(e);
322 }
323 }290 }
324291
325 void startThreads() throws PersistitException {292 void startThreads() throws PersistitException {
@@ -329,9 +296,7 @@
329 void close() {296 void close() {
330 _closed.set(true);297 _closed.set(true);
331 _persistit.waitForIOTaskStop(_writer);298 _persistit.waitForIOTaskStop(_writer);
332 _persistit.waitForIOTaskStop(_cacher);
333 _writer = null;299 _writer = null;
334 _cacher = null;
335 }300 }
336301
337 /**302 /**
@@ -340,7 +305,6 @@
340 */305 */
341 void crash() {306 void crash() {
342 IOTaskRunnable.crash(_writer);307 IOTaskRunnable.crash(_writer);
343 IOTaskRunnable.crash(_cacher);
344 }308 }
345309
346 void flush(final long timestamp) throws PersistitInterruptedException {310 void flush(final long timestamp) throws PersistitInterruptedException {
@@ -433,35 +397,6 @@
433 }397 }
434 }398 }
435399
436 private void populateWarmupFile() throws PersistitException {
437 final File file = new File(_defaultLogPath);
438
439 try {
440 final BufferedWriter writer = new BufferedWriter(new FileWriter(file));
441 for (int i = 0; i < _buffers.length; ++i) {
442 final Buffer b = _buffers[i];
443 if (b != null && b.isValid() && !b.isDirty()) {
444 final long page = b.getPageAddress();
445 final Volume volume = b.getVolume();
446 final long page2 = b.getPageAddress();
447 final Volume volume2 = b.getVolume();
448
449 // Check if buffer has changed while reading
450 if (page == page2 && volume == volume2 && volume != null) {
451 final String addr = Long.toString(page);
452 final String vol = volume.getName();
453 writer.append(addr + " " + vol);
454 writer.newLine();
455 writer.flush();
456 }
457 }
458 }
459 writer.close();
460 } catch (final IOException e) {
461 throw new PersistitException(e);
462 }
463 }
464
465 private boolean selected(final Buffer buffer, final int includeMask, final int excludeMask) {400 private boolean selected(final Buffer buffer, final int includeMask, final int excludeMask) {
466 return ((includeMask == 0) || (buffer.getStatus() & includeMask) != 0)401 return ((includeMask == 0) || (buffer.getStatus() & includeMask) != 0)
467 && (buffer.getStatus() & excludeMask) == 0;402 && (buffer.getStatus() & excludeMask) == 0;
@@ -1403,35 +1338,6 @@
1403 }1338 }
1404 }1339 }
14051340
1406 /**
1407 * Implementation of PAGE_CACHER thread
1408 */
1409 class PageCacher extends IOTaskRunnable {
1410
1411 PageCacher() {
1412 super(BufferPool.this._persistit);
1413 }
1414
1415 void start() {
1416 start("PAGE_CACHER:" + _bufferSize, _cacherPollInterval);
1417 }
1418
1419 @Override
1420 public void runTask() throws Exception {
1421 populateWarmupFile();
1422 }
1423
1424 @Override
1425 protected boolean shouldStop() {
1426 return _closed.get() && !isFlushing();
1427 }
1428
1429 @Override
1430 protected long pollInterval() {
1431 return isFlushing() ? 0 : _cacherPollInterval;
1432 }
1433 }
1434
1435 @Override1341 @Override
1436 public String toString() {1342 public String toString() {
1437 return "BufferPool[" + _bufferCount + "@" + _bufferSize + (_closed.get() ? ":closed" : "") + "]";1343 return "BufferPool[" + _bufferCount + "@" + _bufferSize + (_closed.get() ? ":closed" : "") + "]";
@@ -1486,4 +1392,133 @@
1486 }1392 }
1487 stream.flush();1393 stream.flush();
1488 }1394 }
1395
1396 void recordBufferInventory(final long timestamp) throws PersistitException {
1397 final Exchange exchange = getBufferInventoryExchange();
1398 /*
1399 * Advisory only - transaction integrity not needed
1400 */
1401 exchange.ignoreTransactions();
1402 try {
1403 int total = 0;
1404 exchange.clear().append(_bufferSize).append(timestamp).append(Key.BEFORE);
1405 final Value value = exchange.getValue();
1406 final int clockValueBefore = _clock.get();
1407 for (int index = 0; index < _buffers.length; index++) {
1408 final Buffer buffer = _buffers[index];
1409 long page1 = -1, page2 = -1;
1410 Volume volume1 = null, volume2 = null;
1411 if (buffer != null && buffer.isValid()) {
1412 while (true) {
1413 page1 = buffer.getPageAddress();
1414 volume1 = buffer.getVolume();
1415 page2 = buffer.getPageAddress();
1416 volume2 = buffer.getVolume();
1417 if (page1 == page2 && volume1 == volume2) {
1418 break;
1419 }
1420 Util.spinSleep();
1421 }
1422 if (volume1 != null && !volume1.isTemporary()) {
1423 value.clear().setStreamMode(true);
1424 value.put(volume1.getHandle());
1425 value.put(page1);
1426 exchange.to(index).store();
1427 total++;
1428 }
1429 }
1430 }
1431 final int clockValueAfter = _clock.get();
1432 exchange.cut();
1433 value.clear().setStreamMode(true);
1434 value.put(_bufferCount);
1435 value.put(total);
1436 value.put(clockValueBefore);
1437 value.put(clockValueAfter);
1438 value.put(System.currentTimeMillis());
1439 exchange.store();
1440 int count = 0;
1441 while (exchange.previous()) {
1442 if (++count > INVENTORY_VERSIONS) {
1443 exchange.remove(Key.GTEQ);
1444 }
1445 }
1446 } catch (final PersistitException e) {
1447 _persistit.getLogBase().bufferInventoryException.log(e);
1448 }
1449 }
1450
1451 void preloadBufferInventory() {
1452 int count = 0;
1453 int total = 0;
1454 try {
1455 final JournalManager jman = _persistit.getJournalManager();
1456 final Exchange exchange = getBufferInventoryExchange();
1457 final Value value = exchange.getValue();
1458 final List<PageNode> pageNodes = new ArrayList<PageNode>();
1459 boolean foundInventory = false;
1460 exchange.clear().append(_bufferSize).append(Key.AFTER);
1461 while (exchange.previous()) {
1462 if (exchange.getValue().isDefined()) {
1463 foundInventory = true;
1464 break;
1465 }
1466 }
1467 if (!foundInventory) {
1468 return;
1469 }
1470 value.setStreamMode(true);
1471 /* int bufferCount = */value.getInt();
1472 total = value.getInt();
1473 /* int clockValueBefore = */value.getInt();
1474 /* int clockValueAfter = */value.getInt();
1475 final long systemTime = value.getLong();
1476
1477 _persistit.getLogBase().bufferInventoryLoad.log(systemTime);
1478
1479 exchange.append(Key.BEFORE);
1480
1481 while (exchange.next()) {
1482 value.setStreamMode(true);
1483 final int volumeHandle = value.getInt();
1484 final long pageAddress = value.getLong();
1485 final PageNode pn = new PageNode(volumeHandle, pageAddress);
1486 pageNodes.add(pn);
1487 }
1488
1489 Collections.sort(pageNodes, PageNode.READ_COMPARATOR);
1490 for (final PageNode pn : pageNodes) {
1491 final Volume vol = jman.volumeForHandle(pn.getVolumeHandle());
1492 if (vol == null) {
1493 continue;
1494 }
1495 try {
1496 final Buffer buff = get(vol, pn.getPageAddress(), false, true);
1497 buff.release();
1498 count++;
1499 if ((count % INVENTORY_PRELOAD_LOG_MESSAGE_MULTIPLE) == 0) {
1500 _persistit.getLogBase().bufferInventoryProgress.log(count, total);
1501 }
1502 if (count >= _bufferCount) {
1503 //
1504 // If the buffer pool is now smaller, no need to load
1505 // more pages
1506 //
1507 break;
1508 }
1509 } catch (final PersistitException e) {
1510 // ignore it
1511 }
1512 }
1513 } catch (final PersistitException e) {
1514 _persistit.getLogBase().bufferInventoryException.log(e);
1515 } finally {
1516 _persistit.getLogBase().bufferInventoryProgress.log(count, total);
1517 }
1518 }
1519
1520 private Exchange getBufferInventoryExchange() throws PersistitException {
1521 final Volume sysvol = _persistit.getSystemVolume();
1522 return _persistit.getExchange(sysvol, INVENTORY_TREE_NAME, true);
1523 }
1489}1524}
14901525
=== modified file 'src/main/java/com/persistit/CheckpointManager.java'
--- src/main/java/com/persistit/CheckpointManager.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/CheckpointManager.java 2012-08-23 21:28:19 +0000
@@ -201,6 +201,7 @@
201 void pollCreateCheckpoint() throws PersistitException {201 void pollCreateCheckpoint() throws PersistitException {
202 final long now = System.nanoTime();202 final long now = System.nanoTime();
203 if (_lastCheckpointNanos + _checkpointIntervalNanos < now) {203 if (_lastCheckpointNanos + _checkpointIntervalNanos < now) {
204 _persistit.recordBufferPoolInventory();
204 createCheckpoint();205 createCheckpoint();
205 }206 }
206 }207 }
@@ -252,12 +253,12 @@
252 _currentCheckpoint = new Checkpoint(txn.getStartTimestamp(), System.currentTimeMillis());253 _currentCheckpoint = new Checkpoint(txn.getStartTimestamp(), System.currentTimeMillis());
253 _outstandingCheckpoints.add(_currentCheckpoint);254 _outstandingCheckpoints.add(_currentCheckpoint);
254 _persistit.getLogBase().checkpointProposed.log(_currentCheckpoint);255 _persistit.getLogBase().checkpointProposed.log(_currentCheckpoint);
255 return _currentCheckpoint;
256 } catch (final InterruptedException ie) {256 } catch (final InterruptedException ie) {
257 throw new PersistitInterruptedException(ie);257 throw new PersistitInterruptedException(ie);
258 } finally {258 } finally {
259 txn.end();259 txn.end();
260 }260 }
261 return _currentCheckpoint;
261 } finally {262 } finally {
262 _persistit.setSessionId(saveSessionId);263 _persistit.setSessionId(saveSessionId);
263 }264 }
264265
=== modified file 'src/main/java/com/persistit/Configuration.java'
--- src/main/java/com/persistit/Configuration.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/Configuration.java 2012-08-23 21:28:19 +0000
@@ -263,7 +263,7 @@
263 /**263 /**
264 * Property name for the "append only" property.264 * Property name for the "append only" property.
265 */265 */
266 public final static String APPEND_ONLY_PROPERTY = "appendonly";266 public final static String APPEND_ONLY_PROPERTY_NAME = "appendonly";
267267
268 /**268 /**
269 * Property name for the "ignore missing volumes" property.269 * Property name for the "ignore missing volumes" property.
@@ -276,12 +276,15 @@
276 public final static String SPLIT_POLICY_PROPERTY_NAME = "splitpolicy";276 public final static String SPLIT_POLICY_PROPERTY_NAME = "splitpolicy";
277277
278 /**278 /**
279 * Property name to specify the"buffer inventory" property name.279 * Property name to specify whether buffer preloading is enabled.
280 */
281 public final static String BUFFER_PRELOAD_PROPERTY_NAME = "bufferpreload";
282
283 /**
284 * Property name to specify whether buffer inventory is enabled.
280 */285 */
281 public final static String BUFFER_INVENTORY_PROPERTY_NAME = "bufferinventory";286 public final static String BUFFER_INVENTORY_PROPERTY_NAME = "bufferinventory";
282287
283 public final static String BUFFER_POLLING_INTERVAL_PROPERTY = "bufferpollinginterval";
284
285 /**288 /**
286 * Property name to specify the default {@link JoinPolicy}.289 * Property name to specify the default {@link JoinPolicy}.
287 */290 */
@@ -634,9 +637,8 @@
634 private int rmiServerPort;637 private int rmiServerPort;
635 private boolean jmx = true;638 private boolean jmx = true;
636 private boolean appendOnly;639 private boolean appendOnly;
637 private String bufferInventoryPathName;640 private boolean bufferInventoryEnabled;
638 private long bufferInventoryPollInterval = 3000000; // default five minute641 private boolean bufferPreloadEnabled;
639 // polling
640 private boolean ignoreMissingVolumes;642 private boolean ignoreMissingVolumes;
641 private String tmpVolDir;643 private String tmpVolDir;
642 private int tmpVolPageSize;644 private int tmpVolPageSize;
@@ -715,9 +717,7 @@
715 }717 }
716718
717 void loadProperties() throws InvalidVolumeSpecificationException {719 void loadProperties() throws InvalidVolumeSpecificationException {
718 setBufferInventoryPathName(getProperty(BUFFER_INVENTORY_PROPERTY_NAME));720 setAppendOnly(getBooleanProperty(APPEND_ONLY_PROPERTY_NAME, false));
719 setBufferInventoryPollingInterval(getLongProperty(BUFFER_POLLING_INTERVAL_PROPERTY, bufferInventoryPollInterval));
720 setAppendOnly(getBooleanProperty(APPEND_ONLY_PROPERTY, false));
721 setCommitPolicy(getProperty(COMMIT_POLICY_PROPERTY_NAME));721 setCommitPolicy(getProperty(COMMIT_POLICY_PROPERTY_NAME));
722 setConstructorOverride(getBooleanProperty(CONSTRUCTOR_OVERRIDE_PROPERTY_NAME, false));722 setConstructorOverride(getBooleanProperty(CONSTRUCTOR_OVERRIDE_PROPERTY_NAME, false));
723 setIgnoreMissingVolumes(getBooleanProperty(IGNORE_MISSING_VOLUMES_PROPERTY, false));723 setIgnoreMissingVolumes(getBooleanProperty(IGNORE_MISSING_VOLUMES_PROPERTY, false));
@@ -737,6 +737,8 @@
737 setShowGUI(getBooleanProperty(SHOW_GUI_PROPERTY_NAME, false));737 setShowGUI(getBooleanProperty(SHOW_GUI_PROPERTY_NAME, false));
738 setSplitPolicy(getProperty(SPLIT_POLICY_PROPERTY_NAME));738 setSplitPolicy(getProperty(SPLIT_POLICY_PROPERTY_NAME));
739 setSysVolume(getProperty(SYSTEM_VOLUME_PROPERTY_NAME, DEFAULT_SYSTEM_VOLUME_NAME));739 setSysVolume(getProperty(SYSTEM_VOLUME_PROPERTY_NAME, DEFAULT_SYSTEM_VOLUME_NAME));
740 setBufferInventoryEnabled(getBooleanProperty(BUFFER_INVENTORY_PROPERTY_NAME, false));
741 setBufferPreloadEnabled(getBooleanProperty(BUFFER_PRELOAD_PROPERTY_NAME, false));
740742
741 loadPropertiesBufferSpecifications();743 loadPropertiesBufferSpecifications();
742 loadPropertiesVolumeSpecifications();744 loadPropertiesVolumeSpecifications();
@@ -1548,8 +1550,7 @@
1548 /**1550 /**
1549 * <p>1551 * <p>
1550 * Set a pattern that identifies classes to be serialized using standard1552 * Set a pattern that identifies classes to be serialized using standard
1551 * Java serialization rather than Persistit's default serialization. TODO1553 * Java serialization rather than Persistit's default serialization.
1552 * Link to Serialization section of user_guide.html.
1553 * </p>1554 * </p>
1554 * <p>1555 * <p>
1555 * Default value is <code>null</code><br />1556 * Default value is <code>null</code><br />
@@ -1559,6 +1560,8 @@
1559 * @param serialOverride1560 * @param serialOverride
1560 * the serial override pattern to set1561 * the serial override pattern to set
1561 * @see DefaultCoderManager1562 * @see DefaultCoderManager
1563 * @see <a
1564 * href="http://www.akiban.com/ak-docs/admin/persistit/Serialization.html">Serialization</a>
1562 */1565 */
1563 public void setSerialOverride(final String serialOverride) {1566 public void setSerialOverride(final String serialOverride) {
1564 this.serialOverride = serialOverride;1567 this.serialOverride = serialOverride;
@@ -1579,8 +1582,7 @@
1579 * a public no-argument constructor. If so, then that constructor is used1582 * a public no-argument constructor. If so, then that constructor is used
1580 * when deserializing in the {@link DefaultObjectCoder}; if not then1583 * when deserializing in the {@link DefaultObjectCoder}; if not then
1581 * Persistit uses private methods within the JDK to emulate standard Java1584 * Persistit uses private methods within the JDK to emulate standard Java
1582 * serialization logic. TODO Link to Serialization section of1585 * serialization logic.
1583 * user_guide.html.
1584 * </p>1586 * </p>
1585 * <p>1587 * <p>
1586 * Default value is <code>false</code><br />1588 * Default value is <code>false</code><br />
@@ -1589,6 +1591,8 @@
1589 * 1591 *
1590 * @param constructorOverride1592 * @param constructorOverride
1591 * the constructorOverride to set1593 * the constructorOverride to set
1594 * @see <a
1595 * href="http://www.akiban.com/ak-docs/admin/persistit/Serialization.html">Serialization</a>
1592 */1596 */
1593 public void setConstructorOverride(final boolean constructorOverride) {1597 public void setConstructorOverride(final boolean constructorOverride) {
1594 this.constructorOverride = constructorOverride;1598 this.constructorOverride = constructorOverride;
@@ -1791,7 +1795,7 @@
1791 /**1795 /**
1792 * Return the value defined by {@link #setAppendOnly}1796 * Return the value defined by {@link #setAppendOnly}
1793 * 1797 *
1794 * @return the whether to start Persistit in append-only mode1798 * @return <true>true</code> if append-only mode is enabled at startup
1795 */1799 */
1796 public boolean isAppendOnly() {1800 public boolean isAppendOnly() {
1797 return appendOnly;1801 return appendOnly;
@@ -1807,77 +1811,73 @@
1807 * </p>1811 * </p>
1808 * <p>1812 * <p>
1809 * Default value is <code>false</code><br />1813 * Default value is <code>false</code><br />
1810 * Property name is {@value #APPEND_ONLY_PROPERTY}1814 * Property name is {@value #APPEND_ONLY_PROPERTY_NAME}
1811 * </p>1815 * </p>
1812 * 1816 *
1813 * @param appendOnly1817 * @param appendOnly
1814 * <code>true</code> to start Persistit in append-only only1818 * <code>true</code> to start Persistit in append-only mode
1815 */1819 */
1816 public void setAppendOnly(final boolean appendOnly) {1820 public void setAppendOnly(final boolean appendOnly) {
1817 this.appendOnly = appendOnly;1821 this.appendOnly = appendOnly;
1818 }1822 }
18191823
1820 /**1824 /**
1821 * Return the path name defined by {@link #getBufferInventoryPathName}1825 * Return the value defined by {@link #setBufferInventoryEnabled}
1822 * 1826 *
1823 * @return the path where file to warm-up Persistit with sample buffer data1827 * @return <code>true</code> if periodic buffer pool inventory recording is
1824 * is stored1828 * enabled
1825 */1829 */
1826 public String getBufferInventoryPathName() {1830 public boolean isBufferInventoryEnabled() {
1827 return bufferInventoryPathName;1831 return bufferInventoryEnabled;
1828 }1832 }
18291833
1830 /**1834 /**
1831 * <p>1835 * <p>
1832 * Control where Persistit stores its buffer inventory. In this mode1836 * Control whether Persistit periodically records an inventory of its buffer
1833 * Persistit restarts with information from the last run. This method1837 * pools to enable buffer pool preloading on a subsequent startup.
1834 * initializes the warm-up file at the specified location, if none is1838 * </p>
1835 * specified the buffer pool is not warmed up on start-up.1839 * <p>
1836 * </p>1840 * Default value is <code>false</code><br />
1837 * <p>1841 * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}
1838 * Default value is <code>null</code><br />1842 *
1839 * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}1843 * @param bufferInventoryEnabled
1840 * </p>1844 * <code>true</code> to enable periodic buffer inventory behavior
1841 * 1845 */
1842 * @param pathName1846 public void setBufferInventoryEnabled(final boolean bufferInventoryEnabled) {
1843 * the name of the path to the warm-up file1847 this.bufferInventoryEnabled = bufferInventoryEnabled;
1844 */1848 }
1845 public void setBufferInventoryPathName(final String pathName) {1849
1846 bufferInventoryPathName = pathName;1850 /**
18471851 * Return the value defined by {@link #setBufferPreloadEnabled}
1848 }1852 *
18491853 * @return <code>true</code> if the option to preload buffer pools is
1850 /**1854 * enabled
1851 * Return polling interval defined by1855 */
1852 * {@link #getBufferInventoryPollingInterval}1856 public boolean isBufferPreloadEnabled() {
1853 * 1857 return bufferPreloadEnabled;
1854 * @return the number of seconds wait between warm-up polls1858 }
1855 */1859
1856 public long getBufferInventoryPollingInterval() {1860 /**
1857 return bufferInventoryPollInterval;1861 * <p>
1858 }1862 * Control whether Persistit attempts to preload (warm up) the buffer pools
18591863 * by preloading pages recorded in a previously generated inventory.
1860 /**1864 * </p>
1861 * <p>1865 * <p>
1862 * Control the number of seconds between each poll for the cache warm-up1866 * Default value is <code>false</code><br />
1863 * option in Persistit.1867 * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}
1864 * </p>1868 *
1865 * <p>1869 * @param bufferPreloadEnabled
1866 * Default value is <code>3000</code><br />1870 * <code>true</code> to enable buffer pool preloading during
1867 * Property name is {@value #BUFFER_POLLING_INTERVAL_PROPERTY}1871 * startup
1868 * </p>1872 */
1869 * 1873 public void setBufferPreloadEnabled(final boolean bufferPreloadEnabled) {
1870 * @param seconds1874 this.bufferPreloadEnabled = bufferPreloadEnabled;
1871 * the number of seconds between polls
1872 */
1873 public void setBufferInventoryPollingInterval(final long seconds) {
1874 bufferInventoryPollInterval = Util.rangeCheck(seconds, 60L, Long.MAX_VALUE) * 1000L;
1875 }1875 }
18761876
1877 /**1877 /**
1878 * Return the value defined by {@link #setIgnoreMissingVolumes(boolean)}1878 * Return the value defined by {@link #setIgnoreMissingVolumes(boolean)}
1879 * 1879 *
1880 * @return the whether to start Persistit in ignore-missing-volumes mode1880 * @return <code>true</code>to enable ignore-missing-volumes mode
1881 */1881 */
1882 public boolean isIgnoreMissingVolumes() {1882 public boolean isIgnoreMissingVolumes() {
1883 return ignoreMissingVolumes;1883 return ignoreMissingVolumes;
18841884
=== modified file 'src/main/java/com/persistit/JournalManager.java'
--- src/main/java/com/persistit/JournalManager.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/JournalManager.java 2012-08-23 21:28:19 +0000
@@ -690,6 +690,29 @@
690 final ByteBuffer bb = buffer.getByteBuffer();690 final ByteBuffer bb = buffer.getByteBuffer();
691691
692 final Volume volume = buffer.getVolume();692 final Volume volume = buffer.getVolume();
693 final PageNode pn = lookupUpPageNode(pageAddress, volume);
694 if (pn == null) {
695 return false;
696 }
697 bb.position(0);
698 final long recordPageAddress = readPageBufferFromJournal(pn, bb);
699 _persistit.getIOMeter().chargeReadPageFromJournal(volume, pageAddress, bufferSize, pn.getJournalAddress(),
700 buffer.getIndex());
701
702 if (pageAddress != recordPageAddress) {
703 throw new CorruptJournalException("Record at " + pn + " is not volume/page " + buffer.toString());
704 }
705
706 if (bb.limit() != bufferSize) {
707 throw new CorruptJournalException("Record at " + pn + " is wrong size: expected/actual=" + bufferSize + "/"
708 + bb.limit());
709 }
710 _readPageCount++;
711 buffer.getVolume().getStatistics().bumpReadCounter();
712 return true;
713 }
714
715 PageNode lookupUpPageNode(final long pageAddress, final Volume volume) {
693 PageNode pnLookup = null;716 PageNode pnLookup = null;
694 synchronized (this) {717 synchronized (this) {
695 final Integer volumeHandle = _volumeToHandleMap.get(volume);718 final Integer volumeHandle = _volumeToHandleMap.get(volume);
@@ -699,7 +722,7 @@
699 }722 }
700723
701 if (pnLookup == null) {724 if (pnLookup == null) {
702 return false;725 return null;
703 }726 }
704727
705 final PageNode pn = new PageNode(pnLookup.getVolumeHandle(), pnLookup.getPageAddress(),728 final PageNode pn = new PageNode(pnLookup.getVolumeHandle(), pnLookup.getPageAddress(),
@@ -714,25 +737,9 @@
714 * new checkpoints and that keeps the copier from deleting it.737 * new checkpoints and that keeps the copier from deleting it.
715 */738 */
716 if (pnLookup.isInvalid()) {739 if (pnLookup.isInvalid()) {
717 return false;740 return null;
718 }741 }
719742 return pn;
720 bb.position(0);
721 final long recordPageAddress = readPageBufferFromJournal(pn, bb);
722 _persistit.getIOMeter().chargeReadPageFromJournal(volume, pageAddress, bufferSize, pn.getJournalAddress(),
723 buffer.getIndex());
724
725 if (pageAddress != recordPageAddress) {
726 throw new CorruptJournalException("Record at " + pn + " is not volume/page " + buffer.toString());
727 }
728
729 if (bb.limit() != bufferSize) {
730 throw new CorruptJournalException("Record at " + pn + " is wrong size: expected/actual=" + bufferSize + "/"
731 + bb.limit());
732 }
733 _readPageCount++;
734 buffer.getVolume().getStatistics().bumpReadCounter();
735 return true;
736 }743 }
737744
738 private long readPageBufferFromJournal(final PageNode pn, final ByteBuffer bb) throws PersistitIOException,745 private long readPageBufferFromJournal(final PageNode pn, final ByteBuffer bb) throws PersistitIOException,
@@ -1829,6 +1836,10 @@
18291836
1830 PageNode _previous;1837 PageNode _previous;
18311838
1839 PageNode(final int volumeHandle, final long pageAddress) {
1840 this(volumeHandle, pageAddress, Long.MIN_VALUE, -1);
1841 }
1842
1832 PageNode(final int volumeHandle, final long pageAddress, final long journalAddress, final long timestamp) {1843 PageNode(final int volumeHandle, final long pageAddress, final long journalAddress, final long timestamp) {
1833 this._volumeHandle = volumeHandle;1844 this._volumeHandle = volumeHandle;
1834 this._pageAddress = pageAddress;1845 this._pageAddress = pageAddress;
@@ -1950,8 +1961,20 @@
19501961
1951 @Override1962 @Override
1952 public int compare(final PageNode a, final PageNode b) {1963 public int compare(final PageNode a, final PageNode b) {
1953 return a.getJournalAddress() > b.getJournalAddress() ? 1 : a.getJournalAddress() < b1964 if (!a.isInvalid() && !b.isInvalid()) {
1954 .getJournalAddress() ? -1 : 0;1965 return a.getJournalAddress() > b.getJournalAddress() ? 1 : a.getJournalAddress() < b
1966 .getJournalAddress() ? -1 : 0;
1967 }
1968 if (a.isInvalid() && !b.isInvalid()) {
1969 return -1;
1970 }
1971 if (!a.isInvalid() && b.isInvalid()) {
1972 return 1;
1973 }
1974 if (a._volumeHandle != b._volumeHandle) {
1975 return a._volumeHandle - b._volumeHandle;
1976 }
1977 return a._pageAddress > b._pageAddress ? 1 : a._pageAddress < b._pageAddress ? -1 : 0;
1955 }1978 }
1956 };1979 };
19571980
19581981
=== modified file 'src/main/java/com/persistit/MediatedFileChannel.java'
--- src/main/java/com/persistit/MediatedFileChannel.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/MediatedFileChannel.java 2012-08-23 21:28:19 +0000
@@ -342,7 +342,7 @@
342 * 342 *
343 * @param channel343 * @param channel
344 */344 */
345 void setErrorInjectingChannelForTests(final FileChannel channel) {345 void injectChannelForTests(final FileChannel channel) {
346 ((TestChannelInjector) channel).setChannel(_channel);346 ((TestChannelInjector) channel).setChannel(_channel);
347 _channel = channel;347 _channel = channel;
348 }348 }
349349
=== modified file 'src/main/java/com/persistit/Persistit.java'
--- src/main/java/com/persistit/Persistit.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/Persistit.java 2012-08-23 21:28:19 +0000
@@ -403,6 +403,7 @@
403403
404 private final AtomicBoolean _suspendShutdown = new AtomicBoolean(false);404 private final AtomicBoolean _suspendShutdown = new AtomicBoolean(false);
405 private final AtomicBoolean _suspendUpdates = new AtomicBoolean(false);405 private final AtomicBoolean _suspendUpdates = new AtomicBoolean(false);
406 private final AtomicBoolean _enableBufferInventory = new AtomicBoolean(false);
406407
407 private UtilControl _localGUI;408 private UtilControl _localGUI;
408409
@@ -588,9 +589,7 @@
588 initializeVolumes();589 initializeVolumes();
589 startJournal();590 startJournal();
590 startBufferPools();591 startBufferPools();
591 if (_configuration.getBufferInventoryPathName() != null) {592 preloadBufferPools();
592 warmupBufferPools();
593 }
594 finishRecovery();593 finishRecovery();
595 startCheckpointManager();594 startCheckpointManager();
596 startTransactionIndexPollTask();595 startTransactionIndexPollTask();
@@ -699,6 +698,7 @@
699 _defaultSplitPolicy = _configuration.getSplitPolicy();698 _defaultSplitPolicy = _configuration.getSplitPolicy();
700 _defaultJoinPolicy = _configuration.getJoinPolicy();699 _defaultJoinPolicy = _configuration.getJoinPolicy();
701 _defaultCommitPolicy = _configuration.getCommitPolicy();700 _defaultCommitPolicy = _configuration.getCommitPolicy();
701 _enableBufferInventory.set(_configuration.isBufferInventoryEnabled());
702 }702 }
703703
704 void startCheckpointManager() {704 void startCheckpointManager() {
@@ -719,10 +719,24 @@
719 }719 }
720 }720 }
721721
722 void warmupBufferPools() throws PersistitException {722 void recordBufferPoolInventory() {
723 final String pathName = _configuration.getBufferInventoryPathName();723 final long timestamp = _timestampAllocator.getCurrentTimestamp();
724 for (final BufferPool pool : _bufferPoolTable.values()) {724 if (_enableBufferInventory.get()) {
725 pool.warmupBufferPool(pathName, pool.toString());725 for (final BufferPool pool : _bufferPoolTable.values()) {
726 try {
727 pool.recordBufferInventory(timestamp);
728 } catch (PersistitException e) {
729 getLogBase().bufferInventoryException.log(e);
730 }
731 }
732 }
733 }
734
735 void preloadBufferPools() throws PersistitException {
736 if (_configuration.isBufferPreloadEnabled()) {
737 for (final BufferPool pool : _bufferPoolTable.values()) {
738 pool.preloadBufferInventory();
739 }
726 }740 }
727 }741 }
728742
@@ -974,8 +988,6 @@
974 * 988 *
975 * @throws IllegalStateException989 * @throws IllegalStateException
976 */990 */
977
978 // TODO - why not one pool.
979 public void releaseExchange(final Exchange exchange, final boolean secure) {991 public void releaseExchange(final Exchange exchange, final boolean secure) {
980 if (exchange == null) {992 if (exchange == null) {
981 return;993 return;
@@ -1638,6 +1650,7 @@
1638 }1650 }
1639 }1651 }
1640 }1652 }
1653 recordBufferPoolInventory();
16411654
1642 /*1655 /*
1643 * The copier is responsible for background pruning of aborted1656 * The copier is responsible for background pruning of aborted
16441657
=== modified file 'src/main/java/com/persistit/logging/LogBase.java'
--- src/main/java/com/persistit/logging/LogBase.java 2012-08-23 21:28:19 +0000
+++ src/main/java/com/persistit/logging/LogBase.java 2012-08-23 21:28:19 +0000
@@ -244,6 +244,15 @@
244 @Message("ERROR|Too many journal files %,d")244 @Message("ERROR|Too many journal files %,d")
245 public final LogItem tooManyJournalFilesError = PersistitLogMessage.empty();245 public final LogItem tooManyJournalFilesError = PersistitLogMessage.empty();
246246
247 @Message("INFO|Preloading buffer pool inventory recorded at %tc")
248 public final LogItem bufferInventoryLoad = PersistitLogMessage.empty();
249
250 @Message("INFO|Preloaded %,d of %,d buffers")
251 public final LogItem bufferInventoryProgress = PersistitLogMessage.empty();
252
253 @Message("WARNING|Exception while writing buffer pool inventory %s")
254 public final LogItem bufferInventoryException = PersistitLogMessage.empty();
255
247 public static String recurring(final String message, final int count, final long duration) {256 public static String recurring(final String message, final int count, final long duration) {
248 return String.format(RECURRING, message, count, duration);257 return String.format(RECURRING, message, count, duration);
249 }258 }
250259
=== modified file 'src/test/java/com/persistit/IOFailureTest.java'
--- src/test/java/com/persistit/IOFailureTest.java 2012-08-23 21:28:19 +0000
+++ src/test/java/com/persistit/IOFailureTest.java 2012-08-23 21:28:19 +0000
@@ -57,7 +57,7 @@
5757
58 private ErrorInjectingFileChannel errorInjectingChannel(final FileChannel channel) {58 private ErrorInjectingFileChannel errorInjectingChannel(final FileChannel channel) {
59 final ErrorInjectingFileChannel eimfc = new ErrorInjectingFileChannel();59 final ErrorInjectingFileChannel eimfc = new ErrorInjectingFileChannel();
60 ((MediatedFileChannel) channel).setErrorInjectingChannelForTests(eimfc);60 ((MediatedFileChannel) channel).injectChannelForTests(eimfc);
61 return eimfc;61 return eimfc;
62 }62 }
6363
6464
=== modified file 'src/test/java/com/persistit/StressRunner.java'
--- src/test/java/com/persistit/StressRunner.java 2012-08-23 21:28:19 +0000
+++ src/test/java/com/persistit/StressRunner.java 2012-08-23 21:28:19 +0000
@@ -31,6 +31,7 @@
31import com.persistit.stress.MixtureTxn1;31import com.persistit.stress.MixtureTxn1;
32import com.persistit.stress.MixtureTxn2;32import com.persistit.stress.MixtureTxn2;
33import com.persistit.stress.PersistitMap1;33import com.persistit.stress.PersistitMap1;
34import com.persistit.stress.PreloadMixtureTxn1;
34import com.persistit.stress.StartStop;35import com.persistit.stress.StartStop;
35import com.persistit.stress.Stress10Suite;36import com.persistit.stress.Stress10Suite;
36import com.persistit.stress.Stress12txnSuite;37import com.persistit.stress.Stress12txnSuite;
@@ -79,6 +80,7 @@
79 _classes.add(Stress12txnSuite.class);80 _classes.add(Stress12txnSuite.class);
80 _classes.add(Stress4Suite.class);81 _classes.add(Stress4Suite.class);
81 _classes.add(Stress8txnSuite.class);82 _classes.add(Stress8txnSuite.class);
83 _classes.add(PreloadMixtureTxn1.class);
82 }84 }
8385
84 private final static String DURATION_PARAM = "duration=";86 private final static String DURATION_PARAM = "duration=";
8587
=== added file 'src/test/java/com/persistit/TrackingFileChannel.java'
--- src/test/java/com/persistit/TrackingFileChannel.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/persistit/TrackingFileChannel.java 2012-08-23 21:28:19 +0000
@@ -0,0 +1,175 @@
1/**
2 * Copyright © 2012 Akiban Technologies, Inc. All rights reserved.
3 *
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * This program may also be available under different license terms.
10 * For more information, see www.akiban.com or contact licensing@akiban.com.
11 *
12 * Contributors:
13 * Akiban Technologies, Inc.
14 */
15
16package com.persistit;
17
18import static org.junit.Assert.assertEquals;
19import static org.junit.Assert.assertTrue;
20import static org.junit.Assert.fail;
21import java.io.IOException;
22import java.nio.ByteBuffer;
23import java.nio.MappedByteBuffer;
24import java.nio.channels.FileChannel;
25import java.nio.channels.FileLock;
26import java.nio.channels.ReadableByteChannel;
27import java.nio.channels.WritableByteChannel;
28import java.util.ArrayList;
29import java.util.List;
30
31import com.persistit.MediatedFileChannel.TestChannelInjector;
32
33/**
34 * <p>
35 * A {@link FileChannel} implementation that simulates IOExceptions under
36 * control of a unit test program. This class implements only those methods used
37 * by Persistit; many methods of FileChannel throw
38 * {@link UnsupportedOperationException}.
39 * </p>
40 *
41 * @author peter
42 *
43 */
44class TrackingFileChannel extends FileChannel implements TestChannelInjector {
45
46 volatile FileChannel _channel;
47
48 final List<Long> _writePositions = new ArrayList<Long>();
49
50 final List<Long> _readPositions = new ArrayList<Long>();
51
52 @Override
53 public void setChannel(final FileChannel channel) {
54 _channel = channel;
55 }
56
57 @Override
58 protected void implCloseChannel() throws IOException {
59 _channel.close();
60 }
61
62 @Override
63 public void force(final boolean metaData) throws IOException {
64 _channel.force(metaData);
65 }
66
67 @Override
68 public int read(final ByteBuffer byteBuffer, final long position) throws IOException {
69 _readPositions.add(position);
70 return _channel.read(byteBuffer, position);
71 }
72
73 @Override
74 public long size() throws IOException {
75 return _channel.size();
76 }
77
78 @Override
79 public FileChannel truncate(final long size) throws IOException {
80 return _channel.truncate(size);
81 }
82
83 @Override
84 public synchronized FileLock tryLock(final long position, final long size, final boolean shared) throws IOException {
85 return _channel.tryLock(position, size, shared);
86 }
87
88 @Override
89 public int write(final ByteBuffer byteBuffer, final long position) throws IOException {
90 _writePositions.add(position);
91 final int written = _channel.write(byteBuffer, position);
92 return written;
93 }
94
95 /*
96 * --------------------------------
97 *
98 * Persistit does not use these methods and so they are Unsupported. Note
99 * that it would be difficult to support the relative read/write methods
100 * because the channel size is unavailable after it is closed. Therefore a
101 * client of this class must maintain its own position counter and cannot
102 * use the relative-addressing calls.
103 *
104 * --------------------------------
105 */
106 @Override
107 public FileLock lock(final long position, final long size, final boolean shared) throws IOException {
108 throw new UnsupportedOperationException();
109 }
110
111 @Override
112 public MappedByteBuffer map(final MapMode arg0, final long arg1, final long arg2) throws IOException {
113 throw new UnsupportedOperationException();
114 }
115
116 @Override
117 public long position() throws IOException {
118 throw new UnsupportedOperationException();
119 }
120
121 @Override
122 public FileChannel position(final long arg0) throws IOException {
123 throw new UnsupportedOperationException();
124 }
125
126 @Override
127 public int read(final ByteBuffer byteBuffer) throws IOException {
128 throw new UnsupportedOperationException();
129 }
130
131 @Override
132 public long read(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException {
133 throw new UnsupportedOperationException();
134 }
135
136 @Override
137 public long transferFrom(final ReadableByteChannel arg0, final long arg1, final long arg2) throws IOException {
138 throw new UnsupportedOperationException();
139 }
140
141 @Override
142 public long transferTo(final long arg0, final long arg1, final WritableByteChannel arg2) throws IOException {
143 throw new UnsupportedOperationException();
144 }
145
146 @Override
147 public int write(final ByteBuffer byteBuffer) throws IOException {
148 throw new UnsupportedOperationException();
149 }
150
151 @Override
152 public long write(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException {
153 throw new UnsupportedOperationException();
154 }
155
156 public List<Long> getWritePositionList() {
157 return _writePositions;
158 }
159
160 public List<Long> getReadPositionList() {
161 return _readPositions;
162 }
163
164 public void assertSequential(boolean read, boolean forward) {
165 final List<Long> list = read ? _readPositions : _writePositions;
166 long previous = forward ? -1 : Long.MAX_VALUE;
167 for (final Long position : list) {
168 if (forward) {
169 assertTrue("Position should be larger", position > previous);
170 } else {
171 assertTrue("Position should be smaller", position < previous);
172 }
173 }
174 }
175}
0176
=== modified file 'src/test/java/com/persistit/WarmupTest.java'
--- src/test/java/com/persistit/WarmupTest.java 2012-08-23 21:28:19 +0000
+++ src/test/java/com/persistit/WarmupTest.java 2012-08-23 21:28:19 +0000
@@ -16,6 +16,7 @@
16package com.persistit;16package com.persistit;
1717
18import static org.junit.Assert.assertEquals;18import static org.junit.Assert.assertEquals;
19import static org.junit.Assert.assertTrue;
1920
20import java.util.Properties;21import java.util.Properties;
2122
@@ -25,43 +26,97 @@
2526
26public class WarmupTest extends PersistitUnitTestCase {27public class WarmupTest extends PersistitUnitTestCase {
2728
29 @Override
30 protected Properties getProperties(final boolean cleanup) {
31 final Properties p = super.getProperties(cleanup);
32 p.setProperty("bufferinventory", "true");
33 p.setProperty("bufferpreload", "true");
34 return p;
35 }
36
28 @Test37 @Test
29 public void testWarmup() throws Exception {38 public void testWarmup() throws Exception {
30 Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true);39 Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true);
40 final BufferPool pool = ex.getBufferPool();
31 for (int i = 1; i <= 1000; i++) {41 for (int i = 1; i <= 1000; i++) {
32 ex.getValue().put(RED_FOX);42 ex.getValue().put(RED_FOX);
33 ex.clear().append(i).store();43 ex.clear().append(i).store();
34 }44 }
3545
36 // Assumption: only one buffer pool is created
37 int poolCount = 0;
38 String pathName = "";
39 final Buffer[] buff = new Buffer[100];46 final Buffer[] buff = new Buffer[100];
40 for (final BufferPool p : _persistit.getBufferPoolHashMap().values()) {47 for (int i = 0; i < pool.getBufferCount(); ++i) {
41 poolCount = p.getBufferCount();48 buff[i] = pool.getBufferCopy(i);
42 pathName = p.toString();49 }
43 for (int i = 0; i < poolCount; ++i) {50
44 buff[i] = p.getBufferCopy(i);51 final Configuration config = _persistit.getConfiguration();
45 }52 ex = null;
46 }53 _persistit.close();
4754
48 final Properties properties = _persistit.getProperties();55 _persistit = new Persistit();
49 ex = null;56 _persistit.initialize(config);
50 _persistit.close();57
5158 for (int i = 0; i < pool.getBufferCount(); ++i) {
52 _persistit = new Persistit();59 final Buffer bufferCopy = pool.getBufferCopy(i);
53 _persistit.initialize(properties);60 assertEquals(bufferCopy.getPageAddress(), buff[i].getPageAddress());
5461 assertEquals(bufferCopy.getPageType(), buff[i].getPageType());
55 int poolCount1 = 0;62 assertEquals(bufferCopy.getBufferSize(), buff[i].getBufferSize());
56 for (final BufferPool p : _persistit.getBufferPoolHashMap().values()) {63 }
57 poolCount1 = p.getBufferCount();64 }
58 for (int i = 0; i < poolCount1; ++i) {65
59 final Buffer bufferCopy = p.getBufferCopy(i);66 @Test
60 assertEquals(bufferCopy.getPageAddress(), buff[i].getPageAddress());67 public void readOrderIsSequential() throws Exception {
61 assertEquals(bufferCopy.getPageType(), buff[i].getPageType());68
62 assertEquals(bufferCopy.getBufferSize(), buff[i].getBufferSize());69 Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true);
63 }70 BufferPool pool = ex.getBufferPool();
64 }71
65 assertEquals(poolCount, poolCount1);72 final int full = pool.getBufferCount() * (pool.getBufferSize() / RED_FOX.length());
73 /*
74 * Overflow the buffer pool
75 */
76 for (int i = 1; i <= full * 3; i++) {
77 ex.getValue().put(RED_FOX);
78 ex.clear().append(i).store();
79 }
80 /*
81 * Pull some low-address pages in to scramble the pool
82 */
83 for (int i = full * 2; i >= 0; i -= 1000) {
84 ex.clear().append(i).fetch();
85 }
86 /*
87 * Verify that buffers in pool now have somewhat scrambled page
88 * addresses
89 */
90 int breaks = 0;
91 long previous = -1;
92
93 for (int i = 0; i < pool.getBufferCount(); i++) {
94 final Buffer b = pool.getBufferCopy(i);
95 assertTrue("Every buffer should be valid at this point", b.isValid());
96 if (b.getPageAddress() < previous) {
97 breaks++;
98 }
99 previous = b.getPageAddress();
100 }
101
102 assertTrue("Buffer pool should have scrambled page address", breaks > 0);
103
104 final Configuration config = _persistit.getConfiguration();
105 ex = null;
106 pool = null;
107 _persistit.close();
108
109 _persistit = new Persistit();
110 config.setBufferPreloadEnabled(false);
111 _persistit.initialize(config);
112
113 final Volume volume = _persistit.getVolume("persistit");
114 final MediatedFileChannel mfc = (MediatedFileChannel) volume.getStorage().getChannel();
115 final TrackingFileChannel tfc = new TrackingFileChannel();
116 mfc.injectChannelForTests(tfc);
117 pool = volume.getStructure().getPool();
118 pool.preloadBufferInventory();
119 assertTrue("Preload should have loaded pages from journal file", tfc.getReadPositionList().size() > 0);
120 tfc.assertSequential(true, true);
66 }121 }
67}122}
68123
=== added file 'src/test/java/com/persistit/stress/PreloadMixtureTxn1.java'
--- src/test/java/com/persistit/stress/PreloadMixtureTxn1.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/persistit/stress/PreloadMixtureTxn1.java 2012-08-23 21:28:19 +0000
@@ -0,0 +1,82 @@
1/**
2 * Copyright © 2012 Akiban Technologies, Inc. All rights reserved.
3 *
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * This program may also be available under different license terms.
10 * For more information, see www.akiban.com or contact licensing@akiban.com.
11 *
12 * Contributors:
13 * Akiban Technologies, Inc.
14 */
15
16package com.persistit.stress;
17
18import com.persistit.Configuration;
19import com.persistit.Persistit;
20import com.persistit.Transaction.CommitPolicy;
21import com.persistit.stress.unit.Stress1;
22import com.persistit.stress.unit.Stress2txn;
23import com.persistit.stress.unit.Stress3;
24import com.persistit.stress.unit.Stress3txn;
25import com.persistit.stress.unit.Stress5;
26import com.persistit.stress.unit.Stress6;
27import com.persistit.stress.unit.Stress8txn;
28
29public class PreloadMixtureTxn1 extends AbstractSuite {
30 private final static int CYCLES = 4;
31
32 static String name() {
33 return PreloadMixtureTxn1.class.getSimpleName();
34 }
35
36 public static void main(final String[] args) throws Exception {
37 new PreloadMixtureTxn1(args).runTest();
38 }
39
40 public PreloadMixtureTxn1(final String[] args) {
41 super(name(), args);
42 setDuration(getDuration() / CYCLES);
43 }
44
45 @Override
46 public void runTest() throws Exception {
47
48 deleteFiles(substitute("$datapath$/persistit*"));
49
50 for (int iteration = 0; iteration < CYCLES; iteration++) {
51 clear();
52 add(new Stress1("repeat=10 count=25000"));
53 add(new Stress1("repeat=10 count=25000"));
54 add(new Stress2txn("repeat=10 count=2500 size=4000 seed=118"));
55 add(new Stress2txn("repeat=2 count=25000 seed=119"));
56 add(new Stress3("repeat=5 count=25000 seed=119"));
57 add(new Stress3txn("repeat=5 count=25000 seed=120"));
58 add(new Stress3txn("repeat=5 count=25000"));
59 add(new Stress5("repeat=5 count=25000"));
60 add(new Stress6("repeat=5 count=1000 size=250"));
61 add(new Stress6("repeat=10 count=1000 size=250"));
62 add(new Stress8txn("repeat=2 count=1000 size=1000 seed=1"));
63 add(new Stress8txn("repeat=2 count=1000 size=1000 seed=2"));
64 add(new Stress8txn("repeat=2 count=1000 size=1000 seed=3"));
65 add(new Stress8txn("repeat=2 count=1000 size=1000 seed=4"));
66
67 final Configuration configuration = makeConfiguration(16384, "25000", CommitPolicy.SOFT);
68 configuration.setLogFile(configuration.getLogFile() + "_" + iteration);
69 configuration.setBufferInventoryEnabled(true);
70 configuration.setBufferPreloadEnabled(true);
71
72 final Persistit persistit = new Persistit();
73 persistit.initialize(configuration);
74
75 try {
76 execute(persistit);
77 } finally {
78 persistit.close();
79 }
80 }
81 }
82}
083
=== modified file 'src/test/java/com/persistit/unit/PersistitUnitTestCase.java'
--- src/test/java/com/persistit/unit/PersistitUnitTestCase.java 2012-08-23 21:28:19 +0000
+++ src/test/java/com/persistit/unit/PersistitUnitTestCase.java 2012-08-23 21:28:19 +0000
@@ -47,7 +47,8 @@
47 protected Persistit _persistit = new Persistit();47 protected Persistit _persistit = new Persistit();
4848
49 protected Properties getProperties(final boolean cleanup) {49 protected Properties getProperties(final boolean cleanup) {
50 return UnitTestProperties.getProperties(cleanup);50 final Properties p = UnitTestProperties.getProperties(cleanup);
51 return p;
51 }52 }
5253
53 @Before54 @Before
5455
=== modified file 'src/test/java/com/persistit/unit/UnitTestProperties.java'
--- src/test/java/com/persistit/unit/UnitTestProperties.java 2012-08-07 21:11:28 +0000
+++ src/test/java/com/persistit/unit/UnitTestProperties.java 2012-08-23 21:28:19 +0000
@@ -43,7 +43,6 @@
43 p.setProperty("tmpvoldir", "${datapath}");43 p.setProperty("tmpvoldir", "${datapath}");
44 p.setProperty("rmiport", System.getProperty("rmiport", "8081"));44 p.setProperty("rmiport", System.getProperty("rmiport", "8081"));
45 p.setProperty("jmx", "true");45 p.setProperty("jmx", "true");
46 p.setProperty("bufferinventory", "/tmp/persistit_test_data");
47 return p;46 return p;
48 }47 }
4948

Subscribers

People subscribed via source and target branches