|
17 | 17 | import java.util.Map; |
18 | 18 | import java.util.Set; |
19 | 19 | import java.util.concurrent.Callable; |
| 20 | +import java.util.concurrent.CompletableFuture; |
20 | 21 | import java.util.concurrent.ConcurrentHashMap; |
| 22 | +import java.util.concurrent.ExecutorService; |
| 23 | +import java.util.concurrent.Executors; |
21 | 24 | import java.util.concurrent.TimeUnit; |
22 | 25 | import java.util.concurrent.atomic.AtomicBoolean; |
23 | 26 | import java.util.concurrent.atomic.AtomicInteger; |
@@ -404,28 +407,36 @@ private static void compact(MVStore source, MVStore target) { |
404 | 407 | targetMeta.put(key, m.getValue()); |
405 | 408 | } |
406 | 409 | } |
407 | | - // We are going to cheat a little bit in the copyFrom() by employing "incomplete" pages, |
408 | | - // which would be spared of saving, but save completed pages underneath, |
409 | | - // and those may appear as dead (non-reachable). |
410 | | - // That's why it is important to preserve all chunks |
411 | | - // created in the process, especially if retention time |
412 | | - // is set to a lower value, or even 0. |
413 | | - for (String mapName : source.getMapNames()) { |
414 | | - MVMap.Builder<Object, Object> mp = MVStoreTool.getGenericMapBuilder(); |
415 | | - // This is a hack to preserve chunks occupancy rate accounting. |
416 | | - // It exposes design deficiency flaw in MVStore related to lack of |
417 | | - // map's type metadata. |
418 | | - // TODO: Introduce type metadata which will allow to open any store |
419 | | - // TODO: without prior knowledge of keys / values types and map implementation |
420 | | - // TODO: (MVMap vs MVRTreeMap, regular vs. singleWriter etc.) |
421 | | - if (mapName.startsWith(TransactionStore.UNDO_LOG_NAME_PREFIX)) { |
422 | | - mp.singleWriter(); |
423 | | - } |
424 | | - MVMap<Object, Object> sourceMap = source.openMap(mapName, mp); |
425 | | - MVMap<Object, Object> targetMap = target.openMap(mapName, mp); |
426 | | - targetMap.copyFrom(sourceMap); |
427 | | - targetMeta.put(MVMap.getMapKey(targetMap.getId()), sourceMeta.get(MVMap.getMapKey(sourceMap.getId()))); |
428 | | - } |
| 410 | + |
| 411 | + int poolSize = Integer.getInteger("h2.compactThreads", Math.max(1, Runtime.getRuntime().availableProcessors() / 4)); |
| 412 | + ExecutorService pool = Executors.newFixedThreadPool(poolSize); |
| 413 | + CompletableFuture.allOf( |
| 414 | + // We are going to cheat a little bit in the copyFrom() by employing "incomplete" pages, |
| 415 | + // which would be spared of saving, but save completed pages underneath, |
| 416 | + // and those may appear as dead (non-reachable). |
| 417 | + // That's why it is important to preserve all chunks |
| 418 | + // created in the process, especially if retention time |
| 419 | + // is set to a lower value, or even 0. |
| 420 | + source.getMapNames().stream().map(mapName -> |
| 421 | + CompletableFuture.runAsync(() -> { |
| 422 | + MVMap.Builder<Object, Object> mp = MVStoreTool.getGenericMapBuilder(); |
| 423 | + // This is a hack to preserve chunks occupancy rate accounting. |
| 424 | + // It exposes design deficiency flaw in MVStore related to lack of |
| 425 | + // map's type metadata. |
| 426 | + // TODO: Introduce type metadata which will allow to open any store |
| 427 | + // TODO: without prior knowledge of keys / values types and map implementation |
| 428 | + // TODO: (MVMap vs MVRTreeMap, regular vs. singleWriter etc.) |
| 429 | + if (mapName.startsWith(TransactionStore.UNDO_LOG_NAME_PREFIX)) { |
| 430 | + mp.singleWriter(); |
| 431 | + } |
| 432 | + MVMap<Object, Object> sourceMap = source.openMap(mapName, mp); |
| 433 | + MVMap<Object, Object> targetMap = target.openMap(mapName, mp); |
| 434 | + targetMap.copyFrom(sourceMap); |
| 435 | + targetMeta.put(MVMap.getMapKey(targetMap.getId()), sourceMeta.get(MVMap.getMapKey(sourceMap.getId()))); |
| 436 | + }, pool) |
| 437 | + ).toArray(CompletableFuture[]::new) |
| 438 | + ).join(); |
| 439 | + pool.shutdownNow(); |
429 | 440 | // this will end hacky mode of operation with incomplete pages |
430 | 441 | // end ensure that all pages are saved |
431 | 442 | target.commit(); |
|
0 commit comments