pnever 2005/02/25 07:30:53
Modified:
proposals/tamino/src/store/org/apache/slide/store/tamino/datastore
Tag: TWS421_BRANCH TaminoCodes.java
proposals/tamino/src/store/org/apache/slide/store/tamino/store
Tag: TWS421_BRANCH XChildStore.java
XDescriptorsStore.java
proposals/tamino/src/store/org/apache/slide/store/tamino/common
Tag: TWS421_BRANCH XDescriptorsCache.java
XDescriptorsHandler.java
proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects
Tag: TWS421_BRANCH XTLock.java
Added: proposals/tamino/src/store/org/apache/slide/store/tamino/common
Tag: TWS421_BRANCH XTLockSettings.java
Log:
Fixed problems with t-locks
Added READ_COMMITTED level
Minor fixes
Revision Changes Path
No revision
No revision
1.1.2.2 +22 -11
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/Attic/TaminoCodes.java
Index: TaminoCodes.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/Attic/TaminoCodes.java,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -r1.1.2.1 -r1.1.2.2
--- TaminoCodes.java 1 Feb 2005 11:27:18 -0000 1.1.2.1
+++ TaminoCodes.java 25 Feb 2005 15:30:52 -0000 1.1.2.2
@@ -22,12 +22,9 @@
package org.apache.slide.store.tamino.datastore;
+import java.util.*;
+
import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TreeSet;
import org.apache.slide.common.Domain;
@@ -43,19 +40,33 @@
private static Set nonabortingCodes = null;
private static DecimalFormat df = new DecimalFormat("0000");
+ private static boolean allCodesAreNonAborting = false;
public static boolean isNonaborting(String code) {
if (nonabortingCodes == null) {
loadCodes();
- System.out.println("@@@ Tamino codes non-aborting:
"+nonabortingCodes);
+ System.out.println("@@@ Tamino codes non-aborting:
"+(allCodesAreNonAborting
+ ? "***
DISABLED ***"
+ :
String.valueOf(nonabortingCodes)));
+ }
+ if (allCodesAreNonAborting) {
+ return true;
}
+ else {
return nonabortingCodes.contains(code);
}
+ }
private static void loadCodes() {
- String codes = Domain.getParameter("taminocodes-nonaborting", "");
+ String codes = Domain.getParameter("taminocodes-nonaborting");
+ if (codes == null) {
+ allCodesAreNonAborting = true;
+ nonabortingCodes = Collections.EMPTY_SET;
+ }
+ else {
nonabortingCodes = loadCodes(codes);
}
+ }
private static Set loadCodes(String codes) {
Set result = new TreeSet();
No revision
No revision
1.1.4.5 +25 -36
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/store/XChildStore.java
Index: XChildStore.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/store/XChildStore.java,v
retrieving revision 1.1.4.4
retrieving revision 1.1.4.5
diff -u -r1.1.4.4 -r1.1.4.5
--- XChildStore.java 14 Jan 2005 14:49:44 -0000 1.1.4.4
+++ XChildStore.java 25 Feb 2005 15:30:52 -0000 1.1.4.5
@@ -21,6 +21,10 @@
*/
package org.apache.slide.store.tamino.store;
+import org.apache.slide.common.*;
+import org.apache.slide.store.tamino.common.*;
+import org.apache.slide.store.tamino.datastore.*;
+
import com.softwareag.common.instrumentation.logging.Level;
import com.softwareag.common.instrumentation.logging.Logger;
import com.softwareag.common.instrumentation.logging.LoggerFactory;
@@ -30,36 +34,8 @@
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
-import org.apache.slide.common.AbstractService;
-import org.apache.slide.common.Domain;
-import org.apache.slide.common.Namespace;
-import org.apache.slide.common.NamespaceAccessToken;
-import org.apache.slide.common.Scope;
-import org.apache.slide.common.ServiceAccessException;
-import org.apache.slide.common.ServiceConnectionFailedException;
-import org.apache.slide.common.ServiceDisconnectionFailedException;
-import org.apache.slide.common.ServiceInitializationFailedException;
-import org.apache.slide.common.ServiceParameterErrorException;
-import org.apache.slide.common.ServiceParameterMissingException;
-import org.apache.slide.common.SlideToken;
-import org.apache.slide.common.Uri;
import org.apache.slide.macro.ConflictException;
import org.apache.slide.macro.ForbiddenException;
-import org.apache.slide.store.tamino.common.IDescriptorsHandler;
-import org.apache.slide.store.tamino.common.XConflictException;
-import org.apache.slide.store.tamino.common.XForbiddenException;
-import org.apache.slide.store.tamino.common.XGlobals;
-import
org.apache.slide.store.tamino.common.XOldMetadataSchemaVersionException;
-import org.apache.slide.store.tamino.datastore.IDbSession;
-import org.apache.slide.store.tamino.datastore.MetaDataURLAccessor;
-import org.apache.slide.store.tamino.datastore.XAuthenticator;
-import org.apache.slide.store.tamino.datastore.XConnection;
-import org.apache.slide.store.tamino.datastore.XConnectionKey;
-import org.apache.slide.store.tamino.datastore.XConnectionPool;
-import org.apache.slide.store.tamino.datastore.XDbHandler;
-import org.apache.slide.store.tamino.datastore.XDbSession;
-import org.apache.slide.store.tamino.datastore.XSecurity;
-import org.apache.slide.store.tamino.datastore.XSecurityMultiUser;
import org.apache.slide.store.tamino.datastore.metadata.GlobalsAccessor;
import org.apache.slide.store.tamino.store.monitoring.IMonitor;
import org.apache.slide.store.tamino.store.monitoring.IMonitorable;
@@ -70,8 +46,6 @@
import org.apache.slide.store.tamino.tools.stores.XStore;
import org.apache.slide.util.ClassName;
import org.apache.slide.util.XException;
-import org.apache.slide.util.cli.Abort;
-import org.apache.slide.util.os.Catalina;
import org.jdom.Element;
@@ -92,6 +66,7 @@
/** Name of the WAIT_FOR_TLOCK_TIMEOUT parameter */
private static final String WAIT_FOR_TLOCK_TIMEOUT =
"waitForTlockTimeout";
+ private static final String TLOCK_ISOLATION_LEVEL =
"tlockIsolationLevel";
/** True, if this store is initialized. */
protected boolean initialized = false;
@@ -633,13 +608,13 @@
//--
/** helper for initialization */
- public long getTimeout() throws ServiceInitializationFailedException {
+ private long getTimeout() throws ServiceInitializationFailedException {
String str;
long num;
str = getParameter(WAIT_FOR_TLOCK_TIMEOUT);
if (str == null) {
- return 5000; // TODO: was 3000
+ return 3000;
} else {
try {
num = Long.parseLong(str);
@@ -653,6 +628,20 @@
}
}
+ private int getIsolationLevel() throws
ServiceInitializationFailedException {
+ String p = getParameter(TLOCK_ISOLATION_LEVEL);
+ if (XTLockSettings.S_READ_COMMITTED.equalsIgnoreCase(p)) {
+ return XTLockSettings.READ_COMMITTED;
+ }
+ else {
+ return XTLockSettings.SERIALIZABLE;
+ }
+ }
+
+ public XTLockSettings getTLockSettings() throws
ServiceInitializationFailedException {
+ return new XTLockSettings(getTimeout(), getIsolationLevel());
+ }
+
public String toString() {
return getMonName();
}
1.1.4.1 +5 -5
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/store/XDescriptorsStore.java
Index: XDescriptorsStore.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/store/XDescriptorsStore.java,v
retrieving revision 1.1
retrieving revision 1.1.4.1
diff -u -r1.1 -r1.1.4.1
--- XDescriptorsStore.java 25 Mar 2004 16:18:03 -0000 1.1
+++ XDescriptorsStore.java 25 Feb 2005 15:30:52 -0000 1.1.4.1
@@ -171,7 +171,7 @@
if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
"initialize",
new Object[]
{(token!=null ? token.getName() : null)} );
- descriptorsHandler = new XDescriptorsHandler( this, getTimeout() );
+ descriptorsHandler = new XDescriptorsHandler(this,
getTLockSettings());
// monitoring variables
this.monName = "DescriptorsStore";
No revision
No revision
1.1.4.1 +9 -9
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsCache.java
Index: XDescriptorsCache.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsCache.java,v
retrieving revision 1.1
retrieving revision 1.1.4.1
diff -u -r1.1 -r1.1.4.1
--- XDescriptorsCache.java 25 Mar 2004 16:17:59 -0000 1.1
+++ XDescriptorsCache.java 25 Feb 2005 15:30:52 -0000 1.1.4.1
@@ -88,7 +88,7 @@
private final Object sync;
- private final long timeout;
+ private XTLockSettings tlockSettings;
/** Maps uuris to TLocks with SoftReferences */
private final Map container;
@@ -99,12 +99,12 @@
/**
* Default constructor.
*/
- public XDescriptorsCache(Object sync, long timeout, Object
onOpenTaSyncPoint) {
+ public XDescriptorsCache(Object sync, XTLockSettings tlockSettings,
Object onOpenTaSyncPoint) {
if( logger.isLoggable(Level.FINE) )
- logger.entering( CLASSNAME, "<init>" );
+ logger.entering( CLASSNAME, "<init>", new
Object[]{tlockSettings} );
this.sync = sync;
- this.timeout = timeout;
+ this.tlockSettings = tlockSettings;
this.container = new LRUSoftCache(QUEUE_LENGTH, INITIAL_CAPACITY);
this.threadMap = new XThreadMap(onOpenTaSyncPoint);
@@ -213,7 +213,7 @@
if( logger.isLoggable(Level.FINE) )
logger.entering( CLASSNAME, "add", new Object[]{desc} );
- lock = new XTLock(sync, timeout, desc);
+ lock = new XTLock(sync, tlockSettings, desc);
try {
if (lock.acquire(lockType) != XTLock.NO_LOCK) {
// we've just created the TLock object - nobody else can
see/look ip
1.1.4.2 +7 -7
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsHandler.java
Index: XDescriptorsHandler.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsHandler.java,v
retrieving revision 1.1.4.1
retrieving revision 1.1.4.2
diff -u -r1.1.4.1 -r1.1.4.2
--- XDescriptorsHandler.java 9 Sep 2004 08:03:54 -0000 1.1.4.1
+++ XDescriptorsHandler.java 25 Feb 2005 15:30:52 -0000 1.1.4.2
@@ -76,11 +76,11 @@
* @post globalCache != null
* @post deltas != null
*/
- public XDescriptorsHandler( XDescriptorsStore childStore, long timeout )
{
+ public XDescriptorsHandler(XDescriptorsStore childStore, XTLockSettings
tlockSettings) {
if( logger.isLoggable(Level.FINE) )
- logger.entering( CLASSNAME, "<init>", new Object[] {childStore}
);
+ logger.entering( CLASSNAME, "<init>", new Object[] {childStore,
tlockSettings} );
- globalCache = new XDescriptorsCache(this, timeout,
onOpenTaSynchPoint);
+ globalCache = new XDescriptorsCache(this, tlockSettings,
onOpenTaSynchPoint);
if( logger.isLoggable(Level.FINE) )
logger.fine(CLASSNAME, "<init>", "Created global cache");
No revision
Index: XDescriptorsHandler.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsHandler.java,v
retrieving revision 1.1.4.1
retrieving revision 1.1.4.2
diff -u -r1.1.4.1 -r1.1.4.2
--- XDescriptorsHandler.java 9 Sep 2004 08:03:54 -0000 1.1.4.1
+++ XDescriptorsHandler.java 25 Feb 2005 15:30:52 -0000 1.1.4.2
@@ -76,11 +76,11 @@
* @post globalCache != null
* @post deltas != null
*/
- public XDescriptorsHandler( XDescriptorsStore childStore, long timeout )
{
+ public XDescriptorsHandler(XDescriptorsStore childStore, XTLockSettings
tlockSettings) {
if( logger.isLoggable(Level.FINE) )
- logger.entering( CLASSNAME, "<init>", new Object[] {childStore}
);
+ logger.entering( CLASSNAME, "<init>", new Object[] {childStore,
tlockSettings} );
- globalCache = new XDescriptorsCache(this, timeout,
onOpenTaSynchPoint);
+ globalCache = new XDescriptorsCache(this, tlockSettings,
onOpenTaSynchPoint);
if( logger.isLoggable(Level.FINE) )
logger.fine(CLASSNAME, "<init>", "Created global cache");
No revision
Index: XDescriptorsHandler.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/XDescriptorsHandler.java,v
retrieving revision 1.1.4.1
retrieving revision 1.1.4.2
diff -u -r1.1.4.1 -r1.1.4.2
--- XDescriptorsHandler.java 9 Sep 2004 08:03:54 -0000 1.1.4.1
+++ XDescriptorsHandler.java 25 Feb 2005 15:30:52 -0000 1.1.4.2
@@ -76,11 +76,11 @@
* @post globalCache != null
* @post deltas != null
*/
- public XDescriptorsHandler( XDescriptorsStore childStore, long timeout )
{
+ public XDescriptorsHandler(XDescriptorsStore childStore, XTLockSettings
tlockSettings) {
if( logger.isLoggable(Level.FINE) )
- logger.entering( CLASSNAME, "<init>", new Object[] {childStore}
);
+ logger.entering( CLASSNAME, "<init>", new Object[] {childStore,
tlockSettings} );
- globalCache = new XDescriptorsCache(this, timeout,
onOpenTaSynchPoint);
+ globalCache = new XDescriptorsCache(this, tlockSettings,
onOpenTaSynchPoint);
if( logger.isLoggable(Level.FINE) )
logger.fine(CLASSNAME, "<init>", "Created global cache");
1.1.2.1 +104 -0
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/common/Attic/XTLockSettings.java
No revision
No revision
1.1.4.1 +79 -85
jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects/XTLock.java
Index: XTLock.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/jdomobjects/XTLock.java,v
retrieving revision 1.1
retrieving revision 1.1.4.1
diff -u -r1.1 -r1.1.4.1
--- XTLock.java 25 Mar 2004 16:18:02 -0000 1.1
+++ XTLock.java 25 Feb 2005 15:30:53 -0000 1.1.4.1
@@ -29,7 +29,9 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.apache.slide.common.Domain;
import org.apache.slide.store.tamino.common.IDescriptors;
+import org.apache.slide.store.tamino.common.XTLockSettings;
import org.apache.slide.store.tamino.common.XTLockedException;
import org.apache.slide.util.ClassName;
import org.apache.slide.util.XAssertionFailed;
@@ -51,38 +53,38 @@
private static final String LOGNAME = LoggerUtil.getThisClassName();
private static final String CLASSNAME = new
ClassName(LOGNAME).getPlainName();
private static final Logger logger = LoggerFactory.getLogger(LOGNAME +
".tlock");
-
+
// lock types
// Caution: the lock type is relative to the current thread. E.g. if
thread A holds a
// write Lock W, W's lock type releated to thread B is NO_LOCK.
public static final int NO_LOCK = 0;
public static final int READ_LOCK = 1;
public static final int WRITE_LOCK = 2;
-
-
- private final long timeout;
+
+
+ private XTLockSettings tlockSettings;
private final Object sync;
-
+
/** never null */
private IDescriptors readerDesc;
-
+
/** never null if write-locked */
private IDescriptors writerDesc;
-
+
private int waitingWriter;
-
+
/** List of threads. Never contains activeWriter **/
private final List activeReader;
-
+
private Thread activeWriter;
-
- public XTLock(Object sync, long timeout, IDescriptors desc) {
+
+ public XTLock(Object sync, XTLockSettings tlockSettings, IDescriptors
desc) {
if (desc == null) {
throw new XAssertionFailed();
}
- this.timeout = timeout;
+ this.tlockSettings = tlockSettings;
this.sync = sync;
-
+
this.readerDesc = desc;
this.readerDesc.setReadOnly(true);
this.writerDesc = null;
@@ -90,15 +92,15 @@
this.activeReader = new ArrayList();
this.activeWriter = null;
}
-
+
public Thread getActiveWriter() {
return activeWriter;
}
-
+
public String getUuri() {
return readerDesc.getUuri();
}
-
+
/**
** Obtains read or write lock for the current thread.
** The lock will persist til end of transaction.
@@ -117,10 +119,10 @@
throw new XAssertionFailed("acquire failed." + type + " is
invalid");
}
}
-
+
public IDescriptors getDescriptors() {
int type;
-
+
type = getType();
switch (type) {
case NO_LOCK:
@@ -132,11 +134,11 @@
throw new XAssertionFailed("getDescriptors failed." + type +
" is invalid");
}
}
-
+
public int getType() {
return getType(Thread.currentThread());
}
-
+
public int getType(Thread current) {
if (activeWriter == current) {
return WRITE_LOCK;
@@ -146,13 +148,13 @@
}
return NO_LOCK;
}
-
+
/**
** @return current thread's lock type that has been released by this
method.
**/
public int release(boolean commit) {
Thread current;
-
+
current = Thread.currentThread();
if (current == activeWriter) {
activeWriter = null;
@@ -174,23 +176,32 @@
}
return NO_LOCK;
}
-
+
/**
** @return true if there is any thread with lock type != NO_LOCK
**/
public boolean isLocked() {
return activeWriter != null || activeReader.size() > 0;
}
-
+
public String toString() {
String activeWriterName =
(activeWriter!=null)?activeWriter.getName():"NULL";
- return "TLock[uuri=" + readerDesc.getUuri() + ", hashCode=" +
Integer.toHexString(hashCode())
- + ", writer=" + activeWriterName + ", reader=" + activeReader +
", waiting=" + waitingWriter
- + "]";
+ List activeReaderList = new ArrayList(activeReader){
+ public String toString(){
+ String result = "[";
+ Iterator iter = this.iterator();
+ while (iter.hasNext()) {
+ result = result + ((Thread)iter.next()).getName() + ",";
+ }
+ return result + "]";
+ }};
+
+ return "TLock[uuri="+readerDesc.getUuri()+",
hashCode="+Integer.toHexString(hashCode())
+ +", writer="+activeWriterName+", reader="+activeReaderList+",
waiting="+waitingWriter+"]";
}
-
+
//--
-
+
/**
** Obtains a read lock for the current thread.
** The lock will persist till end of transaction.
@@ -199,7 +210,7 @@
**/
private int acquireReader() throws XTLockedException {
Thread current;
-
+
current = Thread.currentThread();
if (current == activeWriter) {
//logSuccess("acquireReader: already write locked");
@@ -214,7 +225,7 @@
logSuccess("+r");
return NO_LOCK;
}
-
+
/**
** Obtains a write lock for the current thread.
** The lock will persist til end of transaction.
@@ -223,7 +234,7 @@
**/
private int acquireWriter() throws XTLockedException {
Thread current;
-
+
current = Thread.currentThread();
if (current == activeWriter) {
//logSuccess("acquireWriter: already write locked");
@@ -249,11 +260,12 @@
return NO_LOCK;
}
}
-
+
private void awaitReader() throws XTLockedException {
long started;
long remaining;
-
+ long timeout = tlockSettings.getTimeout();
+
if (allowReader()) {
return;
}
@@ -262,7 +274,7 @@
logSuccess("?r");
if( logger.isLoggable(Level.FINE) )
logger.fine( "awaitReader has to wait for lock "+ toString()
+
- " [timeout: "+(remaining/1000)+" sec]" );
+ " [timeout: "+(remaining/1000)+" sec]" );
try {
sync.wait(remaining);
} catch (InterruptedException e) {
@@ -274,20 +286,21 @@
}
throw timedOut();
}
-
+
private void awaitWriter() throws XTLockedException {
long started;
long remaining;
-
+ long timeout = tlockSettings.getTimeout();
+
if (allowWriter()) {
return;
}
started = System.currentTimeMillis();
- for (remaining = timeout; remaining > 0; remaining -=
System.currentTimeMillis() - started) {
+ for (remaining = timeout; remaining > 0; remaining = timeout -
(System.currentTimeMillis() - started)) {
logSuccess("?w");
if( logger.isLoggable(Level.FINE) )
logger.fine( "awaitWriter has to wait for lock "+ toString()
+
- " [timeout: "+(remaining/1000)+" sec]" );
+ " [timeout: "+(remaining/1000)+" sec]" );
try {
sync.wait(remaining);
} catch (InterruptedException e) {
@@ -299,14 +312,20 @@
}
throw timedOut();
}
-
+
private boolean allowReader() {
+ if (tlockSettings.getIsolationLevel() ==
XTLockSettings.READ_COMMITTED) {
+ return true;
+ }
return activeWriter == null && waitingWriter == 0;
}
-
+
private boolean allowWriter() {
if (activeWriter != null) {
- return false;
+ return activeWriter == Thread.currentThread();
+ }
+ if (tlockSettings.getIsolationLevel() ==
XTLockSettings.READ_COMMITTED) {
+ return true;
}
switch (activeReader.size()) {
case 0:
@@ -317,58 +336,33 @@
return false;
}
}
-
+
private XTLockedException timedOut() {
if( logger.isLoggable(Level.FINE) )
logger.fine( "TLock wait timed out: "+toString());
-
+
logSuccess("##");
return new XTLockedException( "TLock wait timed out: "+toString());
}
-
+
private void logSuccess(String operation) {
-// printlnSuccess(operation);
+ if ("true".equalsIgnoreCase(Domain.getParameter("debug_tlock",
"false"))) {
+ printlnSuccess(operation);
+ }
if( logger.isLoggable(Level.FINE) ) {
logger.fine(CLASSNAME, "["+Thread.currentThread().getName()+
"]", operation + " success:" + toString());
}
}
-
-
-
+
+
+
private void printlnSuccess(String operation) {
- String activeWriterName =
(activeWriter!=null)?activeWriter.getName():"NULL";
- List activeReaderList = new ArrayList(activeReader){
- public String toString(){
- String result = "[";
- Iterator iter = this.iterator();
- while (iter.hasNext())
- {
- result = result + ((Thread)iter.next()).getName() + ",";
- }
- return result + "]";
- }};
-
- String uri = readerDesc.getUuri();
-
-// try { uri =
XNodeRevisionDescriptor.getOneUri((IDescriptorsHandler)sync,
readerDesc.getUuri()); }
-// catch (Throwable e) { }
-
- if (operation.equals("##")) {
-
- System.out.println(" *** " +
- Thread.currentThread().getName() + " \t" +
- operation + " " +
- "uri=" + uri
- + ", writer=" + activeWriterName + ", reader=" +
activeReaderList + ", waiting=" + waitingWriter
- );
-// if (operation.equals("##")) {
- // TODO: do some more reporting [in the future]
- }
+ System.out.println("---< "+operation+" >---
["+Thread.currentThread().getName()+"] "+toString());
}
-
-
-
-
-
+
+
+
+
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]