Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.log;
import static com.sleepycat.je.log.LogStatDefinition.FSYNCMGR_FSYNCS;
import static com.sleepycat.je.log.LogStatDefinition.FSYNCMGR_FSYNC_REQUESTS;
import static com.sleepycat.je.log.LogStatDefinition.FSYNCMGR_TIMEOUTS;
import static com.sleepycat.je.log.LogStatDefinition.FSYNCMGR_N_GROUP_COMMIT_REQUESTS;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.StatsConfig;
import com.sleepycat.je.ThreadInterruptedException;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.utilint.AtomicLongStat;
import com.sleepycat.je.utilint.LongStat;
import com.sleepycat.je.utilint.StatGroup;
import com.sleepycat.je.utilint.TestHook;
import com.sleepycat.je.utilint.TestHookExecute;
/*
* The FsyncManager ensures that only one file flush+fsync is issued at a
* time, which is called a group commit. The goal is to reduce the number of
* group commits issued by the system by issuing one group commit on behalf
* of a number of threads.
*
* For example, suppose these writes are buffered and all need to be fsynced
* as well as flushed:
*
* thread 1 writes a commit record
* thread 2 writes a checkpoint
* thread 3 writes a commit record
* thread 4 writes a commit record
* thread 5 writes a checkpoint
*
* Rather than executing 5 group commits, which all must happen synchronously,
* we hope to issue fewer. How many fewer depend on timing.
*
* For example:
* thread 1 wants to commit first, no other commit is going on: issue commit
* thread 2 waits
* thread 3 waits
* thread 4 waits
* - before thread 5 comes, thread 1 finishes the commit and returns to
* the caller. Now another commit can be issued that will cover threads
* 2,3,4. One of those threads (2, 3, 4} issues the commit, the others
* block.
* thread 5 wants to commit, but sees one going on, so will wait.
* - the commit issued for 2,3,4 can't cover thread 5 because we're not
* sure if thread 5's write was buffered before that commit. Thread 5 will
* have to issue its own commit.
*
* Target file
* -----------
* Note that when the buffer pool starts a new file, we flush and fsync the
* previous file under the log write latch. Therefore, at any time we only
* have one target file to flush/fsync, which is the current write buffer.
* We do this so that we don't have to coordinate between files. For example,
* suppose log files have 1000 bytes and a commit record is 10 bytes. An
* LSN of value 6/990 is in file 6 at offset 990.
*
* thread 1: logWriteLatch.acquire()
* buffer commit record to LSN 6/980
* logWriteLatch.release()
* thread 2: logWriteLatch.acquire()
* buffer commit record to LSN 6/990
* logWriteLatch.release
* thread 3: logWriteLatch.acquire()
* gets 7/000 as the next LSN to use
* see that we flipped to a new file, so flush and fsync on file 6
* buffer commit record to LSN 7/000
* logWriteLatch.release()
*
* Thread 3 will flush/fsync file 6 within the log write latch. That way, at
* any time, any non-latched commits should only commits the latest file.
* If we didn't do this, there's the chance that thread 3 would flush/fsync
* file 7 and return to its caller before the thread 1 and 2 flushed/fsynced
* file 6. That wouldn't be correct, because thread 3's txn commit might depend
* on file 6.
*
* Note that the FileManager keeps a file descriptor that corresponds to the
* current end of file, and that is what we commit.
*/
class FSyncManager {
private final EnvironmentImpl envImpl;
private final long timeout;
/* Use as the target for a synchronization block. */
private final Object mgrMutex;
private volatile boolean workInProgress;
private FSyncGroup nextFSyncWaiters;
/* stats */
private final StatGroup stats;
private final LongStat nFSyncRequests;
private final AtomicLongStat nFSyncs;
private final LongStat nTimeouts;
private final LongStat nRequests;
/* For unit tests. */
private TestHook