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
1=== modified file 'doc/Configuration.rst'
2--- doc/Configuration.rst 2012-06-11 21:25:37 +0000
3+++ doc/Configuration.rst 2012-08-23 21:28:19 +0000
4@@ -221,7 +221,7 @@
5 ``serialOverride``, ``constructorOverride``: (``com.persistit.Configuration#setSerialOverride`` ``com.persistit.Configuration#setConstructorOverride``)
6 Control aspects of object serialization. See :ref:`Serialization`.
7
8- ``showgui``: (``com.persistit.Configuration#setShowGUI``), True of False.
9+ ``showgui``: (``com.persistit.Configuration#setShowGUI``), True or False (default).
10 If true, Persistit attempts to create and display an instance of the AdminUI utility panel within the current JVM.
11 Alternatively, AdminUI uses RMI and can be launched and run remotely if ``rmiport`` or ``rmihost`` has been
12 specified.
13@@ -231,6 +231,18 @@
14 install a logging adapter to reroute messages through Log4J, SLF4J or other logger. The ``logfile`` property is used
15 only when no adapter has been installed.
16
17+ ``bufferinventory``: (``com.persistit.Configuration#setBufferInventoryEnabled``), True or False (default).
18+ If true, Persistit periodically records an inventory of all the buffes in the buffers pools to the System Volume. The inventory
19+ enables Persistit to preload the buffer pools then next time it starts up with approximately the same pages that were present
20+ before shutdown. To enable buffer preloading, the bufferpreload property must also be true.
21+
22+ ``bufferpreload``: (``com.persistit.Configuration#setBufferPreloadEnabled``), True or False (default).
23+ If true, and if a buffer pool inventory was previously recorded, Persistit attempts to "warm up" the buffer pool
24+ by preloading pages that were present in the buffer pool when Persistit last shut down. This may allow a freshly started
25+ Persistit instance to begin service a workload similar to what it had previously been processing without incurring the
26+ cost of many random disk reads to load pages.
27+
28+
29 For 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.
30
31 A Configuration Example
32
33=== modified file 'src/main/java/com/persistit/BufferPool.java'
34--- src/main/java/com/persistit/BufferPool.java 2012-08-23 21:28:19 +0000
35+++ src/main/java/com/persistit/BufferPool.java 2012-08-23 21:28:19 +0000
36@@ -15,16 +15,14 @@
37
38 package com.persistit;
39
40-import java.io.BufferedReader;
41-import java.io.BufferedWriter;
42 import java.io.DataOutputStream;
43-import java.io.File;
44-import java.io.FileReader;
45-import java.io.FileWriter;
46 import java.io.IOException;
47 import java.nio.ByteBuffer;
48+import java.util.ArrayList;
49 import java.util.Arrays;
50+import java.util.Collections;
51 import java.util.HashSet;
52+import java.util.List;
53 import java.util.Set;
54 import java.util.concurrent.atomic.AtomicBoolean;
55 import java.util.concurrent.atomic.AtomicInteger;
56@@ -32,6 +30,7 @@
57 import java.util.concurrent.atomic.AtomicLongArray;
58 import java.util.concurrent.locks.ReentrantLock;
59
60+import com.persistit.JournalManager.PageNode;
61 import com.persistit.exception.InUseException;
62 import com.persistit.exception.InvalidPageAddressException;
63 import com.persistit.exception.InvalidPageStructureException;
64@@ -92,6 +91,17 @@
65 */
66 private final static int WRITE_AGE_THRESHOLD_RATIO = 4;
67
68+ private final static String INVENTORY_TREE_NAME = "_buffers";
69+ /**
70+ * Maximum number of buffer inventory versions to retain
71+ */
72+ private final static int INVENTORY_VERSIONS = 3;
73+
74+ /**
75+ * Preload log multiple
76+ */
77+ private final static int INVENTORY_PRELOAD_LOG_MESSAGE_MULTIPLE = 10000;
78+
79 /**
80 * The Persistit instance that references this BufferPool.
81 */
82@@ -203,23 +213,11 @@
83 private volatile int _pageWriterTrancheSize = PAGE_WRITER_TRANCHE_SIZE;
84
85 /**
86- * Polling interval for PageCacher
87- */
88- private volatile long _cacherPollInterval;
89-
90- /**
91 * The PAGE_WRITER IOTaskRunnable
92 */
93 private PageWriter _writer;
94
95 /**
96- * The PAGE_CACHER IOTaskRunnable
97- */
98- private PageCacher _cacher;
99-
100- private String _defaultLogPath;
101-
102- /**
103 * Construct a BufferPool with the specified count of <code>Buffer</code>s
104 * of the specified size.
105 *
106@@ -289,37 +287,6 @@
107 throw e;
108 }
109 _writer = new PageWriter();
110- _cacher = new PageCacher();
111- }
112-
113- void warmupBufferPool(final String pathName, final String fname) throws PersistitException {
114- final File file = new File(pathName, fname + ".log");
115- _defaultLogPath = file.getAbsolutePath();
116-
117- try {
118- if (!file.exists()) {
119- file.createNewFile();
120- }
121-
122- final BufferedReader reader = new BufferedReader(new FileReader(file));
123- String currLine;
124- while ((currLine = reader.readLine()) != null) {
125- final String[] info = currLine.split(" ");
126- if (info.length == 2) {
127- final Volume vol = _persistit.getVolume(info[1]);
128- if (vol != null) {
129- final long page = Long.parseLong(info[0]);
130- final Buffer buff = get(vol, page, false, true);
131- buff.release();
132- }
133- }
134- }
135- reader.close();
136- _cacherPollInterval = _persistit.getConfiguration().getBufferInventoryPollingInterval();
137- _cacher.start();
138- } catch (final IOException e) {
139- throw new PersistitException(e);
140- }
141 }
142
143 void startThreads() throws PersistitException {
144@@ -329,9 +296,7 @@
145 void close() {
146 _closed.set(true);
147 _persistit.waitForIOTaskStop(_writer);
148- _persistit.waitForIOTaskStop(_cacher);
149 _writer = null;
150- _cacher = null;
151 }
152
153 /**
154@@ -340,7 +305,6 @@
155 */
156 void crash() {
157 IOTaskRunnable.crash(_writer);
158- IOTaskRunnable.crash(_cacher);
159 }
160
161 void flush(final long timestamp) throws PersistitInterruptedException {
162@@ -433,35 +397,6 @@
163 }
164 }
165
166- private void populateWarmupFile() throws PersistitException {
167- final File file = new File(_defaultLogPath);
168-
169- try {
170- final BufferedWriter writer = new BufferedWriter(new FileWriter(file));
171- for (int i = 0; i < _buffers.length; ++i) {
172- final Buffer b = _buffers[i];
173- if (b != null && b.isValid() && !b.isDirty()) {
174- final long page = b.getPageAddress();
175- final Volume volume = b.getVolume();
176- final long page2 = b.getPageAddress();
177- final Volume volume2 = b.getVolume();
178-
179- // Check if buffer has changed while reading
180- if (page == page2 && volume == volume2 && volume != null) {
181- final String addr = Long.toString(page);
182- final String vol = volume.getName();
183- writer.append(addr + " " + vol);
184- writer.newLine();
185- writer.flush();
186- }
187- }
188- }
189- writer.close();
190- } catch (final IOException e) {
191- throw new PersistitException(e);
192- }
193- }
194-
195 private boolean selected(final Buffer buffer, final int includeMask, final int excludeMask) {
196 return ((includeMask == 0) || (buffer.getStatus() & includeMask) != 0)
197 && (buffer.getStatus() & excludeMask) == 0;
198@@ -1403,35 +1338,6 @@
199 }
200 }
201
202- /**
203- * Implementation of PAGE_CACHER thread
204- */
205- class PageCacher extends IOTaskRunnable {
206-
207- PageCacher() {
208- super(BufferPool.this._persistit);
209- }
210-
211- void start() {
212- start("PAGE_CACHER:" + _bufferSize, _cacherPollInterval);
213- }
214-
215- @Override
216- public void runTask() throws Exception {
217- populateWarmupFile();
218- }
219-
220- @Override
221- protected boolean shouldStop() {
222- return _closed.get() && !isFlushing();
223- }
224-
225- @Override
226- protected long pollInterval() {
227- return isFlushing() ? 0 : _cacherPollInterval;
228- }
229- }
230-
231 @Override
232 public String toString() {
233 return "BufferPool[" + _bufferCount + "@" + _bufferSize + (_closed.get() ? ":closed" : "") + "]";
234@@ -1486,4 +1392,133 @@
235 }
236 stream.flush();
237 }
238+
239+ void recordBufferInventory(final long timestamp) throws PersistitException {
240+ final Exchange exchange = getBufferInventoryExchange();
241+ /*
242+ * Advisory only - transaction integrity not needed
243+ */
244+ exchange.ignoreTransactions();
245+ try {
246+ int total = 0;
247+ exchange.clear().append(_bufferSize).append(timestamp).append(Key.BEFORE);
248+ final Value value = exchange.getValue();
249+ final int clockValueBefore = _clock.get();
250+ for (int index = 0; index < _buffers.length; index++) {
251+ final Buffer buffer = _buffers[index];
252+ long page1 = -1, page2 = -1;
253+ Volume volume1 = null, volume2 = null;
254+ if (buffer != null && buffer.isValid()) {
255+ while (true) {
256+ page1 = buffer.getPageAddress();
257+ volume1 = buffer.getVolume();
258+ page2 = buffer.getPageAddress();
259+ volume2 = buffer.getVolume();
260+ if (page1 == page2 && volume1 == volume2) {
261+ break;
262+ }
263+ Util.spinSleep();
264+ }
265+ if (volume1 != null && !volume1.isTemporary()) {
266+ value.clear().setStreamMode(true);
267+ value.put(volume1.getHandle());
268+ value.put(page1);
269+ exchange.to(index).store();
270+ total++;
271+ }
272+ }
273+ }
274+ final int clockValueAfter = _clock.get();
275+ exchange.cut();
276+ value.clear().setStreamMode(true);
277+ value.put(_bufferCount);
278+ value.put(total);
279+ value.put(clockValueBefore);
280+ value.put(clockValueAfter);
281+ value.put(System.currentTimeMillis());
282+ exchange.store();
283+ int count = 0;
284+ while (exchange.previous()) {
285+ if (++count > INVENTORY_VERSIONS) {
286+ exchange.remove(Key.GTEQ);
287+ }
288+ }
289+ } catch (final PersistitException e) {
290+ _persistit.getLogBase().bufferInventoryException.log(e);
291+ }
292+ }
293+
294+ void preloadBufferInventory() {
295+ int count = 0;
296+ int total = 0;
297+ try {
298+ final JournalManager jman = _persistit.getJournalManager();
299+ final Exchange exchange = getBufferInventoryExchange();
300+ final Value value = exchange.getValue();
301+ final List<PageNode> pageNodes = new ArrayList<PageNode>();
302+ boolean foundInventory = false;
303+ exchange.clear().append(_bufferSize).append(Key.AFTER);
304+ while (exchange.previous()) {
305+ if (exchange.getValue().isDefined()) {
306+ foundInventory = true;
307+ break;
308+ }
309+ }
310+ if (!foundInventory) {
311+ return;
312+ }
313+ value.setStreamMode(true);
314+ /* int bufferCount = */value.getInt();
315+ total = value.getInt();
316+ /* int clockValueBefore = */value.getInt();
317+ /* int clockValueAfter = */value.getInt();
318+ final long systemTime = value.getLong();
319+
320+ _persistit.getLogBase().bufferInventoryLoad.log(systemTime);
321+
322+ exchange.append(Key.BEFORE);
323+
324+ while (exchange.next()) {
325+ value.setStreamMode(true);
326+ final int volumeHandle = value.getInt();
327+ final long pageAddress = value.getLong();
328+ final PageNode pn = new PageNode(volumeHandle, pageAddress);
329+ pageNodes.add(pn);
330+ }
331+
332+ Collections.sort(pageNodes, PageNode.READ_COMPARATOR);
333+ for (final PageNode pn : pageNodes) {
334+ final Volume vol = jman.volumeForHandle(pn.getVolumeHandle());
335+ if (vol == null) {
336+ continue;
337+ }
338+ try {
339+ final Buffer buff = get(vol, pn.getPageAddress(), false, true);
340+ buff.release();
341+ count++;
342+ if ((count % INVENTORY_PRELOAD_LOG_MESSAGE_MULTIPLE) == 0) {
343+ _persistit.getLogBase().bufferInventoryProgress.log(count, total);
344+ }
345+ if (count >= _bufferCount) {
346+ //
347+ // If the buffer pool is now smaller, no need to load
348+ // more pages
349+ //
350+ break;
351+ }
352+ } catch (final PersistitException e) {
353+ // ignore it
354+ }
355+ }
356+ } catch (final PersistitException e) {
357+ _persistit.getLogBase().bufferInventoryException.log(e);
358+ } finally {
359+ _persistit.getLogBase().bufferInventoryProgress.log(count, total);
360+ }
361+ }
362+
363+ private Exchange getBufferInventoryExchange() throws PersistitException {
364+ final Volume sysvol = _persistit.getSystemVolume();
365+ return _persistit.getExchange(sysvol, INVENTORY_TREE_NAME, true);
366+ }
367 }
368
369=== modified file 'src/main/java/com/persistit/CheckpointManager.java'
370--- src/main/java/com/persistit/CheckpointManager.java 2012-08-23 21:28:19 +0000
371+++ src/main/java/com/persistit/CheckpointManager.java 2012-08-23 21:28:19 +0000
372@@ -201,6 +201,7 @@
373 void pollCreateCheckpoint() throws PersistitException {
374 final long now = System.nanoTime();
375 if (_lastCheckpointNanos + _checkpointIntervalNanos < now) {
376+ _persistit.recordBufferPoolInventory();
377 createCheckpoint();
378 }
379 }
380@@ -252,12 +253,12 @@
381 _currentCheckpoint = new Checkpoint(txn.getStartTimestamp(), System.currentTimeMillis());
382 _outstandingCheckpoints.add(_currentCheckpoint);
383 _persistit.getLogBase().checkpointProposed.log(_currentCheckpoint);
384- return _currentCheckpoint;
385 } catch (final InterruptedException ie) {
386 throw new PersistitInterruptedException(ie);
387 } finally {
388 txn.end();
389 }
390+ return _currentCheckpoint;
391 } finally {
392 _persistit.setSessionId(saveSessionId);
393 }
394
395=== modified file 'src/main/java/com/persistit/Configuration.java'
396--- src/main/java/com/persistit/Configuration.java 2012-08-23 21:28:19 +0000
397+++ src/main/java/com/persistit/Configuration.java 2012-08-23 21:28:19 +0000
398@@ -263,7 +263,7 @@
399 /**
400 * Property name for the "append only" property.
401 */
402- public final static String APPEND_ONLY_PROPERTY = "appendonly";
403+ public final static String APPEND_ONLY_PROPERTY_NAME = "appendonly";
404
405 /**
406 * Property name for the "ignore missing volumes" property.
407@@ -276,12 +276,15 @@
408 public final static String SPLIT_POLICY_PROPERTY_NAME = "splitpolicy";
409
410 /**
411- * Property name to specify the"buffer inventory" property name.
412+ * Property name to specify whether buffer preloading is enabled.
413+ */
414+ public final static String BUFFER_PRELOAD_PROPERTY_NAME = "bufferpreload";
415+
416+ /**
417+ * Property name to specify whether buffer inventory is enabled.
418 */
419 public final static String BUFFER_INVENTORY_PROPERTY_NAME = "bufferinventory";
420
421- public final static String BUFFER_POLLING_INTERVAL_PROPERTY = "bufferpollinginterval";
422-
423 /**
424 * Property name to specify the default {@link JoinPolicy}.
425 */
426@@ -634,9 +637,8 @@
427 private int rmiServerPort;
428 private boolean jmx = true;
429 private boolean appendOnly;
430- private String bufferInventoryPathName;
431- private long bufferInventoryPollInterval = 3000000; // default five minute
432- // polling
433+ private boolean bufferInventoryEnabled;
434+ private boolean bufferPreloadEnabled;
435 private boolean ignoreMissingVolumes;
436 private String tmpVolDir;
437 private int tmpVolPageSize;
438@@ -715,9 +717,7 @@
439 }
440
441 void loadProperties() throws InvalidVolumeSpecificationException {
442- setBufferInventoryPathName(getProperty(BUFFER_INVENTORY_PROPERTY_NAME));
443- setBufferInventoryPollingInterval(getLongProperty(BUFFER_POLLING_INTERVAL_PROPERTY, bufferInventoryPollInterval));
444- setAppendOnly(getBooleanProperty(APPEND_ONLY_PROPERTY, false));
445+ setAppendOnly(getBooleanProperty(APPEND_ONLY_PROPERTY_NAME, false));
446 setCommitPolicy(getProperty(COMMIT_POLICY_PROPERTY_NAME));
447 setConstructorOverride(getBooleanProperty(CONSTRUCTOR_OVERRIDE_PROPERTY_NAME, false));
448 setIgnoreMissingVolumes(getBooleanProperty(IGNORE_MISSING_VOLUMES_PROPERTY, false));
449@@ -737,6 +737,8 @@
450 setShowGUI(getBooleanProperty(SHOW_GUI_PROPERTY_NAME, false));
451 setSplitPolicy(getProperty(SPLIT_POLICY_PROPERTY_NAME));
452 setSysVolume(getProperty(SYSTEM_VOLUME_PROPERTY_NAME, DEFAULT_SYSTEM_VOLUME_NAME));
453+ setBufferInventoryEnabled(getBooleanProperty(BUFFER_INVENTORY_PROPERTY_NAME, false));
454+ setBufferPreloadEnabled(getBooleanProperty(BUFFER_PRELOAD_PROPERTY_NAME, false));
455
456 loadPropertiesBufferSpecifications();
457 loadPropertiesVolumeSpecifications();
458@@ -1548,8 +1550,7 @@
459 /**
460 * <p>
461 * Set a pattern that identifies classes to be serialized using standard
462- * Java serialization rather than Persistit's default serialization. TODO
463- * Link to Serialization section of user_guide.html.
464+ * Java serialization rather than Persistit's default serialization.
465 * </p>
466 * <p>
467 * Default value is <code>null</code><br />
468@@ -1559,6 +1560,8 @@
469 * @param serialOverride
470 * the serial override pattern to set
471 * @see DefaultCoderManager
472+ * @see <a
473+ * href="http://www.akiban.com/ak-docs/admin/persistit/Serialization.html">Serialization</a>
474 */
475 public void setSerialOverride(final String serialOverride) {
476 this.serialOverride = serialOverride;
477@@ -1579,8 +1582,7 @@
478 * a public no-argument constructor. If so, then that constructor is used
479 * when deserializing in the {@link DefaultObjectCoder}; if not then
480 * Persistit uses private methods within the JDK to emulate standard Java
481- * serialization logic. TODO Link to Serialization section of
482- * user_guide.html.
483+ * serialization logic.
484 * </p>
485 * <p>
486 * Default value is <code>false</code><br />
487@@ -1589,6 +1591,8 @@
488 *
489 * @param constructorOverride
490 * the constructorOverride to set
491+ * @see <a
492+ * href="http://www.akiban.com/ak-docs/admin/persistit/Serialization.html">Serialization</a>
493 */
494 public void setConstructorOverride(final boolean constructorOverride) {
495 this.constructorOverride = constructorOverride;
496@@ -1791,7 +1795,7 @@
497 /**
498 * Return the value defined by {@link #setAppendOnly}
499 *
500- * @return the whether to start Persistit in append-only mode
501+ * @return <true>true</code> if append-only mode is enabled at startup
502 */
503 public boolean isAppendOnly() {
504 return appendOnly;
505@@ -1807,77 +1811,73 @@
506 * </p>
507 * <p>
508 * Default value is <code>false</code><br />
509- * Property name is {@value #APPEND_ONLY_PROPERTY}
510+ * Property name is {@value #APPEND_ONLY_PROPERTY_NAME}
511 * </p>
512 *
513 * @param appendOnly
514- * <code>true</code> to start Persistit in append-only only
515+ * <code>true</code> to start Persistit in append-only mode
516 */
517 public void setAppendOnly(final boolean appendOnly) {
518 this.appendOnly = appendOnly;
519 }
520
521 /**
522- * Return the path name defined by {@link #getBufferInventoryPathName}
523- *
524- * @return the path where file to warm-up Persistit with sample buffer data
525- * is stored
526- */
527- public String getBufferInventoryPathName() {
528- return bufferInventoryPathName;
529- }
530-
531- /**
532- * <p>
533- * Control where Persistit stores its buffer inventory. In this mode
534- * Persistit restarts with information from the last run. This method
535- * initializes the warm-up file at the specified location, if none is
536- * specified the buffer pool is not warmed up on start-up.
537- * </p>
538- * <p>
539- * Default value is <code>null</code><br />
540- * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}
541- * </p>
542- *
543- * @param pathName
544- * the name of the path to the warm-up file
545- */
546- public void setBufferInventoryPathName(final String pathName) {
547- bufferInventoryPathName = pathName;
548-
549- }
550-
551- /**
552- * Return polling interval defined by
553- * {@link #getBufferInventoryPollingInterval}
554- *
555- * @return the number of seconds wait between warm-up polls
556- */
557- public long getBufferInventoryPollingInterval() {
558- return bufferInventoryPollInterval;
559- }
560-
561- /**
562- * <p>
563- * Control the number of seconds between each poll for the cache warm-up
564- * option in Persistit.
565- * </p>
566- * <p>
567- * Default value is <code>3000</code><br />
568- * Property name is {@value #BUFFER_POLLING_INTERVAL_PROPERTY}
569- * </p>
570- *
571- * @param seconds
572- * the number of seconds between polls
573- */
574- public void setBufferInventoryPollingInterval(final long seconds) {
575- bufferInventoryPollInterval = Util.rangeCheck(seconds, 60L, Long.MAX_VALUE) * 1000L;
576+ * Return the value defined by {@link #setBufferInventoryEnabled}
577+ *
578+ * @return <code>true</code> if periodic buffer pool inventory recording is
579+ * enabled
580+ */
581+ public boolean isBufferInventoryEnabled() {
582+ return bufferInventoryEnabled;
583+ }
584+
585+ /**
586+ * <p>
587+ * Control whether Persistit periodically records an inventory of its buffer
588+ * pools to enable buffer pool preloading on a subsequent startup.
589+ * </p>
590+ * <p>
591+ * Default value is <code>false</code><br />
592+ * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}
593+ *
594+ * @param bufferInventoryEnabled
595+ * <code>true</code> to enable periodic buffer inventory behavior
596+ */
597+ public void setBufferInventoryEnabled(final boolean bufferInventoryEnabled) {
598+ this.bufferInventoryEnabled = bufferInventoryEnabled;
599+ }
600+
601+ /**
602+ * Return the value defined by {@link #setBufferPreloadEnabled}
603+ *
604+ * @return <code>true</code> if the option to preload buffer pools is
605+ * enabled
606+ */
607+ public boolean isBufferPreloadEnabled() {
608+ return bufferPreloadEnabled;
609+ }
610+
611+ /**
612+ * <p>
613+ * Control whether Persistit attempts to preload (warm up) the buffer pools
614+ * by preloading pages recorded in a previously generated inventory.
615+ * </p>
616+ * <p>
617+ * Default value is <code>false</code><br />
618+ * Property name is {@value #BUFFER_INVENTORY_PROPERTY_NAME}
619+ *
620+ * @param bufferPreloadEnabled
621+ * <code>true</code> to enable buffer pool preloading during
622+ * startup
623+ */
624+ public void setBufferPreloadEnabled(final boolean bufferPreloadEnabled) {
625+ this.bufferPreloadEnabled = bufferPreloadEnabled;
626 }
627
628 /**
629 * Return the value defined by {@link #setIgnoreMissingVolumes(boolean)}
630 *
631- * @return the whether to start Persistit in ignore-missing-volumes mode
632+ * @return <code>true</code>to enable ignore-missing-volumes mode
633 */
634 public boolean isIgnoreMissingVolumes() {
635 return ignoreMissingVolumes;
636
637=== modified file 'src/main/java/com/persistit/JournalManager.java'
638--- src/main/java/com/persistit/JournalManager.java 2012-08-23 21:28:19 +0000
639+++ src/main/java/com/persistit/JournalManager.java 2012-08-23 21:28:19 +0000
640@@ -690,6 +690,29 @@
641 final ByteBuffer bb = buffer.getByteBuffer();
642
643 final Volume volume = buffer.getVolume();
644+ final PageNode pn = lookupUpPageNode(pageAddress, volume);
645+ if (pn == null) {
646+ return false;
647+ }
648+ bb.position(0);
649+ final long recordPageAddress = readPageBufferFromJournal(pn, bb);
650+ _persistit.getIOMeter().chargeReadPageFromJournal(volume, pageAddress, bufferSize, pn.getJournalAddress(),
651+ buffer.getIndex());
652+
653+ if (pageAddress != recordPageAddress) {
654+ throw new CorruptJournalException("Record at " + pn + " is not volume/page " + buffer.toString());
655+ }
656+
657+ if (bb.limit() != bufferSize) {
658+ throw new CorruptJournalException("Record at " + pn + " is wrong size: expected/actual=" + bufferSize + "/"
659+ + bb.limit());
660+ }
661+ _readPageCount++;
662+ buffer.getVolume().getStatistics().bumpReadCounter();
663+ return true;
664+ }
665+
666+ PageNode lookupUpPageNode(final long pageAddress, final Volume volume) {
667 PageNode pnLookup = null;
668 synchronized (this) {
669 final Integer volumeHandle = _volumeToHandleMap.get(volume);
670@@ -699,7 +722,7 @@
671 }
672
673 if (pnLookup == null) {
674- return false;
675+ return null;
676 }
677
678 final PageNode pn = new PageNode(pnLookup.getVolumeHandle(), pnLookup.getPageAddress(),
679@@ -714,25 +737,9 @@
680 * new checkpoints and that keeps the copier from deleting it.
681 */
682 if (pnLookup.isInvalid()) {
683- return false;
684- }
685-
686- bb.position(0);
687- final long recordPageAddress = readPageBufferFromJournal(pn, bb);
688- _persistit.getIOMeter().chargeReadPageFromJournal(volume, pageAddress, bufferSize, pn.getJournalAddress(),
689- buffer.getIndex());
690-
691- if (pageAddress != recordPageAddress) {
692- throw new CorruptJournalException("Record at " + pn + " is not volume/page " + buffer.toString());
693- }
694-
695- if (bb.limit() != bufferSize) {
696- throw new CorruptJournalException("Record at " + pn + " is wrong size: expected/actual=" + bufferSize + "/"
697- + bb.limit());
698- }
699- _readPageCount++;
700- buffer.getVolume().getStatistics().bumpReadCounter();
701- return true;
702+ return null;
703+ }
704+ return pn;
705 }
706
707 private long readPageBufferFromJournal(final PageNode pn, final ByteBuffer bb) throws PersistitIOException,
708@@ -1829,6 +1836,10 @@
709
710 PageNode _previous;
711
712+ PageNode(final int volumeHandle, final long pageAddress) {
713+ this(volumeHandle, pageAddress, Long.MIN_VALUE, -1);
714+ }
715+
716 PageNode(final int volumeHandle, final long pageAddress, final long journalAddress, final long timestamp) {
717 this._volumeHandle = volumeHandle;
718 this._pageAddress = pageAddress;
719@@ -1950,8 +1961,20 @@
720
721 @Override
722 public int compare(final PageNode a, final PageNode b) {
723- return a.getJournalAddress() > b.getJournalAddress() ? 1 : a.getJournalAddress() < b
724- .getJournalAddress() ? -1 : 0;
725+ if (!a.isInvalid() && !b.isInvalid()) {
726+ return a.getJournalAddress() > b.getJournalAddress() ? 1 : a.getJournalAddress() < b
727+ .getJournalAddress() ? -1 : 0;
728+ }
729+ if (a.isInvalid() && !b.isInvalid()) {
730+ return -1;
731+ }
732+ if (!a.isInvalid() && b.isInvalid()) {
733+ return 1;
734+ }
735+ if (a._volumeHandle != b._volumeHandle) {
736+ return a._volumeHandle - b._volumeHandle;
737+ }
738+ return a._pageAddress > b._pageAddress ? 1 : a._pageAddress < b._pageAddress ? -1 : 0;
739 }
740 };
741
742
743=== modified file 'src/main/java/com/persistit/MediatedFileChannel.java'
744--- src/main/java/com/persistit/MediatedFileChannel.java 2012-08-23 21:28:19 +0000
745+++ src/main/java/com/persistit/MediatedFileChannel.java 2012-08-23 21:28:19 +0000
746@@ -342,7 +342,7 @@
747 *
748 * @param channel
749 */
750- void setErrorInjectingChannelForTests(final FileChannel channel) {
751+ void injectChannelForTests(final FileChannel channel) {
752 ((TestChannelInjector) channel).setChannel(_channel);
753 _channel = channel;
754 }
755
756=== modified file 'src/main/java/com/persistit/Persistit.java'
757--- src/main/java/com/persistit/Persistit.java 2012-08-23 21:28:19 +0000
758+++ src/main/java/com/persistit/Persistit.java 2012-08-23 21:28:19 +0000
759@@ -403,6 +403,7 @@
760
761 private final AtomicBoolean _suspendShutdown = new AtomicBoolean(false);
762 private final AtomicBoolean _suspendUpdates = new AtomicBoolean(false);
763+ private final AtomicBoolean _enableBufferInventory = new AtomicBoolean(false);
764
765 private UtilControl _localGUI;
766
767@@ -588,9 +589,7 @@
768 initializeVolumes();
769 startJournal();
770 startBufferPools();
771- if (_configuration.getBufferInventoryPathName() != null) {
772- warmupBufferPools();
773- }
774+ preloadBufferPools();
775 finishRecovery();
776 startCheckpointManager();
777 startTransactionIndexPollTask();
778@@ -699,6 +698,7 @@
779 _defaultSplitPolicy = _configuration.getSplitPolicy();
780 _defaultJoinPolicy = _configuration.getJoinPolicy();
781 _defaultCommitPolicy = _configuration.getCommitPolicy();
782+ _enableBufferInventory.set(_configuration.isBufferInventoryEnabled());
783 }
784
785 void startCheckpointManager() {
786@@ -719,10 +719,24 @@
787 }
788 }
789
790- void warmupBufferPools() throws PersistitException {
791- final String pathName = _configuration.getBufferInventoryPathName();
792- for (final BufferPool pool : _bufferPoolTable.values()) {
793- pool.warmupBufferPool(pathName, pool.toString());
794+ void recordBufferPoolInventory() {
795+ final long timestamp = _timestampAllocator.getCurrentTimestamp();
796+ if (_enableBufferInventory.get()) {
797+ for (final BufferPool pool : _bufferPoolTable.values()) {
798+ try {
799+ pool.recordBufferInventory(timestamp);
800+ } catch (PersistitException e) {
801+ getLogBase().bufferInventoryException.log(e);
802+ }
803+ }
804+ }
805+ }
806+
807+ void preloadBufferPools() throws PersistitException {
808+ if (_configuration.isBufferPreloadEnabled()) {
809+ for (final BufferPool pool : _bufferPoolTable.values()) {
810+ pool.preloadBufferInventory();
811+ }
812 }
813 }
814
815@@ -974,8 +988,6 @@
816 *
817 * @throws IllegalStateException
818 */
819-
820- // TODO - why not one pool.
821 public void releaseExchange(final Exchange exchange, final boolean secure) {
822 if (exchange == null) {
823 return;
824@@ -1638,6 +1650,7 @@
825 }
826 }
827 }
828+ recordBufferPoolInventory();
829
830 /*
831 * The copier is responsible for background pruning of aborted
832
833=== modified file 'src/main/java/com/persistit/logging/LogBase.java'
834--- src/main/java/com/persistit/logging/LogBase.java 2012-08-23 21:28:19 +0000
835+++ src/main/java/com/persistit/logging/LogBase.java 2012-08-23 21:28:19 +0000
836@@ -244,6 +244,15 @@
837 @Message("ERROR|Too many journal files %,d")
838 public final LogItem tooManyJournalFilesError = PersistitLogMessage.empty();
839
840+ @Message("INFO|Preloading buffer pool inventory recorded at %tc")
841+ public final LogItem bufferInventoryLoad = PersistitLogMessage.empty();
842+
843+ @Message("INFO|Preloaded %,d of %,d buffers")
844+ public final LogItem bufferInventoryProgress = PersistitLogMessage.empty();
845+
846+ @Message("WARNING|Exception while writing buffer pool inventory %s")
847+ public final LogItem bufferInventoryException = PersistitLogMessage.empty();
848+
849 public static String recurring(final String message, final int count, final long duration) {
850 return String.format(RECURRING, message, count, duration);
851 }
852
853=== modified file 'src/test/java/com/persistit/IOFailureTest.java'
854--- src/test/java/com/persistit/IOFailureTest.java 2012-08-23 21:28:19 +0000
855+++ src/test/java/com/persistit/IOFailureTest.java 2012-08-23 21:28:19 +0000
856@@ -57,7 +57,7 @@
857
858 private ErrorInjectingFileChannel errorInjectingChannel(final FileChannel channel) {
859 final ErrorInjectingFileChannel eimfc = new ErrorInjectingFileChannel();
860- ((MediatedFileChannel) channel).setErrorInjectingChannelForTests(eimfc);
861+ ((MediatedFileChannel) channel).injectChannelForTests(eimfc);
862 return eimfc;
863 }
864
865
866=== modified file 'src/test/java/com/persistit/StressRunner.java'
867--- src/test/java/com/persistit/StressRunner.java 2012-08-23 21:28:19 +0000
868+++ src/test/java/com/persistit/StressRunner.java 2012-08-23 21:28:19 +0000
869@@ -31,6 +31,7 @@
870 import com.persistit.stress.MixtureTxn1;
871 import com.persistit.stress.MixtureTxn2;
872 import com.persistit.stress.PersistitMap1;
873+import com.persistit.stress.PreloadMixtureTxn1;
874 import com.persistit.stress.StartStop;
875 import com.persistit.stress.Stress10Suite;
876 import com.persistit.stress.Stress12txnSuite;
877@@ -79,6 +80,7 @@
878 _classes.add(Stress12txnSuite.class);
879 _classes.add(Stress4Suite.class);
880 _classes.add(Stress8txnSuite.class);
881+ _classes.add(PreloadMixtureTxn1.class);
882 }
883
884 private final static String DURATION_PARAM = "duration=";
885
886=== added file 'src/test/java/com/persistit/TrackingFileChannel.java'
887--- src/test/java/com/persistit/TrackingFileChannel.java 1970-01-01 00:00:00 +0000
888+++ src/test/java/com/persistit/TrackingFileChannel.java 2012-08-23 21:28:19 +0000
889@@ -0,0 +1,175 @@
890+/**
891+ * Copyright © 2012 Akiban Technologies, Inc. All rights reserved.
892+ *
893+ * This program and the accompanying materials are made available
894+ * under the terms of the Eclipse Public License v1.0 which
895+ * accompanies this distribution, and is available at
896+ * http://www.eclipse.org/legal/epl-v10.html
897+ *
898+ * This program may also be available under different license terms.
899+ * For more information, see www.akiban.com or contact licensing@akiban.com.
900+ *
901+ * Contributors:
902+ * Akiban Technologies, Inc.
903+ */
904+
905+package com.persistit;
906+
907+import static org.junit.Assert.assertEquals;
908+import static org.junit.Assert.assertTrue;
909+import static org.junit.Assert.fail;
910+import java.io.IOException;
911+import java.nio.ByteBuffer;
912+import java.nio.MappedByteBuffer;
913+import java.nio.channels.FileChannel;
914+import java.nio.channels.FileLock;
915+import java.nio.channels.ReadableByteChannel;
916+import java.nio.channels.WritableByteChannel;
917+import java.util.ArrayList;
918+import java.util.List;
919+
920+import com.persistit.MediatedFileChannel.TestChannelInjector;
921+
922+/**
923+ * <p>
924+ * A {@link FileChannel} implementation that simulates IOExceptions under
925+ * control of a unit test program. This class implements only those methods used
926+ * by Persistit; many methods of FileChannel throw
927+ * {@link UnsupportedOperationException}.
928+ * </p>
929+ *
930+ * @author peter
931+ *
932+ */
933+class TrackingFileChannel extends FileChannel implements TestChannelInjector {
934+
935+ volatile FileChannel _channel;
936+
937+ final List<Long> _writePositions = new ArrayList<Long>();
938+
939+ final List<Long> _readPositions = new ArrayList<Long>();
940+
941+ @Override
942+ public void setChannel(final FileChannel channel) {
943+ _channel = channel;
944+ }
945+
946+ @Override
947+ protected void implCloseChannel() throws IOException {
948+ _channel.close();
949+ }
950+
951+ @Override
952+ public void force(final boolean metaData) throws IOException {
953+ _channel.force(metaData);
954+ }
955+
956+ @Override
957+ public int read(final ByteBuffer byteBuffer, final long position) throws IOException {
958+ _readPositions.add(position);
959+ return _channel.read(byteBuffer, position);
960+ }
961+
962+ @Override
963+ public long size() throws IOException {
964+ return _channel.size();
965+ }
966+
967+ @Override
968+ public FileChannel truncate(final long size) throws IOException {
969+ return _channel.truncate(size);
970+ }
971+
972+ @Override
973+ public synchronized FileLock tryLock(final long position, final long size, final boolean shared) throws IOException {
974+ return _channel.tryLock(position, size, shared);
975+ }
976+
977+ @Override
978+ public int write(final ByteBuffer byteBuffer, final long position) throws IOException {
979+ _writePositions.add(position);
980+ final int written = _channel.write(byteBuffer, position);
981+ return written;
982+ }
983+
984+ /*
985+ * --------------------------------
986+ *
987+ * Persistit does not use these methods and so they are Unsupported. Note
988+ * that it would be difficult to support the relative read/write methods
989+ * because the channel size is unavailable after it is closed. Therefore a
990+ * client of this class must maintain its own position counter and cannot
991+ * use the relative-addressing calls.
992+ *
993+ * --------------------------------
994+ */
995+ @Override
996+ public FileLock lock(final long position, final long size, final boolean shared) throws IOException {
997+ throw new UnsupportedOperationException();
998+ }
999+
1000+ @Override
1001+ public MappedByteBuffer map(final MapMode arg0, final long arg1, final long arg2) throws IOException {
1002+ throw new UnsupportedOperationException();
1003+ }
1004+
1005+ @Override
1006+ public long position() throws IOException {
1007+ throw new UnsupportedOperationException();
1008+ }
1009+
1010+ @Override
1011+ public FileChannel position(final long arg0) throws IOException {
1012+ throw new UnsupportedOperationException();
1013+ }
1014+
1015+ @Override
1016+ public int read(final ByteBuffer byteBuffer) throws IOException {
1017+ throw new UnsupportedOperationException();
1018+ }
1019+
1020+ @Override
1021+ public long read(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException {
1022+ throw new UnsupportedOperationException();
1023+ }
1024+
1025+ @Override
1026+ public long transferFrom(final ReadableByteChannel arg0, final long arg1, final long arg2) throws IOException {
1027+ throw new UnsupportedOperationException();
1028+ }
1029+
1030+ @Override
1031+ public long transferTo(final long arg0, final long arg1, final WritableByteChannel arg2) throws IOException {
1032+ throw new UnsupportedOperationException();
1033+ }
1034+
1035+ @Override
1036+ public int write(final ByteBuffer byteBuffer) throws IOException {
1037+ throw new UnsupportedOperationException();
1038+ }
1039+
1040+ @Override
1041+ public long write(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException {
1042+ throw new UnsupportedOperationException();
1043+ }
1044+
1045+ public List<Long> getWritePositionList() {
1046+ return _writePositions;
1047+ }
1048+
1049+ public List<Long> getReadPositionList() {
1050+ return _readPositions;
1051+ }
1052+
1053+ public void assertSequential(boolean read, boolean forward) {
1054+ final List<Long> list = read ? _readPositions : _writePositions;
1055+ long previous = forward ? -1 : Long.MAX_VALUE;
1056+ for (final Long position : list) {
1057+ if (forward) {
1058+ assertTrue("Position should be larger", position > previous);
1059+ } else {
1060+ assertTrue("Position should be smaller", position < previous);
1061+ }
1062+ }
1063+ }
1064+}
1065
1066=== modified file 'src/test/java/com/persistit/WarmupTest.java'
1067--- src/test/java/com/persistit/WarmupTest.java 2012-08-23 21:28:19 +0000
1068+++ src/test/java/com/persistit/WarmupTest.java 2012-08-23 21:28:19 +0000
1069@@ -16,6 +16,7 @@
1070 package com.persistit;
1071
1072 import static org.junit.Assert.assertEquals;
1073+import static org.junit.Assert.assertTrue;
1074
1075 import java.util.Properties;
1076
1077@@ -25,43 +26,97 @@
1078
1079 public class WarmupTest extends PersistitUnitTestCase {
1080
1081+ @Override
1082+ protected Properties getProperties(final boolean cleanup) {
1083+ final Properties p = super.getProperties(cleanup);
1084+ p.setProperty("bufferinventory", "true");
1085+ p.setProperty("bufferpreload", "true");
1086+ return p;
1087+ }
1088+
1089 @Test
1090 public void testWarmup() throws Exception {
1091 Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true);
1092+ final BufferPool pool = ex.getBufferPool();
1093 for (int i = 1; i <= 1000; i++) {
1094 ex.getValue().put(RED_FOX);
1095 ex.clear().append(i).store();
1096 }
1097
1098- // Assumption: only one buffer pool is created
1099- int poolCount = 0;
1100- String pathName = "";
1101 final Buffer[] buff = new Buffer[100];
1102- for (final BufferPool p : _persistit.getBufferPoolHashMap().values()) {
1103- poolCount = p.getBufferCount();
1104- pathName = p.toString();
1105- for (int i = 0; i < poolCount; ++i) {
1106- buff[i] = p.getBufferCopy(i);
1107- }
1108- }
1109-
1110- final Properties properties = _persistit.getProperties();
1111- ex = null;
1112- _persistit.close();
1113-
1114- _persistit = new Persistit();
1115- _persistit.initialize(properties);
1116-
1117- int poolCount1 = 0;
1118- for (final BufferPool p : _persistit.getBufferPoolHashMap().values()) {
1119- poolCount1 = p.getBufferCount();
1120- for (int i = 0; i < poolCount1; ++i) {
1121- final Buffer bufferCopy = p.getBufferCopy(i);
1122- assertEquals(bufferCopy.getPageAddress(), buff[i].getPageAddress());
1123- assertEquals(bufferCopy.getPageType(), buff[i].getPageType());
1124- assertEquals(bufferCopy.getBufferSize(), buff[i].getBufferSize());
1125- }
1126- }
1127- assertEquals(poolCount, poolCount1);
1128+ for (int i = 0; i < pool.getBufferCount(); ++i) {
1129+ buff[i] = pool.getBufferCopy(i);
1130+ }
1131+
1132+ final Configuration config = _persistit.getConfiguration();
1133+ ex = null;
1134+ _persistit.close();
1135+
1136+ _persistit = new Persistit();
1137+ _persistit.initialize(config);
1138+
1139+ for (int i = 0; i < pool.getBufferCount(); ++i) {
1140+ final Buffer bufferCopy = pool.getBufferCopy(i);
1141+ assertEquals(bufferCopy.getPageAddress(), buff[i].getPageAddress());
1142+ assertEquals(bufferCopy.getPageType(), buff[i].getPageType());
1143+ assertEquals(bufferCopy.getBufferSize(), buff[i].getBufferSize());
1144+ }
1145+ }
1146+
1147+ @Test
1148+ public void readOrderIsSequential() throws Exception {
1149+
1150+ Exchange ex = _persistit.getExchange("persistit", "WarmupTest", true);
1151+ BufferPool pool = ex.getBufferPool();
1152+
1153+ final int full = pool.getBufferCount() * (pool.getBufferSize() / RED_FOX.length());
1154+ /*
1155+ * Overflow the buffer pool
1156+ */
1157+ for (int i = 1; i <= full * 3; i++) {
1158+ ex.getValue().put(RED_FOX);
1159+ ex.clear().append(i).store();
1160+ }
1161+ /*
1162+ * Pull some low-address pages in to scramble the pool
1163+ */
1164+ for (int i = full * 2; i >= 0; i -= 1000) {
1165+ ex.clear().append(i).fetch();
1166+ }
1167+ /*
1168+ * Verify that buffers in pool now have somewhat scrambled page
1169+ * addresses
1170+ */
1171+ int breaks = 0;
1172+ long previous = -1;
1173+
1174+ for (int i = 0; i < pool.getBufferCount(); i++) {
1175+ final Buffer b = pool.getBufferCopy(i);
1176+ assertTrue("Every buffer should be valid at this point", b.isValid());
1177+ if (b.getPageAddress() < previous) {
1178+ breaks++;
1179+ }
1180+ previous = b.getPageAddress();
1181+ }
1182+
1183+ assertTrue("Buffer pool should have scrambled page address", breaks > 0);
1184+
1185+ final Configuration config = _persistit.getConfiguration();
1186+ ex = null;
1187+ pool = null;
1188+ _persistit.close();
1189+
1190+ _persistit = new Persistit();
1191+ config.setBufferPreloadEnabled(false);
1192+ _persistit.initialize(config);
1193+
1194+ final Volume volume = _persistit.getVolume("persistit");
1195+ final MediatedFileChannel mfc = (MediatedFileChannel) volume.getStorage().getChannel();
1196+ final TrackingFileChannel tfc = new TrackingFileChannel();
1197+ mfc.injectChannelForTests(tfc);
1198+ pool = volume.getStructure().getPool();
1199+ pool.preloadBufferInventory();
1200+ assertTrue("Preload should have loaded pages from journal file", tfc.getReadPositionList().size() > 0);
1201+ tfc.assertSequential(true, true);
1202 }
1203 }
1204
1205=== added file 'src/test/java/com/persistit/stress/PreloadMixtureTxn1.java'
1206--- src/test/java/com/persistit/stress/PreloadMixtureTxn1.java 1970-01-01 00:00:00 +0000
1207+++ src/test/java/com/persistit/stress/PreloadMixtureTxn1.java 2012-08-23 21:28:19 +0000
1208@@ -0,0 +1,82 @@
1209+/**
1210+ * Copyright © 2012 Akiban Technologies, Inc. All rights reserved.
1211+ *
1212+ * This program and the accompanying materials are made available
1213+ * under the terms of the Eclipse Public License v1.0 which
1214+ * accompanies this distribution, and is available at
1215+ * http://www.eclipse.org/legal/epl-v10.html
1216+ *
1217+ * This program may also be available under different license terms.
1218+ * For more information, see www.akiban.com or contact licensing@akiban.com.
1219+ *
1220+ * Contributors:
1221+ * Akiban Technologies, Inc.
1222+ */
1223+
1224+package com.persistit.stress;
1225+
1226+import com.persistit.Configuration;
1227+import com.persistit.Persistit;
1228+import com.persistit.Transaction.CommitPolicy;
1229+import com.persistit.stress.unit.Stress1;
1230+import com.persistit.stress.unit.Stress2txn;
1231+import com.persistit.stress.unit.Stress3;
1232+import com.persistit.stress.unit.Stress3txn;
1233+import com.persistit.stress.unit.Stress5;
1234+import com.persistit.stress.unit.Stress6;
1235+import com.persistit.stress.unit.Stress8txn;
1236+
1237+public class PreloadMixtureTxn1 extends AbstractSuite {
1238+ private final static int CYCLES = 4;
1239+
1240+ static String name() {
1241+ return PreloadMixtureTxn1.class.getSimpleName();
1242+ }
1243+
1244+ public static void main(final String[] args) throws Exception {
1245+ new PreloadMixtureTxn1(args).runTest();
1246+ }
1247+
1248+ public PreloadMixtureTxn1(final String[] args) {
1249+ super(name(), args);
1250+ setDuration(getDuration() / CYCLES);
1251+ }
1252+
1253+ @Override
1254+ public void runTest() throws Exception {
1255+
1256+ deleteFiles(substitute("$datapath$/persistit*"));
1257+
1258+ for (int iteration = 0; iteration < CYCLES; iteration++) {
1259+ clear();
1260+ add(new Stress1("repeat=10 count=25000"));
1261+ add(new Stress1("repeat=10 count=25000"));
1262+ add(new Stress2txn("repeat=10 count=2500 size=4000 seed=118"));
1263+ add(new Stress2txn("repeat=2 count=25000 seed=119"));
1264+ add(new Stress3("repeat=5 count=25000 seed=119"));
1265+ add(new Stress3txn("repeat=5 count=25000 seed=120"));
1266+ add(new Stress3txn("repeat=5 count=25000"));
1267+ add(new Stress5("repeat=5 count=25000"));
1268+ add(new Stress6("repeat=5 count=1000 size=250"));
1269+ add(new Stress6("repeat=10 count=1000 size=250"));
1270+ add(new Stress8txn("repeat=2 count=1000 size=1000 seed=1"));
1271+ add(new Stress8txn("repeat=2 count=1000 size=1000 seed=2"));
1272+ add(new Stress8txn("repeat=2 count=1000 size=1000 seed=3"));
1273+ add(new Stress8txn("repeat=2 count=1000 size=1000 seed=4"));
1274+
1275+ final Configuration configuration = makeConfiguration(16384, "25000", CommitPolicy.SOFT);
1276+ configuration.setLogFile(configuration.getLogFile() + "_" + iteration);
1277+ configuration.setBufferInventoryEnabled(true);
1278+ configuration.setBufferPreloadEnabled(true);
1279+
1280+ final Persistit persistit = new Persistit();
1281+ persistit.initialize(configuration);
1282+
1283+ try {
1284+ execute(persistit);
1285+ } finally {
1286+ persistit.close();
1287+ }
1288+ }
1289+ }
1290+}
1291
1292=== modified file 'src/test/java/com/persistit/unit/PersistitUnitTestCase.java'
1293--- src/test/java/com/persistit/unit/PersistitUnitTestCase.java 2012-08-23 21:28:19 +0000
1294+++ src/test/java/com/persistit/unit/PersistitUnitTestCase.java 2012-08-23 21:28:19 +0000
1295@@ -47,7 +47,8 @@
1296 protected Persistit _persistit = new Persistit();
1297
1298 protected Properties getProperties(final boolean cleanup) {
1299- return UnitTestProperties.getProperties(cleanup);
1300+ final Properties p = UnitTestProperties.getProperties(cleanup);
1301+ return p;
1302 }
1303
1304 @Before
1305
1306=== modified file 'src/test/java/com/persistit/unit/UnitTestProperties.java'
1307--- src/test/java/com/persistit/unit/UnitTestProperties.java 2012-08-07 21:11:28 +0000
1308+++ src/test/java/com/persistit/unit/UnitTestProperties.java 2012-08-23 21:28:19 +0000
1309@@ -43,7 +43,6 @@
1310 p.setProperty("tmpvoldir", "${datapath}");
1311 p.setProperty("rmiport", System.getProperty("rmiport", "8081"));
1312 p.setProperty("jmx", "true");
1313- p.setProperty("bufferinventory", "/tmp/persistit_test_data");
1314 return p;
1315 }
1316

Subscribers

People subscribed via source and target branches