Author: ozeigermann
Date: Thu Jul 12 05:39:49 2007
New Revision: 555614
URL: http://svn.apache.org/viewvc?view=rev&rev=555614
Log:
Next chaotic step to initial version.
- Contains much work_in_progress code in the locking package
- util now contains working code for FileHelpers and FileSequence (cleaned from
1.x logging / exception crap)
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BookKeepingLockManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpCondition.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpLock.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileSequence.java
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java?view=diff&rev=555614&r1=555613&r2=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
(original)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
Thu Jul 12 05:39:49 2007
@@ -16,6 +16,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+// TODO: Add two dedicated locks for close/open resp. spawn
public class ComboInputStreamMulticaster implements InputStreamMulticaster {
private int memoryBufferSize = 8192;
@@ -30,6 +31,7 @@
protected boolean isOpen = false;
+ @Override
public synchronized void close() {
if (!isOpen) {
throw new IllegalStateException("You can not close: Stream
multicaster is not open!");
@@ -37,6 +39,7 @@
isOpen = false;
}
+ @Override
public synchronized void open(InputStream backingInputStream) throws
IOException {
if (isOpen) {
throw new IllegalStateException(
@@ -75,6 +78,7 @@
isOpen = true;
}
+ @Override
public synchronized InputStream spawn() throws IOException {
if (!isOpen) {
throw new IllegalStateException(
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java?view=diff&rev=555614&r1=555613&r2=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
(original)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
Thu Jul 12 05:39:49 2007
@@ -1,9 +1,12 @@
package org.apache.commons.transaction.file;
+
import java.io.IOException;
import java.io.InputStream;
public interface InputStreamMulticaster {
void open(InputStream backingInputStream) throws IOException;
+
InputStream spawn() throws IOException;
+
void close() throws IOException;
}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BookKeepingLockManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BookKeepingLockManager.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BookKeepingLockManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BookKeepingLockManager.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,11 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.Set;
+
+public interface BookKeepingLockManager<K, L> extends LockManager<K, L> {
+ public Set<L> getAllLocksForCurrentThread();
+
+ // TODO: We need a means for a global timeout or at least
+ // something to demarcate transaction boundaries
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,15 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class GenericBookKeepingLockManager<K, L> extends GenericLockManager<K,
L> implements BookKeepingLockManager<K, L>{
+
+ protected final ConcurrentHashMap<K, L> globalOwners = new
ConcurrentHashMap<K, L>();
+
+ public Set<L> getAllLocksForCurrentThread() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java?view=diff&rev=555614&r1=555613&r2=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
(original)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
Thu Jul 12 05:39:49 2007
@@ -4,7 +4,7 @@
public class GenericLockManager<K, L> implements LockManager<K, L> {
- private final ConcurrentHashMap<K, L> globalLocks = new
ConcurrentHashMap<K, L>();
+ protected final ConcurrentHashMap<K, L> globalLocks = new
ConcurrentHashMap<K, L>();
@Override
public L getLock(K key) {
Modified:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java?view=diff&rev=555614&r1=555613&r2=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
(original)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
Thu Jul 12 05:39:49 2007
@@ -1,10 +1,10 @@
package org.apache.commons.transaction.locking;
+
public interface LockManager<K, L> {
public L getLock(K key);
public L createLockIfAbsent(K key, L lock);
public L removeLock(K key);
-
}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,7 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.concurrent.locks.Lock;
+
+public interface MultiLevelLock {
+ Lock getLock(int level);
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,73 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.LockSupport;
+
+public class MultiLevelLockImpl implements MultiLevelLock {
+
+ private int maxLevel;
+ private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
+
+ public MultiLevelLockImpl(int maxLevel) {
+ if (maxLevel < 1)
+ throw new IllegalArgumentException("The maximum lock level must be
at least 1 ("
+ + maxLevel + " was specified)");
+
+ this.maxLevel = maxLevel;
+ }
+
+ // for getter / setter injection
+ public MultiLevelLockImpl() {
+ }
+
+ public Lock getLock(int level) {
+ if (level > maxLevel)
+ throw new IllegalArgumentException("The requested lock level (" +
level
+ + ") is higher than the maximum lock level (" + maxLevel +
")");
+
+ }
+
+ private class InternalMLLock implements Lock {
+
+ public void lock() {
+ LockSupport.park();
+ }
+
+ public void lockInterruptibly() throws InterruptedException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Condition newCondition() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean tryLock() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean tryLock(long time, TimeUnit unit) throws
InterruptedException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void unlock() {
+ LockSupport.unpark(thread)();
+ }
+ }
+
+ public int getMaxLevel() {
+ return maxLevel;
+ }
+
+ public void setMaxLevel(int maxLevel) {
+ this.maxLevel = maxLevel;
+ }
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,5 @@
+package org.apache.commons.transaction.locking;
+
+
+public class MultiLevelLockManager extends GenericLockManager<Object,
MultiLevelLock> implements LockManager<Object, MultiLevelLock> {
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpCondition.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpCondition.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpCondition.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpCondition.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,51 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+
+public class NoOpCondition implements Condition {
+
+ @Override
+ public void await() throws InterruptedException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean await(long time, TimeUnit unit) throws InterruptedException
{
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public long awaitNanos(long nanosTimeout) throws InterruptedException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void awaitUninterruptibly() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean awaitUntil(Date deadline) throws InterruptedException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void signal() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void signalAll() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpLock.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpLock.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpLock.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpLock.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,40 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+public class NoOpLock implements Lock {
+
+ private final transient NoOpCondition internalCondition = new
NoOpCondition();
+
+ @Override
+ public void lock() {
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ if (Thread.currentThread().isInterrupted())
+ throw new InterruptedException();
+ }
+
+ @Override
+ public Condition newCondition() {
+ return internalCondition;
+ }
+
+ @Override
+ public boolean tryLock() {
+ return true;
+ }
+
+ @Override
+ public boolean tryLock(long time, TimeUnit unit) throws
InterruptedException {
+ return true;
+ }
+
+ @Override
+ public void unlock() {
+ }
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,13 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.concurrent.locks.Lock;
+
+public class NoOpMultiLevelLock implements MultiLevelLock {
+ private final transient NoOpLock internalLock = new NoOpLock();
+
+
+ public Lock getLock(int level) {
+ return internalLock;
+ }
+
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,335 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Helper methods for file manipulation.
+ * All methods are <em>thread safe</em>.
+ *
+ * @version $Id: FileHelper.java 493628 2007-01-07 01:42:48Z joerg $
+ */
+public final class FileHelper {
+
+ private static int BUF_SIZE = 50000;
+ private static byte[] BUF = new byte[BUF_SIZE];
+
+ /**
+ * Deletes a file specified by a path.
+ *
+ * @param path path of file to be deleted
+ * @return <code>true</code> if file has been deleted, <code>false</code>
otherwise
+ */
+ public static boolean deleteFile(String path) {
+ File file = new File(path);
+ return file.delete();
+ }
+
+ /**
+ * Checks if a file specified by a path exits.
+ *
+ * @param path path of file to be checked
+ * @return <code>true</code> if file exists, <code>false</code> otherwise
+ */
+ public static boolean fileExists(String path) {
+ File file = new File(path);
+ return file.exists();
+ }
+
+ /**
+ * Creates a file specified by a path. All necessary directories will be
created.
+ *
+ * @param path path of file to be created
+ * @return <code>true</code> if file has been created, <code>false</code>
if the file already exists
+ * @throws IOException
+ * If an I/O error occurred
+ */
+ public static boolean createFile(String path) throws IOException {
+ File file = new File(path);
+ if (file.isDirectory()) {
+ return file.mkdirs();
+ } else {
+ File dir = file.getParentFile();
+ // do not check if this worked, as it may also return false, when
all neccessary dirs are present
+ dir.mkdirs();
+ return file.createNewFile();
+ }
+ }
+
+ /**
+ * Removes a file. If the specified file is a directory all contained
files will
+ * be removed recursively as well.
+ *
+ * @param toRemove file to be removed
+ */
+ public static void removeRec(File toRemove) {
+ if (toRemove.isDirectory()) {
+ File fileList[] = toRemove.listFiles();
+ for (int a = 0; a < fileList.length; a++) {
+ removeRec(fileList[a]);
+ }
+ }
+ toRemove.delete();
+ }
+
+ /**
+ * Moves one directory or file to another. Existing files will be replaced.
+ *
+ * @param source file to move from
+ * @param target file to move to
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ */
+ public static void moveRec(File source, File target) throws IOException {
+ byte[] sharedBuffer = new byte[BUF_SIZE];
+ moveRec(source, target, sharedBuffer);
+ }
+
+ static void moveRec(File source, File target, byte[] sharedBuffer) throws
IOException {
+ if (source.isDirectory()) {
+ if (!target.exists()) {
+ target.mkdirs();
+ }
+ if (target.isDirectory()) {
+
+ File[] files = source.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ File targetFile = new File(target, file.getName());
+ if (file.isFile()) {
+ if (targetFile.exists()) {
+ targetFile.delete();
+ }
+ if (!file.renameTo(targetFile)) {
+ copy(file, targetFile, sharedBuffer);
+ file.delete();
+ }
+ } else {
+ if (!targetFile.exists()) {
+ if (!targetFile.mkdirs()) {
+ throw new IOException("Could not create target
directory: "
+ + targetFile);
+ }
+ }
+ moveRec(file, targetFile);
+ }
+ }
+ source.delete();
+ }
+ } else {
+ if (!target.isDirectory()) {
+ copy(source, target, sharedBuffer);
+ source.delete();
+ }
+ }
+ }
+
+ /**
+ * Copies one directory or file to another. Existing files will be
replaced.
+ *
+ * @param source directory or file to copy from
+ * @param target directory or file to copy to
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ */
+ public static void copyRec(File source, File target) throws IOException {
+ byte[] sharedBuffer = new byte[BUF_SIZE];
+ copyRec(source, target, sharedBuffer);
+ }
+
+ static void copyRec(File source, File target, byte[] sharedBuffer) throws
IOException {
+ if (source.isDirectory()) {
+ if (!target.exists()) {
+ target.mkdirs();
+ }
+ if (target.isDirectory()) {
+
+ File[] files = source.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ File targetFile = new File(target, file.getName());
+ if (file.isFile()) {
+ if (targetFile.exists()) {
+ targetFile.delete();
+ }
+ copy(file, targetFile, sharedBuffer);
+ } else {
+ targetFile.mkdirs();
+ copyRec(file, targetFile);
+ }
+ }
+ }
+ } else {
+ if (!target.isDirectory()) {
+ if (!target.exists()) {
+ File dir = target.getParentFile();
+ if(!dir.exists() && !dir.mkdirs()) {
+ throw new IOException("Could not create target
directory: " + dir);
+ }
+ if (!target.createNewFile()) {
+ throw new IOException("Could not create target file: "
+ target);
+ }
+ }
+ copy(source, target, sharedBuffer);
+ }
+ }
+ }
+
+ /**
+ * Copies one file to another using [EMAIL PROTECTED] #copy(InputStream,
OutputStream)}.
+ *
+ * @param input
+ * source file
+ * @param output
+ * destination file
+ * @return the number of bytes copied
+ * @throws IOException
+ * if an I/O error occurs (may result in partially done work)
+ * @see #copy(InputStream, OutputStream)
+ */
+ public static long copy(File input, File output) throws IOException {
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(input);
+ return copy(in, output);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Copies one file to another using the supplied buffer.
+ *
+ * @param input source file
+ * @param output destination file
+ * @param copyBuffer buffer used for copying
+ * @return the number of bytes copied
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ * @see #copy(InputStream, OutputStream)
+ */
+ public static long copy(File input, File output, byte[] copyBuffer) throws
IOException {
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ try {
+ in = new FileInputStream(input);
+ out = new FileOutputStream(output);
+ return copy(in, out, copyBuffer);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Copies an <code>InputStream</code> to a file using [EMAIL PROTECTED]
#copy(InputStream, OutputStream)}.
+ *
+ * @param in stream to copy from
+ * @param outputFile file to copy to
+ * @return the number of bytes copied
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ * @see #copy(InputStream, OutputStream)
+ */
+ public static long copy(InputStream in, File outputFile) throws
IOException {
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(outputFile);
+ return copy(in, out);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Copies an <code>InputStream</code> to an <code>OutputStream</code>
using a local internal buffer for performance.
+ * Compared to [EMAIL PROTECTED] #globalBufferCopy(InputStream,
OutputStream)} this method allows for better
+ * concurrency, but each time it is called generates a buffer which will
be garbage.
+ *
+ * @param in stream to copy from
+ * @param out stream to copy to
+ * @return the number of bytes copied
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ * @see #globalBufferCopy(InputStream, OutputStream)
+ */
+ public static long copy(InputStream in, OutputStream out) throws
IOException {
+ // we need a buffer of our own, so no one else interferes
+ byte[] buf = new byte[BUF_SIZE];
+ return copy(in, out, buf);
+ }
+
+ /**
+ * Copies an <code>InputStream</code> to an <code>OutputStream</code>
using a global internal buffer for performance.
+ * Compared to [EMAIL PROTECTED] #copy(InputStream, OutputStream)} this
method generated no garbage,
+ * but decreases concurrency.
+ *
+ * @param in stream to copy from
+ * @param out stream to copy to
+ * @return the number of bytes copied
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ * @see #copy(InputStream, OutputStream)
+ */
+ public static long globalBufferCopy(InputStream in, OutputStream out)
throws IOException {
+ synchronized (BUF) {
+ return copy(in, out, BUF);
+ }
+ }
+
+ /**
+ * Copies an <code>InputStream</code> to an <code>OutputStream</code>
using the specified buffer.
+ *
+ * @param in stream to copy from
+ * @param out stream to copy to
+ * @param copyBuffer buffer used for copying
+ * @return the number of bytes copied
+ * @throws IOException if an I/O error occurs (may result in partially
done work)
+ * @see #globalBufferCopy(InputStream, OutputStream)
+ * @see #copy(InputStream, OutputStream)
+ */
+ public static long copy(InputStream in, OutputStream out, byte[]
copyBuffer) throws IOException {
+ long bytesCopied = 0;
+ int read = -1;
+
+ while ((read = in.read(copyBuffer, 0, copyBuffer.length)) != -1) {
+ out.write(copyBuffer, 0, read);
+ bytesCopied += read;
+ }
+ return bytesCopied;
+ }
+}
Added:
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileSequence.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileSequence.java?view=auto&rev=555614
==============================================================================
---
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileSequence.java
(added)
+++
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileSequence.java
Thu Jul 12 05:39:49 2007
@@ -0,0 +1,283 @@
+/*
+ * 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.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.util.FileHelper;
+
+/**
+ * Fail-Safe sequence store implementation using the file system. Works by
+ * versioning values of sequences and throwing away all versions, but the
+ * current and the previous one.
+ *
+ * @version $Id: FileSequence.java 493628 2007-01-07 01:42:48Z joerg $
+ */
+public class FileSequence {
+
+ private Log logger = LogFactory.getLog(getClass());
+
+ protected final String storeDir;
+
+ /**
+ * Creates a new resouce manager operation on the specified directories.
+ *
+ * @param storeDir
+ * directory where sequence information is stored
+ * @param logger
+ * logger used for warnings only
+ */
+ public FileSequence(String storeDir) {
+ this.storeDir = storeDir;
+ File file = new File(storeDir);
+ file.mkdirs();
+ if (!file.exists()) {
+ throw new IllegalStateException("Can not create working directory
" + storeDir);
+ }
+ }
+
+ /**
+ * Checks if the sequence already exists.
+ *
+ * @param sequenceName
+ * the name of the sequence you want to check
+ * @return <code>true</code> if the sequence already exists,
+ * <code>false</code> otherwise
+ */
+ public synchronized boolean exists(String sequenceName) {
+ String pathI = getPathI(sequenceName);
+ String pathII = getPathII(sequenceName);
+
+ return (FileHelper.fileExists(pathI) || FileHelper.fileExists(pathII));
+ }
+
+ /**
+ * Creates a sequence if it does not already exist.
+ *
+ * @param sequenceName
+ * the name of the sequence you want to create
+ * @return <code>true</code> if the sequence has been created,
+ * <code>false</code> if it already existed
+ */
+ public synchronized boolean create(String sequenceName, long initialValue)
{
+ if (exists(sequenceName))
+ return false;
+ write(sequenceName, initialValue);
+ return true;
+ }
+
+ /**
+ * Deletes a sequence if it exists.
+ *
+ * @param sequenceName
+ * the name of the sequence you want to delete
+ * @return <code>true</code> if the sequence has been deleted,
+ * <code>false</code> if not
+ */
+ public synchronized boolean delete(String sequenceName) {
+ if (!exists(sequenceName))
+ return false;
+ String pathI = getPathI(sequenceName);
+ String pathII = getPathII(sequenceName);
+
+ // XXX be careful no to use shortcut eval with || might not delete
+ // second file
+ boolean res1 = FileHelper.deleteFile(pathI);
+ boolean res2 = FileHelper.deleteFile(pathII);
+
+ return (res1 || res2);
+ }
+
+ /**
+ * Gets the next value of the sequence.
+ *
+ * @param sequenceName
+ * the name of the sequence you want the next value for
+ * @param increment
+ * the increment for the sequence, i.e. how much to add to the
+ * sequence with this call
+ * @return the next value of the sequence <em>not yet incremented</em>,
+ * i.e. the increment is recorded internally, but not returned with
+ * the next call to this method
+ * @throws ResourceManagerException
+ * if anything goes wrong while accessing the sequence
+ */
+ public synchronized long nextSequenceValueBottom(String sequenceName, long
increment) {
+ if (!exists(sequenceName)) {
+ throw new IllegalStateException("Sequence " + sequenceName + "
does not exist");
+ }
+ if (increment <= 0) {
+ throw new IllegalArgumentException("Increment must be greater than
0, was " + increment);
+ }
+ long value = read(sequenceName);
+ long newValue = value + increment;
+ write(sequenceName, newValue);
+ return value;
+ }
+
+ protected long read(String sequenceName) {
+ String pathI = getPathI(sequenceName);
+ String pathII = getPathII(sequenceName);
+
+ long returnValue = -1;
+
+ long valueI = -1;
+ if (FileHelper.fileExists(pathI)) {
+ try {
+ valueI = readFromPath(pathI);
+ } catch (NumberFormatException e) {
+ throw new Error("Fatal internal error: Backup sequence value
corrupted");
+ } catch (FileNotFoundException e) {
+ throw new Error("Fatal internal error: Backup sequence
vanished");
+ } catch (IOException e) {
+ throw new Error("Fatal internal error: Backup sequence value
corrupted");
+ }
+ }
+
+ long valueII = -1;
+ if (FileHelper.fileExists(pathII)) {
+ try {
+ valueII = readFromPath(pathII);
+ if (valueII > valueI) {
+ returnValue = valueII;
+ } else {
+ // if it is smaller than previous this *must* be an error
as
+ // we constantly increment
+ logger
+ .warn("Latest sequence value smaller than
previous, reverting to previous");
+ FileHelper.deleteFile(pathII);
+ returnValue = valueI;
+ }
+ } catch (NumberFormatException e) {
+ logger.warn("Latest sequence value corrupted, reverting to
previous");
+ FileHelper.deleteFile(pathII);
+ returnValue = valueI;
+ } catch (FileNotFoundException e) {
+ logger.warn("Can not find latest sequence value, reverting to
previous");
+ FileHelper.deleteFile(pathII);
+ returnValue = valueI;
+ } catch (IOException e) {
+ logger.warn("Can not read latest sequence value, reverting to
previous");
+ FileHelper.deleteFile(pathII);
+ returnValue = valueI;
+ }
+ } else {
+ logger.warn("Can not read latest sequence value, reverting to
previous");
+ returnValue = valueI;
+ }
+
+ if (returnValue != -1) {
+ return returnValue;
+ } else {
+ throw new Error("Fatal internal error: Could not compute valid
sequence value");
+ }
+ }
+
+ protected void write(String sequenceName, long value) {
+ String pathII = getPathII(sequenceName);
+
+ File f2 = new File(pathII);
+ // by contract when this method is called an f2 exists it must be valid
+ if (f2.exists()) {
+ // move previous value to backup position
+ String pathI = getPathI(sequenceName);
+ File f1 = new File(pathI);
+ f1.delete();
+ if (!f2.renameTo(f1)) {
+ throw new Error("Fatal internal error: Can not create backup
value at" + pathI);
+ }
+ }
+ try {
+ if (!f2.createNewFile()) {
+ throw new Error("Fatal internal error: Can not create new
value at" + pathII);
+ }
+ } catch (IOException e) {
+ throw new Error("Fatal internal error: Can not create new value
at" + pathII, e);
+ }
+ writeToPath(pathII, value);
+ }
+
+ protected String getPathI(String sequenceName) {
+ return storeDir + "/" + sequenceName + "_1.seq";
+ }
+
+ protected String getPathII(String sequenceName) {
+ return storeDir + "/" + sequenceName + "_2.seq";
+ }
+
+ protected long readFromPath(String path) throws NumberFormatException,
FileNotFoundException,
+ IOException {
+ File file = new File(path);
+ BufferedReader reader = null;
+ try {
+ InputStream is = new FileInputStream(file);
+
+ // we do not care for encoding as we only have numbers
+ reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ String valueString = reader.readLine();
+ long value = Long.parseLong(valueString);
+ return value;
+ } catch (UnsupportedEncodingException e) {
+ throw new Error("Fatal internal error, encoding UTF-8 unknown");
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+
+ }
+ }
+ }
+
+ protected void writeToPath(String path, long value) {
+ File file = new File(path);
+ BufferedWriter writer = null;
+ try {
+ OutputStream os = new FileOutputStream(file);
+ writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
+ String valueString = Long.toString(value);
+ writer.write(valueString);
+ writer.write('\n');
+ } catch (FileNotFoundException e) {
+ throw new Error("Fatal internal error: Can not find sequence at "
+ path);
+ } catch (IOException e) {
+ throw new Error("Fatal internal error: Can not write to sequence
at " + path);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ }
+
+ }
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]