Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.storagemanager;
import java.io.*;
import java.util.*;
import org.eclipse.osgi.framework.internal.reliablefile.*;
import org.eclipse.osgi.internal.location.LocationHelper;
import org.eclipse.osgi.internal.location.Locker;
import org.eclipse.osgi.internal.messages.Msg;
/**
* Storage managers provide a facility for tracking the state of a group of files having
* relationship with each others and being updated by several entities at the same time.
* The typical usecase is in shared configuration data areas.
*
* The facilities provided here are cooperative. That is, all participants must
* agree to the conventions and to calling the given API. There is no capacity
* to enforce these conventions or prohibit corruption.
*
*
* Clients can not extend this class
*
*
* Example
*
* //Open the storage manager
* org.eclipse.osgi.storagemanager.StorageManager cacheStorageManager = new StorageManager("d:/sharedFolder/bar/", false); //$NON-NLS-1$
* try {
* cacheStorageManager.open(true);
* } catch (IOException e) {
* // Ignore the exception. The registry will be rebuilt from source.
* }
*
* //To read from a file
* java.io.File fileA = cacheStorageManager.lookup("fileA", false));
* java.io.File fileB = cacheStorageManager.lookup("fileB", false));
* //Do the reading code
* new java.io.FileOutputStream(fileA);
*
* //To write in files
* cacheStorageManager.add("fileC"); //add the file to the filemanager (in this case we assume it is not already here)
* cacheStorageManager.add("fileD");
*
* // The file is never written directly into the file name, so we create some temporary file
* java.io.File fileC = cacheStorageManager.createTempFile("fileC");
* java.io.File fileD = cacheStorageManager.createTempFile("fileD");
*
* //Do the actual writing here...
*
* //Finally update the storagemanager with the actual file to manage.
* cacheStorageManager.update(new String[] {"fileC", "fileD"}, new String[] {fileC.getName(), fileD.getName()};
*
* //Close the file manager at the end
* cacheStorageManager.close();
*
*
*
* Implementation details
* The following implementation details are provided to help with understanding the
* behavior of this class.
* The general principle is to maintain a table which maps user-level file names
* onto an actual disk files. If a file needs to be modified,
* it is stored into a new file. The old content is not removed from disk until all entities
* have closed there instance of the storage manager.
* Once the instance has been created, open() must be called before performing any other operation.
* On open the storage manager obtains a snapshot of the current managed files contents. If an
* entity updates a managed file, the storage manager will save the content for that instance of the
* storage manager, all other storage manager instances will still have access to that managed file's
* content as it was when the instance was first opened.
*
* @since 3.2
*/
// Note the implementation of this class originated from the following deprecated classes:
// /org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/FileManager.java
// /org.eclipse.osgi/eclipseAdaptor/src/org/eclipse/core/runtime/adaptor/StreamManager.java
public final class StorageManager {
private static final int FILETYPE_STANDARD = 0;
private static final int FILETYPE_RELIABLEFILE = 1;
private static final String MANAGER_FOLDER = ".manager"; //$NON-NLS-1$
private static final String TABLE_FILE = ".fileTable"; //$NON-NLS-1$
private static final String LOCK_FILE = ".fileTableLock"; //$NON-NLS-1$
private static final int MAX_LOCK_WAIT = 5000; // 5 seconds
// these should be static but the tests expect to be able to create new managers after changing this setting dynamically
private final boolean useReliableFiles = Boolean.valueOf(System.getProperty("osgi.useReliableFiles")).booleanValue(); //$NON-NLS-1$
private final boolean tempCleanup = Boolean.valueOf(System.getProperty("osgi.embedded.cleanTempFiles")).booleanValue(); //$NON-NLS-1$
private final boolean openCleanup = Boolean.valueOf(System.getProperty("osgi.embedded.cleanupOnOpen")).booleanValue(); //$NON-NLS-1$
private final boolean saveCleanup = Boolean.valueOf(System.getProperty("osgi.embedded.cleanupOnSave")).booleanValue(); //$NON-NLS-1$
private class Entry {
int readId;
int writeId;
int fileType;
Entry(int readId, int writeId, int type) {
this.readId = readId;
this.writeId = writeId;
this.fileType = type;
}
int getReadId() {
return readId;
}
int getWriteId() {
return writeId;
}
int getFileType() {
return fileType;
}
void setReadId(int value) {
readId = value;
}
void setWriteId(int value) {
writeId = value;
}
void setFileType(int type) {
fileType = type;
}
}
private final File base; //The folder managed
private final File managerRoot; //The folder that will contain all the file related to the functionning of the manager (typically a subdir of base)
private final String lockMode;
private final File tableFile;
private final File lockFile; // The lock file for the table (this file is the same for all the instances)
private Locker locker; // The locker for the lock
private File instanceFile; //The file representing the running instance. It is created when the table file is read.
private Locker instanceLocker = null; //The locker for the instance file.
private final boolean readOnly; // Whether this storage manager is in read-only mode
private boolean open; // Whether this storage manager is open for use
// locking related fields
private int tableStamp = -1;
private final Properties table = new Properties();
/**
* Returns a new storage manager for the area identified by the given base
* directory.
*
* @param base the directory holding the files to be managed
* @param lockMode the lockMode to use for the storage manager. It can have one the 3 values: none, java.io, java.nio
* and also supports null in which case the lock strategy will be the global one.
*/
public StorageManager(File base, String lockMode) {
this(base, lockMode, false);
}
/**
* Returns a new storage manager for the area identified by the given base
* directory.
*
* @param base the directory holding the files to be managed
* @param lockMode the lockMode to use for the storage manager. It can have one the 3 values: none, java.io, java.nio
* and also supports null in which case the lock strategy will be the global one.
* @param readOnly true if the managed files are read-only
*/
public StorageManager(File base, String lockMode, boolean readOnly) {
this.base = base;
this.lockMode = lockMode;
this.managerRoot = new File(base, MANAGER_FOLDER);
this.tableFile = new File(managerRoot, TABLE_FILE);
this.lockFile = new File(managerRoot, LOCK_FILE);
this.readOnly = readOnly;
open = false;
}
private void initializeInstanceFile() throws IOException {
if (instanceFile != null || readOnly)
return;
this.instanceFile = File.createTempFile(".tmp", ".instance", managerRoot); //$NON-NLS-1$//$NON-NLS-2$
this.instanceFile.deleteOnExit();
instanceLocker = LocationHelper.createLocker(instanceFile, lockMode, false);
instanceLocker.lock();
}
private String getAbsolutePath(String file) {
return new File(base, file).getAbsolutePath();
}
/**
* Add the given managed file name to the list of files managed by this manager.
*
* @param managedFile name of the file to manage
* @throws IOException if there are any problems adding the given file name to the manager
*/
public void add(String managedFile) throws IOException {
add(managedFile, FILETYPE_STANDARD);
}
/* (non-Javadoc
* Add the given file name to the list of files managed by this manager.
*
* @param managedFile name of the file to manage.
* @param fileType the file type.
* @throws IOException if there are any problems adding the given file to the manager
*/
private void add(String managedFile, int fileType) throws IOException {
if (!open)
throw new IOException(Msg.fileManager_notOpen);
if (readOnly)
throw new IOException(Msg.fileManager_illegalInReadOnlyMode);
if (!lock(true))
throw new IOException(Msg.fileManager_cannotLock);
try {
updateTable();
Entry entry = (Entry) table.get(managedFile);
if (entry == null) {
entry = new Entry(0, 1, fileType);
table.put(managedFile, entry);
// if this managed file existed before, ensure there is not an old
// version on the disk to avoid name collisions. If version found,
// us the oldest generation+1 for the write ID.
int oldestGeneration = findOldestGeneration(managedFile);
if (oldestGeneration != 0)
entry.setWriteId(oldestGeneration + 1);
save();
} else {
if (entry.getFileType() != fileType) {
entry.setFileType(fileType);
updateTable();
save();
}
}
} finally {
release();
}
}
/* (non-Javadoc)
* Find the oldest generation of a file still available on disk
* @param file the file from which to obtain the oldest generation.
* @return the oldest generation of the file or 0 if the file does
* not exist.
*/
private int findOldestGeneration(String managedFile) {
String[] files = base.list();
int oldestGeneration = 0;
if (files != null) {
String name = managedFile + '.';
int len = name.length();
for (int i = 0; i < files.length; i++) {
if (!files[i].startsWith(name))
continue;
try {
int generation = Integer.parseInt(files[i].substring(len));
if (generation > oldestGeneration)
oldestGeneration = generation;
} catch (NumberFormatException e) {
continue;
}
}
}
return oldestGeneration;
}
/**
* Update the given managed files with the content in the given source files.
* The managedFiles is a list of managed file names which are currently managed.
* If a managed file name is not currently managed it will be added as a
* managed file for this storage manager.
* The sources are absolute (or relative to the current working directory)
* file paths containing the new content for the corresponding managed files.
*
* @param managedFiles the managed files to update
* @param sources the new content for the managed files
* @throws IOException if there are any problems updating the given managed files
*/
public void update(String[] managedFiles, String[] sources) throws IOException {
if (!open)
throw new IOException(Msg.fileManager_notOpen);
if (readOnly)
throw new IOException(Msg.fileManager_illegalInReadOnlyMode);
if (!lock(true))
throw new IOException(Msg.fileManager_cannotLock);
try {
updateTable();
int[] originalReadIDs = new int[managedFiles.length];
boolean error = false;
for (int i = 0; i < managedFiles.length; i++) {
originalReadIDs[i] = getId(managedFiles[i]);
if (!update(managedFiles[i], sources[i]))
error = true;
}
if (error) {
// restore the original readIDs to avoid inconsistency for this group
for (int i = 0; i < managedFiles.length; i++) {
Entry entry = (Entry) table.get(managedFiles[i]);
entry.setReadId(originalReadIDs[i]);
}
throw new IOException(Msg.fileManager_updateFailed);
}
save(); //save only if no errors
} finally {
release();
}
}
/**
* Returns a list of all the managed files currently being managed.
*
* @return the names of the managed files
*/
public String[] getManagedFiles() {
if (!open)
return null;
Set