1 8 9 package com.sleepycat.je.cleaner; 10 11 import java.util.Collections ; 12 import java.util.HashMap ; 13 import java.util.HashSet ; 14 import java.util.LinkedList ; 15 import java.util.List ; 16 import java.util.Map ; 17 import java.util.Set ; 18 import java.util.SortedSet ; 19 import java.util.TreeSet ; 20 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.dbi.DatabaseId; 23 import com.sleepycat.je.tree.LN; 24 25 28 public class FileSelector { 29 30 41 42 50 private SortedSet toBeCleanedFiles; 51 52 58 private Set beingCleanedFiles; 59 60 82 private Set cleanedFiles; 83 private LinkedList cleanedDeferredWriteDbs; 84 85 92 private Set checkpointedFiles; 93 94 112 private Set fullyProcessedFiles; 113 114 121 private Set safeToDeleteFiles; 122 123 127 private Map pendingLNs; 128 129 135 private Set pendingDBs; 136 137 146 private boolean anyPendingDuringCheckpoint; 147 148 153 private Set lowUtilizationFiles; 154 155 FileSelector() { 156 toBeCleanedFiles = new TreeSet (); 157 cleanedFiles = new HashSet (); 158 cleanedDeferredWriteDbs = new LinkedList (); 159 checkpointedFiles = new HashSet (); 160 fullyProcessedFiles = new HashSet (); 161 safeToDeleteFiles = new HashSet (); 162 pendingLNs = new HashMap (); 163 pendingDBs = new HashSet (); 164 lowUtilizationFiles = Collections.EMPTY_SET; 165 beingCleanedFiles = new HashSet (); 166 } 167 168 184 Long selectFileForCleaning(UtilizationProfile profile, 185 boolean forceCleaning, 186 boolean calcLowUtilizationFiles, 187 int maxBatchFiles) 188 throws DatabaseException { 189 190 Set newLowUtilizationFiles = calcLowUtilizationFiles ? 191 (new HashSet ()) : null; 192 193 197 while (true) { 198 199 if (maxBatchFiles > 0) { 200 synchronized (this) { 201 if (toBeCleanedFiles.size() >= maxBatchFiles) { 202 break; 203 } 204 } 205 } 206 207 Long fileNum = profile.getBestFileForCleaning 208 (this, forceCleaning, newLowUtilizationFiles); 209 210 if (fileNum == null) { 211 break; 212 } 213 214 synchronized (this) { 215 toBeCleanedFiles.add(fileNum); 216 } 217 } 218 219 220 if (newLowUtilizationFiles != null) { 221 lowUtilizationFiles = newLowUtilizationFiles; 222 } 223 224 229 SortedSet availableFiles; 230 synchronized (this) { 231 availableFiles = new TreeSet (toBeCleanedFiles); 232 } 233 Long file = profile.getCheapestFileToClean(availableFiles); 234 if (file != null) { 235 synchronized (this) { 236 toBeCleanedFiles.remove(file); 237 beingCleanedFiles.add(file); 238 } 239 } 240 return file; 241 } 242 243 246 synchronized boolean isFileCleaningInProgress(Long file) { 247 return toBeCleanedFiles.contains(file) || 248 beingCleanedFiles.contains(file) || 249 cleanedFiles.contains(file) || 250 checkpointedFiles.contains(file) || 251 fullyProcessedFiles.contains(file) || 252 safeToDeleteFiles.contains(file); 253 } 254 255 259 synchronized void putBackFileForCleaning(Long fileNum) { 260 toBeCleanedFiles.add(fileNum); 261 beingCleanedFiles.remove(fileNum); 262 } 263 264 268 synchronized void addCleanedFile(Long fileNum, Set deferredWriteDbs) { 269 cleanedFiles.add(fileNum); 270 cleanedDeferredWriteDbs.addAll(deferredWriteDbs); 271 beingCleanedFiles.remove(fileNum); 272 } 273 274 278 Set getLowUtilizationFiles() { 279 280 return lowUtilizationFiles; 281 } 282 283 287 synchronized Set getMustBeCleanedFiles() { 288 Set set = new HashSet (toBeCleanedFiles); 289 set.addAll(beingCleanedFiles); 290 return set; 291 } 292 293 296 synchronized int getBacklog() { 297 return toBeCleanedFiles.size(); 298 } 299 300 304 synchronized CheckpointStartCleanerState getFilesAtCheckpointStart() { 305 306 anyPendingDuringCheckpoint = !pendingLNs.isEmpty() || 307 !pendingDBs.isEmpty(); 308 309 CheckpointStartCleanerState info = 310 new CheckpointStartCleanerState(cleanedFiles, 311 fullyProcessedFiles, 312 cleanedDeferredWriteDbs); 313 return info; 314 } 315 316 322 synchronized void updateFilesAtCheckpointEnd( 323 CheckpointStartCleanerState info) { 324 325 if (!info.isEmpty()) { 326 327 Set previouslyCleanedFiles = info.getCleanedFiles(); 328 if (previouslyCleanedFiles != null) { 329 if (anyPendingDuringCheckpoint) { 330 checkpointedFiles.addAll(previouslyCleanedFiles); 331 } else { 332 safeToDeleteFiles.addAll(previouslyCleanedFiles); 333 } 334 cleanedFiles.removeAll(previouslyCleanedFiles); 335 } 336 337 Set previouslyProcessedFiles = 338 info.getFullyProcessedFiles(); 339 if (previouslyProcessedFiles != null) { 340 safeToDeleteFiles.addAll(previouslyProcessedFiles); 341 fullyProcessedFiles.removeAll(previouslyProcessedFiles); 342 } 343 344 int previousSize = cleanedDeferredWriteDbs.size(); 345 int numDbsSyncedByCheckpoint = 346 info.getDeferredWriteDbsSize(); 347 for (int i = 0; i < numDbsSyncedByCheckpoint; i++) { 348 cleanedDeferredWriteDbs.removeFirst(); 349 } 350 351 assert cleanedDeferredWriteDbs.size() == 352 previousSize - numDbsSyncedByCheckpoint; 353 354 updateProcessedFiles(); 355 } 356 } 357 358 361 synchronized boolean addPendingLN(LN ln, DatabaseId dbId, 362 byte[] key, byte[] dupKey) { 363 assert ln != null; 364 365 boolean added = pendingLNs.put 366 (new Long (ln.getNodeId()), 367 new LNInfo(ln, dbId, key, dupKey)) != null; 368 369 anyPendingDuringCheckpoint = true; 370 return added; 371 } 372 373 377 synchronized LNInfo[] getPendingLNs() { 378 379 if (pendingLNs.size() > 0) { 380 LNInfo[] lns = new LNInfo[pendingLNs.size()]; 381 pendingLNs.values().toArray(lns); 382 return lns; 383 } else { 384 return null; 385 } 386 } 387 388 391 synchronized void removePendingLN(long nodeId) { 392 393 pendingLNs.remove(new Long (nodeId)); 394 updateProcessedFiles(); 395 } 396 397 400 synchronized boolean addPendingDB(DatabaseId dbId) { 401 402 boolean added = pendingDBs.add(dbId); 403 404 anyPendingDuringCheckpoint = true; 405 return added; 406 } 407 408 412 synchronized DatabaseId[] getPendingDBs() { 413 414 if (pendingDBs.size() > 0) { 415 DatabaseId[] dbs = new DatabaseId[pendingDBs.size()]; 416 pendingDBs.toArray(dbs); 417 return dbs; 418 } else { 419 return null; 420 } 421 } 422 423 426 synchronized void removePendingDB(DatabaseId dbId) { 427 428 pendingDBs.remove(dbId); 429 updateProcessedFiles(); 430 } 431 432 435 synchronized Set copySafeToDeleteFiles() { 436 if (safeToDeleteFiles.size() == 0) { 437 return null; 438 } else { 439 return new HashSet (safeToDeleteFiles); 440 } 441 } 442 443 447 synchronized void removeDeletedFile(Long fileNum) { 448 safeToDeleteFiles.remove(fileNum); 449 } 450 451 457 private void updateProcessedFiles() { 458 if (pendingLNs.isEmpty() && pendingDBs.isEmpty()) { 459 fullyProcessedFiles.addAll(checkpointedFiles); 460 checkpointedFiles.clear(); 461 } 462 } 463 464 467 static public class CheckpointStartCleanerState { 468 469 470 private Set cleanedFiles; 471 private Set fullyProcessedFiles; 472 private Set deferredWriteDbs; 473 474 CheckpointStartCleanerState(Set cleanedFiles, 475 Set fullyProcessedFiles, 476 List cleanedDeferredWriteDbs) { 477 478 482 this.cleanedFiles = new HashSet (cleanedFiles); 483 this.fullyProcessedFiles = new HashSet (fullyProcessedFiles); 484 deferredWriteDbs = new HashSet (cleanedDeferredWriteDbs); 485 } 486 487 public boolean isEmpty() { 488 return ((cleanedFiles.size() == 0) && 489 (fullyProcessedFiles.size() == 0) && 490 (deferredWriteDbs.size() == 0)); 491 } 492 493 public Set getCleanedFiles() { 494 return cleanedFiles; 495 } 496 497 public Set getFullyProcessedFiles() { 498 return fullyProcessedFiles; 499 } 500 501 public Set getDeferredWriteDbs() { 502 return deferredWriteDbs; 503 } 504 505 public int getDeferredWriteDbsSize() { 506 return deferredWriteDbs.size(); 507 } 508 } 509 } 510 | Popular Tags |