/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.storage.lowlevel;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import org.apache.log4j.Logger;
import fedora.server.errors.LowlevelStorageException;
import fedora.server.errors.LowlevelStorageInconsistencyException;
/**
* @author Bill Niebel
*/
public abstract class PathRegistry {
/** Logger for this class. */
private static final Logger LOG =
Logger.getLogger(PathRegistry.class.getName());
protected static final int NO_REPORT = 0; //<=========????????
protected static final int ERROR_REPORT = 1;
protected static final int FULL_REPORT = 2;
protected static final int REPORT_FILES = 0;
protected static final int AUDIT_FILES = 1;
protected static final int REBUILD = 2;
protected final String registryName;
protected final String[] storeBases;
public PathRegistry(Map<String, ?> configuration) {
registryName = (String) configuration.get("registryName");
storeBases = (String[]) configuration.get("storeBases");
}
public abstract String get(String pid) throws LowlevelStorageException;
public abstract void put(String pid, String path)
throws LowlevelStorageException;
public abstract void remove(String pid) throws LowlevelStorageException;
public abstract void rebuild() throws LowlevelStorageException;
public abstract void auditFiles() throws LowlevelStorageException;
public void auditRegistry() throws LowlevelStorageException {
LOG.info("begin audit: registry-against-files");
Enumeration<String> keys = keys();
while (keys.hasMoreElements()) {
String pid = keys.nextElement();
try {
String path = get(pid);
File file = new File(path);
boolean fileExists = file.exists();
LOG.info((fileExists ? "" : "ERROR: ") + "registry has [" + pid
+ "] => [" + path + "] " + (fileExists ? "and" : "BUT")
+ " file does " + (fileExists ? "" : "NOT") + "exist");
} catch (LowlevelStorageException e) {
LOG.error("ERROR: registry has [" + pid + "] => []", e);
}
}
LOG.info("end audit: registry-against-files (ending normally)");
}
protected final String getRegistryName() {
return registryName;
}
public static final boolean stringNull(String string) {
return null == string || string.equals("");
}
private final void traverseFiles(File[] files,
int operation,
boolean stopOnError,
int report)
throws LowlevelStorageException {
for (File element : files) {
if (element.exists()) {
if (element.isDirectory()) {
traverseFiles(element.listFiles(),
operation,
stopOnError,
report);
} else {
String filename = element.getName();
String path = null;
try {
path = element.getCanonicalPath();
} catch (IOException e) {
if (report != NO_REPORT) {
LOG.error("couldn't get File path", e);
}
if (stopOnError) {
throw new LowlevelStorageException(true,
"couldn't get File path",
e);
}
}
if (path != null) {
String pid = PathAlgorithm.decode(filename);
if (pid == null) {
if (report != NO_REPORT) {
LOG.error("unexpected file at [" + path + "]");
}
if (stopOnError) {
throw new LowlevelStorageException(true,
"unexpected file traversing object store at ["
+ path
+ "]");
}
} else {
switch (operation) {
case REPORT_FILES: {
if (report == FULL_REPORT) {
LOG.info("file [" + path
+ "] would have pid [" + pid
+ "]");
}
break;
}
case REBUILD: {
put(pid, path);
if (report == FULL_REPORT) {
LOG.info("added to registry: [" + pid
+ "] ==> [" + path + "]");
}
break;
}
case AUDIT_FILES: {
String rpath = null;
try {
rpath = get(pid);
} catch (LowlevelStorageException e) {
}
boolean matches = rpath.equals(path);
if (report == FULL_REPORT || !matches) {
LOG
.info((matches ? "" : "ERROR: ")
+ "["
+ path
+ "] "
+ (matches ? ""
: "NOT ")
+ "in registry"
+ (matches ? ""
: "; pid ["
+ pid
+ "] instead registered as ["
+ (rpath == null ? "[OBJECT NOT IN STORE]"
: rpath)
+ "]"));
}
}
}
}
}
}
}
}
}
public void traverseFiles(String[] storeBases,
int operation,
boolean stopOnError,
int report) throws LowlevelStorageException {
File files[];
try {
files = new File[storeBases.length];
for (int i = 0; i < storeBases.length; i++) {
files[i] = new File(storeBases[i]);
}
} catch (Exception e) {
throw new LowlevelStorageException(true,
"couldn't rebuild VolatilePathRegistry",
e);
}
traverseFiles(files, operation, stopOnError, report);
}
protected abstract Enumeration<String> keys() throws LowlevelStorageException,
LowlevelStorageInconsistencyException;
}