AbstractRepository.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
xnap.io |
![]() |
![]() |
XNap 2 |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* XNap
*
* A pure java file sharing client.
*
* See AUTHORS for copyright information.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package xnap.io;
import xnap.*;
import xnap.cmdl.*;
import xnap.util.*;
import java.beans.*;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;
public abstract class AbstractRepository extends EventVector {
//--- Constant(s) ---
// --- Data Field(s) ---
protected static Logger logger = Logger.getLogger(AbstractRepository.class);
protected String dbFilename;
protected int version;
/**
* Maps absolute filename to repository index.
*/
private Hashtable indicies = new Hashtable();
/**
* Contains all files that have been deleted from disk.
*/
private HashSet deletedFiles = new HashSet();
private long lastModified;
private int nonNullCount = 0;
private Thread runner;
private Object updateLock = new Object();
private boolean updatePending = false;
private boolean updateRunning = false;
/**
*
*/
protected boolean allowWrite = true;
protected boolean deleteOnly;
// --- Constructor(s) ---
public AbstractRepository(String dbFilename, int version, boolean deleteOnly)
{
this.dbFilename = dbFilename;
this.deleteOnly = deleteOnly;
this.lastModified = (new File(dbFilename)).lastModified();
this.version = version;
}
public AbstractRepository(String dbFilename, int version)
{
this(dbFilename, version, false);
}
// --- Method(s) ---
public void add(File f)
{
boolean success = false;
while (!success) {
synchronized (updateLock) {
if (updateRunning) {
try {
logger.debug("add: waiting in spinlock");
updateLock.wait(100);
}
catch (InterruptedException e) {
}
}
else {
addFile(f);
success = true;
}
}
}
}
public abstract String getDirs();
protected boolean exists(File f)
{
return f.exists();
}
public int getNonNullSize()
{
return nonNullCount;
}
public synchronized int indexOf(File f)
{
return ((Integer)indicies.get(f)).intValue();
}
public boolean isUpdateRunning()
{
synchronized (updateLock) {
return updateRunning;
}
}
/**
* Updates the repository.
*/
public void updateLater()
{
updateLater(false);
}
/**
* Convinience access.
*/
protected void readAndUpdateLater()
{
updateLater(true);
}
/**
* Optionaly reads the repository and then always updates the repository.
*/
protected void updateLater(boolean read)
{
updatePending = true;
synchronized (updateLock) {
if (updateRunning) {
return;
}
updateRunning = true;
}
runner = new Thread(new UpdateRunner(read), "UpdateRepository");
runner.start();
}
protected void read()
{
logger.info("reading: " + dbFilename);
preRead();
boolean success = false;
String response = null;
try {
ObjectInputStream in
= new ObjectInputStream(new FileInputStream(dbFilename));
int size = in.readInt();
int v = in.readInt();
logger.debug("current version: " + v
+ ", repository version: " + version);
/* this destroys the old repository, so don't save any meta
information there */
if (v < version) {
logger.debug("discarding old repository");
return;
}
if (size >= 0) {
logger.debug(dbFilename + ": allocating " + size + " items");
ensureCapacity(size);
}
Object o;
for (int i = 0; i < size; i++) {
try {
o = in.readObject();
if (o != null && o instanceof File) {
addDirectory((File)o);
}
}
catch (Exception e) {
logger.error(i + "/" + size + " error reading repository", e);
allowWrite = false;
}
}
success = true;
}
catch(FileNotFoundException e) {
response = "Could not find file";
}
catch(IOException e) {
response = "Could not read file";
allowWrite = false;
}
postRead(success, response);
}
/**
* Writes repository contents to disk.
*/
protected boolean write()
{
if (!allowWrite) {
return false;
}
String response = null;
logger.info("write: " + dbFilename);
try {
ObjectOutputStream out
= new ObjectOutputStream(new FileOutputStream(dbFilename));
out.writeInt(nonNullCount);
out.writeInt(version);
for (Iterator i = super.iterator(); i.hasNext();) {
Object f = i.next();
if (f != null) {
out.writeObject(f);
}
}
out.flush();
out.close();
lastModified = (new File(dbFilename)).lastModified();
response = "Wrote " + dbFilename;
return true;
}
catch(FileNotFoundException e) {
response = "Invalid directory " + dbFilename;
}
catch(IOException e) {
response = "Could not write file " + dbFilename;
}
return false;
}
/**
* Adds new files, removes old files and writes the repository to disk.
*/
protected void update()
{
logger.debug("update: " + dbFilename);
StringTokenizer t = new StringTokenizer(getDirs(), ";");
deletedFiles.clear();
if (deleteOnly) {
for (Iterator i = super.iterator(); i.hasNext();) {
File f = (File)i.next();
if (f != null && !exists(f)) {
deletedFiles.add(f);
}
}
}
else {
for (Iterator i = super.iterator(); i.hasNext();) {
File f = (File)i.next();
if (f != null) {
deletedFiles.add(f);
}
}
while (t.hasMoreTokens()) {
addDirectory(new File(t.nextToken()));
}
}
for (Iterator e = deletedFiles.iterator(); e.hasNext();) {
File f = (File)e.next();
int i = indexOf(f);
logger.debug("Repository.update: deleted (" + i + ") " + f);
// don't acctually remove file to not mess up indicies
super.set(i, null);
indicies.remove(f);
nonNullCount--;
fireElementRemoved(f, i);
}
write();
}
protected void preRead()
{
}
protected void postRead(boolean success, String response)
{
}
protected void preUpdate()
{
}
protected void postUpdate()
{
}
/**
* Adds a directory recursively.
*/
private void addDirectory(File f)
{
if (!isPartOfRepository(f)) {
return;
}
if (f.isDirectory()) {
// logger.info("addDirectory: searching " + f);
File list[] = f.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
addDirectory(list[i]);
}
}
}
else if (f.isFile() && f.canRead()) {
addFile(f);
}
}
/**
* Adds file if not already present.
*/
private void addFile(File f)
{
deletedFiles.remove(f);
Integer index = (Integer)indicies.get(f);
if (index == null) {
//Debug.log("Repository.addFile: new " + f + ", " + f.getClass());
addNewFile(f);
indicies.put(f, new Integer(super.size() - 1));
nonNullCount++;
}
else if (f.lastModified() > lastModified) {
logger.debug("addFile: update " + f);
// FIX ME: this breaks ResumeRepository if the
// same file is downloaded twice
//super.set(index.intValue(), FileHelper.handle(f));
}
}
protected void addNewFile(File f)
{
super.add(f);
}
protected boolean isPartOfRepository(File f)
{
return true;
}
private class UpdateRunner implements Runnable
{
boolean read;
public UpdateRunner(boolean read)
{
this.read = read;
}
public void run()
{
if (read) {
read();
}
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
preUpdate();
while (updatePending) {
updatePending = false;
update();
}
synchronized (updateLock) {
updateRunning = false;
}
postUpdate();
}
}
}
The table below shows all metrics for AbstractRepository.java.




