Author: ozeigermann
Date: Mon Jul 23 13:54:15 2007
New Revision: 558857
URL: http://svn.apache.org/viewvc?view=rev&rev=558857
Log:
First step to (yet non-working) pessimistic tx file manager having undo log
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceUndoManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/MemoryUndoManager.java
Removed:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/PathManager.java
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java?view=auto&rev=558857
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
Mon Jul 23 13:54:15 2007
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.transaction.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.resource.ResourceException;
+import org.apache.commons.transaction.resource.ResourceManager;
+import org.apache.commons.transaction.resource.StreamableResource;
+import org.apache.commons.transaction.util.FileHelper;
+
+public class FileResourceManager implements
ResourceManager<StreamableResource> {
+
+ private Log logger = LogFactory.getLog(getClass());
+
+ protected String rootPath;
+
+ public FileResourceManager(String rootPath) {
+ this.rootPath = rootPath;
+ }
+
+ public StreamableResource getResource(String path) throws
ResourceException {
+ return new FileResource(path);
+ }
+
+ public String getRootPath() {
+ return rootPath;
+ }
+
+ protected static class FileResource implements StreamableResource {
+
+ protected File file;
+
+ public FileResource(String path) {
+ this.file = new File(path);
+ }
+
+ public FileResource(File file) {
+ this.file = file;
+ }
+
+ public void createAsDirectory() throws ResourceException {
+ if (!file.mkdirs()) {
+ throw new ResourceException("Could not create directory");
+ }
+
+ }
+
+ public void createAsFile() throws ResourceException {
+ try {
+ if (!file.createNewFile()) {
+ throw new ResourceException("Could not create file");
+ }
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public void delete() throws ResourceException {
+ if (!file.delete())
+ throw new ResourceException("Could not create file");
+
+ }
+
+ public boolean exists() {
+ return file.exists();
+ }
+
+ public List<StreamableResource> getChildren() throws ResourceException
{
+ List<StreamableResource> result = new
ArrayList<StreamableResource>();
+ File[] files = file.listFiles();
+ for (File file : files) {
+ result.add(new FileResource(file));
+ }
+ return result;
+ }
+
+ public StreamableResource getParent() throws ResourceException {
+ // FIXME: Is reasonable, but would require refernce to enclosing
class
+ /*
+ if (getPath().equals(getRootPath()))
+ return null;
+ */
+ File parent = file.getParentFile();
+ return new FileResource(parent);
+ }
+
+ public String getPath() throws ResourceException {
+ try {
+ return file.getCanonicalPath();
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public boolean isDirectory() {
+ return file.isDirectory();
+ }
+
+ public boolean isFile() {
+ return file.isFile();
+ }
+
+ public void move(String destinationpath) throws ResourceException {
+ File destination = new File(destinationpath);
+ try {
+ FileHelper.moveUsingNIO(file, destination);
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public void copy(String destinationpath) throws ResourceException {
+ File destination = new File(destinationpath);
+ try {
+ FileHelper.copyUsingNIO(file, destination);
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public InputStream readStream() throws ResourceException {
+ try {
+ FileInputStream is = new FileInputStream(file);
+ return is;
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public OutputStream writeStream(boolean append) throws
ResourceException {
+ try {
+ FileOutputStream os = new FileOutputStream(file);
+ return os;
+ } catch (IOException e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ public void removeProperty(String name) {
+ throw new UnsupportedOperationException("You can not remove
properties from files!");
+ }
+
+ public void setProperty(String name, Object newValue) {
+ throw new UnsupportedOperationException("You can not set
properties on files!");
+ }
+
+ public Object getProperty(String name) {
+ if (name.equals("lastModified")) {
+ return file.lastModified();
+ }
+ if (name.equals("length")) {
+ return file.length();
+ }
+ return null;
+ }
+
+ // XXX no op, only way to lock is using FileChannel#lock() and
+ // FileChannel#tryLock()
+ public boolean tryReadLock() {
+ return true;
+ }
+
+ // XXX no op, only way to lock is using FileChannel#lock() and
+ // FileChannel#tryLock()
+ public boolean tryWriteLock() {
+ return true;
+ }
+
+ // XXX no op, only way to lock is using FileChannel#lock() and
+ // FileChannel#tryLock()
+ public void readLock() {
+ }
+
+ // XXX no op, only way to lock is using FileChannel#lock() and
+ // FileChannel#tryLock()
+ public void writeLock() {
+ }
+
+ }
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceUndoManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceUndoManager.java?view=auto&rev=558857
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceUndoManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceUndoManager.java
Mon Jul 23 13:54:15 2007
@@ -0,0 +1,31 @@
+package org.apache.commons.transaction.file;
+
+import java.io.File;
+
+public interface FileResourceUndoManager {
+
+ public enum Code {
+ CREATED_DIRECTORY, CREATED_FILE, DELETED_DIRECTORY, MOVED, COPIED,
CONTENT_CHANGED, PROPERTY_CHANGED
+ }
+
+ public void startRecord();
+
+ public void undoRecord();
+
+ public void forgetRecord();
+
+ public void recordCopy(File from, File to);
+
+ public void recordCreateAsDirectory(File directory);
+
+ public void recordCreateAsFile(File file);
+
+ public void recordDelete(File file);
+
+ public void recordMove(File from, File to);
+
+ public void recordChangeProperty(File file, String name, Object oldValue);
+
+ public void recordChangeContent(File file);
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/MemoryUndoManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/MemoryUndoManager.java?view=auto&rev=558857
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/MemoryUndoManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/MemoryUndoManager.java
Mon Jul 23 13:54:15 2007
@@ -0,0 +1,136 @@
+package org.apache.commons.transaction.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.util.FileHelper;
+
+// TODO: memory version to be serialized to XML using JAXB
+public class MemoryUndoManager implements FileResourceUndoManager {
+
+ private Log logger = LogFactory.getLog(getClass());
+ protected ThreadLocal<List<UndoRecord>> localRecords = new
ThreadLocal<List<UndoRecord>>();
+
+
+ public void recordChangeContent(File file) {
+ UndoRecord record = new UndoRecord();
+ record.code = Code.CONTENT_CHANGED;
+ record.file = file;
+ try {
+ record.oldConent = new
ByteArrayInputStream(FileHelper.readInto(file));
+ } catch (IOException e) {
+ logger.fatal("Could not store changed content for "+file);
+ // FIXME: This really should cause an error
+ }
+ storeRecord(record);
+ }
+
+ public void recordCopy(File from, File to) {
+ if (to.exists()) {
+ recordChangeContent(to);
+ }
+ UndoRecord record = new UndoRecord();
+ record.code = Code.COPIED;
+ record.file = from;
+ record.to = to;
+ storeRecord(record);
+ }
+
+ public void recordCreateAsDirectory(File directory) {
+ UndoRecord record = new UndoRecord();
+ record.code = Code.CREATED_DIRECTORY;
+ record.file = directory;
+ storeRecord(record);
+ }
+
+ public void recordCreateAsFile(File file) {
+ UndoRecord record = new UndoRecord();
+ record.code = Code.CREATED_FILE;
+ record.file = file;
+ storeRecord(record);
+ }
+
+ public void recordDelete(File file) {
+ if (file.isFile()) {
+ recordChangeContent(file);
+ } else {
+ UndoRecord record = new UndoRecord();
+ record.code = Code.DELETED_DIRECTORY;
+ record.file = file;
+ storeRecord(record);
+ }
+ }
+
+ public void recordMove(File from, File to) {
+ if (to.exists()) {
+ recordChangeContent(to);
+ }
+ UndoRecord record = new UndoRecord();
+ record.code = Code.MOVED;
+ record.file = from;
+ record.to = to;
+ storeRecord(record);
+ }
+
+ public void recordChangeProperty(File file, String name, Object oldValue) {
+ UndoRecord record = new UndoRecord();
+ record.code = Code.PROPERTY_CHANGED;
+ record.file = file;
+ record.propertyName = name;
+ record.oldValue = oldValue;
+ storeRecord(record);
+ }
+
+ public void startRecord() {
+ localRecords.set(new ArrayList<UndoRecord>());
+ }
+
+ public void undoRecord() {
+ List<UndoRecord> records = new
ArrayList<UndoRecord>(localRecords.get());
+ Collections.reverse(records);
+ for (UndoRecord record : records) {
+ record.undo();
+ }
+ }
+
+ public void forgetRecord() {
+ localRecords.set(null);
+ }
+
+ protected void storeRecord(UndoRecord record) {
+ List<UndoRecord> records = localRecords.get();
+ records.add(record);
+ }
+
+ protected static class UndoRecord {
+ Code code;
+
+ File file;
+
+ File to;
+
+ String propertyName;
+
+ Object oldValue;
+
+ InputStream oldConent;
+
+ // FIXME: Needs implementation (not that hard)
+ // ugly c-style - who cares?
+ public void undo() {
+ // TODO
+ switch (code) {
+
+ }
+
+ }
+ }
+
+}
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java?view=diff&rev=558857&r1=558856&r2=558857
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
(original)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
Mon Jul 23 13:54:15 2007
@@ -18,82 +18,46 @@
import java.io.Closeable;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.transaction.AbstractTransactionalResourceManager;
-import org.apache.commons.transaction.TransactionalResourceManager;
+import org.apache.commons.transaction.ManageableResourceManager;
import
org.apache.commons.transaction.AbstractTransactionalResourceManager.AbstractTxContext;
+import org.apache.commons.transaction.file.FileResourceManager.FileResource;
import org.apache.commons.transaction.locking.LockException;
+import org.apache.commons.transaction.resource.ResourceException;
import org.apache.commons.transaction.resource.ResourceManager;
import org.apache.commons.transaction.resource.StreamableResource;
-import org.apache.commons.transaction.util.FileHelper;
public class TxFileResourceManager extends
AbstractTransactionalResourceManager<TxFileResourceManager.FileTxContext>
implements
- ResourceManager<StreamableResource> {
+ ManageableResourceManager, ResourceManager<StreamableResource> {
private Log logger = LogFactory.getLog(getClass());
protected String contextFileName = "transaction.log";
- protected PathManager idMapper;
+ protected String rootPath;
- protected TransactionalResourceManager tm;
+ protected FileResourceManager wrapped;
- public static void applyDeletes(File removeDir, File targetDir, File
rootDir)
- throws IOException {
- if (removeDir.isDirectory() && targetDir.isDirectory()) {
- File[] files = removeDir.listFiles();
- for (int i = 0; i < files.length; i++) {
- File removeFile = files[i];
- File targetFile = new File(targetDir, removeFile.getName());
- if (!removeFile.isDirectory()) {
- if (targetFile.exists()) {
- if (!targetFile.delete()) {
- throw new IOException("Could not delete file " +
removeFile.getName()
- + " in directory targetDir");
- }
- } else if (!targetFile.isFile()) {
- // this is likely a dangling link
- targetFile.delete();
- }
- // indicate, this has been done
- removeFile.delete();
- } else {
- applyDeletes(removeFile, targetFile, rootDir);
- }
- // delete empty target directories, except root dir
- if (!targetDir.equals(rootDir) && targetDir.list().length ==
0) {
- targetDir.delete();
- }
- }
- }
- }
+ protected FileResourceUndoManager undoManager;
- public String getContextFileName() {
- return contextFileName;
+ public TxFileResourceManager(String rootPath) {
+ this.rootPath = rootPath;
+ wrapped = new FileResourceManager(rootPath);
}
public void setContextFileName(String contextFile) {
this.contextFileName = contextFile;
}
- public PathManager getIdMapper() {
- return idMapper;
- }
-
- public void setIdMapper(PathManager idMapper) {
- this.idMapper = idMapper;
- }
-
@Override
protected FileTxContext createContext() {
return new FileTxContext();
@@ -101,91 +65,175 @@
// TODO resource manager needs to forward requests to this context, locking
// will happen here
- public class FileTxContext extends AbstractTxContext implements
FileResourceManager {
+ // FIXME
+ // needs
+ // - custom commit / rollback
+ // - proper resource tracking
+ public class FileTxContext extends AbstractTxContext implements
+ ResourceManager<StreamableResource> {
// list of streams participating in this tx
private Collection<Closeable> openStreams = new ArrayList<Closeable>();
public FileTxContext() {
- super();
- String changeDir = getIdMapper().getChangeBaseDir();
- String deleteDir = getIdMapper().getDeleteBaseDir();
-
- new File(changeDir).mkdirs();
- new File(deleteDir).mkdirs();
}
- public void commit() {
- super.commit();
- String changeDir = getIdMapper().getChangeBaseDir();
- String deleteDir = getIdMapper().getDeleteBaseDir();
- String storeDir = getIdMapper().getStoreDir();
-
- try {
- applyDeletes(new File(deleteDir), new File(storeDir), new
File(storeDir));
- FileHelper.moveRec(new File(changeDir), new File(storeDir));
- } catch (IOException e) {
- throw new LockException(LockException.Code.COMMIT_FAILED, e);
- }
+ protected void registerStream(Closeable stream) {
+ openStreams.add(stream);
}
- public void cleanUp() {
- String baseDir = getIdMapper().getTransactionBaseDir();
- FileHelper.removeRec(new File(baseDir));
+ public StreamableResource getResource(String path) throws
ResourceException {
+ return new TxFileResource(path);
}
- public boolean copy(String sourceId, String destinationId) throws
IOException,
- LockException {
- // TODO Auto-generated method stub
- return false;
+ public String getRootPath() {
+ return TxFileResourceManager.this.getRootPath();
}
- public boolean createDir(String id) throws IOException, LockException {
- // TODO Auto-generated method stub
- return false;
- }
+ // FIXME needs custom implementations
+ // Details:
+ // - Hierarchical locking
+ // - Calls to configured undo manager
+ protected class TxFileResource extends FileResource {
- public boolean move(String sourceId, String destinationId) throws
IOException,
- LockException {
- // TODO Auto-generated method stub
- return false;
- }
+ public TxFileResource(File file) {
+ super(file);
+ }
- public InputStream read(String id) throws IOException, LockException {
- readLock(id);
- String path = getIdMapper().getPathForRead(id);
- InputStream is = new FileInputStream(new File(path));
- registerStream(is);
- return is;
- }
+ public TxFileResource(String path) {
+ super(path);
+ }
- public OutputStream write(String id) throws IOException {
- writeLock(id);
- String path = getIdMapper().getPathForRead(id);
- return new FileOutputStream(new File(path));
- }
+ public void copy(String destinationpath) throws ResourceException {
+ super.copy(destinationpath);
+ }
- public boolean remove(String id) throws IOException {
- writeLock(id);
- String path = getIdMapper().getPathForDelete(id);
- return new File(path).delete();
- }
+ public void createAsDirectory() throws ResourceException {
+ super.createAsDirectory();
+ }
- public boolean create(String id) throws IOException {
- writeLock(id);
- String path = getIdMapper().getPathForDelete(id);
- return new File(path).createNewFile();
- }
+ public void createAsFile() throws ResourceException {
+ super.createAsFile();
+ }
+
+ public void delete() throws ResourceException {
+ super.delete();
+ }
+
+ public boolean exists() {
+ return super.exists();
+ }
+
+ public List<StreamableResource> getChildren() throws
ResourceException {
+ return super.getChildren();
+ }
+
+ public StreamableResource getParent() throws ResourceException {
+ return super.getParent();
+ }
+
+ public String getPath() throws ResourceException {
+ return super.getPath();
+ }
+
+ public Object getProperty(String name) {
+ return super.getProperty(name);
+ }
+
+ public boolean isDirectory() {
+ return super.isDirectory();
+ }
+
+ public boolean isFile() {
+ return super.isFile();
+ }
+
+ public void move(String destinationpath) throws ResourceException {
+ super.move(destinationpath);
+ }
+
+ public InputStream readStream() throws ResourceException {
+ return super.readStream();
+ }
+
+ public void removeProperty(String name) {
+ super.removeProperty(name);
+ }
+
+ public void setProperty(String name, Object newValue) {
+ super.setProperty(name, newValue);
+ }
+
+ public boolean tryReadLock() {
+ try {
+ return getLm().tryLock(getName(), getPath(), false);
+ } catch (ResourceException e) {
+ // FIXME: ouch!
+ throw new LockException(e);
+ }
+ }
+
+ public boolean tryWriteLock() {
+ try {
+ return getLm().tryLock(getName(), getPath(), true);
+ } catch (ResourceException e) {
+ // FIXME: ouch!
+ throw new LockException(e);
+ }
+ }
+
+ public void readLock() {
+ try {
+ getLm().lock(getName(), getPath(), false);
+ } catch (ResourceException e) {
+ // FIXME: ouch!
+ throw new LockException(e);
+ }
+ super.readLock();
+ }
+
+ public void writeLock() {
+ try {
+ getLm().lock(getName(), getPath(), true);
+ } catch (ResourceException e) {
+ // FIXME: ouch!
+ throw new LockException(e);
+ }
+ super.writeLock();
+ }
+
+ public OutputStream writeStream(boolean append) throws
ResourceException {
+ return super.writeStream(append);
+ }
- public boolean removeDir(String id) throws IOException, LockException {
- // TODO Auto-generated method stub
- return false;
}
+ }
- protected void registerStream(Closeable stream) {
- openStreams.add(stream);
+ @Override
+ public boolean commitCanFail() {
+ return false;
+ }
+
+ public StreamableResource getResource(String path) throws
ResourceException {
+ FileTxContext context = getActiveTx();
+ if (context != null) {
+ return context.getResource(path);
+ } else {
+ return wrapped.getResource(path);
}
+ }
+
+ public String getRootPath() {
+ return rootPath;
+ }
+
+ public FileResourceUndoManager getUndoManager() {
+ return undoManager;
+ }
+
+ public void setUndoManager(FileResourceUndoManager undoManager) {
+ this.undoManager = undoManager;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]