001/* 002 * #%L 003 * Netarchivesuite - archive 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.archive.arcrepository.bitpreservation; 024 025import java.io.File; 026import java.sql.Date; 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import dk.netarkivet.archive.arcrepositoryadmin.BitPreservationDAO; 037import dk.netarkivet.archive.arcrepositoryadmin.ReplicaCacheDatabase; 038import dk.netarkivet.archive.arcrepositoryadmin.ReplicaFileInfo; 039import dk.netarkivet.common.distribute.arcrepository.ArcRepositoryClientFactory; 040import dk.netarkivet.common.distribute.arcrepository.PreservationArcRepositoryClient; 041import dk.netarkivet.common.distribute.arcrepository.Replica; 042import dk.netarkivet.common.exceptions.ArgumentNotValid; 043import dk.netarkivet.common.exceptions.IOFailure; 044import dk.netarkivet.common.exceptions.NotImplementedException; 045import dk.netarkivet.common.utils.CleanupHook; 046import dk.netarkivet.common.utils.CleanupIF; 047import dk.netarkivet.common.utils.FileUtils; 048 049/** 050 * The database based active bit preservation. This is the alternative to the FileBasedActiveBitPreservation. 051 * <p> 052 * A database is used to handle the bitpreservation. 053 */ 054public final class DatabaseBasedActiveBitPreservation implements ActiveBitPreservation, CleanupIF { 055 056 /** The log. */ 057 private static final Logger log = LoggerFactory.getLogger(DatabaseBasedActiveBitPreservation.class); 058 059 /** 060 * When replacing a broken file, the broken file is downloaded and stored in a temporary directory under 061 * Settings.COMMON_TEMP_DIR with this name. It can then be inspected at your leisure. TODO this is the same constant 062 * as in FileBasedActiveBitPreservation, thus change to global constant instead. Perhaps constant in parent class. 063 */ 064 private static final String REMOVED_FILES = "bitpreservation"; 065 066 /** The current instance. */ 067 private static DatabaseBasedActiveBitPreservation instance; 068 069 /** Hook to close down this application. */ 070 private CleanupHook closeHook; 071 072 /** The instance to contain the access to the database. */ 073 private BitPreservationDAO cache; 074 075 /** The list of the replicas, which are having their filelist updated. */ 076 private List<Replica> updateFilelistReplicas = Collections.synchronizedList(new ArrayList<Replica>()); 077 078 /** The list of the replicas, which are having their checksums updated. */ 079 private List<Replica> updateChecksumReplicas = Collections.synchronizedList(new ArrayList<Replica>()); 080 081 /** 082 * Constructor. Initialises the database and closeHook. 083 */ 084 private DatabaseBasedActiveBitPreservation() { 085 // initialise the database. 086 cache = ReplicaCacheDatabase.getInstance(); 087 088 // create and initialise the closing hook 089 closeHook = new CleanupHook(this); 090 Runtime.getRuntime().addShutdownHook(closeHook); 091 } 092 093 /** 094 * Method for retrieving the current instance of this class. 095 * 096 * @return The instance. 097 */ 098 public static synchronized DatabaseBasedActiveBitPreservation getInstance() { 099 if (instance == null) { 100 instance = new DatabaseBasedActiveBitPreservation(); 101 } 102 return instance; 103 } 104 105 /** 106 * Method for retrieving the filelist from a specific replica. A GetAllFilenamesMessage is sent to the specific 107 * replica. 108 * 109 * @param replica The replica to retrieve the filelist from. 110 * @return The names of the files in a File. 111 * @throws ArgumentNotValid If the replica is 'null'. 112 */ 113 private File getFilenamesAsFile(Replica replica) throws ArgumentNotValid { 114 // validate 115 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 116 117 // send request 118 log.info("Retrieving filelist from replica '{}'.", replica); 119 120 // Retrieve a file containing the list of filenames of the replica. 121 File result = ArcRepositoryClientFactory.getPreservationInstance().getAllFilenames(replica.getId()); 122 log.info("Retrieved filelist from replica '{}'.", replica); 123 return result; 124 } 125 126 /** 127 * Method for retrieving the checksums from a specific replica. A GetAllChecksumsMessage is sent to the specific 128 * replica. 129 * 130 * @param replica The replica to retrieve the checksums from. 131 * @return A file containing the checksumjob results, i.e. a filename##checksum. 132 * @throws ArgumentNotValid If the replica is null. 133 */ 134 private File getChecksumListAsFile(Replica replica) throws ArgumentNotValid { 135 // validate 136 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 137 138 log.info("Retrieving checksum from replica '{}'.", replica); 139 140 // Request and retrieve a file containing the checksums of the replica, 141 // and return this 142 File outputFile = ArcRepositoryClientFactory.getPreservationInstance().getAllChecksums(replica.getId()); 143 144 log.info("Retrieved checksum from replica '{}'.", replica); 145 146 return outputFile; 147 } 148 149 /** 150 * Method to reestablish a file missing in a replica. The file is retrieved from a given bitarchive replica, which 151 * is known to contain a proper version of this file. The reestablishment is done by first retrieving the file and 152 * then sending out a store message with this file. Then any replica who is missing the file will obtain it. 153 * 154 * @param filename The name of the file to reestablish. 155 * @param repWithFile The replica where the file should be retrieved from. 156 * @throws IOFailure If the attempt to reestablish the file fails. 157 */ 158 private void reestablishMissingFile(String filename, Replica repWithFile) throws IOFailure { 159 // send a GetFileMessage to this bitarchive replica for the file. 160 try { 161 // Contact the ArcRepository. 162 PreservationArcRepositoryClient arcrep = ArcRepositoryClientFactory.getPreservationInstance(); 163 // Create temporary file. 164 File tmpDir = FileUtils.createUniqueTempDir(FileUtils.getTempDir(), REMOVED_FILES); 165 File missingFile = new File(tmpDir, filename); 166 // retrieve the file and send store message with it. Then the 167 // file will be stored in all replicas, where it is missing. 168 arcrep.getFile(filename, repWithFile, missingFile); 169 arcrep.store(missingFile); 170 // remove the temporary file afterwards. 171 tmpDir.delete(); 172 173 // Update the checksum status for the file. 174 cache.updateChecksumStatus(filename); 175 } catch (Exception e) { 176 String errMsg = "Failed to reestablish '" + filename + "' with copy from '" + repWithFile + "'"; 177 log.warn(errMsg); 178 // log error and report file. 179 throw new IOFailure(errMsg, e); 180 } 181 } 182 183 /** 184 * Method for retrieving a file from a bitarchive (for replacing a bad entry in another replica). 185 * 186 * @param filename The file to retrieve. 187 * @param repWithFile The replica where the file should be retrieved from. 188 * @return The file from the bitarchive. 189 */ 190 private File retrieveRemoteFile(String filename, Replica repWithFile) { 191 // Contact the ArcRepository. 192 PreservationArcRepositoryClient arcrep = ArcRepositoryClientFactory.getPreservationInstance(); 193 // Create temporary file. 194 File tmpDir = FileUtils.createUniqueTempDir(FileUtils.getTempDir(), REMOVED_FILES); 195 File missingFile = new File(tmpDir, filename); 196 // retrieve the file and send store message with it. Then the 197 // file will be stored in all replicas, where it is missing. 198 arcrep.getFile(filename, repWithFile, missingFile); 199 200 return missingFile; 201 } 202 203 /** 204 * This method is used for making sure, that all replicas are up-to-date before trying to validate the checksums of 205 * the files within it. 206 * <p> 207 * TODO set a time limit for last date to update. This has to be a variable in settings, which should have the 208 * default '0', meaning no time limit. If more time has passed than acceptable, then a new checksum job should be 209 * run. This has to do with assignment B.2.4 - Bitpreservation scheduler. 210 */ 211 private void initChecksumStatusUpdate() { 212 // go through all replicas. 213 for (Replica replica : Replica.getKnown()) { 214 // retrieve the date for the last checksum update. 215 Date csDate = cache.getDateOfLastWrongFilesUpdate(replica); 216 217 if (csDate == null) { 218 // run a checksum job on the replica. 219 log.info("Starting checksum update for replica {}", replica); 220 runChecksum(replica); 221 log.info("Finished the checksum update for replica {}", replica); 222 } 223 } 224 } 225 226 /** 227 * The method for retrieving the checksums for all the files within a replica. This method sends the checksum job to 228 * the replica archive. 229 * 230 * @param replica The replica to retrieve the checksums from. 231 */ 232 private void runChecksum(Replica replica) { 233 File checksumlistFile = null; 234 try { 235 checksumlistFile = getChecksumListAsFile(replica); 236 cache.addChecksumInformation(checksumlistFile, replica); 237 } finally { 238 if (checksumlistFile != null) { 239 FileUtils.remove(checksumlistFile); 240 } 241 } 242 } 243 244 /** 245 * Retrieves and update the status of a file for a specific replica. 246 * 247 * @param filename The name of the file. 248 */ 249 private void updateChecksumStatus(String filename) { 250 // retrieve the ArcRepositoryClient before using it in the for-loop. 251 PreservationArcRepositoryClient arcClient = ArcRepositoryClientFactory.getPreservationInstance(); 252 253 // retrieve the checksum status for the file for all the replicas 254 for (Replica replica : Replica.getKnown()) { 255 // retrieve the checksum. 256 String checksum = arcClient.getChecksum(replica.getId(), filename); 257 258 // insert the checksum results for the file into the database. 259 cache.updateChecksumInformationForFileOnReplica(filename, checksum, replica); 260 } 261 262 // Vote for the specific file. 263 cache.updateChecksumStatus(filename); 264 } 265 266 /** 267 * The method calculates the number of files which has a wrong checksum for the replica. This simple counts all the 268 * entries in the replicafileinfo table for the replica where the filelist_status is set to CORRUPT. 269 * 270 * @param replica The replica for which to count the number of changed files. 271 * @return The number of files for the replica where the checksum does not correspond to the checksum of the same 272 * file in the other replicas. 273 * @throws ArgumentNotValid If the replica is null. 274 */ 275 public long getNumberOfChangedFiles(Replica replica) throws ArgumentNotValid { 276 // validate 277 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 278 279 // Retrieves the number of entries in replicafileinfo which has 280 // filelist_status set to 'CORRUPT' and belong to the replica. 281 return cache.getNumberOfWrongFilesInLastUpdate(replica); 282 } 283 284 /** 285 * This method retrieves the name of all the files which has a wrong checksum for the replica. It simple returns the 286 * filename of all the entries in the replicafileinfo table for the replica where the filelist_status is set to 287 * CORRUPT. 288 * 289 * @param replica The replica for which the changed files should be found. 290 * @return The names of files in the replica where the checksum does not correspond to the checksum of the same file 291 * in the other replicas. 292 * @throws ArgumentNotValid If the replica is null. 293 */ 294 public Iterable<String> getChangedFiles(Replica replica) throws ArgumentNotValid { 295 // validate 296 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 297 298 // Retrieves the list of filenames for the entries in replicafileinfo 299 // which has filelist_status set to 'CORRUPT' and belong to the replica. 300 return cache.getWrongFilesInLastUpdate(replica); 301 } 302 303 /** 304 * This method calculates the number of files which are not found in the given replica. This simple counts all the 305 * entries in the replicafileinfo table for the replica where the filelist_status is set to MISSING. 306 * 307 * @param replica The replica for which to count the number of missing files. 308 * @return The number of files which is missing in the replica. 309 * @throws ArgumentNotValid If the replica is null. 310 */ 311 public long getNumberOfMissingFiles(Replica replica) throws ArgumentNotValid { 312 // validate 313 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 314 315 // Retrieves the number of entries in replicafileinfo which has 316 // filelist_status set to 'MISSING' and belong to the replica. 317 return cache.getNumberOfMissingFilesInLastUpdate(replica); 318 } 319 320 /** 321 * This method retrieves the name of all the files which are missing for the given replica. It simple returns the 322 * filename of all the entries in the replicafileinfo table for the replica where the filelist_status is set to 323 * MISSING. 324 * 325 * @param replica The replica for which the missing files should be found. 326 * @return The names of files in the replica which are missing. 327 * @throws ArgumentNotValid If the replica is null. 328 */ 329 public Iterable<String> getMissingFiles(Replica replica) throws ArgumentNotValid { 330 // validate 331 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 332 333 // Retrieves the list of filenames for the entries in replicafileinfo 334 // which has filelist_status set to 'MISSING' and belong to the replica. 335 return cache.getMissingFilesInLastUpdate(replica); 336 } 337 338 /** 339 * This method retrieves the date for the latest checksum update was performed for the replica. This means the date 340 * for the latest the replica has calculated the checksum of all the files within its archive. 341 * <p> 342 * This method does not call out to the replicas. It only contacts the local database. 343 * 344 * @param replica The replica for which the date for last checksum update should be retrieved. 345 * @return The date for the last time the checksums has been update. If the checksum update has never occurred, then 346 * a null is returned. 347 * @throws ArgumentNotValid If the replica is null. 348 */ 349 public Date getDateForChangedFiles(Replica replica) throws ArgumentNotValid { 350 // validate 351 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 352 353 // Retrieves the checksum_updated date for the entry in the replica 354 // table in the database corresponding to the replica argument. 355 return cache.getDateOfLastWrongFilesUpdate(replica); 356 } 357 358 /** 359 * This method retrieves the date for the latest filelist update was performed for the replica. This means the date 360 * for the latest the replica has retrieved the list of all the files within the archive. 361 * <p> 362 * This method does not call out to the replicas. It only contacts the local database. 363 * 364 * @param replica The replica for which the date for last filelist update should be retrieved. 365 * @return The date for the last time the filelist has been update. If the filelist update has never occurred, then 366 * a null is returned. 367 * @throws ArgumentNotValid If the replica is null. 368 */ 369 public Date getDateForMissingFiles(Replica replica) throws ArgumentNotValid { 370 // validate 371 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 372 373 // Retrieves the filelist_updated date for the entry in the replica 374 // table in the database corresponding to the replica argument. 375 return cache.getDateOfLastMissingFilesUpdate(replica); 376 } 377 378 /** 379 * The method is used to update the checksum for all the files in a replica. The checksum for the replica is 380 * retrieved through GetAllChecksumMessages. This will take a very large amount of time for the bitarchive, but a 381 * more limited amount of time for the checksumarchive. 382 * <p> 383 * The corresponding replicafileinfo entries in the database for the retrieved checksum results will be updated. 384 * Then a checksum update will be performed to check for corrupted replicafileinfo. 385 * <p> 386 * Each replica can only be updated once at the time. 387 * 388 * @param replica The replica to find the changed files for. 389 * @throws ArgumentNotValid If the replica is null. 390 */ 391 public void findChangedFiles(Replica replica) throws ArgumentNotValid { 392 // validate 393 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 394 395 // check whether a update of the replica is already in progress. 396 if (updateChecksumReplicas.contains(replica)) { 397 log.warn("A checksum update is already being performed for replica '{}'. Operation ignored!", replica); 398 return; 399 } 400 401 log.info("Initiating findChangedFiles for replica '{}'.", replica); 402 updateChecksumReplicas.add(replica); 403 404 try { 405 // retrieve updated checksums from the replica. 406 runChecksum(replica); 407 408 // make sure, that all replicas are up-to-date. 409 initChecksumStatusUpdate(); 410 411 // update to find changes. 412 cache.updateChecksumStatus(); 413 log.info("Completed findChangedFiles for replica '{}'.", replica); 414 } finally { 415 updateChecksumReplicas.remove(replica); 416 } 417 } 418 419 /** 420 * This method retrieves the filelist for the replica, and then it updates the database with this list of filenames. 421 * Each replica can only be updated once at the time. 422 * 423 * @param replica The replica to find the missing files for. 424 * @throws ArgumentNotValid If the replica is null. 425 */ 426 public void findMissingFiles(Replica replica) throws ArgumentNotValid { 427 // validate 428 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 429 430 // check whether a update of the replica is already in progress. 431 if (updateFilelistReplicas.contains(replica)) { 432 log.warn("A filelist update is already being performed for " + "replica '{}'. Operation ignored!", replica); 433 return; 434 } 435 log.info("Initiating findMissingFiles for replica '{}'.", replica); 436 updateFilelistReplicas.add(replica); 437 File filenamesFile = null; 438 try { 439 // retrieve the filelist from the replica 440 filenamesFile = getFilenamesAsFile(replica); 441 // put them into the database. 442 cache.addFileListInformation(filenamesFile, replica); 443 log.info("Completed findMissingFiles for replica '{}'.", replica); 444 } finally { 445 updateFilelistReplicas.remove(replica); 446 if (filenamesFile != null) { 447 FileUtils.remove(filenamesFile); 448 } 449 } 450 } 451 452 /** 453 * Method for retrieving the FilePreservationState for a specific file. 454 * 455 * @param filename The name of the file for whom the FilePreservationState should be retrieved. 456 * @return The FilePreservationState for the file. 457 * @throws ArgumentNotValid If the filename is null or the empty string. 458 */ 459 @Override 460 public PreservationState getPreservationState(String filename) throws ArgumentNotValid { 461 ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename"); 462 463 // Initialize the list of replicafileinfos, with one entry per replica. 464 List<ReplicaFileInfo> rfis = new ArrayList<ReplicaFileInfo>(Replica.getKnown().size()); 465 466 // update the checksum status for the file for all the replicas. 467 updateChecksumStatus(filename); 468 469 // Retrieve the replicafileinfo entries for the file. 470 for (Replica replica : Replica.getKnown()) { 471 rfis.add(cache.getReplicaFileInfo(filename, replica)); 472 } 473 474 // use filename and replicafileinfos to make the resulting 475 // DatabasePreservationState. 476 return new DatabasePreservationState(filename, rfis); 477 } 478 479 /** 480 * Method for retrieving the FilePreservationState for a list of files. 481 * 482 * @param filenames The list of filenames whose FilePreservationState should be retrieved. 483 * @return A mapping between the filenames and their FilePreservationState. 484 * @throws ArgumentNotValid If the list of filenames are null. 485 */ 486 @Override 487 public Map<String, PreservationState> getPreservationStateMap(String... filenames) throws ArgumentNotValid { 488 ArgumentNotValid.checkNotNull(filenames, "String... filenames"); 489 490 // make the resulting map. 491 Map<String, PreservationState> res = new HashMap<String, PreservationState>(); 492 493 // retrieve the preservation states and put them into the map. 494 for (String file : filenames) { 495 res.put(file, getPreservationState(file)); 496 } 497 498 return res; 499 } 500 501 /** 502 * This method finds the number of files which are known to be in the archive of a specific replica. This method 503 * will not go out to the replica, but only contact the local database. The number of files in the replica is 504 * retrieved from the database by counting the amount of files in the replicafileinfo table which belong to the 505 * replica and which has the filelist_status set to OK. 506 * 507 * @param replica The replica for which the number of files should be counted. 508 * @return The number of files for a specific replica. 509 * @throws ArgumentNotValid If the replica is null. 510 */ 511 public long getNumberOfFiles(Replica replica) throws ArgumentNotValid { 512 // validate 513 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 514 515 // returns the amount of files, which is not missing. 516 return cache.getNumberOfFiles(replica); 517 } 518 519 /** 520 * Check that the checksum of the file is indeed different to the value in admin data and reference replica. If so, 521 * remove missing file and upload it from reference replica to this replica. 522 * 523 * @param replica The replica to restore file to 524 * @param filename The name of the file 525 * @param credentials The credentials used to perform this replace operation 526 * @param checksum The known bad checksum. Only a file with this bad checksum is attempted repaired. 527 * @throws ArgumentNotValid If any of the arguments are not valid. 528 */ 529 public void replaceChangedFile(Replica replica, String filename, String credentials, String checksum) 530 throws ArgumentNotValid { 531 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 532 ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename"); 533 ArgumentNotValid.checkNotNullOrEmpty(checksum, "String checksum"); 534 ArgumentNotValid.checkNotNullOrEmpty(credentials, "String credentials"); 535 536 // find replica 537 Replica repWithFile = cache.getBitarchiveWithGoodFile(filename, replica); 538 // retrieve the file from the replica. 539 File missingFile = retrieveRemoteFile(filename, repWithFile); 540 // upload the file to the replica where it is missing 541 ArcRepositoryClientFactory.getPreservationInstance().correct(replica.getId(), checksum, missingFile, 542 credentials); 543 } 544 545 /** 546 * This method is used to upload missing files to a replica. For each file a good version of this file is found, and 547 * it is reestablished on the replicas where it is missing. 548 * 549 * @param replica The replica where the files are missing. 550 * @param filenames The names of the files which are missing in the given replica. 551 * @throws ArgumentNotValid If the replica or list of filenames is null, or if the list of filenames is empty. 552 * @throws IOFailure If some files could not be established. 553 */ 554 public void uploadMissingFiles(Replica replica, String... filenames) throws ArgumentNotValid, IOFailure { 555 ArgumentNotValid.checkNotNull(replica, "Replica replica"); 556 ArgumentNotValid.checkNotNull(filenames, "String... filenames"); 557 ArgumentNotValid.checkPositive(filenames.length, "Length of argument String... filenames"); 558 log.info("UploadMissingFiles initiated of {} filenames", filenames.length); 559 // make record of files, which is not uploaded correct. 560 List<String> filesFailedReestablishment = new ArrayList<String>(); 561 562 // For each file in filenames 563 for (String file : filenames) { 564 // retrieve a replica which has the file and the checksum_status 565 // is 'OK'. Though do not allow the replica where the file is 566 // missing to be returned. 567 Replica fileRep = cache.getBitarchiveWithGoodFile(file, replica); 568 569 // make sure, that a replica was found. 570 if (fileRep == null) { 571 // issue warning, report file, and continue to next file. 572 String errMsg = "No bitarchive replica contains a version of " 573 + "the file with an acceptable checksum."; 574 log.warn(errMsg); 575 filesFailedReestablishment.add(file); 576 continue; 577 } 578 579 try { 580 // reestablish the missing file. 581 reestablishMissingFile(file, fileRep); 582 } catch (IOFailure e) { 583 // if error, then not successfully reestablishment for the file. 584 log.warn("The file '{}' has not been reestablished on replica '{}' with a correct version " 585 + "from replica '{}'.", file, replica, fileRep, e); 586 filesFailedReestablishment.add(file); 587 } 588 } 589 590 // make warning if not all the files could be reestablished. 591 if (filesFailedReestablishment.size() > 0) { 592 throw new IOFailure("The following " + filesFailedReestablishment.size() + " out of " + filenames.length 593 + " files could not be reestablished: " + filesFailedReestablishment); 594 } 595 log.info("UploadMissingFiles completed of {} filenames", filenames.length); 596 } 597 598 /** 599 * This should reestablish the state for the file. 600 * 601 * @param filename The name of the file to change the state for. 602 * @throws ArgumentNotValid If the filename is invalid. 603 * @throws NotImplementedException This will not be implemented. 604 */ 605 @Override 606 public void changeStateForAdminData(String filename) throws ArgumentNotValid, NotImplementedException { 607 ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename"); 608 609 // This function should not deal with admin.data. 610 throw new NotImplementedException("This will not be implemented"); 611 } 612 613 /** 614 * Old method, which refers to the checksum replica part of admin data. 615 * 616 * @return Nothing, since it always throws an exception. 617 * @throws NotImplementedException This method will not be implemented. 618 */ 619 @Override 620 public Iterable<String> getMissingFilesForAdminData() throws NotImplementedException { 621 // This function should not deal with admin.data. 622 throw new NotImplementedException("Old method, which refers to the " + "checksum replica part of admin data."); 623 } 624 625 /** 626 * Old method, which refers to the checksum replica part of admin data. 627 * 628 * @return Nothing, since it always throws an exception. 629 * @throws NotImplementedException This method will not be implemented. 630 */ 631 @Override 632 public Iterable<String> getChangedFilesForAdminData() throws NotImplementedException { 633 // This function should not deal with admin.data. 634 throw new NotImplementedException("Old method, which refers to the " + "checksum replica part of admin data."); 635 } 636 637 /** 638 * Old method, which refers to the checksum replica part of admin data. 639 * 640 * @param filenames The list of filenames which should be added to admin data. 641 * @throws NotImplementedException This method will not be implemented. 642 * @throws ArgumentNotValid If filenames invalid. 643 */ 644 @Override 645 public void addMissingFilesToAdminData(String... filenames) throws ArgumentNotValid, NotImplementedException { 646 ArgumentNotValid.checkNotNull(filenames, "String... filenames"); 647 648 // This function should not deal with admin.data. 649 throw new NotImplementedException("Old method, which refers to the " + "checksum replica part of admin data."); 650 } 651 652 /** 653 * Method for closing the running instance of this class. 654 */ 655 public void close() { 656 if (closeHook != null) { 657 Runtime.getRuntime().removeShutdownHook(closeHook); 658 } 659 cleanup(); 660 } 661 662 /** 663 * Method for cleaning up this instance. 664 */ 665 @Override 666 public void cleanup() { 667 instance = null; 668 cache.cleanup(); 669 } 670 671}