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