1 8 9 package com.sleepycat.je.log; 10 11 import com.sleepycat.je.DatabaseException; 12 import com.sleepycat.je.EnvironmentStats; 13 import com.sleepycat.je.RunRecoveryException; 14 import com.sleepycat.je.StatsConfig; 15 import com.sleepycat.je.config.EnvironmentParams; 16 import com.sleepycat.je.dbi.EnvironmentImpl; 17 import com.sleepycat.je.latch.Latch; 18 import com.sleepycat.je.latch.LatchSupport; 19 import com.sleepycat.je.utilint.PropUtil; 20 21 83 class FSyncManager { 84 private EnvironmentImpl envImpl; 85 private long timeout; 86 87 88 private Latch fsyncLatch; 89 90 private volatile boolean fsyncInProgress; 91 private FSyncGroup nextFSyncWaiters; 92 93 94 private long nFSyncRequests = 0; 95 private long nFSyncs = 0; 96 private long nTimeouts = 0; 97 98 FSyncManager(EnvironmentImpl envImpl) 99 throws DatabaseException { 100 timeout = PropUtil.microsToMillis(envImpl.getConfigManager().getLong( 101 EnvironmentParams.LOG_FSYNC_TIMEOUT)); 102 this.envImpl = envImpl; 103 104 fsyncLatch = LatchSupport.makeLatch("fsyncLatch", envImpl); 105 fsyncInProgress = false; 106 nextFSyncWaiters = new FSyncGroup(timeout, envImpl); 107 } 108 109 137 void fsync() 138 throws DatabaseException { 139 140 boolean doFsync = false; 141 boolean isLeader = false; 142 boolean needToWait = false; 143 FSyncGroup inProgressGroup = null; 144 FSyncGroup myGroup = null; 145 146 synchronized (fsyncLatch) { 147 nFSyncRequests++; 148 149 150 if (fsyncInProgress) { 151 needToWait = true; 152 myGroup = nextFSyncWaiters; 153 } else { 154 isLeader = true; 155 doFsync = true; 156 fsyncInProgress = true; 157 inProgressGroup = nextFSyncWaiters; 158 nextFSyncWaiters = new FSyncGroup(timeout, envImpl); 159 } 160 } 161 162 if (needToWait) { 163 164 173 int waitStatus = myGroup.waitForFsync(); 174 175 if (waitStatus == FSyncGroup.DO_LEADER_FSYNC) { 176 synchronized (fsyncLatch) { 177 178 185 if (!fsyncInProgress) { 186 isLeader = true; 187 doFsync = true; 188 fsyncInProgress = true; 189 inProgressGroup = myGroup; 190 nextFSyncWaiters = new FSyncGroup(timeout, envImpl); 191 } 192 } 193 } else if (waitStatus == FSyncGroup.DO_TIMEOUT_FSYNC) { 194 doFsync = true; 195 synchronized (fsyncLatch) { 196 nTimeouts++; 197 } 198 } 199 } 200 201 if (doFsync) { 202 203 218 executeFSync(); 219 220 synchronized (fsyncLatch) { 221 nFSyncs++; 222 if (isLeader) { 223 224 228 inProgressGroup.wakeupAll(); 229 230 234 nextFSyncWaiters.wakeupOne(); 235 fsyncInProgress = false; 236 } 237 } 238 } 239 } 240 241 244 long getNFSyncRequests() { 245 return nFSyncRequests; 246 } 247 248 long getNFSyncs() { 249 return nFSyncs; 250 } 251 252 long getNTimeouts() { 253 return nTimeouts; 254 } 255 256 void loadStats(StatsConfig config, EnvironmentStats stats) 257 throws DatabaseException { 258 259 stats.setNFSyncs(nFSyncs); 260 stats.setNFSyncRequests(nFSyncRequests); 261 stats.setNFSyncTimeouts(nTimeouts); 262 263 if (config.getClear()) { 264 nFSyncs = 0; 265 nFSyncRequests = 0; 266 nTimeouts = 0; 267 } 268 } 269 270 274 protected void executeFSync() 275 throws DatabaseException { 276 277 envImpl.getFileManager().syncLogEnd(); 278 } 279 280 285 static class FSyncGroup { 286 static int DO_TIMEOUT_FSYNC = 0; 287 static int DO_LEADER_FSYNC = 1; 288 static int NO_FSYNC_NEEDED = 2; 289 290 private volatile boolean fsyncDone; 291 private long fsyncTimeout; 292 private boolean leaderExists; 293 private EnvironmentImpl envImpl; 294 295 FSyncGroup(long fsyncTimeout, EnvironmentImpl envImpl) { 296 this.fsyncTimeout = fsyncTimeout; 297 fsyncDone = false; 298 leaderExists = false; 299 this.envImpl = envImpl; 300 } 301 302 synchronized boolean getLeader() { 303 if (fsyncDone) { 304 return false; 305 } else { 306 if (leaderExists) { 307 return false; 308 } else { 309 leaderExists = true; 310 return true; 311 } 312 } 313 } 314 315 323 synchronized int waitForFsync() 324 throws RunRecoveryException { 325 326 int status = 0; 327 328 if (!fsyncDone) { 329 long startTime = System.currentTimeMillis(); 330 while (true) { 331 332 try { 333 wait(fsyncTimeout); 334 } catch (InterruptedException e) { 335 throw new RunRecoveryException(envImpl, 336 "Unexpected interrupt while waiting for fsync", e); 337 } 338 339 343 if (fsyncDone) { 344 345 status = NO_FSYNC_NEEDED; 346 break; 347 } else { 348 349 353 if (!leaderExists) { 354 leaderExists = true; 355 status = DO_LEADER_FSYNC; 356 break; 357 } else { 358 359 363 long now = System.currentTimeMillis(); 364 if ((now - startTime) > fsyncTimeout) { 365 366 status = DO_TIMEOUT_FSYNC; 367 break; 368 } 369 } 370 } 371 } 372 } 373 374 return status; 375 } 376 377 synchronized void wakeupAll() { 378 fsyncDone = true; 379 notifyAll(); 380 } 381 382 synchronized void wakeupOne() { 383 384 notify(); 385 } 386 } 387 } 388 | Popular Tags |