package org.opendedup.sdfs.filestore;
import java.io.File;
import java.io.IOException;
//import java.nio.file.LinkOption;
//import java.nio.file.Path;
//import java.nio.file.Paths;
//import java.nio.file.attribute.Attributes;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.opendedup.sdfs.Main;
import org.opendedup.sdfs.io.MetaDataDedupFile;
import com.reardencommerce.kernel.collections.shared.evictable.ConcurrentLinkedHashMap;
/**
*
* @author Sam Silverberg
*
* The MetaFileStore is a static class used to get, update, create, or
* clone MetaDataDedup files. MetaDataDedupFile(s) are serialized to a
* JDBM database with a key of the uuid for the MetaDataDedupFile.
*
*
*/
public class MetaFileStore {
// private static String dbURL =
// "jdbc:derby:myDB;create=true;user=me;password=mine";
// A quick lookup table for path to MetaDataDedupFile
private static Logger log = Logger.getLogger("sdfs");
private static ConcurrentLinkedHashMap<String, MetaDataDedupFile> pathMap = ConcurrentLinkedHashMap
.create(
ConcurrentLinkedHashMap.EvictionPolicy.LRU,
10000,
Main.writeThreads,
new ConcurrentLinkedHashMap.EvictionListener<String, MetaDataDedupFile>() {
// This method is called just after a new entry has been
// added
public void onEviction(String key,
MetaDataDedupFile file) {
file.unmarshal();
}
});
/**
* caches a file to the pathmap
*
* @param mf
*/
private static void cacheMF(MetaDataDedupFile mf) {
pathMap.put(mf.getPath(), mf);
}
public static void rename(String src,String dst,MetaDataDedupFile mf){
pathMap.remove(src);
pathMap.put(dst, mf);
}
/**
* Removes a cached file from the pathmap
*
* @param path
* the path of the MetaDataDedupFile
*/
public static void removedCachedMF(String path) {
pathMap.remove(path);
}
/**
*
* @param path
* the path to the MetaDataDedupFile
* @return the MetaDataDedupFile
*/
public static synchronized MetaDataDedupFile getMF(String path) {
File f = new File(path);
if (f.isDirectory()) {
return MetaDataDedupFile.getFile(f.getPath());
}
MetaDataDedupFile mf = (MetaDataDedupFile) pathMap.get(f.getPath());
if (mf == null) {
mf = MetaDataDedupFile.getFile(f.getPath());
cacheMF(mf);
}
return mf;
}
/**
*
* @param parent
* path for the parent
* @param child
* the child file
* @return the MetaDataDedupFile associated with this path.
*/
public static MetaDataDedupFile getMF(File parent, String child) {
String pth = parent.getAbsolutePath() + File.separator + child;
return getMF(pth);
}
/**
* Clones a MetaDataDedupFile and the DedupFile.
*
* @param origionalPath
* the path of the source
* @param snapPath
* the path of the destination
* @param overwrite
* whether or not to overwrite the destination if it exists
* @return the destination file.
* @throws IOException
*/
public static MetaDataDedupFile snapshot(String origionalPath,
String snapPath, boolean overwrite) throws IOException {
MetaDataDedupFile mf = getMF(origionalPath);
synchronized (mf) {
MetaDataDedupFile _mf = mf.snapshot(snapPath, overwrite);
return _mf;
}
}
/**
* Commits data to the jdbm database
*
* @return true if committed
*/
public static boolean commit() {
try {
Object[] files = pathMap.values().toArray();
int z = 0;
for (int i = 0; i <files.length; i++) {
MetaDataDedupFile buf = (MetaDataDedupFile) files[i];
buf.unmarshal();
z++;
}
log.finer("flushed " + z + " files ");
//recman.commit();
return true;
} catch (Exception e) {
log.log(Level.SEVERE,"unable to commit transaction",e);
}
return false;
}
/**
* Removes a file from the jdbm db
*
* @param guid
* the guid for the MetaDataDedupFile
*/
public static synchronized boolean removeMetaFile(String path) {
MetaDataDedupFile mf = null;
boolean deleted = false;
try {
// Path p = Paths.get(path);
File p = new File(path);
// boolean isDir = Attributes.readBasicFileAttributes(p,
// LinkOption.NOFOLLOW_LINKS).isDirectory();
boolean isDir = p.isDirectory();
// boolean isSymlink = Attributes.readBasicFileAttributes(p,
// LinkOption.NOFOLLOW_LINKS).isSymbolicLink();
if(isDir) {
File ps = new File(path);
File[] files = ps.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
removeMetaFile(files[i].getPath());
} else {
files[i].delete();
}
}
return (ps.delete());
// }
// if (isSymlink) {
// p.delete();
// p = null;
// return true;
} else {
mf = getMF(path);
pathMap.remove(mf.getPath());
deleted = mf.getDedupFile().delete();
deleted = mf.deleteStub();
Main.volume.updateCurrentSize(-1 * mf.length());
if (!deleted) {
log.info("could not delete " + mf.getPath());
return deleted;
}
}
} catch (Exception e) {
if (mf != null)
log.log(Level.FINEST, "unable to remove " + path, e);
if (mf == null)
log.log(Level.FINEST, "unable to remove because [" + path
+ "] is null");
}
mf = null;
return deleted;
}
/**
* closes the jdbm database.
*/
public static void close() {
System.out.println("Closing metafilestore");
try {
commit();
} catch (Exception e) {
}
System.out.println("metafilestore closed");
}
}