Package org.ardverk.dht.storage

Source Code of org.ardverk.dht.storage.PersistentDatastore

package org.ardverk.dht.storage;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.concurrent.TimeUnit;

import org.ardverk.coding.CodingUtils;
import org.ardverk.dht.routing.Contact;
import org.ardverk.dht.rsrc.FileValue;
import org.ardverk.dht.rsrc.Key;
import org.ardverk.dht.rsrc.Value;
import org.ardverk.io.IoUtils;
import org.ardverk.security.MessageDigestUtils;
import org.ardverk.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A very simple implementation of {@link Datastore}.
*/
public class PersistentDatastore extends SimpleDatastore {

  private static final Logger LOG
    = LoggerFactory.getLogger(PersistentDatastore.class);
 
  private final File store;
 
  private final File tmp;
 
  public PersistentDatastore(File dir, long frequency, TimeUnit unit) {
    this(dir, frequency, frequency, unit);
  }
 
  public PersistentDatastore(File dir, long frequency,
      long timeout, final TimeUnit unit) {
    super(frequency, timeout, unit);
   
    this.store = mkdirs(new File(dir, "store"));
    this.tmp = mkdirs(new File(dir, "tmp"));
  }
 
  @Override
  protected void evict(long timeout, TimeUnit unit) {
    final long now = System.currentTimeMillis();
    final long timeoutInMillis = unit.toMillis(timeout);
   
    FileFilter filter = new FileFilter() {
      @Override
      public boolean accept(File file) {
        if (file.isFile()) {
          if ((now - file.lastModified()) >= timeoutInMillis) {
            if (LOG.isTraceEnabled()) {
              LOG.trace("Deleting: " + file);
            }
            file.delete();
          }
        }
        return false;
      }
    };
   
    store.listFiles(filter);
    tmp.listFiles(filter);
  }
 
  @Override
  public Value store(Contact src, Key key, Value value) {
    Value response = OK;
    try {
      String name = createFileName(key);
      File tmp = createTmpFile(name);
      try {
       
        long length = consume(value, tmp);
        File file = createStoreFile(name);
       
        if (length == 0L) {
          boolean success = file.delete();
          if (!success) {
            if (LOG.isTraceEnabled()) {
              LOG.trace("Not Found: " + file);
            }
            response = NOT_FOUND;
          }
        } else {
          boolean success = tmp.renameTo(file);
          if (!success) {
            if (LOG.isErrorEnabled()) {
              LOG.error("Failed to rename " + tmp + " to " + file);
            }
            response = INTERNAL_ERROR;
          }
        }
      } finally {
        tmp.delete();
      }
     
    } catch (IOException err) {
      LOG.error("IOException", err);
      response = INTERNAL_ERROR;
    }
   
    return response;
  }

  @Override
  public Value get(Contact src, Key key) {
    String name = createFileName(key);
    File file = createStoreFile(name);
    if (file.exists()) {
      return new FileValue(file);
    }
    return null;
  }
 
  private File createStoreFile(String name) {
    return new File(store, name);
  }
 
  private File createTmpFile(String name) throws IOException {
    return File.createTempFile(name + "-", ".tmp", tmp);
  }
 
  private static long consume(Value value, File dst) throws IOException {
   
    BufferedOutputStream out
      = new BufferedOutputStream(
        new FileOutputStream(dst));
   
    try {
      InputStream in = value.getContent();
      try {
        long length = 0;
       
        byte[] buffer = new byte[4*1024];
        int len = -1;
        while ((len = in.read(buffer)) != -1) {
          out.write(buffer, 0, len);
          length += len;
        }
        return length;
      } finally {
        IoUtils.close(in);
      }
    } finally {
      IoUtils.close(out);
    }
  }
 
  private static File mkdirs(File dir) {
    if (!dir.exists()) {
      dir.mkdirs();
     
      if (!dir.exists()) {
        throw new IllegalStateException(dir.getAbsolutePath());
      }
    }
    return dir;
  }
 
  private static String createFileName(Key key) {
    MessageDigest md = MessageDigestUtils.createSHA1();
    md.update(StringUtils.getBytes(key.getPath()));
    return CodingUtils.encodeBase16(md.digest());
  }
}
TOP

Related Classes of org.ardverk.dht.storage.PersistentDatastore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.