superman
7 years ago
164 changed files with 41211 additions and 6 deletions
@ -0,0 +1,118 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* A base implementation of <code>KeyedPooledObjectFactory</code>. |
||||
* <p> |
||||
* All operations defined here are essentially no-op's. |
||||
* </p> |
||||
* This class is immutable, and therefore thread-safe. |
||||
* |
||||
* @see KeyedPooledObjectFactory |
||||
* |
||||
* @param <K> The type of keys managed by this factory. |
||||
* @param <V> Type of element managed by this factory. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public abstract class BaseKeyedPooledObjectFactory<K,V> extends BaseObject |
||||
implements KeyedPooledObjectFactory<K,V> { |
||||
|
||||
/** |
||||
* Create an instance that can be served by the pool. |
||||
* |
||||
* @param key the key used when constructing the object |
||||
* @return an instance that can be served by the pool |
||||
* |
||||
* @throws Exception if there is a problem creating a new instance, |
||||
* this will be propagated to the code requesting an object. |
||||
*/ |
||||
public abstract V create(K key) |
||||
throws Exception; |
||||
|
||||
/** |
||||
* Wrap the provided instance with an implementation of |
||||
* {@link PooledObject}. |
||||
* |
||||
* @param value the instance to wrap |
||||
* |
||||
* @return The provided instance, wrapped by a {@link PooledObject} |
||||
*/ |
||||
public abstract PooledObject<V> wrap(V value); |
||||
|
||||
@Override |
||||
public PooledObject<V> makeObject(final K key) throws Exception { |
||||
return wrap(create(key)); |
||||
} |
||||
|
||||
/** |
||||
* Destroy an instance no longer needed by the pool. |
||||
* <p> |
||||
* The default implementation is a no-op. |
||||
* |
||||
* @param key the key used when selecting the instance |
||||
* @param p a {@code PooledObject} wrapping the instance to be destroyed |
||||
*/ |
||||
@Override |
||||
public void destroyObject(final K key, final PooledObject<V> p) |
||||
throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
|
||||
/** |
||||
* Ensures that the instance is safe to be returned by the pool. |
||||
* <p> |
||||
* The default implementation always returns {@code true}. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be validated |
||||
* @return always <code>true</code> in the default implementation |
||||
*/ |
||||
@Override |
||||
public boolean validateObject(final K key, final PooledObject<V> p) { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Reinitialize an instance to be returned by the pool. |
||||
* <p> |
||||
* The default implementation is a no-op. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be activated |
||||
*/ |
||||
@Override |
||||
public void activateObject(final K key, final PooledObject<V> p) |
||||
throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
|
||||
/** |
||||
* Uninitialize an instance to be returned to the idle object pool. |
||||
* <p> |
||||
* The default implementation is a no-op. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be passivated |
||||
*/ |
||||
@Override |
||||
public void passivateObject(final K key, final PooledObject<V> p) |
||||
throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* A base class for common functionality. |
||||
* |
||||
* @since 2.4.3 |
||||
*/ |
||||
public abstract class BaseObject { |
||||
|
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append(getClass().getSimpleName()); |
||||
builder.append(" ["); |
||||
toStringAppendFields(builder); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Used by sub-classes to include the fields defined by the sub-class in the |
||||
* {@link #toString()} output. |
||||
* |
||||
* @param builder Field names and values are appended to this object |
||||
*/ |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
// do nothing by default, needed for b/w compatibility.
|
||||
} |
||||
} |
@ -0,0 +1,125 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* A simple base implementation of {@link ObjectPool}. |
||||
* Optional operations are implemented to either do nothing, return a value |
||||
* indicating it is unsupported or throw {@link UnsupportedOperationException}. |
||||
* <p> |
||||
* This class is intended to be thread-safe. |
||||
* |
||||
* @param <T> Type of element pooled in this pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public abstract class BaseObjectPool<T> extends BaseObject implements ObjectPool<T> { |
||||
|
||||
@Override |
||||
public abstract T borrowObject() throws Exception; |
||||
|
||||
@Override |
||||
public abstract void returnObject(T obj) throws Exception; |
||||
|
||||
@Override |
||||
public abstract void invalidateObject(T obj) throws Exception; |
||||
|
||||
/** |
||||
* Not supported in this base implementation. |
||||
* |
||||
* @return a negative value. |
||||
*/ |
||||
@Override |
||||
public int getNumIdle() { |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* Not supported in this base implementation. |
||||
* |
||||
* @return a negative value. |
||||
*/ |
||||
@Override |
||||
public int getNumActive() { |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* Not supported in this base implementation. |
||||
* |
||||
* @throws UnsupportedOperationException if the pool does not implement this |
||||
* method |
||||
*/ |
||||
@Override |
||||
public void clear() throws Exception, UnsupportedOperationException { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
/** |
||||
* Not supported in this base implementation. Subclasses should override |
||||
* this behavior. |
||||
* |
||||
* @throws UnsupportedOperationException if the pool does not implement this |
||||
* method |
||||
*/ |
||||
@Override |
||||
public void addObject() throws Exception, UnsupportedOperationException { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* <p> |
||||
* This affects the behavior of <code>isClosed</code> and |
||||
* <code>assertOpen</code>. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
closed = true; |
||||
} |
||||
|
||||
/** |
||||
* Has this pool instance been closed. |
||||
* |
||||
* @return <code>true</code> when this pool has been closed. |
||||
*/ |
||||
public final boolean isClosed() { |
||||
return closed; |
||||
} |
||||
|
||||
/** |
||||
* Throws an <code>IllegalStateException</code> when this pool has been |
||||
* closed. |
||||
* |
||||
* @throws IllegalStateException when this pool has been closed. |
||||
* |
||||
* @see #isClosed() |
||||
*/ |
||||
protected final void assertOpen() throws IllegalStateException { |
||||
if (isClosed()) { |
||||
throw new IllegalStateException("Pool not open"); |
||||
} |
||||
} |
||||
|
||||
private volatile boolean closed = false; |
||||
|
||||
@Override |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
builder.append("closed="); |
||||
builder.append(closed); |
||||
} |
||||
} |
@ -0,0 +1,104 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* A base implementation of <code>PoolableObjectFactory</code>. |
||||
* <p> |
||||
* All operations defined here are essentially no-op's. |
||||
* <p> |
||||
* This class is immutable, and therefore thread-safe |
||||
* |
||||
* @param <T> Type of element managed in this factory. |
||||
* |
||||
* @see PooledObjectFactory |
||||
* @see BaseKeyedPooledObjectFactory |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public abstract class BasePooledObjectFactory<T> extends BaseObject implements PooledObjectFactory<T> { |
||||
/** |
||||
* Creates an object instance, to be wrapped in a {@link PooledObject}. |
||||
* <p>This method <strong>must</strong> support concurrent, multi-threaded |
||||
* activation.</p> |
||||
* |
||||
* @return an instance to be served by the pool |
||||
* |
||||
* @throws Exception if there is a problem creating a new instance, |
||||
* this will be propagated to the code requesting an object. |
||||
*/ |
||||
public abstract T create() throws Exception; |
||||
|
||||
/** |
||||
* Wrap the provided instance with an implementation of |
||||
* {@link PooledObject}. |
||||
* |
||||
* @param obj the instance to wrap |
||||
* |
||||
* @return The provided instance, wrapped by a {@link PooledObject} |
||||
*/ |
||||
public abstract PooledObject<T> wrap(T obj); |
||||
|
||||
@Override |
||||
public PooledObject<T> makeObject() throws Exception { |
||||
return wrap(create()); |
||||
} |
||||
|
||||
/** |
||||
* No-op. |
||||
* |
||||
* @param p ignored |
||||
*/ |
||||
@Override |
||||
public void destroyObject(final PooledObject<T> p) |
||||
throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
|
||||
/** |
||||
* This implementation always returns {@code true}. |
||||
* |
||||
* @param p ignored |
||||
* |
||||
* @return {@code true} |
||||
*/ |
||||
@Override |
||||
public boolean validateObject(final PooledObject<T> p) { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* No-op. |
||||
* |
||||
* @param p ignored |
||||
*/ |
||||
@Override |
||||
public void activateObject(final PooledObject<T> p) throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
|
||||
/** |
||||
* No-op. |
||||
* |
||||
* @param p ignored |
||||
*/ |
||||
@Override |
||||
public void passivateObject(final PooledObject<T> p) |
||||
throws Exception { |
||||
// The default implementation is a no-op.
|
||||
} |
||||
} |
@ -0,0 +1,230 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
/** |
||||
* A "keyed" pooling interface. |
||||
* <p> |
||||
* A keyed pool maintains a pool of instances for each key value. |
||||
* <p> |
||||
* Example of use: |
||||
* <pre style="border:solid thin; padding: 1ex;" |
||||
* > Object obj = <code style="color:#00C">null</code>; |
||||
* Object key = <code style="color:#C00">"Key"</code>; |
||||
* |
||||
* <code style="color:#00C">try</code> { |
||||
* obj = pool.borrowObject(key); |
||||
* <code style="color:#0C0">//...use the object...</code>
|
||||
* } <code style="color:#00C">catch</code>(Exception e) { |
||||
* <code style="color:#0C0">// invalidate the object</code>
|
||||
* pool.invalidateObject(key, obj); |
||||
* <code style="color:#0C0">// do not return the object to the pool twice</code>
|
||||
* obj = <code style="color:#00C">null</code>; |
||||
* } <code style="color:#00C">finally</code> { |
||||
* <code style="color:#0C0">// make sure the object is returned to the pool</code>
|
||||
* <code style="color:#00C">if</code>(<code style="color:#00C">null</code> != obj) { |
||||
* pool.returnObject(key, obj); |
||||
* } |
||||
* }</pre> |
||||
* <p> |
||||
* {@link KeyedObjectPool} implementations <i>may</i> choose to store at most |
||||
* one instance per key value, or may choose to maintain a pool of instances |
||||
* for each key (essentially creating a {@link java.util.Map Map} of |
||||
* {@link ObjectPool pools}). |
||||
* <p> |
||||
* See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool |
||||
* GenericKeyedObjectPool} for an implementation. |
||||
* |
||||
* @param <K> The type of keys maintained by this pool. |
||||
* @param <V> Type of element pooled in this pool. |
||||
* |
||||
* @see KeyedPooledObjectFactory |
||||
* @see ObjectPool |
||||
* @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface KeyedObjectPool<K,V> extends Closeable { |
||||
/** |
||||
* Obtains an instance from this pool for the specified <code>key</code>. |
||||
* <p> |
||||
* Instances returned from this method will have been either newly created |
||||
* with {@link KeyedPooledObjectFactory#makeObject makeObject} or will be |
||||
* a previously idle object and have been activated with |
||||
* {@link KeyedPooledObjectFactory#activateObject activateObject} and then |
||||
* (optionally) validated with |
||||
* {@link KeyedPooledObjectFactory#validateObject validateObject}. |
||||
* <p> |
||||
* By contract, clients <strong>must</strong> return the borrowed object |
||||
* using {@link #returnObject returnObject}, |
||||
* {@link #invalidateObject invalidateObject}, or a related method as |
||||
* defined in an implementation or sub-interface, using a <code>key</code> |
||||
* that is {@link Object#equals equivalent} to the one used to borrow the |
||||
* instance in the first place. |
||||
* <p> |
||||
* The behaviour of this method when the pool has been exhausted is not |
||||
* strictly specified (although it may be specified by implementations). |
||||
* |
||||
* @param key the key used to obtain the object |
||||
* |
||||
* @return an instance from this pool. |
||||
* |
||||
* @throws IllegalStateException |
||||
* after {@link #close close} has been called on this pool |
||||
* @throws Exception |
||||
* when {@link KeyedPooledObjectFactory#makeObject |
||||
* makeObject} throws an exception |
||||
* @throws NoSuchElementException |
||||
* when the pool is exhausted and cannot or will not return |
||||
* another instance |
||||
*/ |
||||
V borrowObject(K key) throws Exception, NoSuchElementException, IllegalStateException; |
||||
|
||||
/** |
||||
* Return an instance to the pool. By contract, <code>obj</code> |
||||
* <strong>must</strong> have been obtained using |
||||
* {@link #borrowObject borrowObject} or a related method as defined in an |
||||
* implementation or sub-interface using a <code>key</code> that is |
||||
* equivalent to the one used to borrow the instance in the first place. |
||||
* |
||||
* @param key the key used to obtain the object |
||||
* @param obj a {@link #borrowObject borrowed} instance to be returned. |
||||
* |
||||
* @throws IllegalStateException |
||||
* if an attempt is made to return an object to the pool that |
||||
* is in any state other than allocated (i.e. borrowed). |
||||
* Attempting to return an object more than once or attempting |
||||
* to return an object that was never borrowed from the pool |
||||
* will trigger this exception. |
||||
* |
||||
* @throws Exception if an instance cannot be returned to the pool |
||||
*/ |
||||
void returnObject(K key, V obj) throws Exception; |
||||
|
||||
/** |
||||
* Invalidates an object from the pool. |
||||
* <p> |
||||
* By contract, <code>obj</code> <strong>must</strong> have been obtained |
||||
* using {@link #borrowObject borrowObject} or a related method as defined |
||||
* in an implementation or sub-interface using a <code>key</code> that is |
||||
* equivalent to the one used to borrow the <code>Object</code> in the first |
||||
* place. |
||||
* <p> |
||||
* This method should be used when an object that has been borrowed is |
||||
* determined (due to an exception or other problem) to be invalid. |
||||
* |
||||
* @param key the key used to obtain the object |
||||
* @param obj a {@link #borrowObject borrowed} instance to be returned. |
||||
* |
||||
* @throws Exception if the instance cannot be invalidated |
||||
*/ |
||||
void invalidateObject(K key, V obj) throws Exception; |
||||
|
||||
/** |
||||
* Create an object using the {@link KeyedPooledObjectFactory factory} or |
||||
* other implementation dependent mechanism, passivate it, and then place it |
||||
* in the idle object pool. <code>addObject</code> is useful for |
||||
* "pre-loading" a pool with idle objects (Optional operation). |
||||
* |
||||
* @param key the key a new instance should be added to |
||||
* |
||||
* @throws Exception |
||||
* when {@link KeyedPooledObjectFactory#makeObject} fails. |
||||
* @throws IllegalStateException |
||||
* after {@link #close} has been called on this pool. |
||||
* @throws UnsupportedOperationException |
||||
* when this pool cannot add new idle objects. |
||||
*/ |
||||
void addObject(K key) throws Exception, IllegalStateException, |
||||
UnsupportedOperationException; |
||||
|
||||
/** |
||||
* Returns the number of instances corresponding to the given |
||||
* <code>key</code> currently idle in this pool. Returns a negative value if |
||||
* this information is not available. |
||||
* |
||||
* @param key the key to query |
||||
* @return the number of instances corresponding to the given |
||||
* <code>key</code> currently idle in this pool. |
||||
*/ |
||||
int getNumIdle(K key); |
||||
|
||||
/** |
||||
* Returns the number of instances currently borrowed from but not yet |
||||
* returned to the pool corresponding to the given <code>key</code>. |
||||
* Returns a negative value if this information is not available. |
||||
* |
||||
* @param key the key to query |
||||
* @return the number of instances currently borrowed from but not yet |
||||
* returned to the pool corresponding to the given <code>key</code>. |
||||
= */ |
||||
int getNumActive(K key); |
||||
|
||||
/** |
||||
* Returns the total number of instances currently idle in this pool. |
||||
* Returns a negative value if this information is not available. |
||||
* @return the total number of instances currently idle in this pool. |
||||
= */ |
||||
int getNumIdle(); |
||||
|
||||
/** |
||||
* Returns the total number of instances current borrowed from this pool but |
||||
* not yet returned. Returns a negative value if this information is not |
||||
* available. |
||||
* @return the total number of instances current borrowed from this pool but |
||||
* not yet returned. |
||||
*/ |
||||
int getNumActive(); |
||||
|
||||
/** |
||||
* Clears the pool, removing all pooled instances (optional operation). |
||||
* |
||||
* @throws UnsupportedOperationException when this implementation doesn't |
||||
* support the operation |
||||
* |
||||
* @throws Exception if the pool cannot be cleared |
||||
*/ |
||||
void clear() throws Exception, UnsupportedOperationException; |
||||
|
||||
/** |
||||
* Clears the specified pool, removing all pooled instances corresponding to |
||||
* the given <code>key</code> (optional operation). |
||||
* |
||||
* @param key the key to clear |
||||
* |
||||
* @throws UnsupportedOperationException when this implementation doesn't |
||||
* support the operation |
||||
* |
||||
* @throws Exception if the key cannot be cleared |
||||
*/ |
||||
void clear(K key) throws Exception, UnsupportedOperationException; |
||||
|
||||
/** |
||||
* Close this pool, and free any resources associated with it. |
||||
* <p> |
||||
* Calling {@link #addObject addObject} or |
||||
* {@link #borrowObject borrowObject} after invoking this method on a pool |
||||
* will cause them to throw an {@link IllegalStateException}. |
||||
* <p> |
||||
* Implementations should silently fail if not all resources can be freed. |
||||
*/ |
||||
@Override |
||||
void close(); |
||||
} |
@ -0,0 +1,148 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* An interface defining life-cycle methods for |
||||
* instances to be served by a {@link KeyedObjectPool}. |
||||
* <p> |
||||
* By contract, when an {@link KeyedObjectPool} |
||||
* delegates to a {@link KeyedPooledObjectFactory}, |
||||
* <ol> |
||||
* <li> |
||||
* {@link #makeObject} is called whenever a new instance is needed. |
||||
* </li> |
||||
* <li> |
||||
* {@link #activateObject} is invoked on every instance that has been |
||||
* {@link #passivateObject passivated} before it is |
||||
* {@link KeyedObjectPool#borrowObject borrowed} from the pool. |
||||
* </li> |
||||
* <li> |
||||
* {@link #validateObject} may be invoked on {@link #activateObject activated} |
||||
* instances to make sure they can be |
||||
* {@link KeyedObjectPool#borrowObject borrowed} from the pool. |
||||
* <code>validateObject</code> may also be used to test an |
||||
* instance being {@link KeyedObjectPool#returnObject returned} to the pool |
||||
* before it is {@link #passivateObject passivated}. It will only be invoked |
||||
* on an activated instance. |
||||
* </li> |
||||
* <li> |
||||
* {@link #passivateObject passivateObject} |
||||
* is invoked on every instance when it is returned to the pool. |
||||
* </li> |
||||
* <li> |
||||
* {@link #destroyObject destroyObject} |
||||
* is invoked on every instance when it is being "dropped" from the |
||||
* pool (whether due to the response from <code>validateObject</code>, |
||||
* or for reasons specific to the pool implementation.) There is no |
||||
* guarantee that the instance being destroyed will |
||||
* be considered active, passive or in a generally consistent state. |
||||
* </li> |
||||
* </ol> |
||||
* {@link KeyedPooledObjectFactory} must be thread-safe. The only promise |
||||
* an {@link KeyedObjectPool} makes is that the same instance of an object will |
||||
* not be passed to more than one method of a |
||||
* <code>KeyedPoolableObjectFactory</code> at a time. |
||||
* <p> |
||||
* While clients of a {@link KeyedObjectPool} borrow and return instances of |
||||
* the underlying value type V, the factory methods act on instances of |
||||
* {@link PooledObject PooledObject<V>}. These are the object wrappers that |
||||
* pools use to track and maintain state informations about the objects that |
||||
* they manage. |
||||
* |
||||
* @see KeyedObjectPool |
||||
* @see BaseKeyedPooledObjectFactory |
||||
* |
||||
* @param <K> The type of keys managed by this factory. |
||||
* @param <V> Type of element managed by this factory. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface KeyedPooledObjectFactory<K,V> { |
||||
/** |
||||
* Create an instance that can be served by the pool and |
||||
* wrap it in a {@link PooledObject} to be managed by the pool. |
||||
* |
||||
* @param key the key used when constructing the object |
||||
* |
||||
* @return a {@code PooledObject} wrapping an instance that can |
||||
* be served by the pool. |
||||
* |
||||
* @throws Exception if there is a problem creating a new instance, |
||||
* this will be propagated to the code requesting an object. |
||||
*/ |
||||
PooledObject<V> makeObject(K key) throws Exception; |
||||
|
||||
/** |
||||
* Destroy an instance no longer needed by the pool. |
||||
* <p> |
||||
* It is important for implementations of this method to be aware that there |
||||
* is no guarantee about what state <code>obj</code> will be in and the |
||||
* implementation should be prepared to handle unexpected errors. |
||||
* <p> |
||||
* Also, an implementation must take in to consideration that instances lost |
||||
* to the garbage collector may never be destroyed. |
||||
* |
||||
* @param key the key used when selecting the instance |
||||
* @param p a {@code PooledObject} wrapping the instance to be destroyed |
||||
* |
||||
* @throws Exception should be avoided as it may be swallowed by |
||||
* the pool implementation. |
||||
* |
||||
* @see #validateObject |
||||
* @see KeyedObjectPool#invalidateObject |
||||
*/ |
||||
void destroyObject(K key, PooledObject<V> p) throws Exception; |
||||
|
||||
/** |
||||
* Ensures that the instance is safe to be returned by the pool. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be validated |
||||
* |
||||
* @return <code>false</code> if <code>obj</code> is not valid and should |
||||
* be dropped from the pool, <code>true</code> otherwise. |
||||
*/ |
||||
boolean validateObject(K key, PooledObject<V> p); |
||||
|
||||
/** |
||||
* Reinitialize an instance to be returned by the pool. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be activated |
||||
* |
||||
* @throws Exception if there is a problem activating <code>obj</code>, |
||||
* this exception may be swallowed by the pool. |
||||
* |
||||
* @see #destroyObject |
||||
*/ |
||||
void activateObject(K key, PooledObject<V> p) throws Exception; |
||||
|
||||
/** |
||||
* Uninitialize an instance to be returned to the idle object pool. |
||||
* |
||||
* @param key the key used when selecting the object |
||||
* @param p a {@code PooledObject} wrapping the instance to be passivated |
||||
* |
||||
* @throws Exception if there is a problem passivating <code>obj</code>, |
||||
* this exception may be swallowed by the pool. |
||||
* |
||||
* @see #destroyObject |
||||
*/ |
||||
void passivateObject(K key, PooledObject<V> p) throws Exception; |
||||
} |
||||
|
@ -0,0 +1,178 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
/** |
||||
* A pooling simple interface. |
||||
* <p> |
||||
* Example of use: |
||||
* <pre style="border:solid thin; padding: 1ex;" |
||||
* > Object obj = <code style="color:#00C">null</code>; |
||||
* |
||||
* <code style="color:#00C">try</code> { |
||||
* obj = pool.borrowObject(); |
||||
* <code style="color:#00C">try</code> { |
||||
* <code style="color:#0C0">//...use the object...</code>
|
||||
* } <code style="color:#00C">catch</code>(Exception e) { |
||||
* <code style="color:#0C0">// invalidate the object</code>
|
||||
* pool.invalidateObject(obj); |
||||
* <code style="color:#0C0">// do not return the object to the pool twice</code>
|
||||
* obj = <code style="color:#00C">null</code>; |
||||
* } <code style="color:#00C">finally</code> { |
||||
* <code style="color:#0C0">// make sure the object is returned to the pool</code>
|
||||
* <code style="color:#00C">if</code>(<code style="color:#00C">null</code> != obj) { |
||||
* pool.returnObject(obj); |
||||
* } |
||||
* } |
||||
* } <code style="color:#00C">catch</code>(Exception e) { |
||||
* <code style="color:#0C0">// failed to borrow an object</code>
|
||||
* }</pre> |
||||
* <p> |
||||
* See {@link BaseObjectPool} for a simple base implementation. |
||||
* |
||||
* @param <T> Type of element pooled in this pool. |
||||
* |
||||
* @see PooledObjectFactory |
||||
* @see KeyedObjectPool |
||||
* @see BaseObjectPool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface ObjectPool<T> extends Closeable { |
||||
/** |
||||
* Obtains an instance from this pool. |
||||
* <p> |
||||
* Instances returned from this method will have been either newly created |
||||
* with {@link PooledObjectFactory#makeObject} or will be a previously |
||||
* idle object and have been activated with |
||||
* {@link PooledObjectFactory#activateObject} and then validated with |
||||
* {@link PooledObjectFactory#validateObject}. |
||||
* <p> |
||||
* By contract, clients <strong>must</strong> return the borrowed instance |
||||
* using {@link #returnObject}, {@link #invalidateObject}, or a related |
||||
* method as defined in an implementation or sub-interface. |
||||
* <p> |
||||
* The behaviour of this method when the pool has been exhausted |
||||
* is not strictly specified (although it may be specified by |
||||
* implementations). |
||||
* |
||||
* @return an instance from this pool. |
||||
* |
||||
* @throws IllegalStateException |
||||
* after {@link #close close} has been called on this pool. |
||||
* @throws Exception |
||||
* when {@link PooledObjectFactory#makeObject} throws an |
||||
* exception. |
||||
* @throws NoSuchElementException |
||||
* when the pool is exhausted and cannot or will not return |
||||
* another instance. |
||||
*/ |
||||
T borrowObject() throws Exception, NoSuchElementException, |
||||
IllegalStateException; |
||||
|
||||
/** |
||||
* Return an instance to the pool. By contract, <code>obj</code> |
||||
* <strong>must</strong> have been obtained using {@link #borrowObject()} or |
||||
* a related method as defined in an implementation or sub-interface. |
||||
* |
||||
* @param obj a {@link #borrowObject borrowed} instance to be returned. |
||||
* |
||||
* @throws IllegalStateException |
||||
* if an attempt is made to return an object to the pool that |
||||
* is in any state other than allocated (i.e. borrowed). |
||||
* Attempting to return an object more than once or attempting |
||||
* to return an object that was never borrowed from the pool |
||||
* will trigger this exception. |
||||
* |
||||
* @throws Exception if an instance cannot be returned to the pool |
||||
*/ |
||||
void returnObject(T obj) throws Exception; |
||||
|
||||
/** |
||||
* Invalidates an object from the pool. |
||||
* <p> |
||||
* By contract, <code>obj</code> <strong>must</strong> have been obtained |
||||
* using {@link #borrowObject} or a related method as defined in an |
||||
* implementation or sub-interface. |
||||
* <p> |
||||
* This method should be used when an object that has been borrowed is |
||||
* determined (due to an exception or other problem) to be invalid. |
||||
* |
||||
* @param obj a {@link #borrowObject borrowed} instance to be disposed. |
||||
* |
||||
* @throws Exception if the instance cannot be invalidated |
||||
*/ |
||||
void invalidateObject(T obj) throws Exception; |
||||
|
||||
/** |
||||
* Create an object using the {@link PooledObjectFactory factory} or other |
||||
* implementation dependent mechanism, passivate it, and then place it in |
||||
* the idle object pool. <code>addObject</code> is useful for "pre-loading" |
||||
* a pool with idle objects. (Optional operation). |
||||
* |
||||
* @throws Exception |
||||
* when {@link PooledObjectFactory#makeObject} fails. |
||||
* @throws IllegalStateException |
||||
* after {@link #close} has been called on this pool. |
||||
* @throws UnsupportedOperationException |
||||
* when this pool cannot add new idle objects. |
||||
*/ |
||||
void addObject() throws Exception, IllegalStateException, |
||||
UnsupportedOperationException; |
||||
|
||||
/** |
||||
* Return the number of instances currently idle in this pool. This may be |
||||
* considered an approximation of the number of objects that can be |
||||
* {@link #borrowObject borrowed} without creating any new instances. |
||||
* Returns a negative value if this information is not available. |
||||
* @return the number of instances currently idle in this pool. |
||||
*/ |
||||
int getNumIdle(); |
||||
|
||||
/** |
||||
* Return the number of instances currently borrowed from this pool. Returns |
||||
* a negative value if this information is not available. |
||||
* @return the number of instances currently borrowed from this pool. |
||||
*/ |
||||
int getNumActive(); |
||||
|
||||
/** |
||||
* Clears any objects sitting idle in the pool, releasing any associated |
||||
* resources (optional operation). Idle objects cleared must be |
||||
* {@link PooledObjectFactory#destroyObject(PooledObject)}. |
||||
* |
||||
* @throws UnsupportedOperationException |
||||
* if this implementation does not support the operation |
||||
* |
||||
* @throws Exception if the pool cannot be cleared |
||||
*/ |
||||
void clear() throws Exception, UnsupportedOperationException; |
||||
|
||||
/** |
||||
* Close this pool, and free any resources associated with it. |
||||
* <p> |
||||
* Calling {@link #addObject} or {@link #borrowObject} after invoking this |
||||
* method on a pool will cause them to throw an {@link IllegalStateException}. |
||||
* <p> |
||||
* Implementations should silently fail if not all resources can be freed. |
||||
*/ |
||||
@Override |
||||
void close(); |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,218 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.util.Deque; |
||||
|
||||
/** |
||||
* Defines the wrapper that is used to track the additional information, such as |
||||
* state, for the pooled objects. |
||||
* <p> |
||||
* Implementations of this class are required to be thread-safe. |
||||
* |
||||
* @param <T> the type of object in the pool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface PooledObject<T> extends Comparable<PooledObject<T>> { |
||||
|
||||
/** |
||||
* Obtain the underlying object that is wrapped by this instance of |
||||
* {@link PooledObject}. |
||||
* |
||||
* @return The wrapped object |
||||
*/ |
||||
T getObject(); |
||||
|
||||
/** |
||||
* Obtain the time (using the same basis as |
||||
* {@link System#currentTimeMillis()}) that this object was created. |
||||
* |
||||
* @return The creation time for the wrapped object |
||||
*/ |
||||
long getCreateTime(); |
||||
|
||||
/** |
||||
* Obtain the time in milliseconds that this object last spent in the |
||||
* active state (it may still be active in which case subsequent calls will |
||||
* return an increased value). |
||||
* |
||||
* @return The time in milliseconds last spent in the active state |
||||
*/ |
||||
long getActiveTimeMillis(); |
||||
|
||||
/** |
||||
* Obtain the time in milliseconds that this object last spend in the |
||||
* idle state (it may still be idle in which case subsequent calls will |
||||
* return an increased value). |
||||
* |
||||
* @return The time in milliseconds last spent in the idle state |
||||
*/ |
||||
long getIdleTimeMillis(); |
||||
|
||||
/** |
||||
* Obtain the time the wrapped object was last borrowed. |
||||
* |
||||
* @return The time the object was last borrowed |
||||
*/ |
||||
long getLastBorrowTime(); |
||||
|
||||
/** |
||||
* Obtain the time the wrapped object was last returned. |
||||
* |
||||
* @return The time the object was last returned |
||||
*/ |
||||
long getLastReturnTime(); |
||||
|
||||
/** |
||||
* Return an estimate of the last time this object was used. If the class
|
||||
* of the pooled object implements {@link TrackedUse}, what is returned is |
||||
* the maximum of {@link TrackedUse#getLastUsed()} and |
||||
* {@link #getLastBorrowTime()}; otherwise this method gives the same |
||||
* value as {@link #getLastBorrowTime()}. |
||||
* |
||||
* @return the last time this object was used |
||||
*/ |
||||
long getLastUsedTime(); |
||||
|
||||
/** |
||||
* Orders instances based on idle time - i.e. the length of time since the |
||||
* instance was returned to the pool. Used by the GKOP idle object evictor. |
||||
*<p> |
||||
* Note: This class has a natural ordering that is inconsistent with |
||||
* equals if distinct objects have the same identity hash code. |
||||
* <p> |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
int compareTo(PooledObject<T> other); |
||||
|
||||
@Override |
||||
boolean equals(Object obj); |
||||
|
||||
@Override |
||||
int hashCode(); |
||||
|
||||
/** |
||||
* Provides a String form of the wrapper for debug purposes. The format is |
||||
* not fixed and may change at any time. |
||||
* <p> |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
String toString(); |
||||
|
||||
/** |
||||
* Attempt to place the pooled object in the |
||||
* {@link PooledObjectState#EVICTION} state. |
||||
* |
||||
* @return <code>true</code> if the object was placed in the |
||||
* {@link PooledObjectState#EVICTION} state otherwise |
||||
* <code>false</code> |
||||
*/ |
||||
boolean startEvictionTest(); |
||||
|
||||
/** |
||||
* Called to inform the object that the eviction test has ended. |
||||
* |
||||
* @param idleQueue The queue of idle objects to which the object should be |
||||
* returned |
||||
* |
||||
* @return Currently not used |
||||
*/ |
||||
boolean endEvictionTest(Deque<PooledObject<T>> idleQueue); |
||||
|
||||
/** |
||||
* Allocates the object. |
||||
* |
||||
* @return {@code true} if the original state was {@link PooledObjectState#IDLE IDLE} |
||||
*/ |
||||
boolean allocate(); |
||||
|
||||
/** |
||||
* Deallocates the object and sets it {@link PooledObjectState#IDLE IDLE} |
||||
* if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED}. |
||||
* |
||||
* @return {@code true} if the state was {@link PooledObjectState#ALLOCATED ALLOCATED} |
||||
*/ |
||||
boolean deallocate(); |
||||
|
||||
/** |
||||
* Sets the state to {@link PooledObjectState#INVALID INVALID} |
||||
*/ |
||||
void invalidate(); |
||||
|
||||
/** |
||||
* Is abandoned object tracking being used? If this is true the |
||||
* implementation will need to record the stack trace of the last caller to |
||||
* borrow this object. |
||||
* |
||||
* @param logAbandoned The new configuration setting for abandoned |
||||
* object tracking |
||||
*/ |
||||
void setLogAbandoned(boolean logAbandoned); |
||||
|
||||
// TODO: uncomment in 3.0 (API compatibility)
|
||||
// /**
|
||||
// * Configures the stack trace generation strategy based on whether or not fully
|
||||
// * detailed stack traces are required. When set to false, abandoned logs may
|
||||
// * only include caller class information rather than method names, line numbers,
|
||||
// * and other normal metadata available in a full stack trace.
|
||||
// *
|
||||
// * @param requireFullStackTrace the new configuration setting for abandoned object
|
||||
// * logging
|
||||
// */
|
||||
// void setRequireFullStackTrace(boolean requireFullStackTrace);
|
||||
|
||||
/** |
||||
* Record the current stack trace as the last time the object was used. |
||||
*/ |
||||
void use(); |
||||
|
||||
/** |
||||
* Prints the stack trace of the code that borrowed this pooled object and |
||||
* the stack trace of the last code to use this object (if available) to |
||||
* the supplied writer. |
||||
* |
||||
* @param writer The destination for the debug output |
||||
*/ |
||||
void printStackTrace(PrintWriter writer); |
||||
|
||||
/** |
||||
* Returns the state of this object. |
||||
* @return state |
||||
*/ |
||||
PooledObjectState getState(); |
||||
|
||||
/** |
||||
* Marks the pooled object as abandoned. |
||||
*/ |
||||
void markAbandoned(); |
||||
|
||||
/** |
||||
* Marks the object as returning to the pool. |
||||
*/ |
||||
void markReturning(); |
||||
|
||||
// TODO: Uncomment this for version 3 (can't add it to 2.x as it will break
|
||||
// API compatibility)
|
||||
///**
|
||||
// * Get the number of times this object has been borrowed.
|
||||
// */
|
||||
//long getBorrowedCount();
|
||||
} |
@ -0,0 +1,137 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* An interface defining life-cycle methods for instances to be served by an |
||||
* {@link ObjectPool}. |
||||
* <p> |
||||
* By contract, when an {@link ObjectPool} delegates to a |
||||
* {@link PooledObjectFactory}, |
||||
* <ol> |
||||
* <li> |
||||
* {@link #makeObject} is called whenever a new instance is needed. |
||||
* </li> |
||||
* <li> |
||||
* {@link #activateObject} is invoked on every instance that has been |
||||
* {@link #passivateObject passivated} before it is |
||||
* {@link ObjectPool#borrowObject borrowed} from the pool. |
||||
* </li> |
||||
* <li> |
||||
* {@link #validateObject} may be invoked on {@link #activateObject activated} |
||||
* instances to make sure they can be {@link ObjectPool#borrowObject borrowed} |
||||
* from the pool. {@link #validateObject} may also be used to |
||||
* test an instance being {@link ObjectPool#returnObject returned} to the pool |
||||
* before it is {@link #passivateObject passivated}. It will only be invoked |
||||
* on an activated instance. |
||||
* </li> |
||||
* <li> |
||||
* {@link #passivateObject} is invoked on every instance when it is returned |
||||
* to the pool. |
||||
* </li> |
||||
* <li> |
||||
* {@link #destroyObject} is invoked on every instance when it is being |
||||
* "dropped" from the pool (whether due to the response from |
||||
* {@link #validateObject}, or for reasons specific to the pool |
||||
* implementation.) There is no guarantee that the instance being destroyed |
||||
* will be considered active, passive or in a generally consistent state. |
||||
* </li> |
||||
* </ol> |
||||
* {@link PooledObjectFactory} must be thread-safe. The only promise |
||||
* an {@link ObjectPool} makes is that the same instance of an object will not |
||||
* be passed to more than one method of a <code>PoolableObjectFactory</code> |
||||
* at a time. |
||||
* <p> |
||||
* While clients of a {@link KeyedObjectPool} borrow and return instances of |
||||
* the underlying value type {@code V}, the factory methods act on instances of |
||||
* {@link PooledObject PooledObject<V>}. These are the object wrappers that |
||||
* pools use to track and maintain state information about the objects that |
||||
* they manage. |
||||
* |
||||
* @param <T> Type of element managed in this factory. |
||||
* |
||||
* @see ObjectPool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface PooledObjectFactory<T> { |
||||
/** |
||||
* Create an instance that can be served by the pool and wrap it in a |
||||
* {@link PooledObject} to be managed by the pool. |
||||
* |
||||
* @return a {@code PooledObject} wrapping an instance that can be served by the pool |
||||
* |
||||
* @throws Exception if there is a problem creating a new instance, |
||||
* this will be propagated to the code requesting an object. |
||||
*/ |
||||
PooledObject<T> makeObject() throws Exception; |
||||
|
||||
/** |
||||
* Destroys an instance no longer needed by the pool. |
||||
* <p> |
||||
* It is important for implementations of this method to be aware that there |
||||
* is no guarantee about what state <code>obj</code> will be in and the |
||||
* implementation should be prepared to handle unexpected errors. |
||||
* <p> |
||||
* Also, an implementation must take in to consideration that instances lost |
||||
* to the garbage collector may never be destroyed. |
||||
* </p> |
||||
* |
||||
* @param p a {@code PooledObject} wrapping the instance to be destroyed |
||||
* |
||||
* @throws Exception should be avoided as it may be swallowed by |
||||
* the pool implementation. |
||||
* |
||||
* @see #validateObject |
||||
* @see ObjectPool#invalidateObject |
||||
*/ |
||||
void destroyObject(PooledObject<T> p) throws Exception; |
||||
|
||||
/** |
||||
* Ensures that the instance is safe to be returned by the pool. |
||||
* |
||||
* @param p a {@code PooledObject} wrapping the instance to be validated |
||||
* |
||||
* @return <code>false</code> if <code>obj</code> is not valid and should |
||||
* be dropped from the pool, <code>true</code> otherwise. |
||||
*/ |
||||
boolean validateObject(PooledObject<T> p); |
||||
|
||||
/** |
||||
* Reinitialize an instance to be returned by the pool. |
||||
* |
||||
* @param p a {@code PooledObject} wrapping the instance to be activated |
||||
* |
||||
* @throws Exception if there is a problem activating <code>obj</code>, |
||||
* this exception may be swallowed by the pool. |
||||
* |
||||
* @see #destroyObject |
||||
*/ |
||||
void activateObject(PooledObject<T> p) throws Exception; |
||||
|
||||
/** |
||||
* Uninitialize an instance to be returned to the idle object pool. |
||||
* |
||||
* @param p a {@code PooledObject} wrapping the instance to be passivated |
||||
* |
||||
* @throws Exception if there is a problem passivating <code>obj</code>, |
||||
* this exception may be swallowed by the pool. |
||||
* |
||||
* @see #destroyObject |
||||
*/ |
||||
void passivateObject(PooledObject<T> p) throws Exception; |
||||
} |
@ -0,0 +1,86 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* Provides the possible states that a {@link PooledObject} may be in. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public enum PooledObjectState { |
||||
/** |
||||
* In the queue, not in use. |
||||
*/ |
||||
IDLE, |
||||
|
||||
/** |
||||
* In use. |
||||
*/ |
||||
ALLOCATED, |
||||
|
||||
/** |
||||
* In the queue, currently being tested for possible eviction. |
||||
*/ |
||||
EVICTION, |
||||
|
||||
/** |
||||
* Not in the queue, currently being tested for possible eviction. An |
||||
* attempt to borrow the object was made while being tested which removed it |
||||
* from the queue. It should be returned to the head of the queue once |
||||
* eviction testing completes. |
||||
* TODO: Consider allocating object and ignoring the result of the eviction |
||||
* test. |
||||
*/ |
||||
EVICTION_RETURN_TO_HEAD, |
||||
|
||||
/** |
||||
* In the queue, currently being validated. |
||||
*/ |
||||
VALIDATION, |
||||
|
||||
/** |
||||
* Not in queue, currently being validated. The object was borrowed while |
||||
* being validated and since testOnBorrow was configured, it was removed |
||||
* from the queue and pre-allocated. It should be allocated once validation |
||||
* completes. |
||||
*/ |
||||
VALIDATION_PREALLOCATED, |
||||
|
||||
/** |
||||
* Not in queue, currently being validated. An attempt to borrow the object |
||||
* was made while previously being tested for eviction which removed it from |
||||
* the queue. It should be returned to the head of the queue once validation |
||||
* completes. |
||||
*/ |
||||
VALIDATION_RETURN_TO_HEAD, |
||||
|
||||
/** |
||||
* Failed maintenance (e.g. eviction test or validation) and will be / has |
||||
* been destroyed |
||||
*/ |
||||
INVALID, |
||||
|
||||
/** |
||||
* Deemed abandoned, to be invalidated. |
||||
*/ |
||||
ABANDONED, |
||||
|
||||
/** |
||||
* Returning to the pool. |
||||
*/ |
||||
RETURNING |
||||
} |
@ -0,0 +1,36 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* Pools that unavoidably swallow exceptions may be configured with an instance |
||||
* of this listener so the user may receive notification of when this happens. |
||||
* The listener should not throw an exception when called but pools calling |
||||
* listeners should protect themselves against exceptions anyway. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface SwallowedExceptionListener { |
||||
|
||||
/** |
||||
* This method is called every time the implementation unavoidably swallows |
||||
* an exception. |
||||
* |
||||
* @param e The exception that was swallowed |
||||
*/ |
||||
void onSwallowException(Exception e); |
||||
} |
@ -0,0 +1,36 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* This interface allows pooled objects to make information available about when |
||||
* and how they were used available to the object pool. The object pool may, but |
||||
* is not required, to use this information to make more informed decisions when |
||||
* determining the state of a pooled object - for instance whether or not the |
||||
* object has been abandoned. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface TrackedUse { |
||||
|
||||
/** |
||||
* Get the last time this object was used in ms. |
||||
* |
||||
* @return long time in ms |
||||
*/ |
||||
long getLastUsed(); |
||||
} |
@ -0,0 +1,39 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2; |
||||
|
||||
/** |
||||
* This interface may be implemented by an object pool to enable clients |
||||
* (primarily those clients that wrap pools to provide pools with extended |
||||
* features) to provide additional information to the pool relating to object |
||||
* using allowing more informed decisions and reporting to be made regarding |
||||
* abandoned objects. |
||||
* |
||||
* @param <T> The type of object provided by the pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface UsageTracking<T> { |
||||
|
||||
/** |
||||
* This method is called every time a pooled object is used to enable the pool to |
||||
* better track borrowed objects. |
||||
* |
||||
* @param pooledObject The object that is being used |
||||
*/ |
||||
void use(T pooledObject); |
||||
} |
@ -0,0 +1,289 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.TrackedUse; |
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
import java.io.PrintWriter; |
||||
|
||||
/** |
||||
* Configuration settings for abandoned object removal. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class AbandonedConfig { |
||||
|
||||
/** |
||||
* Whether or not borrowObject performs abandoned object removal. |
||||
*/ |
||||
private boolean removeAbandonedOnBorrow = false; |
||||
|
||||
/** |
||||
* <p>Flag to remove abandoned objects if they exceed the |
||||
* removeAbandonedTimeout when borrowObject is invoked.</p> |
||||
* |
||||
* <p>The default value is false.</p> |
||||
* |
||||
* <p>If set to true, abandoned objects are removed by borrowObject if |
||||
* there are fewer than 2 idle objects available in the pool and |
||||
* <code>getNumActive() > getMaxTotal() - 3</code></p> |
||||
* |
||||
* @return true if abandoned objects are to be removed by borrowObject |
||||
*/ |
||||
public boolean getRemoveAbandonedOnBorrow() { |
||||
return this.removeAbandonedOnBorrow; |
||||
} |
||||
|
||||
/** |
||||
* <p>Flag to remove abandoned objects if they exceed the |
||||
* removeAbandonedTimeout when borrowObject is invoked.</p> |
||||
* |
||||
* @param removeAbandonedOnBorrow true means abandoned objects will be |
||||
* removed by borrowObject |
||||
* @see #getRemoveAbandonedOnBorrow() |
||||
*/ |
||||
public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { |
||||
this.removeAbandonedOnBorrow = removeAbandonedOnBorrow; |
||||
} |
||||
|
||||
/** |
||||
* Whether or not pool maintenance (evictor) performs abandoned object |
||||
* removal. |
||||
*/ |
||||
private boolean removeAbandonedOnMaintenance = false; |
||||
|
||||
/** |
||||
* <p>Flag to remove abandoned objects if they exceed the |
||||
* removeAbandonedTimeout when pool maintenance (the "evictor") |
||||
* runs.</p> |
||||
* |
||||
* <p>The default value is false.</p> |
||||
* |
||||
* <p>If set to true, abandoned objects are removed by the pool |
||||
* maintenance thread when it runs. This setting has no effect |
||||
* unless maintenance is enabled by setting |
||||
*{@link GenericObjectPool#getTimeBetweenEvictionRunsMillis() timeBetweenEvictionRunsMillis} |
||||
* to a positive number.</p> |
||||
* |
||||
* @return true if abandoned objects are to be removed by the evictor |
||||
*/ |
||||
public boolean getRemoveAbandonedOnMaintenance() { |
||||
return this.removeAbandonedOnMaintenance; |
||||
} |
||||
|
||||
/** |
||||
* <p>Flag to remove abandoned objects if they exceed the |
||||
* removeAbandonedTimeout when pool maintenance runs.</p> |
||||
* |
||||
* @param removeAbandonedOnMaintenance true means abandoned objects will be |
||||
* removed by pool maintenance |
||||
* @see #getRemoveAbandonedOnMaintenance |
||||
*/ |
||||
public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { |
||||
this.removeAbandonedOnMaintenance = removeAbandonedOnMaintenance; |
||||
} |
||||
|
||||
/** |
||||
* Timeout in seconds before an abandoned object can be removed. |
||||
*/ |
||||
private int removeAbandonedTimeout = 300; |
||||
|
||||
/** |
||||
* <p>Timeout in seconds before an abandoned object can be removed.</p> |
||||
* |
||||
* <p>The time of most recent use of an object is the maximum (latest) of |
||||
* {@link TrackedUse#getLastUsed()} (if this class of the object implements |
||||
* TrackedUse) and the time when the object was borrowed from the pool.</p> |
||||
* |
||||
* <p>The default value is 300 seconds.</p> |
||||
* |
||||
* @return the abandoned object timeout in seconds |
||||
*/ |
||||
public int getRemoveAbandonedTimeout() { |
||||
return this.removeAbandonedTimeout; |
||||
} |
||||
|
||||
/** |
||||
* <p>Sets the timeout in seconds before an abandoned object can be |
||||
* removed</p> |
||||
* |
||||
* <p>Setting this property has no effect if |
||||
* {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and |
||||
* {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance} |
||||
* are both false.</p> |
||||
* |
||||
* @param removeAbandonedTimeout new abandoned timeout in seconds |
||||
* @see #getRemoveAbandonedTimeout() |
||||
*/ |
||||
public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) { |
||||
this.removeAbandonedTimeout = removeAbandonedTimeout; |
||||
} |
||||
|
||||
/** |
||||
* Determines whether or not to log stack traces for application code |
||||
* which abandoned an object. |
||||
*/ |
||||
private boolean logAbandoned = false; |
||||
|
||||
/** |
||||
* Flag to log stack traces for application code which abandoned |
||||
* an object. |
||||
* |
||||
* Defaults to false. |
||||
* Logging of abandoned objects adds overhead for every object created |
||||
* because a stack trace has to be generated. |
||||
* |
||||
* @return boolean true if stack trace logging is turned on for abandoned |
||||
* objects |
||||
* |
||||
*/ |
||||
public boolean getLogAbandoned() { |
||||
return this.logAbandoned; |
||||
} |
||||
|
||||
/** |
||||
* Sets the flag to log stack traces for application code which abandoned |
||||
* an object. |
||||
* |
||||
* @param logAbandoned true turns on abandoned stack trace logging |
||||
* @see #getLogAbandoned() |
||||
* |
||||
*/ |
||||
public void setLogAbandoned(final boolean logAbandoned) { |
||||
this.logAbandoned = logAbandoned; |
||||
} |
||||
|
||||
/** |
||||
* Determines whether or not to log full stack traces when logAbandoned is true. |
||||
* If disabled, then a faster method for logging stack traces with only class data |
||||
* may be used if possible. |
||||
* |
||||
* @since 2.5 |
||||
*/ |
||||
private boolean requireFullStackTrace = true; |
||||
|
||||
/** |
||||
* Indicates if full stack traces are required when {@link #getLogAbandoned() logAbandoned} |
||||
* is true. Defaults to true. Logging of abandoned objects requiring a full stack trace will |
||||
* generate an entire stack trace to generate for every object created. If this is disabled, |
||||
* a faster but less informative stack walking mechanism may be used if available. |
||||
* |
||||
* @return true if full stack traces are required for logging abandoned connections, or false |
||||
* if abbreviated stack traces are acceptable |
||||
* @see CallStack |
||||
* @since 2.5 |
||||
*/ |
||||
public boolean getRequireFullStackTrace() { |
||||
return requireFullStackTrace; |
||||
} |
||||
|
||||
/** |
||||
* Sets the flag to require full stack traces for logging abandoned connections when enabled. |
||||
* |
||||
* @param requireFullStackTrace indicates whether or not full stack traces are required in |
||||
* abandoned connection logs |
||||
* @see CallStack |
||||
* @see #getRequireFullStackTrace() |
||||
* @since 2.5 |
||||
*/ |
||||
public void setRequireFullStackTrace(boolean requireFullStackTrace) { |
||||
this.requireFullStackTrace = requireFullStackTrace; |
||||
} |
||||
|
||||
/** |
||||
* PrintWriter to use to log information on abandoned objects. |
||||
* Use of default system encoding is deliberate. |
||||
*/ |
||||
private PrintWriter logWriter = new PrintWriter(System.out); |
||||
|
||||
/** |
||||
* Returns the log writer being used by this configuration to log |
||||
* information on abandoned objects. If not set, a PrintWriter based on |
||||
* System.out with the system default encoding is used. |
||||
* |
||||
* @return log writer in use |
||||
*/ |
||||
public PrintWriter getLogWriter() { |
||||
return logWriter; |
||||
} |
||||
|
||||
/** |
||||
* Sets the log writer to be used by this configuration to log |
||||
* information on abandoned objects. |
||||
* |
||||
* @param logWriter The new log writer |
||||
*/ |
||||
public void setLogWriter(final PrintWriter logWriter) { |
||||
this.logWriter = logWriter; |
||||
} |
||||
|
||||
/** |
||||
* If the pool implements {@link UsageTracking}, should the pool record a |
||||
* stack trace every time a method is called on a pooled object and retain |
||||
* the most recent stack trace to aid debugging of abandoned objects? |
||||
*/ |
||||
private boolean useUsageTracking = false; |
||||
|
||||
/** |
||||
* If the pool implements {@link UsageTracking}, should the pool record a |
||||
* stack trace every time a method is called on a pooled object and retain |
||||
* the most recent stack trace to aid debugging of abandoned objects? |
||||
* |
||||
* @return <code>true</code> if usage tracking is enabled |
||||
*/ |
||||
public boolean getUseUsageTracking() { |
||||
return useUsageTracking; |
||||
} |
||||
|
||||
/** |
||||
* If the pool implements {@link UsageTracking}, configure whether the pool |
||||
* should record a stack trace every time a method is called on a pooled |
||||
* object and retain the most recent stack trace to aid debugging of |
||||
* abandoned objects. |
||||
* |
||||
* @param useUsageTracking A value of <code>true</code> will enable |
||||
* the recording of a stack trace on every use |
||||
* of a pooled object |
||||
*/ |
||||
public void setUseUsageTracking(final boolean useUsageTracking) { |
||||
this.useUsageTracking = useUsageTracking; |
||||
} |
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("AbandonedConfig [removeAbandonedOnBorrow="); |
||||
builder.append(removeAbandonedOnBorrow); |
||||
builder.append(", removeAbandonedOnMaintenance="); |
||||
builder.append(removeAbandonedOnMaintenance); |
||||
builder.append(", removeAbandonedTimeout="); |
||||
builder.append(removeAbandonedTimeout); |
||||
builder.append(", logAbandoned="); |
||||
builder.append(logAbandoned); |
||||
builder.append(", logWriter="); |
||||
builder.append(logWriter); |
||||
builder.append(", useUsageTracking="); |
||||
builder.append(useUsageTracking); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,718 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.BaseObject; |
||||
|
||||
/** |
||||
* Provides the implementation for the common attributes shared by the |
||||
* sub-classes. New instances of this class will be created using the defaults |
||||
* defined by the public constants. |
||||
* <p> |
||||
* This class is not thread-safe. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public abstract class BaseObjectPoolConfig extends BaseObject implements Cloneable { |
||||
|
||||
/** |
||||
* The default value for the {@code lifo} configuration attribute. |
||||
* @see GenericObjectPool#getLifo() |
||||
* @see GenericKeyedObjectPool#getLifo() |
||||
*/ |
||||
public static final boolean DEFAULT_LIFO = true; |
||||
|
||||
/** |
||||
* The default value for the {@code fairness} configuration attribute. |
||||
* @see GenericObjectPool#getFairness() |
||||
* @see GenericKeyedObjectPool#getFairness() |
||||
*/ |
||||
public static final boolean DEFAULT_FAIRNESS = false; |
||||
|
||||
/** |
||||
* The default value for the {@code maxWait} configuration attribute. |
||||
* @see GenericObjectPool#getMaxWaitMillis() |
||||
* @see GenericKeyedObjectPool#getMaxWaitMillis() |
||||
*/ |
||||
public static final long DEFAULT_MAX_WAIT_MILLIS = -1L; |
||||
|
||||
/** |
||||
* The default value for the {@code minEvictableIdleTimeMillis} |
||||
* configuration attribute. |
||||
* @see GenericObjectPool#getMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = |
||||
1000L * 60L * 30L; |
||||
|
||||
/** |
||||
* The default value for the {@code softMinEvictableIdleTimeMillis} |
||||
* configuration attribute. |
||||
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1; |
||||
|
||||
/** |
||||
* The default value for {@code evictorShutdownTimeoutMillis} configuration |
||||
* attribute. |
||||
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis() |
||||
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis() |
||||
*/ |
||||
public static final long DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS = |
||||
10L * 1000L; |
||||
|
||||
/** |
||||
* The default value for the {@code numTestsPerEvictionRun} configuration |
||||
* attribute. |
||||
* @see GenericObjectPool#getNumTestsPerEvictionRun() |
||||
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun() |
||||
*/ |
||||
public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; |
||||
|
||||
/** |
||||
* The default value for the {@code testOnCreate} configuration attribute. |
||||
* @see GenericObjectPool#getTestOnCreate() |
||||
* @see GenericKeyedObjectPool#getTestOnCreate() |
||||
* |
||||
* @since 2.2 |
||||
*/ |
||||
public static final boolean DEFAULT_TEST_ON_CREATE = false; |
||||
|
||||
/** |
||||
* The default value for the {@code testOnBorrow} configuration attribute. |
||||
* @see GenericObjectPool#getTestOnBorrow() |
||||
* @see GenericKeyedObjectPool#getTestOnBorrow() |
||||
*/ |
||||
public static final boolean DEFAULT_TEST_ON_BORROW = false; |
||||
|
||||
/** |
||||
* The default value for the {@code testOnReturn} configuration attribute. |
||||
* @see GenericObjectPool#getTestOnReturn() |
||||
* @see GenericKeyedObjectPool#getTestOnReturn() |
||||
*/ |
||||
public static final boolean DEFAULT_TEST_ON_RETURN = false; |
||||
|
||||
/** |
||||
* The default value for the {@code testWhileIdle} configuration attribute. |
||||
* @see GenericObjectPool#getTestWhileIdle() |
||||
* @see GenericKeyedObjectPool#getTestWhileIdle() |
||||
*/ |
||||
public static final boolean DEFAULT_TEST_WHILE_IDLE = false; |
||||
|
||||
/** |
||||
* The default value for the {@code timeBetweenEvictionRunsMillis} |
||||
* configuration attribute. |
||||
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
*/ |
||||
public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; |
||||
|
||||
/** |
||||
* The default value for the {@code blockWhenExhausted} configuration |
||||
* attribute. |
||||
* @see GenericObjectPool#getBlockWhenExhausted() |
||||
* @see GenericKeyedObjectPool#getBlockWhenExhausted() |
||||
*/ |
||||
public static final boolean DEFAULT_BLOCK_WHEN_EXHAUSTED = true; |
||||
|
||||
/** |
||||
* The default value for enabling JMX for pools created with a configuration |
||||
* instance. |
||||
*/ |
||||
public static final boolean DEFAULT_JMX_ENABLE = true; |
||||
|
||||
/** |
||||
* The default value for the prefix used to name JMX enabled pools created |
||||
* with a configuration instance. |
||||
* @see GenericObjectPool#getJmxName() |
||||
* @see GenericKeyedObjectPool#getJmxName() |
||||
*/ |
||||
public static final String DEFAULT_JMX_NAME_PREFIX = "pool"; |
||||
|
||||
/** |
||||
* The default value for the base name to use to name JMX enabled pools |
||||
* created with a configuration instance. The default is <code>null</code> |
||||
* which means the pool will provide the base name to use. |
||||
* @see GenericObjectPool#getJmxName() |
||||
* @see GenericKeyedObjectPool#getJmxName() |
||||
*/ |
||||
public static final String DEFAULT_JMX_NAME_BASE = null; |
||||
|
||||
/** |
||||
* The default value for the {@code evictionPolicyClassName} configuration |
||||
* attribute. |
||||
* @see GenericObjectPool#getEvictionPolicyClassName() |
||||
* @see GenericKeyedObjectPool#getEvictionPolicyClassName() |
||||
*/ |
||||
public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = |
||||
"org.apache.commons.pool2.impl.DefaultEvictionPolicy"; |
||||
|
||||
|
||||
private boolean lifo = DEFAULT_LIFO; |
||||
|
||||
private boolean fairness = DEFAULT_FAIRNESS; |
||||
|
||||
private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS; |
||||
|
||||
private long minEvictableIdleTimeMillis = |
||||
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
||||
|
||||
private long evictorShutdownTimeoutMillis = |
||||
DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS; |
||||
|
||||
private long softMinEvictableIdleTimeMillis = |
||||
DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
||||
|
||||
private int numTestsPerEvictionRun = |
||||
DEFAULT_NUM_TESTS_PER_EVICTION_RUN; |
||||
|
||||
private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME; |
||||
|
||||
private boolean testOnCreate = DEFAULT_TEST_ON_CREATE; |
||||
|
||||
private boolean testOnBorrow = DEFAULT_TEST_ON_BORROW; |
||||
|
||||
private boolean testOnReturn = DEFAULT_TEST_ON_RETURN; |
||||
|
||||
private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE; |
||||
|
||||
private long timeBetweenEvictionRunsMillis = |
||||
DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; |
||||
|
||||
private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED; |
||||
|
||||
private boolean jmxEnabled = DEFAULT_JMX_ENABLE; |
||||
|
||||
// TODO Consider changing this to a single property for 3.x
|
||||
private String jmxNamePrefix = DEFAULT_JMX_NAME_PREFIX; |
||||
|
||||
private String jmxNameBase = DEFAULT_JMX_NAME_BASE; |
||||
|
||||
|
||||
/** |
||||
* Get the value for the {@code lifo} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code lifo} for this configuration |
||||
* instance |
||||
* |
||||
* @see GenericObjectPool#getLifo() |
||||
* @see GenericKeyedObjectPool#getLifo() |
||||
*/ |
||||
public boolean getLifo() { |
||||
return lifo; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code fairness} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code fairness} for this configuration |
||||
* instance |
||||
* |
||||
* @see GenericObjectPool#getFairness() |
||||
* @see GenericKeyedObjectPool#getFairness() |
||||
*/ |
||||
public boolean getFairness() { |
||||
return fairness; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code lifo} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @param lifo The new setting of {@code lifo} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getLifo() |
||||
* @see GenericKeyedObjectPool#getLifo() |
||||
*/ |
||||
public void setLifo(final boolean lifo) { |
||||
this.lifo = lifo; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code fairness} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @param fairness The new setting of {@code fairness} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getFairness() |
||||
* @see GenericKeyedObjectPool#getFairness() |
||||
*/ |
||||
public void setFairness(final boolean fairness) { |
||||
this.fairness = fairness; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code maxWait} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxWait} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMaxWaitMillis() |
||||
* @see GenericKeyedObjectPool#getMaxWaitMillis() |
||||
*/ |
||||
public long getMaxWaitMillis() { |
||||
return maxWaitMillis; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxWait} configuration attribute for pools |
||||
* created with this configuration instance. |
||||
* |
||||
* @param maxWaitMillis The new setting of {@code maxWaitMillis} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMaxWaitMillis() |
||||
* @see GenericKeyedObjectPool#getMaxWaitMillis() |
||||
*/ |
||||
public void setMaxWaitMillis(final long maxWaitMillis) { |
||||
this.maxWaitMillis = maxWaitMillis; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code minEvictableIdleTimeMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code minEvictableIdleTimeMillis} for |
||||
* this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public long getMinEvictableIdleTimeMillis() { |
||||
return minEvictableIdleTimeMillis; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code minEvictableIdleTimeMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @param minEvictableIdleTimeMillis The new setting of |
||||
* {@code minEvictableIdleTimeMillis} for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { |
||||
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code softMinEvictableIdleTimeMillis} |
||||
* configuration attribute for pools created with this configuration |
||||
* instance. |
||||
* |
||||
* @return The current setting of {@code softMinEvictableIdleTimeMillis} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public long getSoftMinEvictableIdleTimeMillis() { |
||||
return softMinEvictableIdleTimeMillis; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code softMinEvictableIdleTimeMillis} |
||||
* configuration attribute for pools created with this configuration |
||||
* instance. |
||||
* |
||||
* @param softMinEvictableIdleTimeMillis The new setting of |
||||
* {@code softMinEvictableIdleTimeMillis} for this configuration |
||||
* instance |
||||
* |
||||
* @see GenericObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
* @see GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis() |
||||
*/ |
||||
public void setSoftMinEvictableIdleTimeMillis( |
||||
final long softMinEvictableIdleTimeMillis) { |
||||
this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code numTestsPerEvictionRun} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code numTestsPerEvictionRun} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getNumTestsPerEvictionRun() |
||||
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun() |
||||
*/ |
||||
public int getNumTestsPerEvictionRun() { |
||||
return numTestsPerEvictionRun; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code numTestsPerEvictionRun} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @param numTestsPerEvictionRun The new setting of |
||||
* {@code numTestsPerEvictionRun} for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getNumTestsPerEvictionRun() |
||||
* @see GenericKeyedObjectPool#getNumTestsPerEvictionRun() |
||||
*/ |
||||
public void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { |
||||
this.numTestsPerEvictionRun = numTestsPerEvictionRun; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code evictorShutdownTimeoutMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code evictorShutdownTimeoutMillis} for |
||||
* this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis() |
||||
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis() |
||||
*/ |
||||
public long getEvictorShutdownTimeoutMillis() { |
||||
return evictorShutdownTimeoutMillis; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code evictorShutdownTimeoutMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @param evictorShutdownTimeoutMillis The new setting of |
||||
* {@code evictorShutdownTimeoutMillis} for this configuration |
||||
* instance |
||||
* |
||||
* @see GenericObjectPool#getEvictorShutdownTimeoutMillis() |
||||
* @see GenericKeyedObjectPool#getEvictorShutdownTimeoutMillis() |
||||
*/ |
||||
public void setEvictorShutdownTimeoutMillis( |
||||
final long evictorShutdownTimeoutMillis) { |
||||
this.evictorShutdownTimeoutMillis = evictorShutdownTimeoutMillis; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code testOnCreate} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code testOnCreate} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnCreate() |
||||
* @see GenericKeyedObjectPool#getTestOnCreate() |
||||
* |
||||
* @since 2.2 |
||||
*/ |
||||
public boolean getTestOnCreate() { |
||||
return testOnCreate; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code testOnCreate} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param testOnCreate The new setting of {@code testOnCreate} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnCreate() |
||||
* @see GenericKeyedObjectPool#getTestOnCreate() |
||||
* |
||||
* @since 2.2 |
||||
*/ |
||||
public void setTestOnCreate(final boolean testOnCreate) { |
||||
this.testOnCreate = testOnCreate; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code testOnBorrow} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code testOnBorrow} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnBorrow() |
||||
* @see GenericKeyedObjectPool#getTestOnBorrow() |
||||
*/ |
||||
public boolean getTestOnBorrow() { |
||||
return testOnBorrow; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code testOnBorrow} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param testOnBorrow The new setting of {@code testOnBorrow} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnBorrow() |
||||
* @see GenericKeyedObjectPool#getTestOnBorrow() |
||||
*/ |
||||
public void setTestOnBorrow(final boolean testOnBorrow) { |
||||
this.testOnBorrow = testOnBorrow; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code testOnReturn} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code testOnReturn} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnReturn() |
||||
* @see GenericKeyedObjectPool#getTestOnReturn() |
||||
*/ |
||||
public boolean getTestOnReturn() { |
||||
return testOnReturn; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code testOnReturn} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param testOnReturn The new setting of {@code testOnReturn} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestOnReturn() |
||||
* @see GenericKeyedObjectPool#getTestOnReturn() |
||||
*/ |
||||
public void setTestOnReturn(final boolean testOnReturn) { |
||||
this.testOnReturn = testOnReturn; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code testWhileIdle} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code testWhileIdle} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestWhileIdle() |
||||
* @see GenericKeyedObjectPool#getTestWhileIdle() |
||||
*/ |
||||
public boolean getTestWhileIdle() { |
||||
return testWhileIdle; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code testWhileIdle} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param testWhileIdle The new setting of {@code testWhileIdle} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTestWhileIdle() |
||||
* @see GenericKeyedObjectPool#getTestWhileIdle() |
||||
*/ |
||||
public void setTestWhileIdle(final boolean testWhileIdle) { |
||||
this.testWhileIdle = testWhileIdle; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code timeBetweenEvictionRunsMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code timeBetweenEvictionRunsMillis} for |
||||
* this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
*/ |
||||
public long getTimeBetweenEvictionRunsMillis() { |
||||
return timeBetweenEvictionRunsMillis; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code timeBetweenEvictionRunsMillis} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @param timeBetweenEvictionRunsMillis The new setting of |
||||
* {@code timeBetweenEvictionRunsMillis} for this configuration |
||||
* instance |
||||
* |
||||
* @see GenericObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
* @see GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() |
||||
*/ |
||||
public void setTimeBetweenEvictionRunsMillis( |
||||
final long timeBetweenEvictionRunsMillis) { |
||||
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code evictionPolicyClassName} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code evictionPolicyClassName} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getEvictionPolicyClassName() |
||||
* @see GenericKeyedObjectPool#getEvictionPolicyClassName() |
||||
*/ |
||||
public String getEvictionPolicyClassName() { |
||||
return evictionPolicyClassName; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code evictionPolicyClassName} configuration |
||||
* attribute for pools created with this configuration instance. |
||||
* |
||||
* @param evictionPolicyClassName The new setting of |
||||
* {@code evictionPolicyClassName} for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getEvictionPolicyClassName() |
||||
* @see GenericKeyedObjectPool#getEvictionPolicyClassName() |
||||
*/ |
||||
public void setEvictionPolicyClassName(final String evictionPolicyClassName) { |
||||
this.evictionPolicyClassName = evictionPolicyClassName; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code blockWhenExhausted} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code blockWhenExhausted} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getBlockWhenExhausted() |
||||
* @see GenericKeyedObjectPool#getBlockWhenExhausted() |
||||
*/ |
||||
public boolean getBlockWhenExhausted() { |
||||
return blockWhenExhausted; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code blockWhenExhausted} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @param blockWhenExhausted The new setting of {@code blockWhenExhausted} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#getBlockWhenExhausted() |
||||
* @see GenericKeyedObjectPool#getBlockWhenExhausted() |
||||
*/ |
||||
public void setBlockWhenExhausted(final boolean blockWhenExhausted) { |
||||
this.blockWhenExhausted = blockWhenExhausted; |
||||
} |
||||
|
||||
/** |
||||
* Gets the value of the flag that determines if JMX will be enabled for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code jmxEnabled} for this configuration |
||||
* instance |
||||
*/ |
||||
public boolean getJmxEnabled() { |
||||
return jmxEnabled; |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of the flag that determines if JMX will be enabled for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param jmxEnabled The new setting of {@code jmxEnabled} |
||||
* for this configuration instance |
||||
*/ |
||||
public void setJmxEnabled(final boolean jmxEnabled) { |
||||
this.jmxEnabled = jmxEnabled; |
||||
} |
||||
|
||||
/** |
||||
* Gets the value of the JMX name base that will be used as part of the |
||||
* name assigned to JMX enabled pools created with this configuration |
||||
* instance. A value of <code>null</code> means that the pool will define |
||||
* the JMX name base. |
||||
* |
||||
* @return The current setting of {@code jmxNameBase} for this |
||||
* configuration instance |
||||
*/ |
||||
public String getJmxNameBase() { |
||||
return jmxNameBase; |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of the JMX name base that will be used as part of the |
||||
* name assigned to JMX enabled pools created with this configuration |
||||
* instance. A value of <code>null</code> means that the pool will define |
||||
* the JMX name base. |
||||
* |
||||
* @param jmxNameBase The new setting of {@code jmxNameBase} |
||||
* for this configuration instance |
||||
*/ |
||||
public void setJmxNameBase(final String jmxNameBase) { |
||||
this.jmxNameBase = jmxNameBase; |
||||
} |
||||
|
||||
/** |
||||
* Gets the value of the JMX name prefix that will be used as part of the |
||||
* name assigned to JMX enabled pools created with this configuration |
||||
* instance. |
||||
* |
||||
* @return The current setting of {@code jmxNamePrefix} for this |
||||
* configuration instance |
||||
*/ |
||||
public String getJmxNamePrefix() { |
||||
return jmxNamePrefix; |
||||
} |
||||
|
||||
/** |
||||
* Sets the value of the JMX name prefix that will be used as part of the |
||||
* name assigned to JMX enabled pools created with this configuration |
||||
* instance. |
||||
* |
||||
* @param jmxNamePrefix The new setting of {@code jmxNamePrefix} |
||||
* for this configuration instance |
||||
*/ |
||||
public void setJmxNamePrefix(final String jmxNamePrefix) { |
||||
this.jmxNamePrefix = jmxNamePrefix; |
||||
} |
||||
|
||||
@Override |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
builder.append("lifo="); |
||||
builder.append(lifo); |
||||
builder.append(", fairness="); |
||||
builder.append(fairness); |
||||
builder.append(", maxWaitMillis="); |
||||
builder.append(maxWaitMillis); |
||||
builder.append(", minEvictableIdleTimeMillis="); |
||||
builder.append(minEvictableIdleTimeMillis); |
||||
builder.append(", softMinEvictableIdleTimeMillis="); |
||||
builder.append(softMinEvictableIdleTimeMillis); |
||||
builder.append(", numTestsPerEvictionRun="); |
||||
builder.append(numTestsPerEvictionRun); |
||||
builder.append(", evictionPolicyClassName="); |
||||
builder.append(evictionPolicyClassName); |
||||
builder.append(", testOnCreate="); |
||||
builder.append(testOnCreate); |
||||
builder.append(", testOnBorrow="); |
||||
builder.append(testOnBorrow); |
||||
builder.append(", testOnReturn="); |
||||
builder.append(testOnReturn); |
||||
builder.append(", testWhileIdle="); |
||||
builder.append(testWhileIdle); |
||||
builder.append(", timeBetweenEvictionRunsMillis="); |
||||
builder.append(timeBetweenEvictionRunsMillis); |
||||
builder.append(", blockWhenExhausted="); |
||||
builder.append(blockWhenExhausted); |
||||
builder.append(", jmxEnabled="); |
||||
builder.append(jmxEnabled); |
||||
builder.append(", jmxNamePrefix="); |
||||
builder.append(jmxNamePrefix); |
||||
builder.append(", jmxNameBase="); |
||||
builder.append(jmxNameBase); |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
import java.io.PrintWriter; |
||||
|
||||
/** |
||||
* Strategy for obtaining and printing the current call stack. This is primarily useful for |
||||
* {@linkplain UsageTracking usage tracking} so that different JVMs and configurations can use more efficient strategies |
||||
* for obtaining the current call stack depending on metadata needs. |
||||
* |
||||
* @see CallStackUtils |
||||
* @since 2.4.3 |
||||
*/ |
||||
public interface CallStack { |
||||
|
||||
/** |
||||
* Prints the current stack trace if available to a PrintWriter. The format is undefined and is primarily useful |
||||
* for debugging issues with {@link PooledObject} usage in user code. |
||||
* |
||||
* @param writer a PrintWriter to write the current stack trace to if available |
||||
* @return true if a stack trace was available to print or false if nothing was printed |
||||
*/ |
||||
boolean printStackTrace(final PrintWriter writer); |
||||
|
||||
/** |
||||
* Takes a snapshot of the current call stack. Subsequent calls to {@link #printStackTrace(PrintWriter)} will print |
||||
* out that stack trace until it is {@linkplain #clear() cleared}. |
||||
*/ |
||||
void fillInStackTrace(); |
||||
|
||||
/** |
||||
* Clears the current stack trace snapshot. Subsequent calls to {@link #printStackTrace(PrintWriter)} will be |
||||
* no-ops until another call to {@link #fillInStackTrace()}. |
||||
*/ |
||||
void clear(); |
||||
} |
@ -0,0 +1,89 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.security.AccessControlException; |
||||
|
||||
/** |
||||
* Utility methods for {@link CallStack}. |
||||
* |
||||
* @since 2.4.3 |
||||
*/ |
||||
public final class CallStackUtils { |
||||
|
||||
private static final boolean CAN_CREATE_SECURITY_MANAGER; |
||||
|
||||
static { |
||||
CAN_CREATE_SECURITY_MANAGER = canCreateSecurityManager(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@code true} if it is able to create a security manager in the current environment, {@code false} |
||||
* otherwise. |
||||
*/ |
||||
private static boolean canCreateSecurityManager() { |
||||
final SecurityManager manager = System.getSecurityManager(); |
||||
if (manager == null) { |
||||
return true; |
||||
} |
||||
try { |
||||
manager.checkPermission(new RuntimePermission("createSecurityManager")); |
||||
return true; |
||||
} catch (final AccessControlException ignored) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new {@link CallStack} using the fastest allowed strategy. |
||||
* |
||||
* @param messageFormat message (or format) to print first in stack traces |
||||
* @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; otherwise, |
||||
* print message format literally |
||||
* @return a new CallStack |
||||
* @deprecated use {@link #newCallStack(String, boolean, boolean)} |
||||
*/ |
||||
@Deprecated |
||||
public static CallStack newCallStack(final String messageFormat, final boolean useTimestamp) { |
||||
return newCallStack(messageFormat, useTimestamp, false); |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new {@link CallStack} using the fasted allowed strategy. |
||||
* |
||||
* @param messageFormat message (or format) to print first in stack traces |
||||
* @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; |
||||
* otherwise, print message format literally |
||||
* @param requireFullStackTrace if true, forces the use of a stack walking mechanism that includes full stack trace |
||||
* information; otherwise, uses a faster implementation if possible |
||||
* @return a new CallStack |
||||
* @since 2.5 |
||||
*/ |
||||
public static CallStack newCallStack(final String messageFormat, |
||||
final boolean useTimestamp, |
||||
final boolean requireFullStackTrace) { |
||||
return CAN_CREATE_SECURITY_MANAGER && !requireFullStackTrace |
||||
? new SecurityManagerCallStack(messageFormat, useTimestamp) |
||||
: new ThrowableCallStack(messageFormat, useTimestamp); |
||||
} |
||||
|
||||
/** |
||||
* Hidden constructor. |
||||
*/ |
||||
private CallStackUtils() { |
||||
} |
||||
} |
@ -0,0 +1,53 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
|
||||
/** |
||||
* Provides the default implementation of {@link EvictionPolicy} used by the |
||||
* pools. Objects will be evicted if the following conditions are met: |
||||
* <ul> |
||||
* <li>the object has been idle longer than |
||||
* {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} / |
||||
* {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()}</li> |
||||
* <li>there are more than {@link GenericObjectPool#getMinIdle()} / |
||||
* {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} idle objects in |
||||
* the pool and the object has been idle for longer than |
||||
* {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} / |
||||
* {@link GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()} |
||||
* </ul> |
||||
* This class is immutable and thread-safe. |
||||
* |
||||
* @param <T> the type of objects in the pool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class DefaultEvictionPolicy<T> implements EvictionPolicy<T> { |
||||
|
||||
@Override |
||||
public boolean evict(final EvictionConfig config, final PooledObject<T> underTest, |
||||
final int idleCount) { |
||||
|
||||
if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() && |
||||
config.getMinIdle() < idleCount) || |
||||
config.getIdleEvictTime() < underTest.getIdleTimeMillis()) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,297 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectState; |
||||
import com.fr.third.org.apache.commons.pool2.TrackedUse; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.util.Deque; |
||||
|
||||
/** |
||||
* This wrapper is used to track the additional information, such as state, for |
||||
* the pooled objects. |
||||
* <p> |
||||
* This class is intended to be thread-safe. |
||||
* |
||||
* @param <T> the type of object in the pool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class DefaultPooledObject<T> implements PooledObject<T> { |
||||
|
||||
private final T object; |
||||
private PooledObjectState state = PooledObjectState.IDLE; // @GuardedBy("this") to ensure transitions are valid
|
||||
private final long createTime = System.currentTimeMillis(); |
||||
private volatile long lastBorrowTime = createTime; |
||||
private volatile long lastUseTime = createTime; |
||||
private volatile long lastReturnTime = createTime; |
||||
private volatile boolean logAbandoned = false; |
||||
private volatile CallStack borrowedBy = NoOpCallStack.INSTANCE; |
||||
private volatile CallStack usedBy = NoOpCallStack.INSTANCE; |
||||
private volatile long borrowedCount = 0; |
||||
|
||||
/** |
||||
* Create a new instance that wraps the provided object so that the pool can |
||||
* track the state of the pooled object. |
||||
* |
||||
* @param object The object to wrap |
||||
*/ |
||||
public DefaultPooledObject(final T object) { |
||||
this.object = object; |
||||
} |
||||
|
||||
@Override |
||||
public T getObject() { |
||||
return object; |
||||
} |
||||
|
||||
@Override |
||||
public long getCreateTime() { |
||||
return createTime; |
||||
} |
||||
|
||||
@Override |
||||
public long getActiveTimeMillis() { |
||||
// Take copies to avoid threading issues
|
||||
final long rTime = lastReturnTime; |
||||
final long bTime = lastBorrowTime; |
||||
|
||||
if (rTime > bTime) { |
||||
return rTime - bTime; |
||||
} |
||||
return System.currentTimeMillis() - bTime; |
||||
} |
||||
|
||||
@Override |
||||
public long getIdleTimeMillis() { |
||||
final long elapsed = System.currentTimeMillis() - lastReturnTime; |
||||
// elapsed may be negative if:
|
||||
// - another thread updates lastReturnTime during the calculation window
|
||||
// - System.currentTimeMillis() is not monotonic (e.g. system time is set back)
|
||||
return elapsed >= 0 ? elapsed : 0; |
||||
} |
||||
|
||||
@Override |
||||
public long getLastBorrowTime() { |
||||
return lastBorrowTime; |
||||
} |
||||
|
||||
@Override |
||||
public long getLastReturnTime() { |
||||
return lastReturnTime; |
||||
} |
||||
|
||||
/** |
||||
* Get the number of times this object has been borrowed. |
||||
* @return The number of times this object has been borrowed. |
||||
* @since 2.1 |
||||
*/ |
||||
public long getBorrowedCount() { |
||||
return borrowedCount; |
||||
} |
||||
|
||||
/** |
||||
* Return an estimate of the last time this object was used. If the class
|
||||
* of the pooled object implements {@link TrackedUse}, what is returned is |
||||
* the maximum of {@link TrackedUse#getLastUsed()} and |
||||
* {@link #getLastBorrowTime()}; otherwise this method gives the same |
||||
* value as {@link #getLastBorrowTime()}. |
||||
* |
||||
* @return the last time this object was used |
||||
*/ |
||||
@Override |
||||
public long getLastUsedTime() { |
||||
if (object instanceof TrackedUse) { |
||||
return Math.max(((TrackedUse) object).getLastUsed(), lastUseTime); |
||||
} |
||||
return lastUseTime; |
||||
} |
||||
|
||||
@Override |
||||
public int compareTo(final PooledObject<T> other) { |
||||
final long lastActiveDiff = this.getLastReturnTime() - other.getLastReturnTime(); |
||||
if (lastActiveDiff == 0) { |
||||
// Make sure the natural ordering is broadly consistent with equals
|
||||
// although this will break down if distinct objects have the same
|
||||
// identity hash code.
|
||||
// see java.lang.Comparable Javadocs
|
||||
return System.identityHashCode(this) - System.identityHashCode(other); |
||||
} |
||||
// handle int overflow
|
||||
return (int)Math.min(Math.max(lastActiveDiff, Integer.MIN_VALUE), Integer.MAX_VALUE); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder result = new StringBuilder(); |
||||
result.append("Object: "); |
||||
result.append(object.toString()); |
||||
result.append(", State: "); |
||||
synchronized (this) { |
||||
result.append(state.toString()); |
||||
} |
||||
return result.toString(); |
||||
// TODO add other attributes
|
||||
} |
||||
|
||||
@Override |
||||
public synchronized boolean startEvictionTest() { |
||||
if (state == PooledObjectState.IDLE) { |
||||
state = PooledObjectState.EVICTION; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public synchronized boolean endEvictionTest( |
||||
final Deque<PooledObject<T>> idleQueue) { |
||||
if (state == PooledObjectState.EVICTION) { |
||||
state = PooledObjectState.IDLE; |
||||
return true; |
||||
} else if (state == PooledObjectState.EVICTION_RETURN_TO_HEAD) { |
||||
state = PooledObjectState.IDLE; |
||||
if (!idleQueue.offerFirst(this)) { |
||||
// TODO - Should never happen
|
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Allocates the object. |
||||
* |
||||
* @return {@code true} if the original state was {@link PooledObjectState#IDLE IDLE} |
||||
*/ |
||||
@Override |
||||
public synchronized boolean allocate() { |
||||
if (state == PooledObjectState.IDLE) { |
||||
state = PooledObjectState.ALLOCATED; |
||||
lastBorrowTime = System.currentTimeMillis(); |
||||
lastUseTime = lastBorrowTime; |
||||
borrowedCount++; |
||||
if (logAbandoned) { |
||||
borrowedBy.fillInStackTrace(); |
||||
} |
||||
return true; |
||||
} else if (state == PooledObjectState.EVICTION) { |
||||
// TODO Allocate anyway and ignore eviction test
|
||||
state = PooledObjectState.EVICTION_RETURN_TO_HEAD; |
||||
return false; |
||||
} |
||||
// TODO if validating and testOnBorrow == true then pre-allocate for
|
||||
// performance
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Deallocates the object and sets it {@link PooledObjectState#IDLE IDLE} |
||||
* if it is currently {@link PooledObjectState#ALLOCATED ALLOCATED}. |
||||
* |
||||
* @return {@code true} if the state was {@link PooledObjectState#ALLOCATED ALLOCATED} |
||||
*/ |
||||
@Override |
||||
public synchronized boolean deallocate() { |
||||
if (state == PooledObjectState.ALLOCATED || |
||||
state == PooledObjectState.RETURNING) { |
||||
state = PooledObjectState.IDLE; |
||||
lastReturnTime = System.currentTimeMillis(); |
||||
borrowedBy.clear(); |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Sets the state to {@link PooledObjectState#INVALID INVALID} |
||||
*/ |
||||
@Override |
||||
public synchronized void invalidate() { |
||||
state = PooledObjectState.INVALID; |
||||
} |
||||
|
||||
@Override |
||||
public void use() { |
||||
lastUseTime = System.currentTimeMillis(); |
||||
usedBy.fillInStackTrace(); |
||||
} |
||||
|
||||
@Override |
||||
public void printStackTrace(final PrintWriter writer) { |
||||
boolean written = borrowedBy.printStackTrace(writer); |
||||
written |= usedBy.printStackTrace(writer); |
||||
if (written) { |
||||
writer.flush(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the state of this object. |
||||
* @return state |
||||
*/ |
||||
@Override |
||||
public synchronized PooledObjectState getState() { |
||||
return state; |
||||
} |
||||
|
||||
/** |
||||
* Marks the pooled object as abandoned. |
||||
*/ |
||||
@Override |
||||
public synchronized void markAbandoned() { |
||||
state = PooledObjectState.ABANDONED; |
||||
} |
||||
|
||||
/** |
||||
* Marks the object as returning to the pool. |
||||
*/ |
||||
@Override |
||||
public synchronized void markReturning() { |
||||
state = PooledObjectState.RETURNING; |
||||
} |
||||
|
||||
@Override |
||||
public void setLogAbandoned(final boolean logAbandoned) { |
||||
this.logAbandoned = logAbandoned; |
||||
} |
||||
|
||||
/** |
||||
* Configures the stack trace generation strategy based on whether or not fully |
||||
* detailed stack traces are required. When set to false, abandoned logs may |
||||
* only include caller class information rather than method names, line numbers, |
||||
* and other normal metadata available in a full stack trace. |
||||
* |
||||
* @param requireFullStackTrace the new configuration setting for abandoned object |
||||
* logging |
||||
* @since 2.5 |
||||
*/ |
||||
// TODO: uncomment below in 3.0
|
||||
// @Override
|
||||
public void setRequireFullStackTrace(final boolean requireFullStackTrace) { |
||||
borrowedBy = CallStackUtils.newCallStack("'Pooled object created' " + |
||||
"yyyy-MM-dd HH:mm:ss Z 'by the following code has not been returned to the pool:'", |
||||
true, requireFullStackTrace); |
||||
usedBy = CallStackUtils.newCallStack("The last code to use this object was:", |
||||
false, requireFullStackTrace); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,114 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.text.SimpleDateFormat; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
|
||||
/** |
||||
* Implementation of object that is used to provide information on pooled |
||||
* objects via JMX. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class DefaultPooledObjectInfo implements DefaultPooledObjectInfoMBean { |
||||
|
||||
private final PooledObject<?> pooledObject; |
||||
|
||||
/** |
||||
* Create a new instance for the given pooled object. |
||||
* |
||||
* @param pooledObject The pooled object that this instance will represent |
||||
*/ |
||||
public DefaultPooledObjectInfo(final PooledObject<?> pooledObject) { |
||||
this.pooledObject = pooledObject; |
||||
} |
||||
|
||||
@Override |
||||
public long getCreateTime() { |
||||
return pooledObject.getCreateTime(); |
||||
} |
||||
|
||||
@Override |
||||
public String getCreateTimeFormatted() { |
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); |
||||
return sdf.format(Long.valueOf(pooledObject.getCreateTime())); |
||||
} |
||||
|
||||
@Override |
||||
public long getLastBorrowTime() { |
||||
return pooledObject.getLastBorrowTime(); |
||||
} |
||||
|
||||
@Override |
||||
public String getLastBorrowTimeFormatted() { |
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); |
||||
return sdf.format(Long.valueOf(pooledObject.getLastBorrowTime())); |
||||
} |
||||
|
||||
@Override |
||||
public String getLastBorrowTrace() { |
||||
final StringWriter sw = new StringWriter(); |
||||
pooledObject.printStackTrace(new PrintWriter(sw)); |
||||
return sw.toString(); |
||||
} |
||||
|
||||
@Override |
||||
public long getLastReturnTime() { |
||||
return pooledObject.getLastReturnTime(); |
||||
} |
||||
|
||||
@Override |
||||
public String getLastReturnTimeFormatted() { |
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); |
||||
return sdf.format(Long.valueOf(pooledObject.getLastReturnTime())); |
||||
} |
||||
|
||||
@Override |
||||
public String getPooledObjectType() { |
||||
return pooledObject.getObject().getClass().getName(); |
||||
} |
||||
|
||||
@Override |
||||
public String getPooledObjectToString() { |
||||
return pooledObject.getObject().toString(); |
||||
} |
||||
|
||||
@Override |
||||
public long getBorrowedCount() { |
||||
// TODO Simplify this once getBorrowedCount has been added to PooledObject
|
||||
if (pooledObject instanceof DefaultPooledObject) { |
||||
return ((DefaultPooledObject<?>) pooledObject).getBorrowedCount(); |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("DefaultPooledObjectInfo [pooledObject="); |
||||
builder.append(pooledObject); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,115 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
/** |
||||
* The interface that defines the information about pooled objects that will be |
||||
* exposed via JMX. |
||||
* |
||||
* NOTE: This interface exists only to define those attributes and methods that |
||||
* will be made available via JMX. It must not be implemented by clients |
||||
* as it is subject to change between major, minor and patch version |
||||
* releases of commons pool. Clients that implement this interface may |
||||
* not, therefore, be able to upgrade to a new minor or patch release |
||||
* without requiring code changes. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface DefaultPooledObjectInfoMBean { |
||||
/** |
||||
* Obtain the time (using the same basis as |
||||
* {@link System#currentTimeMillis()}) that pooled object was created. |
||||
* |
||||
* @return The creation time for the pooled object |
||||
*/ |
||||
long getCreateTime(); |
||||
|
||||
/** |
||||
* Obtain the time that pooled object was created. |
||||
* |
||||
* @return The creation time for the pooled object formatted as |
||||
* <code>yyyy-MM-dd HH:mm:ss Z</code> |
||||
*/ |
||||
String getCreateTimeFormatted(); |
||||
|
||||
/** |
||||
* Obtain the time (using the same basis as |
||||
* {@link System#currentTimeMillis()}) the polled object was last borrowed. |
||||
* |
||||
* @return The time the pooled object was last borrowed |
||||
*/ |
||||
long getLastBorrowTime(); |
||||
|
||||
/** |
||||
* Obtain the time that pooled object was last borrowed. |
||||
* |
||||
* @return The last borrowed time for the pooled object formated as |
||||
* <code>yyyy-MM-dd HH:mm:ss Z</code> |
||||
*/ |
||||
String getLastBorrowTimeFormatted(); |
||||
|
||||
/** |
||||
* Obtain the stack trace recorded when the pooled object was last borrowed. |
||||
* |
||||
* @return The stack trace showing which code last borrowed the pooled |
||||
* object |
||||
*/ |
||||
String getLastBorrowTrace(); |
||||
|
||||
|
||||
/** |
||||
* Obtain the time (using the same basis as |
||||
* {@link System#currentTimeMillis()})the wrapped object was last returned. |
||||
* |
||||
* @return The time the object was last returned |
||||
*/ |
||||
long getLastReturnTime(); |
||||
|
||||
/** |
||||
* Obtain the time that pooled object was last returned. |
||||
* |
||||
* @return The last returned time for the pooled object formated as |
||||
* <code>yyyy-MM-dd HH:mm:ss Z</code> |
||||
*/ |
||||
String getLastReturnTimeFormatted(); |
||||
|
||||
/** |
||||
* Obtain the name of the class of the pooled object. |
||||
* |
||||
* @return The pooled object's class name |
||||
* |
||||
* @see Class#getName() |
||||
*/ |
||||
String getPooledObjectType(); |
||||
|
||||
/** |
||||
* Provides a String form of the wrapper for debug purposes. The format is |
||||
* not fixed and may change at any time. |
||||
* |
||||
* @return A string representation of the pooled object |
||||
* |
||||
* @see Object#toString() |
||||
*/ |
||||
String getPooledObjectToString(); |
||||
|
||||
/** |
||||
* Get the number of times this object has been borrowed. |
||||
* @return The number of times this object has been borrowed. |
||||
* @since 2.1 |
||||
*/ |
||||
long getBorrowedCount(); |
||||
} |
@ -0,0 +1,114 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
/** |
||||
* This class is used by pool implementations to pass configuration information |
||||
* to {@link EvictionPolicy} instances. The {@link EvictionPolicy} may also have |
||||
* its own specific configuration attributes. |
||||
* <p> |
||||
* This class is immutable and thread-safe. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class EvictionConfig { |
||||
|
||||
private final long idleEvictTime; |
||||
private final long idleSoftEvictTime; |
||||
private final int minIdle; |
||||
|
||||
/** |
||||
* Create a new eviction configuration with the specified parameters. |
||||
* Instances are immutable. |
||||
* |
||||
* @param poolIdleEvictTime Expected to be provided by |
||||
* {@link BaseGenericObjectPool#getMinEvictableIdleTimeMillis()} |
||||
* @param poolIdleSoftEvictTime Expected to be provided by |
||||
* {@link BaseGenericObjectPool#getSoftMinEvictableIdleTimeMillis()} |
||||
* @param minIdle Expected to be provided by |
||||
* {@link GenericObjectPool#getMinIdle()} or |
||||
* {@link GenericKeyedObjectPool#getMinIdlePerKey()} |
||||
*/ |
||||
public EvictionConfig(final long poolIdleEvictTime, final long poolIdleSoftEvictTime, |
||||
final int minIdle) { |
||||
if (poolIdleEvictTime > 0) { |
||||
idleEvictTime = poolIdleEvictTime; |
||||
} else { |
||||
idleEvictTime = Long.MAX_VALUE; |
||||
} |
||||
if (poolIdleSoftEvictTime > 0) { |
||||
idleSoftEvictTime = poolIdleSoftEvictTime; |
||||
} else { |
||||
idleSoftEvictTime = Long.MAX_VALUE; |
||||
} |
||||
this.minIdle = minIdle; |
||||
} |
||||
|
||||
/** |
||||
* Obtain the {@code idleEvictTime} for this eviction configuration |
||||
* instance. |
||||
* <p> |
||||
* How the evictor behaves based on this value will be determined by the |
||||
* configured {@link EvictionPolicy}. |
||||
* |
||||
* @return The {@code idleEvictTime} in milliseconds |
||||
*/ |
||||
public long getIdleEvictTime() { |
||||
return idleEvictTime; |
||||
} |
||||
|
||||
/** |
||||
* Obtain the {@code idleSoftEvictTime} for this eviction configuration |
||||
* instance. |
||||
* <p> |
||||
* How the evictor behaves based on this value will be determined by the |
||||
* configured {@link EvictionPolicy}. |
||||
* |
||||
* @return The (@code idleSoftEvictTime} in milliseconds |
||||
*/ |
||||
public long getIdleSoftEvictTime() { |
||||
return idleSoftEvictTime; |
||||
} |
||||
|
||||
/** |
||||
* Obtain the {@code minIdle} for this eviction configuration instance. |
||||
* <p> |
||||
* How the evictor behaves based on this value will be determined by the |
||||
* configured {@link EvictionPolicy}. |
||||
* |
||||
* @return The {@code minIdle} |
||||
*/ |
||||
public int getMinIdle() { |
||||
return minIdle; |
||||
} |
||||
|
||||
/** |
||||
* @since 2.4 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("EvictionConfig [idleEvictTime="); |
||||
builder.append(idleEvictTime); |
||||
builder.append(", idleSoftEvictTime="); |
||||
builder.append(idleSoftEvictTime); |
||||
builder.append(", minIdle="); |
||||
builder.append(minIdle); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
|
||||
/** |
||||
* To provide a custom eviction policy (i.e. something other than {@link |
||||
* DefaultEvictionPolicy} for a pool, users must provide an implementation of |
||||
* this interface that provides the required eviction policy. |
||||
* |
||||
* @param <T> the type of objects in the pool |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface EvictionPolicy<T> { |
||||
|
||||
/** |
||||
* This method is called to test if an idle object in the pool should be |
||||
* evicted or not. |
||||
* |
||||
* @param config The pool configuration settings related to eviction |
||||
* @param underTest The pooled object being tested for eviction |
||||
* @param idleCount The current number of idle objects in the pool including |
||||
* the object under test |
||||
* @return <code>true</code> if the object should be evicted, otherwise |
||||
* <code>false</code> |
||||
*/ |
||||
boolean evict(EvictionConfig config, PooledObject<T> underTest, |
||||
int idleCount); |
||||
} |
@ -0,0 +1,129 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.security.AccessController; |
||||
import java.security.PrivilegedAction; |
||||
import java.util.TimerTask; |
||||
import java.util.concurrent.ScheduledThreadPoolExecutor; |
||||
import java.util.concurrent.ThreadFactory; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
/** |
||||
* Provides a shared idle object eviction timer for all pools. This class is |
||||
* currently implemented using {@link ScheduledThreadPoolExecutor}. This |
||||
* implementation may change in any future release. This class keeps track of |
||||
* how many pools are using it. If no pools are using the timer, it is cancelled. |
||||
* This prevents a thread being left running which, in application server |
||||
* environments, can lead to memory leads and/or prevent applications from |
||||
* shutting down or reloading cleanly. |
||||
* <p> |
||||
* This class has package scope to prevent its inclusion in the pool public API. |
||||
* The class declaration below should *not* be changed to public. |
||||
* <p> |
||||
* This class is intended to be thread-safe. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class EvictionTimer { |
||||
|
||||
/** Executor instance */ |
||||
private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class")
|
||||
|
||||
/** Static usage count tracker */ |
||||
private static int usageCount; //@GuardedBy("EvictionTimer.class")
|
||||
|
||||
/** Prevent instantiation */ |
||||
private EvictionTimer() { |
||||
// Hide the default constructor
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("EvictionTimer []"); |
||||
return builder.toString(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add the specified eviction task to the timer. Tasks that are added with a |
||||
* call to this method *must* call {@link #cancel(TimerTask)} to cancel the |
||||
* task to prevent memory and/or thread leaks in application server |
||||
* environments. |
||||
* @param task Task to be scheduled |
||||
* @param delay Delay in milliseconds before task is executed |
||||
* @param period Time in milliseconds between executions |
||||
*/ |
||||
static synchronized void schedule(final Runnable task, final long delay, final long period) { |
||||
if (null == executor) { |
||||
executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory()); |
||||
} |
||||
usageCount++; |
||||
executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS); |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified eviction task from the timer. |
||||
* |
||||
* @param task Task to be cancelled |
||||
* @param timeout If the associated executor is no longer required, how |
||||
* long should this thread wait for the executor to |
||||
* terminate? |
||||
* @param unit The units for the specified timeout |
||||
*/ |
||||
static synchronized void cancel(final TimerTask task, final long timeout, final TimeUnit unit) { |
||||
task.cancel(); |
||||
usageCount--; |
||||
if (usageCount == 0) { |
||||
executor.shutdown(); |
||||
try { |
||||
executor.awaitTermination(timeout, unit); |
||||
} catch (final InterruptedException e) { |
||||
// Swallow
|
||||
// Significant API changes would be required to propagate this
|
||||
} |
||||
executor.setCorePoolSize(0); |
||||
executor = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Thread factory that creates a thread, with the context classloader from this class. |
||||
*/ |
||||
private static class EvictorThreadFactory implements ThreadFactory { |
||||
|
||||
@Override |
||||
public Thread newThread(final Runnable r) { |
||||
final Thread t = new Thread(null, r, "commons-pool-evictor-thread"); |
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
||||
@Override |
||||
public Void run() { |
||||
t.setContextClassLoader(EvictorThreadFactory.class.getClassLoader()); |
||||
return null; |
||||
} |
||||
}); |
||||
|
||||
return t; |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,195 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
/** |
||||
* A simple "struct" encapsulating the configuration for a |
||||
* {@link GenericKeyedObjectPool}. |
||||
* |
||||
* <p> |
||||
* This class is not thread-safe; it is only intended to be used to provide |
||||
* attributes used when creating a pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class GenericKeyedObjectPoolConfig extends BaseObjectPoolConfig { |
||||
|
||||
/** |
||||
* The default value for the {@code maxTotalPerKey} configuration attribute. |
||||
* @see GenericKeyedObjectPool#getMaxTotalPerKey() |
||||
*/ |
||||
public static final int DEFAULT_MAX_TOTAL_PER_KEY = 8; |
||||
|
||||
/** |
||||
* The default value for the {@code maxTotal} configuration attribute. |
||||
* @see GenericKeyedObjectPool#getMaxTotal() |
||||
*/ |
||||
public static final int DEFAULT_MAX_TOTAL = -1; |
||||
|
||||
/** |
||||
* The default value for the {@code minIdlePerKey} configuration attribute. |
||||
* @see GenericKeyedObjectPool#getMinIdlePerKey() |
||||
*/ |
||||
public static final int DEFAULT_MIN_IDLE_PER_KEY = 0; |
||||
|
||||
/** |
||||
* The default value for the {@code maxIdlePerKey} configuration attribute. |
||||
* @see GenericKeyedObjectPool#getMaxIdlePerKey() |
||||
*/ |
||||
public static final int DEFAULT_MAX_IDLE_PER_KEY = 8; |
||||
|
||||
|
||||
private int minIdlePerKey = DEFAULT_MIN_IDLE_PER_KEY; |
||||
|
||||
private int maxIdlePerKey = DEFAULT_MAX_IDLE_PER_KEY; |
||||
|
||||
private int maxTotalPerKey = DEFAULT_MAX_TOTAL_PER_KEY; |
||||
|
||||
private int maxTotal = DEFAULT_MAX_TOTAL; |
||||
|
||||
/** |
||||
* Create a new configuration with default settings. |
||||
*/ |
||||
public GenericKeyedObjectPoolConfig() { |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code maxTotal} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxTotal} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#getMaxTotal() |
||||
*/ |
||||
public int getMaxTotal() { |
||||
return maxTotal; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxTotal} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param maxTotal The new setting of {@code maxTotal} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#setMaxTotal(int) |
||||
*/ |
||||
public void setMaxTotal(final int maxTotal) { |
||||
this.maxTotal = maxTotal; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code maxTotalPerKey} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxTotalPerKey} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#getMaxTotalPerKey() |
||||
*/ |
||||
public int getMaxTotalPerKey() { |
||||
return maxTotalPerKey; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxTotalPerKey} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param maxTotalPerKey The new setting of {@code maxTotalPerKey} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#setMaxTotalPerKey(int) |
||||
*/ |
||||
public void setMaxTotalPerKey(final int maxTotalPerKey) { |
||||
this.maxTotalPerKey = maxTotalPerKey; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code minIdlePerKey} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code minIdlePerKey} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#getMinIdlePerKey() |
||||
*/ |
||||
public int getMinIdlePerKey() { |
||||
return minIdlePerKey; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code minIdlePerKey} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param minIdlePerKey The new setting of {@code minIdlePerKey} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#setMinIdlePerKey(int) |
||||
*/ |
||||
public void setMinIdlePerKey(final int minIdlePerKey) { |
||||
this.minIdlePerKey = minIdlePerKey; |
||||
} |
||||
|
||||
/** |
||||
* Get the value for the {@code maxIdlePerKey} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxIdlePerKey} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#getMaxIdlePerKey() |
||||
*/ |
||||
public int getMaxIdlePerKey() { |
||||
return maxIdlePerKey; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxIdlePerKey} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param maxIdlePerKey The new setting of {@code maxIdlePerKey} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericKeyedObjectPool#setMaxIdlePerKey(int) |
||||
*/ |
||||
public void setMaxIdlePerKey(final int maxIdlePerKey) { |
||||
this.maxIdlePerKey = maxIdlePerKey; |
||||
} |
||||
|
||||
@Override |
||||
public GenericKeyedObjectPoolConfig clone() { |
||||
try { |
||||
return (GenericKeyedObjectPoolConfig) super.clone(); |
||||
} catch (final CloneNotSupportedException e) { |
||||
throw new AssertionError(); // Can't happen
|
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
super.toStringAppendFields(builder); |
||||
builder.append(", minIdlePerKey="); |
||||
builder.append(minIdlePerKey); |
||||
builder.append(", maxIdlePerKey="); |
||||
builder.append(maxIdlePerKey); |
||||
builder.append(", maxTotalPerKey="); |
||||
builder.append(maxTotalPerKey); |
||||
builder.append(", maxTotal="); |
||||
builder.append(maxTotal); |
||||
} |
||||
} |
@ -0,0 +1,205 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Defines the methods that will be made available via JMX. |
||||
* |
||||
* NOTE: This interface exists only to define those attributes and methods that |
||||
* will be made available via JMX. It must not be implemented by clients |
||||
* as it is subject to change between major, minor and patch version |
||||
* releases of commons pool. Clients that implement this interface may |
||||
* not, therefore, be able to upgrade to a new minor or patch release |
||||
* without requiring code changes. |
||||
* |
||||
* @param <K> The type of keys maintained by the pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface GenericKeyedObjectPoolMXBean<K> { |
||||
// Expose getters for configuration settings
|
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getBlockWhenExhausted()} |
||||
* @return See {@link GenericKeyedObjectPool#getBlockWhenExhausted()} |
||||
*/ |
||||
boolean getBlockWhenExhausted(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getFairness()} |
||||
* @return See {@link GenericKeyedObjectPool#getFairness()} |
||||
*/ |
||||
boolean getFairness(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getLifo()} |
||||
* @return See {@link GenericKeyedObjectPool#getLifo()} |
||||
*/ |
||||
boolean getLifo(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxIdlePerKey()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxIdlePerKey()} |
||||
*/ |
||||
int getMaxIdlePerKey(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxTotal()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxTotal()} |
||||
*/ |
||||
int getMaxTotal(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxTotalPerKey()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxTotalPerKey()} |
||||
*/ |
||||
int getMaxTotalPerKey(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxWaitMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxWaitMillis()} |
||||
*/ |
||||
long getMaxWaitMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMinEvictableIdleTimeMillis()} |
||||
*/ |
||||
long getMinEvictableIdleTimeMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMinIdlePerKey()} |
||||
* @return See {@link GenericKeyedObjectPool#getMinIdlePerKey()} |
||||
*/ |
||||
int getMinIdlePerKey(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumActive()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumActive()} |
||||
*/ |
||||
int getNumActive(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumIdle()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumIdle()} |
||||
*/ |
||||
int getNumIdle(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()} |
||||
*/ |
||||
int getNumTestsPerEvictionRun(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getTestOnCreate()} |
||||
* @return See {@link GenericKeyedObjectPool#getTestOnCreate()} |
||||
* @since 2.2 |
||||
*/ |
||||
boolean getTestOnCreate(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getTestOnBorrow()} |
||||
* @return See {@link GenericKeyedObjectPool#getTestOnBorrow()} |
||||
*/ |
||||
boolean getTestOnBorrow(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getTestOnReturn()} |
||||
* @return See {@link GenericKeyedObjectPool#getTestOnReturn()} |
||||
*/ |
||||
boolean getTestOnReturn(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getTestWhileIdle()} |
||||
* @return See {@link GenericKeyedObjectPool#getTestWhileIdle()} |
||||
*/ |
||||
boolean getTestWhileIdle(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis()} |
||||
*/ |
||||
long getTimeBetweenEvictionRunsMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#isClosed()} |
||||
* @return See {@link GenericKeyedObjectPool#isClosed()} |
||||
*/ |
||||
boolean isClosed(); |
||||
// Expose getters for monitoring attributes
|
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumActivePerKey()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumActivePerKey()} |
||||
*/ |
||||
Map<String,Integer> getNumActivePerKey(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getBorrowedCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getBorrowedCount()} |
||||
*/ |
||||
long getBorrowedCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getReturnedCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getReturnedCount()} |
||||
*/ |
||||
long getReturnedCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getCreatedCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getCreatedCount()} |
||||
*/ |
||||
long getCreatedCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getDestroyedCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getDestroyedCount()} |
||||
*/ |
||||
long getDestroyedCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()} |
||||
*/ |
||||
long getDestroyedByEvictorCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()} |
||||
* @return See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()} |
||||
*/ |
||||
long getDestroyedByBorrowValidationCount(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()} |
||||
*/ |
||||
long getMeanActiveTimeMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()} |
||||
*/ |
||||
long getMeanIdleTimeMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
*/ |
||||
long getMeanBorrowWaitTimeMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
* @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
*/ |
||||
long getMaxBorrowWaitTimeMillis(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getCreationStackTrace()} |
||||
* @return See {@link GenericKeyedObjectPool#getCreationStackTrace()} |
||||
*/ |
||||
String getCreationStackTrace(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumWaiters()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumWaiters()} |
||||
*/ |
||||
int getNumWaiters(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#getNumWaitersByKey()} |
||||
* @return See {@link GenericKeyedObjectPool#getNumWaitersByKey()} |
||||
*/ |
||||
Map<String,Integer> getNumWaitersByKey(); |
||||
/** |
||||
* See {@link GenericKeyedObjectPool#listAllObjects()} |
||||
* @return See {@link GenericKeyedObjectPool#listAllObjects()} |
||||
*/ |
||||
Map<String,List<DefaultPooledObjectInfo>> listAllObjects(); |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,155 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
/** |
||||
* A simple "struct" encapsulating the configuration for a |
||||
* {@link GenericObjectPool}. |
||||
* |
||||
* <p> |
||||
* This class is not thread-safe; it is only intended to be used to provide |
||||
* attributes used when creating a pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class GenericObjectPoolConfig extends BaseObjectPoolConfig { |
||||
|
||||
/** |
||||
* The default value for the {@code maxTotal} configuration attribute. |
||||
* @see GenericObjectPool#getMaxTotal() |
||||
*/ |
||||
public static final int DEFAULT_MAX_TOTAL = 8; |
||||
|
||||
/** |
||||
* The default value for the {@code maxIdle} configuration attribute. |
||||
* @see GenericObjectPool#getMaxIdle() |
||||
*/ |
||||
public static final int DEFAULT_MAX_IDLE = 8; |
||||
|
||||
/** |
||||
* The default value for the {@code minIdle} configuration attribute. |
||||
* @see GenericObjectPool#getMinIdle() |
||||
*/ |
||||
public static final int DEFAULT_MIN_IDLE = 0; |
||||
|
||||
|
||||
private int maxTotal = DEFAULT_MAX_TOTAL; |
||||
|
||||
private int maxIdle = DEFAULT_MAX_IDLE; |
||||
|
||||
private int minIdle = DEFAULT_MIN_IDLE; |
||||
|
||||
/** |
||||
* Get the value for the {@code maxTotal} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxTotal} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMaxTotal() |
||||
*/ |
||||
public int getMaxTotal() { |
||||
return maxTotal; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxTotal} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param maxTotal The new setting of {@code maxTotal} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#setMaxTotal(int) |
||||
*/ |
||||
public void setMaxTotal(final int maxTotal) { |
||||
this.maxTotal = maxTotal; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the value for the {@code maxIdle} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code maxIdle} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMaxIdle() |
||||
*/ |
||||
public int getMaxIdle() { |
||||
return maxIdle; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code maxIdle} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param maxIdle The new setting of {@code maxIdle} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#setMaxIdle(int) |
||||
*/ |
||||
public void setMaxIdle(final int maxIdle) { |
||||
this.maxIdle = maxIdle; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get the value for the {@code minIdle} configuration attribute |
||||
* for pools created with this configuration instance. |
||||
* |
||||
* @return The current setting of {@code minIdle} for this |
||||
* configuration instance |
||||
* |
||||
* @see GenericObjectPool#getMinIdle() |
||||
*/ |
||||
public int getMinIdle() { |
||||
return minIdle; |
||||
} |
||||
|
||||
/** |
||||
* Set the value for the {@code minIdle} configuration attribute for |
||||
* pools created with this configuration instance. |
||||
* |
||||
* @param minIdle The new setting of {@code minIdle} |
||||
* for this configuration instance |
||||
* |
||||
* @see GenericObjectPool#setMinIdle(int) |
||||
*/ |
||||
public void setMinIdle(final int minIdle) { |
||||
this.minIdle = minIdle; |
||||
} |
||||
|
||||
@Override |
||||
public GenericObjectPoolConfig clone() { |
||||
try { |
||||
return (GenericObjectPoolConfig) super.clone(); |
||||
} catch (final CloneNotSupportedException e) { |
||||
throw new AssertionError(); // Can't happen
|
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
super.toStringAppendFields(builder); |
||||
builder.append(", maxTotal="); |
||||
builder.append(maxTotal); |
||||
builder.append(", maxIdle="); |
||||
builder.append(maxIdle); |
||||
builder.append(", minIdle="); |
||||
builder.append(minIdle); |
||||
} |
||||
} |
@ -0,0 +1,219 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Defines the methods that will be made available via JMX. |
||||
* |
||||
* NOTE: This interface exists only to define those attributes and methods that |
||||
* will be made available via JMX. It must not be implemented by clients |
||||
* as it is subject to change between major, minor and patch version |
||||
* releases of commons pool. Clients that implement this interface may |
||||
* not, therefore, be able to upgrade to a new minor or patch release |
||||
* without requiring code changes. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public interface GenericObjectPoolMXBean { |
||||
// Getters for basic configuration settings
|
||||
/** |
||||
* See {@link GenericObjectPool#getBlockWhenExhausted()} |
||||
* @return See {@link GenericObjectPool#getBlockWhenExhausted()} |
||||
*/ |
||||
boolean getBlockWhenExhausted(); |
||||
/** |
||||
* See {@link GenericObjectPool#getLifo()} |
||||
* @return See {@link GenericObjectPool#getLifo()} |
||||
*/ |
||||
boolean getFairness(); |
||||
/** |
||||
* See {@link GenericObjectPool#getFairness()} |
||||
* @return See {@link GenericObjectPool#getFairness()} |
||||
*/ |
||||
boolean getLifo(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMaxIdle()} |
||||
* @return See {@link GenericObjectPool#getMaxIdle()} |
||||
*/ |
||||
int getMaxIdle(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMaxTotal()} |
||||
* @return See {@link GenericObjectPool#getMaxTotal()} |
||||
*/ |
||||
int getMaxTotal(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMaxWaitMillis()} |
||||
* @return See {@link GenericObjectPool#getMaxWaitMillis()} |
||||
*/ |
||||
long getMaxWaitMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} |
||||
* @return See {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} |
||||
*/ |
||||
long getMinEvictableIdleTimeMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMinIdle()} |
||||
* @return See {@link GenericObjectPool#getMinIdle()} |
||||
*/ |
||||
int getMinIdle(); |
||||
/** |
||||
* See {@link GenericObjectPool#getNumActive()} |
||||
* @return See {@link GenericObjectPool#getNumActive()} |
||||
*/ |
||||
int getNumActive(); |
||||
/** |
||||
* See {@link GenericObjectPool#getNumIdle()} |
||||
* @return See {@link GenericObjectPool#getNumIdle()} |
||||
*/ |
||||
int getNumIdle(); |
||||
/** |
||||
* See {@link GenericObjectPool#getNumTestsPerEvictionRun()} |
||||
* @return See {@link GenericObjectPool#getNumTestsPerEvictionRun()} |
||||
*/ |
||||
int getNumTestsPerEvictionRun(); |
||||
/** |
||||
* See {@link GenericObjectPool#getTestOnCreate()} |
||||
* @return See {@link GenericObjectPool#getTestOnCreate()} |
||||
* @since 2.2 |
||||
*/ |
||||
boolean getTestOnCreate(); |
||||
/** |
||||
* See {@link GenericObjectPool#getTestOnBorrow()} |
||||
* @return See {@link GenericObjectPool#getTestOnBorrow()} |
||||
*/ |
||||
boolean getTestOnBorrow(); |
||||
/** |
||||
* See {@link GenericObjectPool#getTestOnReturn()} |
||||
* @return See {@link GenericObjectPool#getTestOnReturn()} |
||||
*/ |
||||
boolean getTestOnReturn(); |
||||
/** |
||||
* See {@link GenericObjectPool#getTestWhileIdle()} |
||||
* @return See {@link GenericObjectPool#getTestWhileIdle()} |
||||
*/ |
||||
boolean getTestWhileIdle(); |
||||
/** |
||||
* See {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()} |
||||
* @return See {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()} |
||||
*/ |
||||
long getTimeBetweenEvictionRunsMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#isClosed()} |
||||
* @return See {@link GenericObjectPool#isClosed()} |
||||
*/ |
||||
boolean isClosed(); |
||||
// Getters for monitoring attributes
|
||||
/** |
||||
* See {@link GenericObjectPool#getBorrowedCount()} |
||||
* @return See {@link GenericObjectPool#getBorrowedCount()} |
||||
*/ |
||||
long getBorrowedCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getReturnedCount()} |
||||
* @return See {@link GenericObjectPool#getReturnedCount()} |
||||
*/ |
||||
long getReturnedCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getCreatedCount()} |
||||
* @return See {@link GenericObjectPool#getCreatedCount()} |
||||
*/ |
||||
long getCreatedCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getDestroyedCount()} |
||||
* @return See {@link GenericObjectPool#getDestroyedCount()} |
||||
*/ |
||||
long getDestroyedCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getDestroyedByEvictorCount()} |
||||
* @return See {@link GenericObjectPool#getDestroyedByEvictorCount()} |
||||
*/ |
||||
long getDestroyedByEvictorCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()} |
||||
* @return See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()} |
||||
*/ |
||||
long getDestroyedByBorrowValidationCount(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMeanActiveTimeMillis()} |
||||
* @return See {@link GenericObjectPool#getMeanActiveTimeMillis()} |
||||
*/ |
||||
long getMeanActiveTimeMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMeanIdleTimeMillis()} |
||||
* @return See {@link GenericObjectPool#getMeanIdleTimeMillis()} |
||||
*/ |
||||
long getMeanIdleTimeMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()} |
||||
* @return See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()} |
||||
*/ |
||||
long getMeanBorrowWaitTimeMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
* @return See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()} |
||||
*/ |
||||
long getMaxBorrowWaitTimeMillis(); |
||||
/** |
||||
* See {@link GenericObjectPool#getCreationStackTrace()} |
||||
* @return See {@link GenericObjectPool#getCreationStackTrace()} |
||||
*/ |
||||
String getCreationStackTrace(); |
||||
/** |
||||
* See {@link GenericObjectPool#getNumWaiters()} |
||||
* @return See {@link GenericObjectPool#getNumWaiters()} |
||||
*/ |
||||
int getNumWaiters(); |
||||
|
||||
// Getters for abandoned object removal configuration
|
||||
/** |
||||
* See {@link GenericObjectPool#isAbandonedConfig()} |
||||
* @return See {@link GenericObjectPool#isAbandonedConfig()} |
||||
*/ |
||||
boolean isAbandonedConfig(); |
||||
/** |
||||
* See {@link GenericObjectPool#getLogAbandoned()} |
||||
* @return See {@link GenericObjectPool#getLogAbandoned()} |
||||
*/ |
||||
boolean getLogAbandoned(); |
||||
/** |
||||
* See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()} |
||||
* @return See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()} |
||||
*/ |
||||
boolean getRemoveAbandonedOnBorrow(); |
||||
/** |
||||
* See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()} |
||||
* @return See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()} |
||||
*/ |
||||
boolean getRemoveAbandonedOnMaintenance(); |
||||
/** |
||||
* See {@link GenericObjectPool#getRemoveAbandonedTimeout()} |
||||
* @return See {@link GenericObjectPool#getRemoveAbandonedTimeout()} |
||||
*/ |
||||
int getRemoveAbandonedTimeout(); |
||||
/** |
||||
* See {@link GenericObjectPool#getFactoryType()} |
||||
* @return See {@link GenericObjectPool#getFactoryType()} |
||||
*/ |
||||
public String getFactoryType(); |
||||
/** |
||||
* See {@link GenericObjectPool#listAllObjects()} |
||||
* @return See {@link GenericObjectPool#listAllObjects()} |
||||
*/ |
||||
Set<DefaultPooledObjectInfo> listAllObjects(); |
||||
} |
@ -0,0 +1,57 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.concurrent.locks.Condition; |
||||
import java.util.concurrent.locks.ReentrantLock; |
||||
|
||||
/** |
||||
* This sub-class was created to expose the waiting threads so that they can be |
||||
* interrupted when the pool using the queue that uses this lock is closed. The |
||||
* class is intended for internal use only. |
||||
* <p> |
||||
* This class is intended to be thread-safe. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class InterruptibleReentrantLock extends ReentrantLock { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* Create a new InterruptibleReentrantLock with the given fairness policy. |
||||
* |
||||
* @param fairness true means threads should acquire contended locks as if |
||||
* waiting in a FIFO queue |
||||
*/ |
||||
public InterruptibleReentrantLock(final boolean fairness) { |
||||
super(fairness); |
||||
} |
||||
|
||||
/** |
||||
* Interrupt the threads that are waiting on a specific condition |
||||
* |
||||
* @param condition the condition on which the threads are waiting. |
||||
*/ |
||||
public void interruptWaiters(final Condition condition) { |
||||
final Collection<Thread> threads = getWaitingThreads(condition); |
||||
for (final Thread thread : threads) { |
||||
thread.interrupt(); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.io.PrintWriter; |
||||
|
||||
/** |
||||
* CallStack strategy using no-op implementations of all functionality. Can be used by default when abandoned object |
||||
* logging is disabled. |
||||
* |
||||
* @since 2.5 |
||||
*/ |
||||
public class NoOpCallStack implements CallStack { |
||||
|
||||
public static final CallStack INSTANCE = new NoOpCallStack(); |
||||
|
||||
private NoOpCallStack() { |
||||
} |
||||
|
||||
@Override |
||||
public boolean printStackTrace(PrintWriter writer) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public void fillInStackTrace() { |
||||
// no-op
|
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
// no-op
|
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.lang.reflect.ParameterizedType; |
||||
import java.lang.reflect.Type; |
||||
import java.lang.reflect.TypeVariable; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectFactory; |
||||
|
||||
/** |
||||
* Implementation specific utilities. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class PoolImplUtils { |
||||
|
||||
/** |
||||
* Identifies the concrete type of object that an object factory creates. |
||||
* |
||||
* @param factory The factory to examine |
||||
* |
||||
* @return the type of object the factory creates |
||||
*/ |
||||
@SuppressWarnings("rawtypes") |
||||
static Class<?> getFactoryType(final Class<? extends PooledObjectFactory> factory) { |
||||
return (Class<?>) getGenericType(PooledObjectFactory.class, factory); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Obtain the concrete type used by an implementation of an interface that |
||||
* uses a generic type. |
||||
* |
||||
* @param type The interface that defines a generic type |
||||
* @param clazz The class that implements the interface with a concrete type |
||||
* @param <T> The interface type |
||||
* |
||||
* @return concrete type used by the implementation |
||||
*/ |
||||
private static <T> Object getGenericType(final Class<T> type, |
||||
final Class<? extends T> clazz) { |
||||
|
||||
// Look to see if this class implements the generic interface
|
||||
|
||||
// Get all the interfaces
|
||||
final Type[] interfaces = clazz.getGenericInterfaces(); |
||||
for (final Type iface : interfaces) { |
||||
// Only need to check interfaces that use generics
|
||||
if (iface instanceof ParameterizedType) { |
||||
final ParameterizedType pi = (ParameterizedType) iface; |
||||
// Look for the generic interface
|
||||
if (pi.getRawType() instanceof Class) { |
||||
if (type.isAssignableFrom((Class<?>) pi.getRawType())) { |
||||
return getTypeParameter( |
||||
clazz, pi.getActualTypeArguments()[0]); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Interface not found on this class. Look at the superclass.
|
||||
@SuppressWarnings("unchecked") |
||||
final |
||||
Class<? extends T> superClazz = |
||||
(Class<? extends T>) clazz.getSuperclass(); |
||||
|
||||
final Object result = getGenericType(type, superClazz); |
||||
if (result instanceof Class<?>) { |
||||
// Superclass implements interface and defines explicit type for
|
||||
// generic
|
||||
return result; |
||||
} else if (result instanceof Integer) { |
||||
// Superclass implements interface and defines unknown type for
|
||||
// generic
|
||||
// Map that unknown type to the generic types defined in this class
|
||||
final ParameterizedType superClassType = |
||||
(ParameterizedType) clazz.getGenericSuperclass(); |
||||
return getTypeParameter(clazz, |
||||
superClassType.getActualTypeArguments()[ |
||||
((Integer) result).intValue()]); |
||||
} else { |
||||
// Error will be logged further up the call stack
|
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* For a generic parameter, return either the Class used or if the type |
||||
* is unknown, the index for the type in definition of the class
|
||||
* |
||||
* @param clazz defining class
|
||||
* @param argType the type argument of interest |
||||
* |
||||
* @return An instance of {@link Class} representing the type used by the |
||||
* type parameter or an instance of {@link Integer} representing |
||||
* the index for the type in the definition of the defining class
|
||||
*/ |
||||
private static Object getTypeParameter(final Class<?> clazz, final Type argType) { |
||||
if (argType instanceof Class<?>) { |
||||
return argType; |
||||
} |
||||
final TypeVariable<?>[] tvs = clazz.getTypeParameters(); |
||||
for (int i = 0; i < tvs.length; i++) { |
||||
if (tvs[i].equals(argType)) { |
||||
return Integer.valueOf(i); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,98 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.lang.ref.SoftReference; |
||||
|
||||
/** |
||||
* Extension of {@link DefaultPooledObject} to wrap pooled soft references. |
||||
* |
||||
* <p>This class is intended to be thread-safe.</p> |
||||
* |
||||
* @param <T> the type of the underlying object that the wrapped SoftReference |
||||
* refers to. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class PooledSoftReference<T> extends DefaultPooledObject<T> { |
||||
|
||||
/** SoftReference wrapped by this object */ |
||||
private volatile SoftReference<T> reference; |
||||
|
||||
/** |
||||
* Creates a new PooledSoftReference wrapping the provided reference. |
||||
* |
||||
* @param reference SoftReference to be managed by the pool |
||||
*/ |
||||
public PooledSoftReference(final SoftReference<T> reference) { |
||||
super(null); // Null the hard reference in the parent
|
||||
this.reference = reference; |
||||
} |
||||
|
||||
/** |
||||
* Returns the object that the wrapped SoftReference refers to. |
||||
* <p> |
||||
* Note that if the reference has been cleared, this method will return |
||||
* null. |
||||
* |
||||
* @return Object referred to by the SoftReference |
||||
*/ |
||||
@Override |
||||
public T getObject() { |
||||
return reference.get(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder result = new StringBuilder(); |
||||
result.append("Referenced Object: "); |
||||
result.append(getObject().toString()); |
||||
result.append(", State: "); |
||||
synchronized (this) { |
||||
result.append(getState().toString()); |
||||
} |
||||
return result.toString(); |
||||
// TODO add other attributes
|
||||
// TODO encapsulate state and other attribute display in parent
|
||||
} |
||||
|
||||
/** |
||||
* Returns the SoftReference wrapped by this object. |
||||
* |
||||
* @return underlying SoftReference |
||||
*/ |
||||
public synchronized SoftReference<T> getReference() { |
||||
return reference; |
||||
} |
||||
|
||||
/** |
||||
* Sets the wrapped reference. |
||||
* |
||||
* <p>This method exists to allow a new, non-registered reference to be |
||||
* held by the pool to track objects that have been checked out of the pool. |
||||
* The actual parameter <strong>should</strong> be a reference to the same |
||||
* object that {@link #getObject()} returns before calling this method.</p> |
||||
* |
||||
* @param reference new reference |
||||
*/ |
||||
public synchronized void setReference(final SoftReference<T> reference) { |
||||
this.reference = reference; |
||||
} |
||||
} |
@ -0,0 +1,129 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.lang.ref.WeakReference; |
||||
import java.security.AccessController; |
||||
import java.security.PrivilegedAction; |
||||
import java.text.DateFormat; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* CallStack strategy using a {@link SecurityManager}. Obtaining the current call stack is much faster via a |
||||
* SecurityManger, but access to the underlying method may be restricted by the current SecurityManager. In environments |
||||
* where a SecurityManager cannot be created, {@link ThrowableCallStack} should be used instead. |
||||
* |
||||
* @see RuntimePermission |
||||
* @see SecurityManager#getClassContext() |
||||
* @since 2.4.3 |
||||
*/ |
||||
public class SecurityManagerCallStack implements CallStack { |
||||
|
||||
private final String messageFormat; |
||||
//@GuardedBy("dateFormat")
|
||||
private final DateFormat dateFormat; |
||||
private final PrivateSecurityManager securityManager; |
||||
|
||||
private volatile Snapshot snapshot; |
||||
|
||||
/** |
||||
* Create a new instance. |
||||
* |
||||
* @param messageFormat message format |
||||
* @param useTimestamp whether to format the dates in the output message or not |
||||
*/ |
||||
public SecurityManagerCallStack(final String messageFormat, final boolean useTimestamp) { |
||||
this.messageFormat = messageFormat; |
||||
this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null; |
||||
this.securityManager = AccessController.doPrivileged(new PrivilegedAction<PrivateSecurityManager>() { |
||||
@Override |
||||
public PrivateSecurityManager run() { |
||||
return new PrivateSecurityManager(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public boolean printStackTrace(final PrintWriter writer) { |
||||
final Snapshot snapshotRef = this.snapshot; |
||||
if (snapshotRef == null) { |
||||
return false; |
||||
} |
||||
final String message; |
||||
if (dateFormat == null) { |
||||
message = messageFormat; |
||||
} else { |
||||
synchronized (dateFormat) { |
||||
message = dateFormat.format(Long.valueOf(snapshotRef.timestamp)); |
||||
} |
||||
} |
||||
writer.println(message); |
||||
for (final WeakReference<Class<?>> reference : snapshotRef.stack) { |
||||
writer.println(reference.get()); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void fillInStackTrace() { |
||||
snapshot = new Snapshot(securityManager.getCallStack()); |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
snapshot = null; |
||||
} |
||||
|
||||
/** |
||||
* A custom security manager. |
||||
*/ |
||||
private static class PrivateSecurityManager extends SecurityManager { |
||||
/** |
||||
* Get the class stack. |
||||
* |
||||
* @return class stack |
||||
*/ |
||||
private List<WeakReference<Class<?>>> getCallStack() { |
||||
final Class<?>[] classes = getClassContext(); |
||||
final List<WeakReference<Class<?>>> stack = new ArrayList<WeakReference<Class<?>>>(classes.length); |
||||
for (final Class<?> klass : classes) { |
||||
stack.add(new WeakReference<Class<?>>(klass)); |
||||
} |
||||
return stack; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* A snapshot of a class stack. |
||||
*/ |
||||
private static class Snapshot { |
||||
private final long timestamp = System.currentTimeMillis(); |
||||
private final List<WeakReference<Class<?>>> stack; |
||||
|
||||
/** |
||||
* Create a new snapshot with a class stack. |
||||
* |
||||
* @param stack class stack |
||||
*/ |
||||
private Snapshot(final List<WeakReference<Class<?>>> stack) { |
||||
this.stack = stack; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,453 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.lang.ref.Reference; |
||||
import java.lang.ref.ReferenceQueue; |
||||
import java.lang.ref.SoftReference; |
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.BaseObjectPool; |
||||
import com.fr.third.org.apache.commons.pool2.ObjectPool; |
||||
import com.fr.third.org.apache.commons.pool2.PoolUtils; |
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectFactory; |
||||
|
||||
/** |
||||
* A {@link SoftReference SoftReference} based {@link ObjectPool}. |
||||
* <p> |
||||
* This class is intended to be thread-safe. |
||||
* |
||||
* @param <T> |
||||
* Type of element pooled in this pool. |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class SoftReferenceObjectPool<T> extends BaseObjectPool<T> { |
||||
|
||||
/** Factory to source pooled objects */ |
||||
private final PooledObjectFactory<T> factory; |
||||
|
||||
/** |
||||
* Queue of broken references that might be able to be removed from |
||||
* <code>_pool</code>. This is used to help {@link #getNumIdle()} be more |
||||
* accurate with minimal performance overhead. |
||||
*/ |
||||
private final ReferenceQueue<T> refQueue = new ReferenceQueue<T>(); |
||||
|
||||
/** Count of instances that have been checkout out to pool clients */ |
||||
private int numActive = 0; // @GuardedBy("this")
|
||||
|
||||
/** Total number of instances that have been destroyed */ |
||||
private long destroyCount = 0; // @GuardedBy("this")
|
||||
|
||||
|
||||
/** Total number of instances that have been created */ |
||||
private long createCount = 0; // @GuardedBy("this")
|
||||
|
||||
/** Idle references - waiting to be borrowed */ |
||||
private final LinkedBlockingDeque<PooledSoftReference<T>> idleReferences = |
||||
new LinkedBlockingDeque<PooledSoftReference<T>>(); |
||||
|
||||
/** All references - checked out or waiting to be borrowed. */ |
||||
private final ArrayList<PooledSoftReference<T>> allReferences = |
||||
new ArrayList<PooledSoftReference<T>>(); |
||||
|
||||
/** |
||||
* Create a <code>SoftReferenceObjectPool</code> with the specified factory. |
||||
* |
||||
* @param factory object factory to use. |
||||
*/ |
||||
public SoftReferenceObjectPool(final PooledObjectFactory<T> factory) { |
||||
this.factory = factory; |
||||
} |
||||
|
||||
/** |
||||
* Borrow an object from the pool. If there are no idle instances available |
||||
* in the pool, the configured factory's |
||||
* {@link PooledObjectFactory#makeObject()} method is invoked to create a |
||||
* new instance. |
||||
* <p> |
||||
* All instances are {@link PooledObjectFactory#activateObject( |
||||
* org.apache.commons.pool2.PooledObject) activated} |
||||
* and {@link PooledObjectFactory#validateObject( |
||||
* org.apache.commons.pool2.PooledObject) |
||||
* validated} before being returned by this method. If validation fails or |
||||
* an exception occurs activating or validating an idle instance, the |
||||
* failing instance is {@link PooledObjectFactory#destroyObject( |
||||
* org.apache.commons.pool2.PooledObject) |
||||
* destroyed} and another instance is retrieved from the pool, validated and |
||||
* activated. This process continues until either the pool is empty or an |
||||
* instance passes validation. If the pool is empty on activation or it does |
||||
* not contain any valid instances, the factory's <code>makeObject</code> |
||||
* method is used to create a new instance. If the created instance either |
||||
* raises an exception on activation or fails validation, |
||||
* <code>NoSuchElementException</code> is thrown. Exceptions thrown by |
||||
* <code>MakeObject</code> are propagated to the caller; but other than |
||||
* <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions |
||||
* generated by activation, validation or destroy methods are swallowed |
||||
* silently. |
||||
* |
||||
* @throws NoSuchElementException |
||||
* if a valid object cannot be provided |
||||
* @throws IllegalStateException |
||||
* if invoked on a {@link #close() closed} pool |
||||
* @throws Exception |
||||
* if an exception occurs creating a new instance |
||||
* @return a valid, activated object instance |
||||
*/ |
||||
@SuppressWarnings("null") // ref cannot be null
|
||||
@Override |
||||
public synchronized T borrowObject() throws Exception { |
||||
assertOpen(); |
||||
T obj = null; |
||||
boolean newlyCreated = false; |
||||
PooledSoftReference<T> ref = null; |
||||
while (null == obj) { |
||||
if (idleReferences.isEmpty()) { |
||||
if (null == factory) { |
||||
throw new NoSuchElementException(); |
||||
} |
||||
newlyCreated = true; |
||||
obj = factory.makeObject().getObject(); |
||||
createCount++; |
||||
// Do not register with the queue
|
||||
ref = new PooledSoftReference<T>(new SoftReference<T>(obj)); |
||||
allReferences.add(ref); |
||||
} else { |
||||
ref = idleReferences.pollFirst(); |
||||
obj = ref.getObject(); |
||||
// Clear the reference so it will not be queued, but replace with a
|
||||
// a new, non-registered reference so we can still track this object
|
||||
// in allReferences
|
||||
ref.getReference().clear(); |
||||
ref.setReference(new SoftReference<T>(obj)); |
||||
} |
||||
if (null != factory && null != obj) { |
||||
try { |
||||
factory.activateObject(ref); |
||||
if (!factory.validateObject(ref)) { |
||||
throw new Exception("ValidateObject failed"); |
||||
} |
||||
} catch (final Throwable t) { |
||||
PoolUtils.checkRethrow(t); |
||||
try { |
||||
destroy(ref); |
||||
} catch (final Throwable t2) { |
||||
PoolUtils.checkRethrow(t2); |
||||
// Swallowed
|
||||
} finally { |
||||
obj = null; |
||||
} |
||||
if (newlyCreated) { |
||||
throw new NoSuchElementException( |
||||
"Could not create a validated object, cause: " + |
||||
t.getMessage()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
numActive++; |
||||
ref.allocate(); |
||||
return obj; |
||||
} |
||||
|
||||
/** |
||||
* Returns an instance to the pool after successful validation and |
||||
* passivation. The returning instance is destroyed if any of the following |
||||
* are true: |
||||
* <ul> |
||||
* <li>the pool is closed</li> |
||||
* <li>{@link PooledObjectFactory#validateObject( |
||||
* org.apache.commons.pool2.PooledObject) validation} fails |
||||
* </li> |
||||
* <li>{@link PooledObjectFactory#passivateObject( |
||||
* org.apache.commons.pool2.PooledObject) passivation} |
||||
* throws an exception</li> |
||||
* </ul> |
||||
* Exceptions passivating or destroying instances are silently swallowed. |
||||
* Exceptions validating instances are propagated to the client. |
||||
* |
||||
* @param obj |
||||
* instance to return to the pool |
||||
*/ |
||||
@Override |
||||
public synchronized void returnObject(final T obj) throws Exception { |
||||
boolean success = !isClosed(); |
||||
final PooledSoftReference<T> ref = findReference(obj); |
||||
if (ref == null) { |
||||
throw new IllegalStateException( |
||||
"Returned object not currently part of this pool"); |
||||
} |
||||
if (factory != null) { |
||||
if (!factory.validateObject(ref)) { |
||||
success = false; |
||||
} else { |
||||
try { |
||||
factory.passivateObject(ref); |
||||
} catch (final Exception e) { |
||||
success = false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
final boolean shouldDestroy = !success; |
||||
numActive--; |
||||
if (success) { |
||||
|
||||
// Deallocate and add to the idle instance pool
|
||||
ref.deallocate(); |
||||
idleReferences.add(ref); |
||||
} |
||||
notifyAll(); // numActive has changed
|
||||
|
||||
if (shouldDestroy && factory != null) { |
||||
try { |
||||
destroy(ref); |
||||
} catch (final Exception e) { |
||||
// ignored
|
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public synchronized void invalidateObject(final T obj) throws Exception { |
||||
final PooledSoftReference<T> ref = findReference(obj); |
||||
if (ref == null) { |
||||
throw new IllegalStateException( |
||||
"Object to invalidate is not currently part of this pool"); |
||||
} |
||||
if (factory != null) { |
||||
destroy(ref); |
||||
} |
||||
numActive--; |
||||
notifyAll(); // numActive has changed
|
||||
} |
||||
|
||||
/** |
||||
* Create an object, and place it into the pool. addObject() is useful for |
||||
* "pre-loading" a pool with idle objects. |
||||
* <p> |
||||
* Before being added to the pool, the newly created instance is |
||||
* {@link PooledObjectFactory#validateObject( |
||||
* org.apache.commons.pool2.PooledObject) validated} and |
||||
* {@link PooledObjectFactory#passivateObject( |
||||
* org.apache.commons.pool2.PooledObject) passivated}. If |
||||
* validation fails, the new instance is |
||||
* {@link PooledObjectFactory#destroyObject( |
||||
* org.apache.commons.pool2.PooledObject) destroyed}. Exceptions |
||||
* generated by the factory <code>makeObject</code> or |
||||
* <code>passivate</code> are propagated to the caller. Exceptions |
||||
* destroying instances are silently swallowed. |
||||
* |
||||
* @throws IllegalStateException |
||||
* if invoked on a {@link #close() closed} pool |
||||
* @throws Exception |
||||
* when the {@link #getFactory() factory} has a problem creating |
||||
* or passivating an object. |
||||
*/ |
||||
@Override |
||||
public synchronized void addObject() throws Exception { |
||||
assertOpen(); |
||||
if (factory == null) { |
||||
throw new IllegalStateException( |
||||
"Cannot add objects without a factory."); |
||||
} |
||||
final T obj = factory.makeObject().getObject(); |
||||
createCount++; |
||||
// Create and register with the queue
|
||||
final PooledSoftReference<T> ref = new PooledSoftReference<T>( |
||||
new SoftReference<T>(obj, refQueue)); |
||||
allReferences.add(ref); |
||||
|
||||
boolean success = true; |
||||
if (!factory.validateObject(ref)) { |
||||
success = false; |
||||
} else { |
||||
factory.passivateObject(ref); |
||||
} |
||||
|
||||
final boolean shouldDestroy = !success; |
||||
if (success) { |
||||
idleReferences.add(ref); |
||||
notifyAll(); // numActive has changed
|
||||
} |
||||
|
||||
if (shouldDestroy) { |
||||
try { |
||||
destroy(ref); |
||||
} catch (final Exception e) { |
||||
// ignored
|
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns an approximation not less than the of the number of idle |
||||
* instances in the pool. |
||||
* |
||||
* @return estimated number of idle instances in the pool |
||||
*/ |
||||
@Override |
||||
public synchronized int getNumIdle() { |
||||
pruneClearedReferences(); |
||||
return idleReferences.size(); |
||||
} |
||||
|
||||
/** |
||||
* Return the number of instances currently borrowed from this pool. |
||||
* |
||||
* @return the number of instances currently borrowed from this pool |
||||
*/ |
||||
@Override |
||||
public synchronized int getNumActive() { |
||||
return numActive; |
||||
} |
||||
|
||||
/** |
||||
* Clears any objects sitting idle in the pool. |
||||
*/ |
||||
@Override |
||||
public synchronized void clear() { |
||||
if (null != factory) { |
||||
final Iterator<PooledSoftReference<T>> iter = idleReferences.iterator(); |
||||
while (iter.hasNext()) { |
||||
try { |
||||
final PooledSoftReference<T> ref = iter.next(); |
||||
if (null != ref.getObject()) { |
||||
factory.destroyObject(ref); |
||||
} |
||||
} catch (final Exception e) { |
||||
// ignore error, keep destroying the rest
|
||||
} |
||||
} |
||||
} |
||||
idleReferences.clear(); |
||||
pruneClearedReferences(); |
||||
} |
||||
|
||||
/** |
||||
* Close this pool, and free any resources associated with it. Invokes |
||||
* {@link #clear()} to destroy and remove instances in the pool. |
||||
* <p> |
||||
* Calling {@link #addObject} or {@link #borrowObject} after invoking this |
||||
* method on a pool will cause them to throw an |
||||
* {@link IllegalStateException}. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
super.close(); |
||||
clear(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the {@link PooledObjectFactory} used by this pool to create and |
||||
* manage object instances. |
||||
* |
||||
* @return the factory |
||||
*/ |
||||
public synchronized PooledObjectFactory<T> getFactory() { |
||||
return factory; |
||||
} |
||||
|
||||
/** |
||||
* If any idle objects were garbage collected, remove their |
||||
* {@link Reference} wrappers from the idle object pool. |
||||
*/ |
||||
private void pruneClearedReferences() { |
||||
// Remove wrappers for enqueued references from idle and allReferences lists
|
||||
removeClearedReferences(idleReferences.iterator()); |
||||
removeClearedReferences(allReferences.iterator()); |
||||
while (refQueue.poll() != null) { |
||||
// empty
|
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Find the PooledSoftReference in allReferences that points to obj. |
||||
* |
||||
* @param obj returning object |
||||
* @return PooledSoftReference wrapping a soft reference to obj |
||||
*/ |
||||
private PooledSoftReference<T> findReference(final T obj) { |
||||
final Iterator<PooledSoftReference<T>> iterator = allReferences.iterator(); |
||||
while (iterator.hasNext()) { |
||||
final PooledSoftReference<T> reference = iterator.next(); |
||||
if (reference.getObject() != null && reference.getObject().equals(obj)) { |
||||
return reference; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Destroy a {@code PooledSoftReference} and remove it from the idle and all |
||||
* references pools. |
||||
* |
||||
* @param toDestroy PooledSoftReference to destroy |
||||
* |
||||
* @throws Exception If an error occurs while trying to destroy the object |
||||
*/ |
||||
private void destroy(final PooledSoftReference<T> toDestroy) throws Exception { |
||||
toDestroy.invalidate(); |
||||
idleReferences.remove(toDestroy); |
||||
allReferences.remove(toDestroy); |
||||
try { |
||||
factory.destroyObject(toDestroy); |
||||
} finally { |
||||
destroyCount++; |
||||
toDestroy.getReference().clear(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Clears cleared references from iterator's collection |
||||
* @param iterator iterator over idle/allReferences |
||||
*/ |
||||
private void removeClearedReferences(final Iterator<PooledSoftReference<T>> iterator) { |
||||
PooledSoftReference<T> ref; |
||||
while (iterator.hasNext()) { |
||||
ref = iterator.next(); |
||||
if (ref.getReference() == null || ref.getReference().isEnqueued()) { |
||||
iterator.remove(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void toStringAppendFields(final StringBuilder builder) { |
||||
super.toStringAppendFields(builder); |
||||
builder.append(", factory="); |
||||
builder.append(factory); |
||||
builder.append(", refQueue="); |
||||
builder.append(refQueue); |
||||
builder.append(", numActive="); |
||||
builder.append(numActive); |
||||
builder.append(", destroyCount="); |
||||
builder.append(destroyCount); |
||||
builder.append(", createCount="); |
||||
builder.append(createCount); |
||||
builder.append(", idleReferences="); |
||||
builder.append(idleReferences); |
||||
builder.append(", allReferences="); |
||||
builder.append(allReferences); |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.impl; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.text.DateFormat; |
||||
import java.text.SimpleDateFormat; |
||||
|
||||
/** |
||||
* CallStack strategy that uses the stack trace from a {@link Throwable}. This strategy, while slower than the |
||||
* SecurityManager implementation, provides call stack method names and other metadata in addition to the call stack |
||||
* of classes. |
||||
* |
||||
* @see Throwable#fillInStackTrace() |
||||
* @since 2.4.3 |
||||
*/ |
||||
public class ThrowableCallStack implements CallStack { |
||||
|
||||
private final String messageFormat; |
||||
//@GuardedBy("dateFormat")
|
||||
private final DateFormat dateFormat; |
||||
|
||||
private volatile Snapshot snapshot; |
||||
|
||||
/** |
||||
* Create a new instance. |
||||
* |
||||
* @param messageFormat message format |
||||
* @param useTimestamp whether to format the dates in the output message or not |
||||
*/ |
||||
public ThrowableCallStack(final String messageFormat, final boolean useTimestamp) { |
||||
this.messageFormat = messageFormat; |
||||
this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null; |
||||
} |
||||
|
||||
@Override |
||||
public synchronized boolean printStackTrace(final PrintWriter writer) { |
||||
final Snapshot snapshotRef = this.snapshot; |
||||
if (snapshotRef == null) { |
||||
return false; |
||||
} |
||||
final String message; |
||||
if (dateFormat == null) { |
||||
message = messageFormat; |
||||
} else { |
||||
synchronized (dateFormat) { |
||||
message = dateFormat.format(Long.valueOf(snapshotRef.timestamp)); |
||||
} |
||||
} |
||||
writer.println(message); |
||||
snapshotRef.printStackTrace(writer); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void fillInStackTrace() { |
||||
snapshot = new Snapshot(); |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
snapshot = null; |
||||
} |
||||
|
||||
/** |
||||
* A snapshot of a throwable. |
||||
*/ |
||||
private static class Snapshot extends Throwable { |
||||
private static final long serialVersionUID = 1L; |
||||
private final long timestamp = System.currentTimeMillis(); |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
<!-- |
||||
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. |
||||
--> |
||||
<!-- $Id$ --> |
||||
<html> |
||||
<head> |
||||
<title>Package Documentation for org.apache.commons.pool2.impl</title> |
||||
</head> |
||||
<body> |
||||
<p> |
||||
Object pooling API implementations. |
||||
</p> |
||||
<p> |
||||
{@link org.apache.commons.pool2.impl.GenericObjectPool GenericObjectPool} |
||||
({@link org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool}) |
||||
provides a more robust (but also more complicated) |
||||
implementation of {@link org.apache.commons.pool2.ObjectPool ObjectPool} |
||||
({@link org.apache.commons.pool2.KeyedObjectPool KeyedObjectPool}). |
||||
</p> |
||||
<p> |
||||
{@link org.apache.commons.pool2.impl.SoftReferenceObjectPool SoftReferenceObjectPool} |
||||
provides a {@link java.lang.ref.SoftReference SoftReference} based |
||||
{@link org.apache.commons.pool2.ObjectPool ObjectPool}. |
||||
</p> |
||||
<p> |
||||
See also the {@link org.apache.commons.pool2} package. |
||||
</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,50 @@
|
||||
<!-- |
||||
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. |
||||
--> |
||||
<!-- $Id$ --> |
||||
<html> |
||||
<head> |
||||
<title>Overview of the org.apache.commons.pool2 component</title> |
||||
</head> |
||||
<body> |
||||
<p> |
||||
Generic Object pooling API with several implementations. |
||||
</p> |
||||
<p> |
||||
The <code>org.apache.commons.pool2</code> package defines a simple |
||||
interface for a pool of object instances, and a handful of base |
||||
classes that may be useful when creating pool implementations. |
||||
The API supports pooling of unique objects which can be requested |
||||
via a key as well as pools where all objects are equivalent. |
||||
</p> |
||||
<p> |
||||
The <code>org.apache.commons.pool2.impl</code> package contains |
||||
several pool implementations. |
||||
{@link org.apache.commons.pool2.impl.GenericObjectPool |
||||
GenericObjectPool} has many configuration options and can support |
||||
a limited set of objects such as would be useful in a database |
||||
connection pool. |
||||
{@link org.apache.commons.pool2.impl.SoftReferenceObjectPool |
||||
SoftReferenceObjectPool} has no limit on the number of objects in the |
||||
pool, but the garbage collector can remove idle objects from the pool |
||||
as needed. There is also a keyed version of |
||||
{@link org.apache.commons.pool2.impl.GenericObjectPool |
||||
GenericObjectPool}, |
||||
{@link org.apache.commons.pool2.impl.GenericKeyedObjectPool |
||||
GenericKeyedObjectPool} |
||||
</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,63 @@
|
||||
<!-- |
||||
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. |
||||
--> |
||||
<!-- $Id$ --> |
||||
<html> |
||||
<head> |
||||
<title>Package Documentation for org.apache.commons.pool2</title> |
||||
</head> |
||||
<body> |
||||
<p> |
||||
Object pooling API. |
||||
</p> |
||||
<p> |
||||
The <code>org.apache.commons.pool2</code> package defines a simple |
||||
interface for a pool of object instances, and a handful of base |
||||
classes that may be useful when creating pool implementations. |
||||
</p> |
||||
<p> |
||||
The <code>pool</code> package itself doesn't define a specific object |
||||
pooling implementation, but rather a contract that implementations may |
||||
support in order to be fully interchangeable. |
||||
</p> |
||||
<p> |
||||
The <code>pool</code> package separates the way in which instances are |
||||
pooled from the way in which they are created, resulting in a pair of |
||||
interfaces: |
||||
</p> |
||||
<dl> |
||||
<dt>{@link org.apache.commons.pool2.ObjectPool ObjectPool}</dt> |
||||
<dd> |
||||
defines a simple object pooling interface, with methods for |
||||
borrowing instances from and returning them to the pool. |
||||
</dd> |
||||
<dt>{@link org.apache.commons.pool2.PooledObjectFactory PooledObjectFactory}</dt> |
||||
<dd> |
||||
defines lifecycle methods for object instances contained within a pool. |
||||
By associating a factory with a pool, the pool can create new object |
||||
instances as needed. |
||||
</dd> |
||||
</dl> |
||||
<p> |
||||
The <code>pool</code> package also provides a keyed pool interface, |
||||
which pools instances of multiple types, accessed according to an |
||||
arbitrary key. See |
||||
{@link org.apache.commons.pool2.KeyedObjectPool KeyedObjectPool} and |
||||
{@link org.apache.commons.pool2.KeyedPooledObjectFactory |
||||
KeyedPooledObjectFactory}. |
||||
</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,121 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Base implementation for object wrappers when using a |
||||
* {@link ProxiedObjectPool}. |
||||
* |
||||
* @param <T> type of the wrapped pooled object |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class BaseProxyHandler<T> { |
||||
|
||||
private volatile T pooledObject; |
||||
private final UsageTracking<T> usageTracking; |
||||
|
||||
|
||||
/** |
||||
* Create a new wrapper for the given pooled object. |
||||
* |
||||
* @param pooledObject The object to wrap |
||||
* @param usageTracking The instance, if any (usually the object pool) to |
||||
* be provided with usage tracking information for this |
||||
* wrapped object |
||||
*/ |
||||
BaseProxyHandler(final T pooledObject, final UsageTracking<T> usageTracking) { |
||||
this.pooledObject = pooledObject; |
||||
this.usageTracking = usageTracking; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Obtain the wrapped, pooled object. |
||||
* |
||||
* @return the underlying pooled object |
||||
*/ |
||||
T getPooledObject() { |
||||
return pooledObject; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Disable the proxy wrapper. Called when the object has been returned to |
||||
* the pool. Further use of the wrapper should result in an |
||||
* {@link IllegalStateException}. |
||||
* |
||||
* @return the object that this proxy was wrapping |
||||
*/ |
||||
T disableProxy() { |
||||
final T result = pooledObject; |
||||
pooledObject = null; |
||||
return result; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Check that the proxy is still valid (i.e. that {@link #disableProxy()} |
||||
* has not been called). |
||||
* |
||||
* @throws IllegalStateException if {@link #disableProxy()} has been called |
||||
*/ |
||||
void validateProxiedObject() { |
||||
if (pooledObject == null) { |
||||
throw new IllegalStateException("This object may no longer be " + |
||||
"used as it has been returned to the Object Pool."); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Invoke the given method on the wrapped object. |
||||
* |
||||
* @param method The method to invoke |
||||
* @param args The arguments to the method |
||||
* @return The result of the method call |
||||
* @throws Throwable If the method invocation fails |
||||
*/ |
||||
Object doInvoke(final Method method, final Object[] args) throws Throwable { |
||||
validateProxiedObject(); |
||||
final T object = getPooledObject(); |
||||
if (usageTracking != null) { |
||||
usageTracking.use(object); |
||||
} |
||||
return method.invoke(object, args); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append(getClass().getName()); |
||||
builder.append(" [pooledObject="); |
||||
builder.append(pooledObject); |
||||
builder.append(", usageTracking="); |
||||
builder.append(usageTracking); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
import com.fr.third.net.sf.cglib.proxy.MethodInterceptor; |
||||
import com.fr.third.net.sf.cglib.proxy.MethodProxy; |
||||
|
||||
/** |
||||
* CGLib implementation of the proxy handler. |
||||
* |
||||
* @param <T> type of the wrapped pooled object |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class CglibProxyHandler<T> extends BaseProxyHandler<T> |
||||
implements MethodInterceptor { |
||||
|
||||
|
||||
/** |
||||
* Create a CGLib proxy instance. |
||||
* |
||||
* @param pooledObject The object to wrap |
||||
* @param usageTracking The instance, if any (usually the object pool) to |
||||
* be provided with usage tracking information for this |
||||
* wrapped object |
||||
*/ |
||||
CglibProxyHandler(final T pooledObject, final UsageTracking<T> usageTracking) { |
||||
super(pooledObject, usageTracking); |
||||
} |
||||
|
||||
@Override |
||||
public Object intercept(final Object object, final Method method, final Object[] args, |
||||
final MethodProxy methodProxy) throws Throwable { |
||||
return doInvoke(method, args); |
||||
} |
||||
} |
@ -0,0 +1,82 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import com.fr.third.net.sf.cglib.proxy.Enhancer; |
||||
import com.fr.third.net.sf.cglib.proxy.Factory; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Provides proxy objects using CGLib. |
||||
* |
||||
* @param <T> type of the pooled object to be proxied |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class CglibProxySource<T> implements ProxySource<T> { |
||||
|
||||
private final Class<? extends T> superclass; |
||||
|
||||
/** |
||||
* Create a new proxy source for the given class. |
||||
* |
||||
* @param superclass The class to proxy |
||||
*/ |
||||
public CglibProxySource(final Class<? extends T> superclass) { |
||||
this.superclass = superclass; |
||||
} |
||||
|
||||
@Override |
||||
public T createProxy(final T pooledObject, final UsageTracking<T> usageTracking) { |
||||
final Enhancer enhancer = new Enhancer(); |
||||
enhancer.setSuperclass(superclass); |
||||
|
||||
final CglibProxyHandler<T> proxyInterceptor = |
||||
new CglibProxyHandler<T>(pooledObject, usageTracking); |
||||
enhancer.setCallback(proxyInterceptor); |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
final |
||||
T proxy = (T) enhancer.create(); |
||||
|
||||
return proxy; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public T resolveProxy(final T proxy) { |
||||
@SuppressWarnings("unchecked") |
||||
final |
||||
CglibProxyHandler<T> cglibProxyHandler = |
||||
(CglibProxyHandler<T>) ((Factory) proxy).getCallback(0); |
||||
final T pooledObject = cglibProxyHandler.disableProxy(); |
||||
return pooledObject; |
||||
} |
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("CglibProxySource [superclass="); |
||||
builder.append(superclass); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,53 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.lang.reflect.InvocationHandler; |
||||
import java.lang.reflect.Method; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Java reflection implementation of the proxy handler. |
||||
* |
||||
* @param <T> type of the wrapped pooled object |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
class JdkProxyHandler<T> extends BaseProxyHandler<T> |
||||
implements InvocationHandler { |
||||
|
||||
/** |
||||
* Create a Java reflection proxy instance. |
||||
* |
||||
* @param pooledObject The object to wrap |
||||
* @param usageTracking The instance, if any (usually the object pool) to |
||||
* be provided with usage tracking information for this |
||||
* wrapped object |
||||
*/ |
||||
JdkProxyHandler(final T pooledObject, final UsageTracking<T> usageTracking) { |
||||
super(pooledObject, usageTracking); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public Object invoke(final Object proxy, final Method method, final Object[] args) |
||||
throws Throwable { |
||||
return doInvoke(method, args); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,85 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.lang.reflect.Proxy; |
||||
import java.util.Arrays; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Provides proxy objects using Java reflection. |
||||
* |
||||
* @param <T> type of the pooled object to be proxied |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class JdkProxySource<T> implements ProxySource<T> { |
||||
|
||||
private final ClassLoader classLoader; |
||||
private final Class<?>[] interfaces; |
||||
|
||||
|
||||
/** |
||||
* Create a new proxy source for the given interfaces. |
||||
* |
||||
* @param classLoader The class loader with which to create the proxy |
||||
* @param interfaces The interfaces to proxy |
||||
*/ |
||||
public JdkProxySource(final ClassLoader classLoader, final Class<?>[] interfaces) { |
||||
this.classLoader = classLoader; |
||||
// Defensive copy
|
||||
this.interfaces = new Class<?>[interfaces.length]; |
||||
System.arraycopy(interfaces, 0, this.interfaces, 0, interfaces.length); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public T createProxy(final T pooledObject, final UsageTracking<T> usageTracking) { |
||||
@SuppressWarnings("unchecked") |
||||
final |
||||
T proxy = (T) Proxy.newProxyInstance(classLoader, interfaces, |
||||
new JdkProxyHandler<T>(pooledObject, usageTracking)); |
||||
return proxy; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public T resolveProxy(final T proxy) { |
||||
@SuppressWarnings("unchecked") |
||||
final |
||||
JdkProxyHandler<T> jdkProxyHandler = |
||||
(JdkProxyHandler<T>) Proxy.getInvocationHandler(proxy); |
||||
final T pooledObject = jdkProxyHandler.disableProxy(); |
||||
return pooledObject; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("JdkProxySource [classLoader="); |
||||
builder.append(classLoader); |
||||
builder.append(", interfaces="); |
||||
builder.append(Arrays.toString(interfaces)); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,134 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.util.NoSuchElementException; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.KeyedObjectPool; |
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Create a new keyed object pool where the pooled objects are wrapped in |
||||
* proxies allowing better control of pooled objects and in particular the |
||||
* prevention of the continued use of an object by a client after that client |
||||
* returns the object to the pool. |
||||
* |
||||
* @param <K> type of the key |
||||
* @param <V> type of the pooled object |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class ProxiedKeyedObjectPool<K,V> implements KeyedObjectPool<K,V> { |
||||
|
||||
private final KeyedObjectPool<K,V> pool; |
||||
private final ProxySource<V> proxySource; |
||||
|
||||
|
||||
/** |
||||
* Create a new proxied object pool. |
||||
* |
||||
* @param pool The object pool to wrap |
||||
* @param proxySource The source of the proxy objects |
||||
*/ |
||||
public ProxiedKeyedObjectPool(final KeyedObjectPool<K,V> pool, |
||||
final ProxySource<V> proxySource) { |
||||
this.pool = pool; |
||||
this.proxySource = proxySource; |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public V borrowObject(final K key) throws Exception, NoSuchElementException, |
||||
IllegalStateException { |
||||
UsageTracking<V> usageTracking = null; |
||||
if (pool instanceof UsageTracking) { |
||||
usageTracking = (UsageTracking<V>) pool; |
||||
} |
||||
final V pooledObject = pool.borrowObject(key); |
||||
final V proxy = proxySource.createProxy(pooledObject, usageTracking); |
||||
return proxy; |
||||
} |
||||
|
||||
@Override |
||||
public void returnObject(final K key, final V proxy) throws Exception { |
||||
final V pooledObject = proxySource.resolveProxy(proxy); |
||||
pool.returnObject(key, pooledObject); |
||||
} |
||||
|
||||
@Override |
||||
public void invalidateObject(final K key, final V proxy) throws Exception { |
||||
final V pooledObject = proxySource.resolveProxy(proxy); |
||||
pool.invalidateObject(key, pooledObject); |
||||
} |
||||
|
||||
@Override |
||||
public void addObject(final K key) throws Exception, IllegalStateException, |
||||
UnsupportedOperationException { |
||||
pool.addObject(key); |
||||
} |
||||
|
||||
@Override |
||||
public int getNumIdle(final K key) { |
||||
return pool.getNumIdle(key); |
||||
} |
||||
|
||||
@Override |
||||
public int getNumActive(final K key) { |
||||
return pool.getNumActive(key); |
||||
} |
||||
|
||||
@Override |
||||
public int getNumIdle() { |
||||
return pool.getNumIdle(); |
||||
} |
||||
|
||||
@Override |
||||
public int getNumActive() { |
||||
return pool.getNumActive(); |
||||
} |
||||
|
||||
@Override |
||||
public void clear() throws Exception, UnsupportedOperationException { |
||||
pool.clear(); |
||||
} |
||||
|
||||
@Override |
||||
public void clear(final K key) throws Exception, UnsupportedOperationException { |
||||
pool.clear(key); |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
pool.close(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("ProxiedKeyedObjectPool [pool="); |
||||
builder.append(pool); |
||||
builder.append(", proxySource="); |
||||
builder.append(proxySource); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import java.util.NoSuchElementException; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.ObjectPool; |
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* Create a new object pool where the pooled objects are wrapped in proxies |
||||
* allowing better control of pooled objects and in particular the prevention |
||||
* of the continued use of an object by a client after that client returns the |
||||
* object to the pool. |
||||
* |
||||
* @param <T> type of the pooled object |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
public class ProxiedObjectPool<T> implements ObjectPool<T> { |
||||
|
||||
private final ObjectPool<T> pool; |
||||
private final ProxySource<T> proxySource; |
||||
|
||||
|
||||
/** |
||||
* Create a new proxied object pool. |
||||
* |
||||
* @param pool The object pool to wrap |
||||
* @param proxySource The source of the proxy objects |
||||
*/ |
||||
public ProxiedObjectPool(final ObjectPool<T> pool, final ProxySource<T> proxySource) { |
||||
this.pool = pool; |
||||
this.proxySource = proxySource; |
||||
} |
||||
|
||||
|
||||
// --------------------------------------------------- ObjectPool<T> methods
|
||||
|
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public T borrowObject() throws Exception, NoSuchElementException, |
||||
IllegalStateException { |
||||
UsageTracking<T> usageTracking = null; |
||||
if (pool instanceof UsageTracking) { |
||||
usageTracking = (UsageTracking<T>) pool; |
||||
} |
||||
final T pooledObject = pool.borrowObject(); |
||||
final T proxy = proxySource.createProxy(pooledObject, usageTracking); |
||||
return proxy; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void returnObject(final T proxy) throws Exception { |
||||
final T pooledObject = proxySource.resolveProxy(proxy); |
||||
pool.returnObject(pooledObject); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void invalidateObject(final T proxy) throws Exception { |
||||
final T pooledObject = proxySource.resolveProxy(proxy); |
||||
pool.invalidateObject(pooledObject); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void addObject() throws Exception, IllegalStateException, |
||||
UnsupportedOperationException { |
||||
pool.addObject(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getNumIdle() { |
||||
return pool.getNumIdle(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getNumActive() { |
||||
return pool.getNumActive(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void clear() throws Exception, UnsupportedOperationException { |
||||
pool.clear(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void close() { |
||||
pool.close(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @since 2.4.3 |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
final StringBuilder builder = new StringBuilder(); |
||||
builder.append("ProxiedObjectPool [pool="); |
||||
builder.append(pool); |
||||
builder.append(", proxySource="); |
||||
builder.append(proxySource); |
||||
builder.append("]"); |
||||
return builder.toString(); |
||||
} |
||||
} |
@ -0,0 +1,51 @@
|
||||
/* |
||||
* 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 com.fr.third.org.apache.commons.pool2.proxy; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.UsageTracking; |
||||
|
||||
/** |
||||
* The interface that any provider of proxy instances must implement to allow the |
||||
* {@link ProxiedObjectPool} to create proxies as required. |
||||
* |
||||
* @param <T> type of the pooled object to be proxied |
||||
* |
||||
* @since 2.0 |
||||
*/ |
||||
interface ProxySource<T> { |
||||
|
||||
/** |
||||
* Create a new proxy object, wrapping the given pooled object. |
||||
* |
||||
* @param pooledObject The object to wrap |
||||
* @param usageTracking The instance, if any (usually the object pool) to |
||||
* be provided with usage tracking information for this |
||||
* wrapped object |
||||
* |
||||
* @return the new proxy object |
||||
*/ |
||||
T createProxy(T pooledObject, UsageTracking<T> usageTracking); |
||||
|
||||
/** |
||||
* Obtain the wrapped object from the given proxy. |
||||
* |
||||
* @param proxy The proxy object |
||||
* |
||||
* @return The pooled object wrapped by the given proxy |
||||
*/ |
||||
T resolveProxy(T proxy); |
||||
} |
@ -0,0 +1,37 @@
|
||||
<!-- |
||||
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. |
||||
--> |
||||
<html> |
||||
<head> |
||||
<title>Package Documentation for org.apache.commons.pool2.proxy</title> |
||||
</head> |
||||
<body> |
||||
<p> |
||||
Object pooling proxy implementation. |
||||
</p> |
||||
<p> |
||||
The <code>org.apache.commons.pool2.proxy</code> package defines a |
||||
object pool that wraps all objects returned to clients. This allows it |
||||
to disable those proxies when the objects are returned thereby enabling |
||||
the continued use of those objects by clients to be detected.. |
||||
</p> |
||||
<p> |
||||
Support is provided for <code>java.lang.reflect.Proxy</code> and for |
||||
<code>net.sf.cglib.proxy</code> based proxies. The latter, requires the |
||||
additional of the optional Code Generation Library (GCLib). |
||||
</p> |
||||
</body> |
||||
</html> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,127 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.MESSAGE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PMESSAGE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.SUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
|
||||
public abstract class BinaryJedisPubSub { |
||||
private int subscribedChannels = 0; |
||||
private Client client; |
||||
|
||||
public void onMessage(byte[] channel, byte[] message) { |
||||
} |
||||
|
||||
public void onPMessage(byte[] pattern, byte[] channel, byte[] message) { |
||||
} |
||||
|
||||
public void onSubscribe(byte[] channel, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onUnsubscribe(byte[] channel, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onPUnsubscribe(byte[] pattern, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onPSubscribe(byte[] pattern, int subscribedChannels) { |
||||
} |
||||
|
||||
public void unsubscribe() { |
||||
client.unsubscribe(); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void unsubscribe(byte[]... channels) { |
||||
client.unsubscribe(channels); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void subscribe(byte[]... channels) { |
||||
client.subscribe(channels); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void psubscribe(byte[]... patterns) { |
||||
client.psubscribe(patterns); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void punsubscribe() { |
||||
client.punsubscribe(); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void punsubscribe(byte[]... patterns) { |
||||
client.punsubscribe(patterns); |
||||
client.flush(); |
||||
} |
||||
|
||||
public boolean isSubscribed() { |
||||
return subscribedChannels > 0; |
||||
} |
||||
|
||||
public void proceedWithPatterns(Client client, byte[]... patterns) { |
||||
this.client = client; |
||||
client.psubscribe(patterns); |
||||
client.flush(); |
||||
process(client); |
||||
} |
||||
|
||||
public void proceed(Client client, byte[]... channels) { |
||||
this.client = client; |
||||
client.subscribe(channels); |
||||
client.flush(); |
||||
process(client); |
||||
} |
||||
|
||||
private void process(Client client) { |
||||
do { |
||||
List<Object> reply = client.getRawObjectMultiBulkReply(); |
||||
final Object firstObj = reply.get(0); |
||||
if (!(firstObj instanceof byte[])) { |
||||
throw new JedisException("Unknown message type: " + firstObj); |
||||
} |
||||
final byte[] resp = (byte[]) firstObj; |
||||
if (Arrays.equals(SUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
onSubscribe(bchannel, subscribedChannels); |
||||
} else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
onUnsubscribe(bchannel, subscribedChannels); |
||||
} else if (Arrays.equals(MESSAGE.raw, resp)) { |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
final byte[] bmesg = (byte[]) reply.get(2); |
||||
onMessage(bchannel, bmesg); |
||||
} else if (Arrays.equals(PMESSAGE.raw, resp)) { |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
final byte[] bchannel = (byte[]) reply.get(2); |
||||
final byte[] bmesg = (byte[]) reply.get(3); |
||||
onPMessage(bpattern, bchannel, bmesg); |
||||
} else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
onPSubscribe(bpattern, subscribedChannels); |
||||
} else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
onPUnsubscribe(bpattern, subscribedChannels); |
||||
} else { |
||||
throw new JedisException("Unknown message type: " + firstObj); |
||||
} |
||||
} while (isSubscribed()); |
||||
} |
||||
|
||||
public int getSubscribedChannels() { |
||||
return subscribedChannels; |
||||
} |
||||
} |
@ -0,0 +1,925 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.fr.third.redis.clients.jedis.commands.BinaryJedisCommands; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.params.GeoRadiusParam; |
||||
import com.fr.third.redis.clients.jedis.params.SetParams; |
||||
import com.fr.third.redis.clients.jedis.params.ZAddParams; |
||||
import com.fr.third.redis.clients.jedis.params.ZIncrByParams; |
||||
import com.fr.third.redis.clients.jedis.util.Hashing; |
||||
import com.fr.third.redis.clients.jedis.util.Sharded; |
||||
|
||||
public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo> implements |
||||
BinaryJedisCommands { |
||||
public BinaryShardedJedis(List<JedisShardInfo> shards) { |
||||
super(shards); |
||||
} |
||||
|
||||
public BinaryShardedJedis(List<JedisShardInfo> shards, Hashing algo) { |
||||
super(shards, algo); |
||||
} |
||||
|
||||
public BinaryShardedJedis(List<JedisShardInfo> shards, Pattern keyTagPattern) { |
||||
super(shards, keyTagPattern); |
||||
} |
||||
|
||||
public BinaryShardedJedis(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) { |
||||
super(shards, algo, keyTagPattern); |
||||
} |
||||
|
||||
public void disconnect() { |
||||
for (Jedis jedis : getAllShards()) { |
||||
if (jedis.isConnected()) { |
||||
try { |
||||
jedis.quit(); |
||||
} catch (JedisConnectionException e) { |
||||
// ignore the exception node, so that all other normal nodes can release all connections.
|
||||
} |
||||
try { |
||||
jedis.disconnect(); |
||||
} catch (JedisConnectionException e) { |
||||
// ignore the exception node, so that all other normal nodes can release all connections.
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected Jedis create(JedisShardInfo shard) { |
||||
return new Jedis(shard); |
||||
} |
||||
|
||||
@Override |
||||
public String set(final byte[] key, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.set(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public String set(final byte[] key, final byte[] value, SetParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.set(key, value, params); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] get(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.get(key); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean exists(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.exists(key); |
||||
} |
||||
|
||||
@Override |
||||
public String type(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.type(key); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] dump(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.dump(key); |
||||
} |
||||
|
||||
@Override |
||||
public String restore(final byte[] key, final int ttl, final byte[] serializedValue) { |
||||
Jedis j = getShard(key); |
||||
return j.restore(key, ttl, serializedValue); |
||||
} |
||||
|
||||
@Override |
||||
public Long expire(final byte[] key, final int seconds) { |
||||
Jedis j = getShard(key); |
||||
return j.expire(key, seconds); |
||||
} |
||||
|
||||
@Override |
||||
public Long pexpire(final byte[] key, final long milliseconds) { |
||||
Jedis j = getShard(key); |
||||
return j.pexpire(key, milliseconds); |
||||
} |
||||
|
||||
@Override |
||||
public Long expireAt(final byte[] key, final long unixTime) { |
||||
Jedis j = getShard(key); |
||||
return j.expireAt(key, unixTime); |
||||
} |
||||
|
||||
@Override |
||||
public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) { |
||||
Jedis j = getShard(key); |
||||
return j.pexpireAt(key, millisecondsTimestamp); |
||||
} |
||||
|
||||
@Override |
||||
public Long ttl(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.ttl(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long pttl(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.pttl(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long touch(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.touch(key); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] getSet(final byte[] key, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.getSet(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long setnx(final byte[] key, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.setnx(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public String setex(final byte[] key, final int seconds, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.setex(key, seconds, value); |
||||
} |
||||
|
||||
@Override |
||||
public String psetex(final byte[] key, final long milliseconds, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.psetex(key, milliseconds, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long decrBy(final byte[] key, final long decrement) { |
||||
Jedis j = getShard(key); |
||||
return j.decrBy(key, decrement); |
||||
} |
||||
|
||||
@Override |
||||
public Long decr(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.decr(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long del(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.del(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long unlink(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.unlink(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long incrBy(final byte[] key, final long increment) { |
||||
Jedis j = getShard(key); |
||||
return j.incrBy(key, increment); |
||||
} |
||||
|
||||
@Override |
||||
public Double incrByFloat(final byte[] key, final double increment) { |
||||
Jedis j = getShard(key); |
||||
return j.incrByFloat(key, increment); |
||||
} |
||||
|
||||
@Override |
||||
public Long incr(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.incr(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long append(final byte[] key, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.append(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] substr(final byte[] key, final int start, final int end) { |
||||
Jedis j = getShard(key); |
||||
return j.substr(key, start, end); |
||||
} |
||||
|
||||
@Override |
||||
public Long hset(final byte[] key, final byte[] field, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.hset(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long hset(final byte[] key, final Map<byte[], byte[]> hash) { |
||||
Jedis j = getShard(key); |
||||
return j.hset(key, hash); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] hget(final byte[] key, final byte[] field) { |
||||
Jedis j = getShard(key); |
||||
return j.hget(key, field); |
||||
} |
||||
|
||||
@Override |
||||
public Long hsetnx(final byte[] key, final byte[] field, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.hsetnx(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public String hmset(final byte[] key, final Map<byte[], byte[]> hash) { |
||||
Jedis j = getShard(key); |
||||
return j.hmset(key, hash); |
||||
} |
||||
|
||||
@Override |
||||
public List<byte[]> hmget(final byte[] key, final byte[]... fields) { |
||||
Jedis j = getShard(key); |
||||
return j.hmget(key, fields); |
||||
} |
||||
|
||||
@Override |
||||
public Long hincrBy(final byte[] key, final byte[] field, final long value) { |
||||
Jedis j = getShard(key); |
||||
return j.hincrBy(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Double hincrByFloat(final byte[] key, final byte[] field, final double value) { |
||||
Jedis j = getShard(key); |
||||
return j.hincrByFloat(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean hexists(final byte[] key, final byte[] field) { |
||||
Jedis j = getShard(key); |
||||
return j.hexists(key, field); |
||||
} |
||||
|
||||
@Override |
||||
public Long hdel(final byte[] key, final byte[]... fields) { |
||||
Jedis j = getShard(key); |
||||
return j.hdel(key, fields); |
||||
} |
||||
|
||||
@Override |
||||
public Long hlen(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.hlen(key); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> hkeys(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.hkeys(key); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<byte[]> hvals(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.hvals(key); |
||||
} |
||||
|
||||
@Override |
||||
public Map<byte[], byte[]> hgetAll(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.hgetAll(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long rpush(final byte[] key, final byte[]... strings) { |
||||
Jedis j = getShard(key); |
||||
return j.rpush(key, strings); |
||||
} |
||||
|
||||
@Override |
||||
public Long lpush(final byte[] key, final byte[]... strings) { |
||||
Jedis j = getShard(key); |
||||
return j.lpush(key, strings); |
||||
} |
||||
|
||||
@Override |
||||
public Long strlen(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.strlen(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long lpushx(final byte[] key, final byte[]... string) { |
||||
Jedis j = getShard(key); |
||||
return j.lpushx(key, string); |
||||
} |
||||
|
||||
@Override |
||||
public Long persist(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.persist(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long rpushx(final byte[] key, final byte[]... string) { |
||||
Jedis j = getShard(key); |
||||
return j.rpushx(key, string); |
||||
} |
||||
|
||||
@Override |
||||
public Long llen(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.llen(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<byte[]> lrange(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.lrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public String ltrim(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.ltrim(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] lindex(final byte[] key, final long index) { |
||||
Jedis j = getShard(key); |
||||
return j.lindex(key, index); |
||||
} |
||||
|
||||
@Override |
||||
public String lset(final byte[] key, final long index, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.lset(key, index, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long lrem(final byte[] key, final long count, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.lrem(key, count, value); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] lpop(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.lpop(key); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] rpop(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.rpop(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long sadd(final byte[] key, final byte[]... members) { |
||||
Jedis j = getShard(key); |
||||
return j.sadd(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> smembers(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.smembers(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long srem(final byte[] key, final byte[]... members) { |
||||
Jedis j = getShard(key); |
||||
return j.srem(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] spop(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.spop(key); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> spop(final byte[] key, final long count) { |
||||
Jedis j = getShard(key); |
||||
return j.spop(key, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long scard(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.scard(key); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean sismember(final byte[] key, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.sismember(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] srandmember(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.srandmember(key); |
||||
} |
||||
|
||||
@Override |
||||
public List srandmember(final byte[] key, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.srandmember(key, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final byte[] key, final double score, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, score, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final byte[] key, final double score, final byte[] member, final ZAddParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, score, member, params); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, scoreMembers); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers, final ZAddParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, scoreMembers, params); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrange(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrem(final byte[] key, final byte[]... members) { |
||||
Jedis j = getShard(key); |
||||
return j.zrem(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public Double zincrby(final byte[] key, final double increment, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.zincrby(key, increment, member); |
||||
} |
||||
|
||||
@Override |
||||
public Double zincrby(final byte[] key, final double increment, final byte[] member, ZIncrByParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zincrby(key, increment, member, params); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrank(final byte[] key, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.zrank(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrevrank(final byte[] key, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrank(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrange(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeWithScores(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeWithScores(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeWithScores(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeWithScores(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcard(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.zcard(key); |
||||
} |
||||
|
||||
@Override |
||||
public Double zscore(final byte[] key, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.zscore(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public List<byte[]> sort(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.sort(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<byte[]> sort(final byte[] key, SortingParams sortingParameters) { |
||||
Jedis j = getShard(key); |
||||
return j.sort(key, sortingParameters); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcount(final byte[] key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcount(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByScore(final byte[] key, final double min, final double max, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, final byte[] max, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, final double min, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max, final double min, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByRank(final byte[] key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByRank(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByScore(final byte[] key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByScore(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zlexcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByLex(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max, |
||||
final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByLex(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByLex(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<byte[]> zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByLex(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByLex(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long linsert(final byte[] key, final ListPosition where, final byte[] pivot, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.linsert(key, where, pivot, value); |
||||
} |
||||
|
||||
public ShardedJedisPipeline pipelined() { |
||||
ShardedJedisPipeline pipeline = new ShardedJedisPipeline(); |
||||
pipeline.setShardedJedis(this); |
||||
return pipeline; |
||||
} |
||||
|
||||
public Long objectRefcount(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.objectRefcount(key); |
||||
} |
||||
|
||||
public byte[] objectEncoding(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.objectEncoding(key); |
||||
} |
||||
|
||||
public Long objectIdletime(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.objectIdletime(key); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean setbit(final byte[] key, final long offset, boolean value) { |
||||
Jedis j = getShard(key); |
||||
return j.setbit(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean setbit(final byte[] key, final long offset, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.setbit(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean getbit(final byte[] key, final long offset) { |
||||
Jedis j = getShard(key); |
||||
return j.getbit(key, offset); |
||||
} |
||||
|
||||
@Override |
||||
public Long setrange(final byte[] key, final long offset, final byte[] value) { |
||||
Jedis j = getShard(key); |
||||
return j.setrange(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] getrange(final byte[] key, final long startOffset, final long endOffset) { |
||||
Jedis j = getShard(key); |
||||
return j.getrange(key, startOffset, endOffset); |
||||
} |
||||
|
||||
@Override |
||||
public Long move(final byte[] key, final int dbIndex) { |
||||
Jedis j = getShard(key); |
||||
return j.move(key, dbIndex); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] echo(final byte[] arg) { |
||||
Jedis j = getShard(arg); |
||||
return j.echo(arg); |
||||
} |
||||
|
||||
public List<byte[]> brpop(final byte[] arg) { |
||||
Jedis j = getShard(arg); |
||||
return j.brpop(arg); |
||||
} |
||||
|
||||
public List<byte[]> blpop(final byte[] arg) { |
||||
Jedis j = getShard(arg); |
||||
return j.blpop(arg); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitcount(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.bitcount(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitcount(final byte[] key, final long start, final long end) { |
||||
Jedis j = getShard(key); |
||||
return j.bitcount(key, start, end); |
||||
} |
||||
|
||||
@Override |
||||
public Long pfadd(final byte[] key, final byte[]... elements) { |
||||
Jedis j = getShard(key); |
||||
return j.pfadd(key, elements); |
||||
} |
||||
|
||||
@Override |
||||
public long pfcount(final byte[] key) { |
||||
Jedis j = getShard(key); |
||||
return j.pfcount(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long geoadd(final byte[] key, final double longitude, final double latitude, final byte[] member) { |
||||
Jedis j = getShard(key); |
||||
return j.geoadd(key, longitude, latitude, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long geoadd(final byte[] key, final Map<byte[], GeoCoordinate> memberCoordinateMap) { |
||||
Jedis j = getShard(key); |
||||
return j.geoadd(key, memberCoordinateMap); |
||||
} |
||||
|
||||
@Override |
||||
public Double geodist(final byte[] key, final byte[] member1, final byte[] member2) { |
||||
Jedis j = getShard(key); |
||||
return j.geodist(key, member1, member2); |
||||
} |
||||
|
||||
@Override |
||||
public Double geodist(final byte[] key, final byte[] member1, final byte[] member2, final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.geodist(key, member1, member2, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<byte[]> geohash(final byte[] key, final byte[]... members) { |
||||
Jedis j = getShard(key); |
||||
return j.geohash(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoCoordinate> geopos(final byte[] key, final byte[]... members) { |
||||
Jedis j = getShard(key); |
||||
return j.geopos(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude, final double latitude, |
||||
final double radius, final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.georadius(key, longitude, latitude, radius, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude, final double latitude, |
||||
final double radius, final GeoUnit unit, final GeoRadiusParam param) { |
||||
Jedis j = getShard(key); |
||||
return j.georadius(key, longitude, latitude, radius, unit, param); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member, final double radius, |
||||
final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.georadiusByMember(key, member, radius, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member, final double radius, |
||||
final GeoUnit unit, final GeoRadiusParam param) { |
||||
Jedis j = getShard(key); |
||||
return j.georadiusByMember(key, member, radius, unit, param); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key, final byte[] cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.hscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key, final byte[] cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.hscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.sscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.sscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.zscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public List<Long> bitfield(final byte[] key, final byte[]... arguments) { |
||||
Jedis j = getShard(key); |
||||
return j.bitfield(key, arguments); |
||||
} |
||||
|
||||
@Override |
||||
public Long hstrlen(final byte[] key, final byte[] field) { |
||||
Jedis j = getShard(key); |
||||
return j.hstrlen(key, field); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,11 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public enum BitOP { |
||||
AND, OR, XOR, NOT; |
||||
|
||||
public final byte[] raw; |
||||
|
||||
private BitOP() { |
||||
this.raw = com.fr.third.redis.clients.jedis.util.SafeEncoder.encode(name()); |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class BitPosParams { |
||||
private List<byte[]> params = new ArrayList<byte[]>(); |
||||
|
||||
protected BitPosParams() { |
||||
} |
||||
|
||||
public BitPosParams(long start) { |
||||
params.add(Protocol.toByteArray(start)); |
||||
} |
||||
|
||||
public BitPosParams(long start, long end) { |
||||
this(start); |
||||
|
||||
params.add(Protocol.toByteArray(end)); |
||||
} |
||||
|
||||
public Collection<byte[]> getParams() { |
||||
return Collections.unmodifiableCollection(params); |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public abstract class Builder<T> { |
||||
public abstract T build(Object data); |
||||
} |
@ -0,0 +1,482 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.Iterator; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.JedisByteHashMap; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public final class BuilderFactory { |
||||
public static final Builder<Double> DOUBLE = new Builder<Double>() { |
||||
@Override |
||||
public Double build(Object data) { |
||||
String string = STRING.build(data); |
||||
if (string == null) return null; |
||||
try { |
||||
return Double.valueOf(string); |
||||
} catch (NumberFormatException e) { |
||||
if (string.equals("inf") || string.equals("+inf")) return Double.POSITIVE_INFINITY; |
||||
if (string.equals("-inf")) return Double.NEGATIVE_INFINITY; |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "double"; |
||||
} |
||||
}; |
||||
public static final Builder<Boolean> BOOLEAN = new Builder<Boolean>() { |
||||
@Override |
||||
public Boolean build(Object data) { |
||||
return ((Long) data) == 1; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "boolean"; |
||||
} |
||||
}; |
||||
public static final Builder<byte[]> BYTE_ARRAY = new Builder<byte[]>() { |
||||
@Override |
||||
public byte[] build(Object data) { |
||||
return ((byte[]) data); // deleted == 1
|
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "byte[]"; |
||||
} |
||||
}; |
||||
|
||||
public static final Builder<Long> LONG = new Builder<Long>() { |
||||
@Override |
||||
public Long build(Object data) { |
||||
return (Long) data; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "long"; |
||||
} |
||||
|
||||
}; |
||||
public static final Builder<String> STRING = new Builder<String>() { |
||||
@Override |
||||
public String build(Object data) { |
||||
return data == null ? null : SafeEncoder.encode((byte[]) data); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "string"; |
||||
} |
||||
|
||||
}; |
||||
public static final Builder<List<String>> STRING_LIST = new Builder<List<String>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public List<String> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
final ArrayList<String> result = new ArrayList<String>(l.size()); |
||||
for (final byte[] barray : l) { |
||||
if (barray == null) { |
||||
result.add(null); |
||||
} else { |
||||
result.add(SafeEncoder.encode(barray)); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "List<String>"; |
||||
} |
||||
|
||||
}; |
||||
public static final Builder<Map<String, String>> STRING_MAP = new Builder<Map<String, String>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Map<String, String> build(Object data) { |
||||
final List<byte[]> flatHash = (List<byte[]>) data; |
||||
final Map<String, String> hash = new HashMap<String, String>(flatHash.size()/2, 1); |
||||
final Iterator<byte[]> iterator = flatHash.iterator(); |
||||
while (iterator.hasNext()) { |
||||
hash.put(SafeEncoder.encode(iterator.next()), SafeEncoder.encode(iterator.next())); |
||||
} |
||||
|
||||
return hash; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Map<String, String>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Map<String, String>> PUBSUB_NUMSUB_MAP = new Builder<Map<String, String>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Map<String, String> build(Object data) { |
||||
final List<Object> flatHash = (List<Object>) data; |
||||
final Map<String, String> hash = new HashMap<String, String>(flatHash.size()/2, 1); |
||||
final Iterator<Object> iterator = flatHash.iterator(); |
||||
while (iterator.hasNext()) { |
||||
hash.put(SafeEncoder.encode((byte[]) iterator.next()), |
||||
String.valueOf((Long) iterator.next())); |
||||
} |
||||
|
||||
return hash; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "PUBSUB_NUMSUB_MAP<String, String>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Set<String>> STRING_SET = new Builder<Set<String>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Set<String> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
final Set<String> result = new HashSet<String>(l.size(), 1); |
||||
for (final byte[] barray : l) { |
||||
if (barray == null) { |
||||
result.add(null); |
||||
} else { |
||||
result.add(SafeEncoder.encode(barray)); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Set<String>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<List<byte[]>> BYTE_ARRAY_LIST = new Builder<List<byte[]>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public List<byte[]> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
|
||||
return l; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "List<byte[]>"; |
||||
} |
||||
}; |
||||
|
||||
public static final Builder<Set<byte[]>> BYTE_ARRAY_ZSET = new Builder<Set<byte[]>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Set<byte[]> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
final Set<byte[]> result = new LinkedHashSet<byte[]>(l); |
||||
for (final byte[] barray : l) { |
||||
if (barray == null) { |
||||
result.add(null); |
||||
} else { |
||||
result.add(barray); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ZSet<byte[]>"; |
||||
} |
||||
}; |
||||
public static final Builder<Map<byte[], byte[]>> BYTE_ARRAY_MAP = new Builder<Map<byte[], byte[]>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Map<byte[], byte[]> build(Object data) { |
||||
final List<byte[]> flatHash = (List<byte[]>) data; |
||||
final Map<byte[], byte[]> hash = new JedisByteHashMap(); |
||||
final Iterator<byte[]> iterator = flatHash.iterator(); |
||||
while (iterator.hasNext()) { |
||||
hash.put(iterator.next(), iterator.next()); |
||||
} |
||||
|
||||
return hash; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Map<byte[], byte[]>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Set<String>> STRING_ZSET = new Builder<Set<String>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Set<String> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
final Set<String> result = new LinkedHashSet<String>(l.size(), 1); |
||||
for (final byte[] barray : l) { |
||||
if (barray == null) { |
||||
result.add(null); |
||||
} else { |
||||
result.add(SafeEncoder.encode(barray)); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ZSet<String>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Set<Tuple>> TUPLE_ZSET = new Builder<Set<Tuple>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public Set<Tuple> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
List<byte[]> l = (List<byte[]>) data; |
||||
final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size()/2, 1); |
||||
Iterator<byte[]> iterator = l.iterator(); |
||||
while (iterator.hasNext()) { |
||||
result.add(new Tuple(iterator.next(), DOUBLE.build(iterator.next()))); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ZSet<Tuple>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Object> EVAL_RESULT = new Builder<Object>() { |
||||
|
||||
@Override |
||||
public Object build(Object data) { |
||||
return evalResult(data); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Eval<Object>"; |
||||
} |
||||
|
||||
private Object evalResult(Object result) { |
||||
if (result instanceof byte[]) return SafeEncoder.encode((byte[]) result); |
||||
|
||||
if (result instanceof List<?>) { |
||||
List<?> list = (List<?>) result; |
||||
List<Object> listResult = new ArrayList<Object>(list.size()); |
||||
for (Object bin : list) { |
||||
listResult.add(evalResult(bin)); |
||||
} |
||||
|
||||
return listResult; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<Object> EVAL_BINARY_RESULT = new Builder<Object>() { |
||||
|
||||
@Override |
||||
public Object build(Object data) { |
||||
return evalResult(data); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Eval<Object>"; |
||||
} |
||||
|
||||
private Object evalResult(Object result) { |
||||
if (result instanceof List<?>) { |
||||
List<?> list = (List<?>) result; |
||||
List<Object> listResult = new ArrayList<Object>(list.size()); |
||||
for (Object bin : list) { |
||||
listResult.add(evalResult(bin)); |
||||
} |
||||
|
||||
return listResult; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
}; |
||||
|
||||
public static final Builder<List<GeoCoordinate>> GEO_COORDINATE_LIST = new Builder<List<GeoCoordinate>>() { |
||||
@Override |
||||
public List<GeoCoordinate> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
return interpretGeoposResult((List<Object>) data); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "List<GeoCoordinate>"; |
||||
} |
||||
|
||||
private List<GeoCoordinate> interpretGeoposResult(List<Object> responses) { |
||||
List<GeoCoordinate> responseCoordinate = new ArrayList<GeoCoordinate>(responses.size()); |
||||
for (Object response : responses) { |
||||
if (response == null) { |
||||
responseCoordinate.add(null); |
||||
} else { |
||||
List<Object> respList = (List<Object>) response; |
||||
GeoCoordinate coord = new GeoCoordinate(DOUBLE.build(respList.get(0)), |
||||
DOUBLE.build(respList.get(1))); |
||||
responseCoordinate.add(coord); |
||||
} |
||||
} |
||||
return responseCoordinate; |
||||
} |
||||
}; |
||||
|
||||
public static final Builder<List<GeoRadiusResponse>> GEORADIUS_WITH_PARAMS_RESULT = new Builder<List<GeoRadiusResponse>>() { |
||||
@Override |
||||
public List<GeoRadiusResponse> build(Object data) { |
||||
if (data == null) { |
||||
return null; |
||||
} |
||||
|
||||
List<Object> objectList = (List<Object>) data; |
||||
|
||||
List<GeoRadiusResponse> responses = new ArrayList<GeoRadiusResponse>(objectList.size()); |
||||
if (objectList.isEmpty()) { |
||||
return responses; |
||||
} |
||||
|
||||
if (objectList.get(0) instanceof List<?>) { |
||||
// list of members with additional informations
|
||||
GeoRadiusResponse resp; |
||||
for (Object obj : objectList) { |
||||
List<Object> informations = (List<Object>) obj; |
||||
|
||||
resp = new GeoRadiusResponse((byte[]) informations.get(0)); |
||||
|
||||
int size = informations.size(); |
||||
for (int idx = 1; idx < size; idx++) { |
||||
Object info = informations.get(idx); |
||||
if (info instanceof List<?>) { |
||||
// coordinate
|
||||
List<Object> coord = (List<Object>) info; |
||||
|
||||
resp.setCoordinate(new GeoCoordinate(DOUBLE.build(coord.get(0)), |
||||
DOUBLE.build(coord.get(1)))); |
||||
} else { |
||||
// distance
|
||||
resp.setDistance(DOUBLE.build(info)); |
||||
} |
||||
} |
||||
|
||||
responses.add(resp); |
||||
} |
||||
} else { |
||||
// list of members
|
||||
for (Object obj : objectList) { |
||||
responses.add(new GeoRadiusResponse((byte[]) obj)); |
||||
} |
||||
} |
||||
|
||||
return responses; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "GeoRadiusWithParamsResult"; |
||||
} |
||||
}; |
||||
|
||||
|
||||
public static final Builder<List<Module>> MODULE_LIST = new Builder<List<Module>>() { |
||||
@Override |
||||
public List<Module> build(Object data) { |
||||
if (data == null) { |
||||
return null; |
||||
} |
||||
|
||||
List<List<Object>> objectList = (List<List<Object>>) data; |
||||
|
||||
List<Module> responses = new ArrayList<Module>(objectList.size()); |
||||
if (objectList.isEmpty()) { |
||||
return responses; |
||||
} |
||||
|
||||
for (List<Object> moduleResp: objectList) { |
||||
Module m = new Module(SafeEncoder.encode((byte[]) moduleResp.get(1)), ((Long) moduleResp.get(3)).intValue()); |
||||
responses.add(m); |
||||
} |
||||
|
||||
return responses; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "List<Module>"; |
||||
} |
||||
}; |
||||
|
||||
public static final Builder<List<Long>> LONG_LIST = new Builder<List<Long>>() { |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public List<Long> build(Object data) { |
||||
if (null == data) { |
||||
return null; |
||||
} |
||||
return (List<Long>) data; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "List<Long>"; |
||||
} |
||||
|
||||
}; |
||||
|
||||
|
||||
private BuilderFactory() { |
||||
throw new InstantiationError( "Must not instantiate this class" ); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public enum ClusterReset { |
||||
SOFT, HARD |
||||
} |
@ -0,0 +1,328 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Closeable; |
||||
import java.io.IOException; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.Socket; |
||||
import java.net.SocketException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import javax.net.ssl.HostnameVerifier; |
||||
import javax.net.ssl.SSLParameters; |
||||
import javax.net.ssl.SSLSocket; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
|
||||
import com.fr.third.redis.clients.jedis.commands.ProtocolCommand; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisDataException; |
||||
import com.fr.third.redis.clients.jedis.util.IOUtils; |
||||
import com.fr.third.redis.clients.jedis.util.RedisInputStream; |
||||
import com.fr.third.redis.clients.jedis.util.RedisOutputStream; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class Connection implements Closeable { |
||||
|
||||
private static final byte[][] EMPTY_ARGS = new byte[0][]; |
||||
|
||||
private String host = Protocol.DEFAULT_HOST; |
||||
private int port = Protocol.DEFAULT_PORT; |
||||
private Socket socket; |
||||
private RedisOutputStream outputStream; |
||||
private RedisInputStream inputStream; |
||||
private int connectionTimeout = Protocol.DEFAULT_TIMEOUT; |
||||
private int soTimeout = Protocol.DEFAULT_TIMEOUT; |
||||
private boolean broken = false; |
||||
private boolean ssl; |
||||
private SSLSocketFactory sslSocketFactory; |
||||
private SSLParameters sslParameters; |
||||
private HostnameVerifier hostnameVerifier; |
||||
|
||||
public Connection() { |
||||
} |
||||
|
||||
public Connection(final String host) { |
||||
this.host = host; |
||||
} |
||||
|
||||
public Connection(final String host, final int port) { |
||||
this.host = host; |
||||
this.port = port; |
||||
} |
||||
|
||||
public Connection(final String host, final int port, final boolean ssl) { |
||||
this.host = host; |
||||
this.port = port; |
||||
this.ssl = ssl; |
||||
} |
||||
|
||||
public Connection(final String host, final int port, final boolean ssl, |
||||
SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this.host = host; |
||||
this.port = port; |
||||
this.ssl = ssl; |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
public Socket getSocket() { |
||||
return socket; |
||||
} |
||||
|
||||
public int getConnectionTimeout() { |
||||
return connectionTimeout; |
||||
} |
||||
|
||||
public int getSoTimeout() { |
||||
return soTimeout; |
||||
} |
||||
|
||||
public void setConnectionTimeout(int connectionTimeout) { |
||||
this.connectionTimeout = connectionTimeout; |
||||
} |
||||
|
||||
public void setSoTimeout(int soTimeout) { |
||||
this.soTimeout = soTimeout; |
||||
} |
||||
|
||||
public void setTimeoutInfinite() { |
||||
try { |
||||
if (!isConnected()) { |
||||
connect(); |
||||
} |
||||
socket.setSoTimeout(0); |
||||
} catch (SocketException ex) { |
||||
broken = true; |
||||
throw new JedisConnectionException(ex); |
||||
} |
||||
} |
||||
|
||||
public void rollbackTimeout() { |
||||
try { |
||||
socket.setSoTimeout(soTimeout); |
||||
} catch (SocketException ex) { |
||||
broken = true; |
||||
throw new JedisConnectionException(ex); |
||||
} |
||||
} |
||||
|
||||
public void sendCommand(final ProtocolCommand cmd, final String... args) { |
||||
final byte[][] bargs = new byte[args.length][]; |
||||
for (int i = 0; i < args.length; i++) { |
||||
bargs[i] = SafeEncoder.encode(args[i]); |
||||
} |
||||
sendCommand(cmd, bargs); |
||||
} |
||||
|
||||
public void sendCommand(final ProtocolCommand cmd) { |
||||
sendCommand(cmd, EMPTY_ARGS); |
||||
} |
||||
|
||||
public void sendCommand(final ProtocolCommand cmd, final byte[]... args) { |
||||
try { |
||||
connect(); |
||||
Protocol.sendCommand(outputStream, cmd, args); |
||||
} catch (JedisConnectionException ex) { |
||||
/* |
||||
* When client send request which formed by invalid protocol, Redis send back error message |
||||
* before close connection. We try to read it to provide reason of failure. |
||||
*/ |
||||
try { |
||||
String errorMessage = Protocol.readErrorLineIfPossible(inputStream); |
||||
if (errorMessage != null && errorMessage.length() > 0) { |
||||
ex = new JedisConnectionException(errorMessage, ex.getCause()); |
||||
} |
||||
} catch (Exception e) { |
||||
/* |
||||
* Catch any IOException or JedisConnectionException occurred from InputStream#read and just |
||||
* ignore. This approach is safe because reading error message is optional and connection |
||||
* will eventually be closed. |
||||
*/ |
||||
} |
||||
// Any other exceptions related to connection?
|
||||
broken = true; |
||||
throw ex; |
||||
} |
||||
} |
||||
|
||||
public String getHost() { |
||||
return host; |
||||
} |
||||
|
||||
public void setHost(final String host) { |
||||
this.host = host; |
||||
} |
||||
|
||||
public int getPort() { |
||||
return port; |
||||
} |
||||
|
||||
public void setPort(final int port) { |
||||
this.port = port; |
||||
} |
||||
|
||||
public void connect() { |
||||
if (!isConnected()) { |
||||
try { |
||||
socket = new Socket(); |
||||
// ->@wjw_add
|
||||
socket.setReuseAddress(true); |
||||
socket.setKeepAlive(true); // Will monitor the TCP connection is
|
||||
// valid
|
||||
socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
|
||||
// ensure timely delivery of data
|
||||
socket.setSoLinger(true, 0); // Control calls close () method,
|
||||
// the underlying socket is closed
|
||||
// immediately
|
||||
// <-@wjw_add
|
||||
|
||||
socket.connect(new InetSocketAddress(host, port), connectionTimeout); |
||||
socket.setSoTimeout(soTimeout); |
||||
|
||||
if (ssl) { |
||||
if (null == sslSocketFactory) { |
||||
sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault(); |
||||
} |
||||
socket = sslSocketFactory.createSocket(socket, host, port, true); |
||||
if (null != sslParameters) { |
||||
((SSLSocket) socket).setSSLParameters(sslParameters); |
||||
} |
||||
if ((null != hostnameVerifier) && |
||||
(!hostnameVerifier.verify(host, ((SSLSocket) socket).getSession()))) { |
||||
String message = String.format( |
||||
"The connection to '%s' failed ssl/tls hostname verification.", host); |
||||
throw new JedisConnectionException(message); |
||||
} |
||||
} |
||||
|
||||
outputStream = new RedisOutputStream(socket.getOutputStream()); |
||||
inputStream = new RedisInputStream(socket.getInputStream()); |
||||
} catch (IOException ex) { |
||||
broken = true; |
||||
throw new JedisConnectionException("Failed connecting to host " |
||||
+ host + ":" + port, ex); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
disconnect(); |
||||
} |
||||
|
||||
public void disconnect() { |
||||
if (isConnected()) { |
||||
try { |
||||
outputStream.flush(); |
||||
socket.close(); |
||||
} catch (IOException ex) { |
||||
broken = true; |
||||
throw new JedisConnectionException(ex); |
||||
} finally { |
||||
IOUtils.closeQuietly(socket); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public boolean isConnected() { |
||||
return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected() |
||||
&& !socket.isInputShutdown() && !socket.isOutputShutdown(); |
||||
} |
||||
|
||||
public String getStatusCodeReply() { |
||||
flush(); |
||||
final byte[] resp = (byte[]) readProtocolWithCheckingBroken(); |
||||
if (null == resp) { |
||||
return null; |
||||
} else { |
||||
return SafeEncoder.encode(resp); |
||||
} |
||||
} |
||||
|
||||
public String getBulkReply() { |
||||
final byte[] result = getBinaryBulkReply(); |
||||
if (null != result) { |
||||
return SafeEncoder.encode(result); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public byte[] getBinaryBulkReply() { |
||||
flush(); |
||||
return (byte[]) readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
public Long getIntegerReply() { |
||||
flush(); |
||||
return (Long) readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
public List<String> getMultiBulkReply() { |
||||
return BuilderFactory.STRING_LIST.build(getBinaryMultiBulkReply()); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public List<byte[]> getBinaryMultiBulkReply() { |
||||
flush(); |
||||
return (List<byte[]>) readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public List<Object> getRawObjectMultiBulkReply() { |
||||
flush(); |
||||
return (List<Object>) readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
public List<Object> getObjectMultiBulkReply() { |
||||
return getRawObjectMultiBulkReply(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public List<Long> getIntegerMultiBulkReply() { |
||||
flush(); |
||||
return (List<Long>) readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
public Object getOne() { |
||||
flush(); |
||||
return readProtocolWithCheckingBroken(); |
||||
} |
||||
|
||||
public boolean isBroken() { |
||||
return broken; |
||||
} |
||||
|
||||
protected void flush() { |
||||
try { |
||||
outputStream.flush(); |
||||
} catch (IOException ex) { |
||||
broken = true; |
||||
throw new JedisConnectionException(ex); |
||||
} |
||||
} |
||||
|
||||
protected Object readProtocolWithCheckingBroken() { |
||||
try { |
||||
return Protocol.read(inputStream); |
||||
} catch (JedisConnectionException exc) { |
||||
broken = true; |
||||
throw exc; |
||||
} |
||||
} |
||||
|
||||
public List<Object> getMany(final int count) { |
||||
flush(); |
||||
final List<Object> responses = new ArrayList<Object>(count); |
||||
for (int i = 0; i < count; i++) { |
||||
try { |
||||
responses.add(readProtocolWithCheckingBroken()); |
||||
} catch (JedisDataException e) { |
||||
responses.add(e); |
||||
} |
||||
} |
||||
return responses; |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public class DebugParams { |
||||
private String[] command; |
||||
|
||||
private DebugParams() { |
||||
|
||||
} |
||||
|
||||
public String[] getCommand() { |
||||
return command; |
||||
} |
||||
|
||||
public static DebugParams SEGFAULT() { |
||||
DebugParams debugParams = new DebugParams(); |
||||
debugParams.command = new String[] { "SEGFAULT" }; |
||||
return debugParams; |
||||
} |
||||
|
||||
public static DebugParams OBJECT(String key) { |
||||
DebugParams debugParams = new DebugParams(); |
||||
debugParams.command = new String[] { "OBJECT", key }; |
||||
return debugParams; |
||||
} |
||||
|
||||
public static DebugParams RELOAD() { |
||||
DebugParams debugParams = new DebugParams(); |
||||
debugParams.command = new String[] { "RELOAD" }; |
||||
return debugParams; |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public class GeoCoordinate { |
||||
private double longitude; |
||||
private double latitude; |
||||
|
||||
public GeoCoordinate(double longitude, double latitude) { |
||||
this.longitude = longitude; |
||||
this.latitude = latitude; |
||||
} |
||||
|
||||
public double getLongitude() { |
||||
return longitude; |
||||
} |
||||
|
||||
public double getLatitude() { |
||||
return latitude; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (!(o instanceof GeoCoordinate)) return false; |
||||
|
||||
GeoCoordinate that = (GeoCoordinate) o; |
||||
|
||||
if (Double.compare(that.longitude, longitude) != 0) return false; |
||||
return Double.compare(that.latitude, latitude) == 0; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
// follows IntelliJ default hashCode implementation
|
||||
int result; |
||||
long temp; |
||||
temp = Double.doubleToLongBits(longitude); |
||||
result = (int) (temp ^ (temp >>> 32)); |
||||
temp = Double.doubleToLongBits(latitude); |
||||
result = 31 * result + (int) (temp ^ (temp >>> 32)); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "(" + longitude + "," + latitude + ")"; |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class GeoRadiusResponse { |
||||
private byte[] member; |
||||
private double distance; |
||||
private GeoCoordinate coordinate; |
||||
|
||||
public GeoRadiusResponse(byte[] member) { |
||||
this.member = member; |
||||
} |
||||
|
||||
public void setDistance(double distance) { |
||||
this.distance = distance; |
||||
} |
||||
|
||||
public void setCoordinate(GeoCoordinate coordinate) { |
||||
this.coordinate = coordinate; |
||||
} |
||||
|
||||
public byte[] getMember() { |
||||
return member; |
||||
} |
||||
|
||||
public String getMemberByString() { |
||||
return SafeEncoder.encode(member); |
||||
} |
||||
|
||||
public double getDistance() { |
||||
return distance; |
||||
} |
||||
|
||||
public GeoCoordinate getCoordinate() { |
||||
return coordinate; |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public enum GeoUnit { |
||||
M, KM, MI, FT; |
||||
|
||||
public final byte[] raw; |
||||
|
||||
GeoUnit() { |
||||
raw = SafeEncoder.encode(this.name().toLowerCase()); |
||||
} |
||||
} |
@ -0,0 +1,153 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Serializable; |
||||
import java.net.InetAddress; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class HostAndPort implements Serializable { |
||||
private static final long serialVersionUID = -519876229978427751L; |
||||
|
||||
protected static Logger log = LoggerFactory.getLogger(HostAndPort.class.getName()); |
||||
public static String localhost; |
||||
|
||||
|
||||
private String host; |
||||
private int port; |
||||
|
||||
public HostAndPort(String host, int port) { |
||||
this.host = host; |
||||
this.port = port; |
||||
} |
||||
|
||||
public String getHost() { |
||||
return host; |
||||
} |
||||
|
||||
public int getPort() { |
||||
return port; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (obj instanceof HostAndPort) { |
||||
HostAndPort hp = (HostAndPort) obj; |
||||
|
||||
String thisHost = convertHost(host); |
||||
String hpHost = convertHost(hp.host); |
||||
return port == hp.port && thisHost.equals(hpHost); |
||||
|
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return 31 * convertHost(host).hashCode() + port; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return host + ":" + port; |
||||
} |
||||
|
||||
/** |
||||
* Splits String into host and port parts. |
||||
* String must be in ( host + ":" + port ) format. |
||||
* Port is optional |
||||
* @param from String to parse |
||||
* @return array of host and port strings |
||||
*/ |
||||
public static String[] extractParts(String from){ |
||||
int idx = from.lastIndexOf(":"); |
||||
String host = idx != -1 ? from.substring(0, idx) : from; |
||||
String port = idx != -1 ? from.substring(idx + 1) : ""; |
||||
return new String[] { host, port }; |
||||
} |
||||
|
||||
/** |
||||
* Creates HostAndPort instance from string. |
||||
* String must be in ( host + ":" + port ) format. |
||||
* Port is mandatory. Can convert host part. |
||||
* @see #convertHost(String) |
||||
* @param from String to parse |
||||
* @return HostAndPort instance |
||||
*/ |
||||
public static HostAndPort parseString(String from){ |
||||
// NOTE: redis answers with
|
||||
// '99aa9999aa9a99aa099aaa990aa99a09aa9a9999 9a09:9a9:a090:9a::99a slave 8c88888888cc08088cc8c8c888c88c8888c88cc8 0 1468251272993 37 connected'
|
||||
// for CLUSTER NODES, ASK and MOVED scenarios. That's why there is no possibility to parse address in 'correct' way.
|
||||
// Redis should switch to 'bracketized' (RFC 3986) IPv6 address.
|
||||
try { |
||||
String[] parts = extractParts(from); |
||||
String host = parts[0]; |
||||
int port = Integer.parseInt(parts[1]); |
||||
return new HostAndPort(convertHost(host), port); |
||||
} catch (NumberFormatException ex) { |
||||
throw new IllegalArgumentException(ex); |
||||
} |
||||
} |
||||
|
||||
public static String convertHost(String host) { |
||||
try { |
||||
/* |
||||
* Validate the host name as an IPV4/IPV6 address. |
||||
* If this is an AWS ENDPOINT it will not parse. |
||||
* In that case accept host as is. |
||||
* |
||||
* Costs: If this is an IPV4/6 encoding, e.g. 127.0.0.1 then no DNS lookup |
||||
* is done. If it is a name then a DNS lookup is done but it is normally cached. |
||||
* Secondarily, this class is typically used to create a connection once |
||||
* at the beginning of processing and then not used again. So even if the DNS |
||||
* lookup needs to be done then the cost is miniscule. |
||||
*/ |
||||
InetAddress inetAddress = InetAddress.getByName(host); |
||||
|
||||
// isLoopbackAddress() handles both IPV4 and IPV6
|
||||
if (inetAddress.isLoopbackAddress() || host.equals("0.0.0.0") || host.startsWith("169.254")) |
||||
return getLocalhost(); |
||||
else |
||||
return host; |
||||
} catch (Exception e) { |
||||
// Not a valid IP address
|
||||
log.warn("{}.convertHost '" + host + "' is not a valid IP address. ", HostAndPort.class.getName(), e); |
||||
return host; |
||||
} |
||||
} |
||||
|
||||
public static void setLocalhost(String localhost) { |
||||
synchronized (HostAndPort.class) { |
||||
HostAndPort.localhost = localhost; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method resolves the localhost in a 'lazy manner'. |
||||
* |
||||
* @return localhost |
||||
*/ |
||||
public static String getLocalhost() { |
||||
if (localhost == null) { |
||||
synchronized (HostAndPort.class) { |
||||
if (localhost == null) { |
||||
return localhost = getLocalHostQuietly(); |
||||
} |
||||
} |
||||
} |
||||
return localhost; |
||||
} |
||||
|
||||
public static String getLocalHostQuietly() { |
||||
String localAddress; |
||||
try { |
||||
localAddress = InetAddress.getLocalHost().getHostAddress(); |
||||
} catch (Exception ex) { |
||||
log.error("{}.getLocalHostQuietly : cant resolve localhost address", |
||||
HostAndPort.class.getName(), ex); |
||||
localAddress = "localhost"; |
||||
} |
||||
return localAddress; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,170 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisAskDataException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisClusterMaxAttemptsException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisClusterOperationException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisMovedDataException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisRedirectionException; |
||||
import com.fr.third.redis.clients.jedis.util.JedisClusterCRC16; |
||||
|
||||
public abstract class JedisClusterCommand<T> { |
||||
|
||||
private static final String NO_DISPATCH_MESSAGE = "No way to dispatch this command to Redis Cluster."; |
||||
|
||||
private final JedisClusterConnectionHandler connectionHandler; |
||||
private final int maxAttempts; |
||||
private final ThreadLocal<Jedis> askConnection = new ThreadLocal<Jedis>(); |
||||
|
||||
public JedisClusterCommand(JedisClusterConnectionHandler connectionHandler, int maxAttempts) { |
||||
this.connectionHandler = connectionHandler; |
||||
this.maxAttempts = maxAttempts; |
||||
} |
||||
|
||||
public abstract T execute(Jedis connection); |
||||
|
||||
public T run(String key) { |
||||
if (key == null) { |
||||
throw new JedisClusterOperationException(NO_DISPATCH_MESSAGE); |
||||
} |
||||
|
||||
return runWithRetries(JedisClusterCRC16.getSlot(key), this.maxAttempts, false, false); |
||||
} |
||||
|
||||
public T run(int keyCount, String... keys) { |
||||
if (keys == null || keys.length == 0) { |
||||
throw new JedisClusterOperationException(NO_DISPATCH_MESSAGE); |
||||
} |
||||
|
||||
// For multiple keys, only execute if they all share the same connection slot.
|
||||
int slot = JedisClusterCRC16.getSlot(keys[0]); |
||||
if (keys.length > 1) { |
||||
for (int i = 1; i < keyCount; i++) { |
||||
int nextSlot = JedisClusterCRC16.getSlot(keys[i]); |
||||
if (slot != nextSlot) { |
||||
throw new JedisClusterOperationException("No way to dispatch this command to Redis " |
||||
+ "Cluster because keys have different slots."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return runWithRetries(slot, this.maxAttempts, false, false); |
||||
} |
||||
|
||||
public T runBinary(byte[] key) { |
||||
if (key == null) { |
||||
throw new JedisClusterOperationException(NO_DISPATCH_MESSAGE); |
||||
} |
||||
|
||||
return runWithRetries(JedisClusterCRC16.getSlot(key), this.maxAttempts, false, false); |
||||
} |
||||
|
||||
public T runBinary(int keyCount, byte[]... keys) { |
||||
if (keys == null || keys.length == 0) { |
||||
throw new JedisClusterOperationException(NO_DISPATCH_MESSAGE); |
||||
} |
||||
|
||||
// For multiple keys, only execute if they all share the same connection slot.
|
||||
int slot = JedisClusterCRC16.getSlot(keys[0]); |
||||
if (keys.length > 1) { |
||||
for (int i = 1; i < keyCount; i++) { |
||||
int nextSlot = JedisClusterCRC16.getSlot(keys[i]); |
||||
if (slot != nextSlot) { |
||||
throw new JedisClusterOperationException("No way to dispatch this command to Redis " |
||||
+ "Cluster because keys have different slots."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return runWithRetries(slot, this.maxAttempts, false, false); |
||||
} |
||||
|
||||
public T runWithAnyNode() { |
||||
Jedis connection = null; |
||||
try { |
||||
connection = connectionHandler.getConnection(); |
||||
return execute(connection); |
||||
} catch (JedisConnectionException e) { |
||||
throw e; |
||||
} finally { |
||||
releaseConnection(connection); |
||||
} |
||||
} |
||||
|
||||
private T runWithRetries(final int slot, int attempts, boolean tryRandomNode, boolean asking) { |
||||
if (attempts <= 0) { |
||||
throw new JedisClusterMaxAttemptsException("No more cluster attempts left."); |
||||
} |
||||
|
||||
Jedis connection = null; |
||||
try { |
||||
|
||||
if (asking) { |
||||
// TODO: Pipeline asking with the original command to make it
|
||||
// faster....
|
||||
connection = askConnection.get(); |
||||
connection.asking(); |
||||
|
||||
// if asking success, reset asking flag
|
||||
asking = false; |
||||
} else { |
||||
if (tryRandomNode) { |
||||
connection = connectionHandler.getConnection(); |
||||
} else { |
||||
connection = connectionHandler.getConnectionFromSlot(slot); |
||||
} |
||||
} |
||||
|
||||
return execute(connection); |
||||
|
||||
} catch (JedisNoReachableClusterNodeException jnrcne) { |
||||
throw jnrcne; |
||||
} catch (JedisConnectionException jce) { |
||||
// release current connection before recursion
|
||||
releaseConnection(connection); |
||||
connection = null; |
||||
|
||||
if (attempts <= 1) { |
||||
//We need this because if node is not reachable anymore - we need to finally initiate slots renewing,
|
||||
//or we can stuck with cluster state without one node in opposite case.
|
||||
//But now if maxAttempts = 1 or 2 we will do it too often. For each time-outed request.
|
||||
//TODO make tracking of successful/unsuccessful operations for node - do renewing only
|
||||
//if there were no successful responses from this node last few seconds
|
||||
this.connectionHandler.renewSlotCache(); |
||||
} |
||||
|
||||
return runWithRetries(slot, attempts - 1, tryRandomNode, asking); |
||||
} catch (JedisRedirectionException jre) { |
||||
// if MOVED redirection occurred,
|
||||
if (jre instanceof JedisMovedDataException) { |
||||
// it rebuilds cluster's slot cache
|
||||
// recommended by Redis cluster specification
|
||||
this.connectionHandler.renewSlotCache(connection); |
||||
} |
||||
|
||||
// release current connection before recursion or renewing
|
||||
releaseConnection(connection); |
||||
connection = null; |
||||
|
||||
if (jre instanceof JedisAskDataException) { |
||||
asking = true; |
||||
askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode())); |
||||
} else if (jre instanceof JedisMovedDataException) { |
||||
} else { |
||||
throw new JedisClusterOperationException(jre); |
||||
} |
||||
|
||||
return runWithRetries(slot, attempts - 1, false, asking); |
||||
} finally { |
||||
releaseConnection(connection); |
||||
} |
||||
} |
||||
|
||||
private void releaseConnection(Jedis connection) { |
||||
if (connection != null) { |
||||
connection.close(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,73 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
|
||||
public abstract class JedisClusterConnectionHandler implements Closeable { |
||||
protected final JedisClusterInfoCache cache; |
||||
|
||||
public JedisClusterConnectionHandler(Set<HostAndPort> nodes, |
||||
final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout, String password) { |
||||
this(nodes, poolConfig, connectionTimeout, soTimeout, password, null); |
||||
} |
||||
|
||||
public JedisClusterConnectionHandler(Set<HostAndPort> nodes, |
||||
final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout, String password, String clientName) { |
||||
this.cache = new JedisClusterInfoCache(poolConfig, connectionTimeout, soTimeout, password, clientName); |
||||
initializeSlotsCache(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName); |
||||
} |
||||
|
||||
abstract Jedis getConnection(); |
||||
|
||||
abstract Jedis getConnectionFromSlot(int slot); |
||||
|
||||
public Jedis getConnectionFromNode(HostAndPort node) { |
||||
return cache.setupNodeIfNotExist(node).getResource(); |
||||
} |
||||
|
||||
public Map<String, JedisPool> getNodes() { |
||||
return cache.getNodes(); |
||||
} |
||||
|
||||
private void initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig, |
||||
int connectionTimeout, int soTimeout, String password, String clientName) { |
||||
for (HostAndPort hostAndPort : startNodes) { |
||||
Jedis jedis = null; |
||||
try { |
||||
jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout, soTimeout); |
||||
if (password != null) { |
||||
jedis.auth(password); |
||||
} |
||||
if (clientName != null) { |
||||
jedis.clientSetname(clientName); |
||||
} |
||||
cache.discoverClusterNodesAndSlots(jedis); |
||||
break; |
||||
} catch (JedisConnectionException e) { |
||||
// try next nodes
|
||||
} finally { |
||||
if (jedis != null) { |
||||
jedis.close(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void renewSlotCache() { |
||||
cache.renewClusterSlots(null); |
||||
} |
||||
|
||||
public void renewSlotCache(Jedis jedis) { |
||||
cache.renewClusterSlots(jedis); |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
cache.reset(); |
||||
} |
||||
} |
@ -0,0 +1,268 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.locks.Lock; |
||||
import java.util.concurrent.locks.ReentrantReadWriteLock; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class JedisClusterInfoCache { |
||||
private final Map<String, JedisPool> nodes = new HashMap<String, JedisPool>(); |
||||
private final Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>(); |
||||
|
||||
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); |
||||
private final Lock r = rwl.readLock(); |
||||
private final Lock w = rwl.writeLock(); |
||||
private volatile boolean rediscovering; |
||||
private final GenericObjectPoolConfig poolConfig; |
||||
|
||||
private int connectionTimeout; |
||||
private int soTimeout; |
||||
private String password; |
||||
private String clientName; |
||||
|
||||
private static final int MASTER_NODE_INDEX = 2; |
||||
|
||||
public JedisClusterInfoCache(final GenericObjectPoolConfig poolConfig, int timeout) { |
||||
this(poolConfig, timeout, timeout, null, null); |
||||
} |
||||
|
||||
public JedisClusterInfoCache(final GenericObjectPoolConfig poolConfig, |
||||
final int connectionTimeout, final int soTimeout, final String password, final String clientName) { |
||||
this.poolConfig = poolConfig; |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
this.password = password; |
||||
this.clientName = clientName; |
||||
} |
||||
|
||||
public void discoverClusterNodesAndSlots(Jedis jedis) { |
||||
w.lock(); |
||||
|
||||
try { |
||||
reset(); |
||||
List<Object> slots = jedis.clusterSlots(); |
||||
|
||||
for (Object slotInfoObj : slots) { |
||||
List<Object> slotInfo = (List<Object>) slotInfoObj; |
||||
|
||||
if (slotInfo.size() <= MASTER_NODE_INDEX) { |
||||
continue; |
||||
} |
||||
|
||||
List<Integer> slotNums = getAssignedSlotArray(slotInfo); |
||||
|
||||
// hostInfos
|
||||
int size = slotInfo.size(); |
||||
for (int i = MASTER_NODE_INDEX; i < size; i++) { |
||||
List<Object> hostInfos = (List<Object>) slotInfo.get(i); |
||||
if (hostInfos.size() <= 0) { |
||||
continue; |
||||
} |
||||
|
||||
HostAndPort targetNode = generateHostAndPort(hostInfos); |
||||
setupNodeIfNotExist(targetNode); |
||||
if (i == MASTER_NODE_INDEX) { |
||||
assignSlotsToNode(slotNums, targetNode); |
||||
} |
||||
} |
||||
} |
||||
} finally { |
||||
w.unlock(); |
||||
} |
||||
} |
||||
|
||||
public void renewClusterSlots(Jedis jedis) { |
||||
//If rediscovering is already in process - no need to start one more same rediscovering, just return
|
||||
if (!rediscovering) { |
||||
try { |
||||
w.lock(); |
||||
rediscovering = true; |
||||
|
||||
if (jedis != null) { |
||||
try { |
||||
discoverClusterSlots(jedis); |
||||
return; |
||||
} catch (JedisException e) { |
||||
//try nodes from all pools
|
||||
} |
||||
} |
||||
|
||||
for (JedisPool jp : getShuffledNodesPool()) { |
||||
Jedis j = null; |
||||
try { |
||||
j = jp.getResource(); |
||||
discoverClusterSlots(j); |
||||
return; |
||||
} catch (JedisConnectionException e) { |
||||
// try next nodes
|
||||
} finally { |
||||
if (j != null) { |
||||
j.close(); |
||||
} |
||||
} |
||||
} |
||||
} finally { |
||||
rediscovering = false; |
||||
w.unlock(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void discoverClusterSlots(Jedis jedis) { |
||||
List<Object> slots = jedis.clusterSlots(); |
||||
this.slots.clear(); |
||||
|
||||
for (Object slotInfoObj : slots) { |
||||
List<Object> slotInfo = (List<Object>) slotInfoObj; |
||||
|
||||
if (slotInfo.size() <= MASTER_NODE_INDEX) { |
||||
continue; |
||||
} |
||||
|
||||
List<Integer> slotNums = getAssignedSlotArray(slotInfo); |
||||
|
||||
// hostInfos
|
||||
List<Object> hostInfos = (List<Object>) slotInfo.get(MASTER_NODE_INDEX); |
||||
if (hostInfos.isEmpty()) { |
||||
continue; |
||||
} |
||||
|
||||
// at this time, we just use master, discard slave information
|
||||
HostAndPort targetNode = generateHostAndPort(hostInfos); |
||||
assignSlotsToNode(slotNums, targetNode); |
||||
} |
||||
} |
||||
|
||||
private HostAndPort generateHostAndPort(List<Object> hostInfos) { |
||||
return new HostAndPort(SafeEncoder.encode((byte[]) hostInfos.get(0)), |
||||
((Long) hostInfos.get(1)).intValue()); |
||||
} |
||||
|
||||
public JedisPool setupNodeIfNotExist(HostAndPort node) { |
||||
w.lock(); |
||||
try { |
||||
String nodeKey = getNodeKey(node); |
||||
JedisPool existingPool = nodes.get(nodeKey); |
||||
if (existingPool != null) return existingPool; |
||||
|
||||
JedisPool nodePool = new JedisPool(poolConfig, node.getHost(), node.getPort(), |
||||
connectionTimeout, soTimeout, password, 0, clientName, false, null, null, null); |
||||
nodes.put(nodeKey, nodePool); |
||||
return nodePool; |
||||
} finally { |
||||
w.unlock(); |
||||
} |
||||
} |
||||
|
||||
public void assignSlotToNode(int slot, HostAndPort targetNode) { |
||||
w.lock(); |
||||
try { |
||||
JedisPool targetPool = setupNodeIfNotExist(targetNode); |
||||
slots.put(slot, targetPool); |
||||
} finally { |
||||
w.unlock(); |
||||
} |
||||
} |
||||
|
||||
public void assignSlotsToNode(List<Integer> targetSlots, HostAndPort targetNode) { |
||||
w.lock(); |
||||
try { |
||||
JedisPool targetPool = setupNodeIfNotExist(targetNode); |
||||
for (Integer slot : targetSlots) { |
||||
slots.put(slot, targetPool); |
||||
} |
||||
} finally { |
||||
w.unlock(); |
||||
} |
||||
} |
||||
|
||||
public JedisPool getNode(String nodeKey) { |
||||
r.lock(); |
||||
try { |
||||
return nodes.get(nodeKey); |
||||
} finally { |
||||
r.unlock(); |
||||
} |
||||
} |
||||
|
||||
public JedisPool getSlotPool(int slot) { |
||||
r.lock(); |
||||
try { |
||||
return slots.get(slot); |
||||
} finally { |
||||
r.unlock(); |
||||
} |
||||
} |
||||
|
||||
public Map<String, JedisPool> getNodes() { |
||||
r.lock(); |
||||
try { |
||||
return new HashMap<String, JedisPool>(nodes); |
||||
} finally { |
||||
r.unlock(); |
||||
} |
||||
} |
||||
|
||||
public List<JedisPool> getShuffledNodesPool() { |
||||
r.lock(); |
||||
try { |
||||
List<JedisPool> pools = new ArrayList<JedisPool>(nodes.values()); |
||||
Collections.shuffle(pools); |
||||
return pools; |
||||
} finally { |
||||
r.unlock(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Clear discovered nodes collections and gently release allocated resources |
||||
*/ |
||||
public void reset() { |
||||
w.lock(); |
||||
try { |
||||
for (JedisPool pool : nodes.values()) { |
||||
try { |
||||
if (pool != null) { |
||||
pool.destroy(); |
||||
} |
||||
} catch (Exception e) { |
||||
// pass
|
||||
} |
||||
} |
||||
nodes.clear(); |
||||
slots.clear(); |
||||
} finally { |
||||
w.unlock(); |
||||
} |
||||
} |
||||
|
||||
public static String getNodeKey(HostAndPort hnp) { |
||||
return hnp.getHost() + ":" + hnp.getPort(); |
||||
} |
||||
|
||||
public static String getNodeKey(Client client) { |
||||
return client.getHost() + ":" + client.getPort(); |
||||
} |
||||
|
||||
public static String getNodeKey(Jedis jedis) { |
||||
return getNodeKey(jedis.getClient()); |
||||
} |
||||
|
||||
private List<Integer> getAssignedSlotArray(List<Object> slotInfo) { |
||||
List<Integer> slotNums = new ArrayList<Integer>(); |
||||
for (int slot = ((Long) slotInfo.get(0)).intValue(); slot <= ((Long) slotInfo.get(1)) |
||||
.intValue(); slot++) { |
||||
slotNums.add(slot); |
||||
} |
||||
return slotNums; |
||||
} |
||||
} |
@ -0,0 +1,157 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.net.URI; |
||||
import java.util.concurrent.atomic.AtomicReference; |
||||
|
||||
import javax.net.ssl.HostnameVerifier; |
||||
import javax.net.ssl.SSLParameters; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectFactory; |
||||
import com.fr.third.org.apache.commons.pool2.impl.DefaultPooledObject; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.InvalidURIException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
import com.fr.third.redis.clients.jedis.util.JedisURIHelper; |
||||
|
||||
/** |
||||
* PoolableObjectFactory custom impl. |
||||
*/ |
||||
class JedisFactory implements PooledObjectFactory<Jedis> { |
||||
private final AtomicReference<HostAndPort> hostAndPort = new AtomicReference<HostAndPort>(); |
||||
private final int connectionTimeout; |
||||
private final int soTimeout; |
||||
private final String password; |
||||
private final int database; |
||||
private final String clientName; |
||||
private final boolean ssl; |
||||
private final SSLSocketFactory sslSocketFactory; |
||||
private final SSLParameters sslParameters; |
||||
private final HostnameVerifier hostnameVerifier; |
||||
|
||||
JedisFactory(final String host, final int port, final int connectionTimeout, |
||||
final int soTimeout, final String password, final int database, final String clientName) { |
||||
this(host, port, connectionTimeout, soTimeout, password, database, clientName, |
||||
false, null, null, null); |
||||
} |
||||
|
||||
JedisFactory(final String host, final int port, final int connectionTimeout, |
||||
final int soTimeout, final String password, final int database, final String clientName, |
||||
final boolean ssl, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this.hostAndPort.set(new HostAndPort(host, port)); |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
this.password = password; |
||||
this.database = database; |
||||
this.clientName = clientName; |
||||
this.ssl = ssl; |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
JedisFactory(final URI uri, final int connectionTimeout, final int soTimeout, |
||||
final String clientName) { |
||||
this(uri, connectionTimeout, soTimeout, clientName, null, null, null); |
||||
} |
||||
|
||||
JedisFactory(final URI uri, final int connectionTimeout, final int soTimeout, |
||||
final String clientName, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
if (!JedisURIHelper.isValid(uri)) { |
||||
throw new InvalidURIException(String.format( |
||||
"Cannot open Redis connection due invalid URI. %s", uri.toString())); |
||||
} |
||||
|
||||
this.hostAndPort.set(new HostAndPort(uri.getHost(), uri.getPort())); |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
this.password = JedisURIHelper.getPassword(uri); |
||||
this.database = JedisURIHelper.getDBIndex(uri); |
||||
this.clientName = clientName; |
||||
this.ssl = JedisURIHelper.isRedisSSLScheme(uri); |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
public void setHostAndPort(final HostAndPort hostAndPort) { |
||||
this.hostAndPort.set(hostAndPort); |
||||
} |
||||
|
||||
@Override |
||||
public void activateObject(PooledObject<Jedis> pooledJedis) throws Exception { |
||||
final BinaryJedis jedis = pooledJedis.getObject(); |
||||
if (jedis.getDB() != database) { |
||||
jedis.select(database); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception { |
||||
final BinaryJedis jedis = pooledJedis.getObject(); |
||||
if (jedis.isConnected()) { |
||||
try { |
||||
try { |
||||
jedis.quit(); |
||||
} catch (Exception e) { |
||||
} |
||||
jedis.disconnect(); |
||||
} catch (Exception e) { |
||||
|
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public PooledObject<Jedis> makeObject() throws Exception { |
||||
final HostAndPort hostAndPort = this.hostAndPort.get(); |
||||
final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout, |
||||
soTimeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
|
||||
try { |
||||
jedis.connect(); |
||||
if (password != null) { |
||||
jedis.auth(password); |
||||
} |
||||
if (database != 0) { |
||||
jedis.select(database); |
||||
} |
||||
if (clientName != null) { |
||||
jedis.clientSetname(clientName); |
||||
} |
||||
} catch (JedisException je) { |
||||
jedis.close(); |
||||
throw je; |
||||
} |
||||
|
||||
return new DefaultPooledObject<Jedis>(jedis); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void passivateObject(PooledObject<Jedis> pooledJedis) throws Exception { |
||||
// TODO maybe should select db 0? Not sure right now.
|
||||
} |
||||
|
||||
@Override |
||||
public boolean validateObject(PooledObject<Jedis> pooledJedis) { |
||||
final BinaryJedis jedis = pooledJedis.getObject(); |
||||
try { |
||||
HostAndPort hostAndPort = this.hostAndPort.get(); |
||||
|
||||
String connectionHost = jedis.getClient().getHost(); |
||||
int connectionPort = jedis.getClient().getPort(); |
||||
|
||||
return hostAndPort.getHost().equals(connectionHost) |
||||
&& hostAndPort.getPort() == connectionPort && jedis.isConnected() |
||||
&& jedis.ping().equals("PONG"); |
||||
} catch (final Exception e) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public abstract class JedisMonitor { |
||||
protected Client client; |
||||
|
||||
public void proceed(Client client) { |
||||
this.client = client; |
||||
this.client.setTimeoutInfinite(); |
||||
do { |
||||
String command = client.getBulkReply(); |
||||
onCommand(command); |
||||
} while (client.isConnected()); |
||||
} |
||||
|
||||
public abstract void onCommand(String command); |
||||
} |
@ -0,0 +1,258 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.net.URI; |
||||
|
||||
import javax.net.ssl.HostnameVerifier; |
||||
import javax.net.ssl.SSLParameters; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPool; |
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
import com.fr.third.redis.clients.jedis.util.JedisURIHelper; |
||||
|
||||
public class JedisPool extends JedisPoolAbstract { |
||||
|
||||
public JedisPool() { |
||||
this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host) { |
||||
this(poolConfig, host, Protocol.DEFAULT_PORT); |
||||
} |
||||
|
||||
public JedisPool(String host, int port) { |
||||
this(new GenericObjectPoolConfig(), host, port); |
||||
} |
||||
|
||||
public JedisPool(final String host) { |
||||
URI uri = URI.create(host); |
||||
if (JedisURIHelper.isValid(uri)) { |
||||
this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(uri, |
||||
Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null), new GenericObjectPoolConfig()); |
||||
} else { |
||||
this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(host, |
||||
Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null, |
||||
Protocol.DEFAULT_DATABASE, null), new GenericObjectPoolConfig()); |
||||
} |
||||
} |
||||
|
||||
public JedisPool(final String host, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
URI uri = URI.create(host); |
||||
if (JedisURIHelper.isValid(uri)) { |
||||
this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(uri, |
||||
Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null, sslSocketFactory, sslParameters, |
||||
hostnameVerifier), new GenericObjectPoolConfig()); |
||||
} else { |
||||
this.internalPool = new GenericObjectPool<Jedis>(new JedisFactory(host, |
||||
Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, null, |
||||
Protocol.DEFAULT_DATABASE, null, false, null, null, null), new GenericObjectPoolConfig()); |
||||
} |
||||
} |
||||
|
||||
public JedisPool(final URI uri) { |
||||
this(new GenericObjectPoolConfig(), uri); |
||||
} |
||||
|
||||
public JedisPool(final URI uri, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final URI uri, final int timeout) { |
||||
this(new GenericObjectPoolConfig(), uri, timeout); |
||||
} |
||||
|
||||
public JedisPool(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password) { |
||||
this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final boolean ssl) { |
||||
this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final boolean ssl, |
||||
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl, |
||||
sslSocketFactory, sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port) { |
||||
this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final boolean ssl) { |
||||
this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final boolean ssl, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, ssl, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final int timeout) { |
||||
this(poolConfig, host, port, timeout, null); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final int timeout, final boolean ssl) { |
||||
this(poolConfig, host, port, timeout, null, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final int timeout, final boolean ssl, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, host, port, timeout, null, ssl, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database) { |
||||
this(poolConfig, host, port, timeout, password, database, null); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database, final boolean ssl) { |
||||
this(poolConfig, host, port, timeout, password, database, null, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database, final boolean ssl, |
||||
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, host, port, timeout, password, database, null, ssl, sslSocketFactory, |
||||
sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database, final String clientName) { |
||||
this(poolConfig, host, port, timeout, timeout, password, database, clientName); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database, final String clientName, |
||||
final boolean ssl) { |
||||
this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
int timeout, final String password, final int database, final String clientName, |
||||
final boolean ssl, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, |
||||
sslSocketFactory, sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
final int connectionTimeout, final int soTimeout, final String password, final int database, |
||||
final String clientName, final boolean ssl, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, |
||||
database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier)); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig) { |
||||
this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); |
||||
} |
||||
|
||||
public JedisPool(final String host, final int port, final boolean ssl) { |
||||
this(new GenericObjectPoolConfig(), host, port, ssl); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, |
||||
final int connectionTimeout, final int soTimeout, final String password, final int database, |
||||
final String clientName) { |
||||
super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, |
||||
database, clientName)); |
||||
} |
||||
|
||||
public JedisPool(final String host, final int port, final boolean ssl, |
||||
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(new GenericObjectPoolConfig(), host, port, ssl, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, |
||||
final int connectionTimeout, final int soTimeout, final String password, final int database, |
||||
final String clientName, final boolean ssl) { |
||||
this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, |
||||
null, null, null); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) { |
||||
this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, |
||||
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout) { |
||||
this(poolConfig, uri, timeout, timeout); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout, |
||||
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, |
||||
final HostnameVerifier hostnameVerifier) { |
||||
this(poolConfig, uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, |
||||
final int connectionTimeout, final int soTimeout) { |
||||
super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null)); |
||||
} |
||||
|
||||
public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, |
||||
final int connectionTimeout, final int soTimeout, final SSLSocketFactory sslSocketFactory, |
||||
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { |
||||
super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null, sslSocketFactory, |
||||
sslParameters, hostnameVerifier)); |
||||
} |
||||
|
||||
@Override |
||||
public Jedis getResource() { |
||||
Jedis jedis = super.getResource(); |
||||
jedis.setDataSource(this); |
||||
return jedis; |
||||
} |
||||
|
||||
@Override |
||||
protected void returnBrokenResource(final Jedis resource) { |
||||
if (resource != null) { |
||||
returnBrokenResourceObject(resource); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void returnResource(final Jedis resource) { |
||||
if (resource != null) { |
||||
try { |
||||
resource.resetState(); |
||||
returnResourceObject(resource); |
||||
} catch (Exception e) { |
||||
returnBrokenResource(resource); |
||||
throw new JedisException("Could not return the resource to the pool", e); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectFactory; |
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.Pool; |
||||
|
||||
public class JedisPoolAbstract extends Pool<Jedis> { |
||||
|
||||
public JedisPoolAbstract() { |
||||
super(); |
||||
} |
||||
|
||||
public JedisPoolAbstract(GenericObjectPoolConfig poolConfig, PooledObjectFactory<Jedis> factory) { |
||||
super(poolConfig, factory); |
||||
} |
||||
|
||||
@Override |
||||
protected void returnBrokenResource(Jedis resource) { |
||||
super.returnBrokenResource(resource); |
||||
} |
||||
|
||||
@Override |
||||
protected void returnResource(Jedis resource) { |
||||
super.returnResource(resource); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
public class JedisPoolConfig extends GenericObjectPoolConfig { |
||||
public JedisPoolConfig() { |
||||
// defaults to make your life with connection pool easier :)
|
||||
setTestWhileIdle(true); |
||||
setMinEvictableIdleTimeMillis(60000); |
||||
setTimeBetweenEvictionRunsMillis(30000); |
||||
setNumTestsPerEvictionRun(-1); |
||||
} |
||||
} |
@ -0,0 +1,179 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.MESSAGE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PMESSAGE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.SUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.PONG; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public abstract class JedisPubSub { |
||||
|
||||
private static final String JEDIS_SUBSCRIPTION_MESSAGE = "JedisPubSub is not subscribed to a Jedis instance."; |
||||
private int subscribedChannels = 0; |
||||
private volatile Client client; |
||||
|
||||
public void onMessage(String channel, String message) { |
||||
} |
||||
|
||||
public void onPMessage(String pattern, String channel, String message) { |
||||
} |
||||
|
||||
public void onSubscribe(String channel, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onUnsubscribe(String channel, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onPUnsubscribe(String pattern, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onPSubscribe(String pattern, int subscribedChannels) { |
||||
} |
||||
|
||||
public void onPong(String pattern) { |
||||
|
||||
} |
||||
|
||||
public void unsubscribe() { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.unsubscribe(); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void unsubscribe(String... channels) { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.unsubscribe(channels); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void subscribe(String... channels) { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.subscribe(channels); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void psubscribe(String... patterns) { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.psubscribe(patterns); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void punsubscribe() { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.punsubscribe(); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void punsubscribe(String... patterns) { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.punsubscribe(patterns); |
||||
client.flush(); |
||||
} |
||||
|
||||
public void ping() { |
||||
if (client == null) { |
||||
throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); |
||||
} |
||||
client.ping(); |
||||
client.flush(); |
||||
} |
||||
|
||||
public boolean isSubscribed() { |
||||
return subscribedChannels > 0; |
||||
} |
||||
|
||||
public void proceedWithPatterns(Client client, String... patterns) { |
||||
this.client = client; |
||||
client.psubscribe(patterns); |
||||
client.flush(); |
||||
process(client); |
||||
} |
||||
|
||||
public void proceed(Client client, String... channels) { |
||||
this.client = client; |
||||
client.subscribe(channels); |
||||
client.flush(); |
||||
process(client); |
||||
} |
||||
|
||||
private void process(Client client) { |
||||
|
||||
do { |
||||
List<Object> reply = client.getRawObjectMultiBulkReply(); |
||||
final Object firstObj = reply.get(0); |
||||
if (!(firstObj instanceof byte[])) { |
||||
throw new JedisException("Unknown message type: " + firstObj); |
||||
} |
||||
final byte[] resp = (byte[]) firstObj; |
||||
if (Arrays.equals(SUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); |
||||
onSubscribe(strchannel, subscribedChannels); |
||||
} else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); |
||||
onUnsubscribe(strchannel, subscribedChannels); |
||||
} else if (Arrays.equals(MESSAGE.raw, resp)) { |
||||
final byte[] bchannel = (byte[]) reply.get(1); |
||||
final byte[] bmesg = (byte[]) reply.get(2); |
||||
final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); |
||||
final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); |
||||
onMessage(strchannel, strmesg); |
||||
} else if (Arrays.equals(PMESSAGE.raw, resp)) { |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
final byte[] bchannel = (byte[]) reply.get(2); |
||||
final byte[] bmesg = (byte[]) reply.get(3); |
||||
final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); |
||||
final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); |
||||
final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); |
||||
onPMessage(strpattern, strchannel, strmesg); |
||||
} else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); |
||||
onPSubscribe(strpattern, subscribedChannels); |
||||
} else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { |
||||
subscribedChannels = ((Long) reply.get(2)).intValue(); |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); |
||||
onPUnsubscribe(strpattern, subscribedChannels); |
||||
} else if (Arrays.equals(PONG.raw, resp)) { |
||||
final byte[] bpattern = (byte[]) reply.get(1); |
||||
final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); |
||||
onPong(strpattern); |
||||
} else { |
||||
throw new JedisException("Unknown message type: " + firstObj); |
||||
} |
||||
} while (isSubscribed()); |
||||
|
||||
/* Invalidate instance since this thread is no longer listening */ |
||||
this.client = null; |
||||
} |
||||
|
||||
public int getSubscribedChannels() { |
||||
return subscribedChannels; |
||||
} |
||||
} |
@ -0,0 +1,348 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
import java.util.concurrent.atomic.AtomicBoolean; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
|
||||
public class JedisSentinelPool extends JedisPoolAbstract { |
||||
|
||||
protected GenericObjectPoolConfig poolConfig; |
||||
|
||||
protected int connectionTimeout = Protocol.DEFAULT_TIMEOUT; |
||||
protected int soTimeout = Protocol.DEFAULT_TIMEOUT; |
||||
|
||||
protected String password; |
||||
|
||||
protected int database = Protocol.DEFAULT_DATABASE; |
||||
|
||||
protected String clientName; |
||||
|
||||
protected Set<MasterListener> masterListeners = new HashSet<MasterListener>(); |
||||
|
||||
protected Logger log = LoggerFactory.getLogger(getClass().getName()); |
||||
|
||||
private volatile JedisFactory factory; |
||||
private volatile HostAndPort currentHostMaster; |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig) { |
||||
this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, null, |
||||
Protocol.DEFAULT_DATABASE); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels) { |
||||
this(masterName, sentinels, new GenericObjectPoolConfig(), Protocol.DEFAULT_TIMEOUT, null, |
||||
Protocol.DEFAULT_DATABASE); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, String password) { |
||||
this(masterName, sentinels, new GenericObjectPoolConfig(), Protocol.DEFAULT_TIMEOUT, password); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, int timeout, final String password) { |
||||
this(masterName, sentinels, poolConfig, timeout, password, Protocol.DEFAULT_DATABASE); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, final int timeout) { |
||||
this(masterName, sentinels, poolConfig, timeout, null, Protocol.DEFAULT_DATABASE); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, final String password) { |
||||
this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, password); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, int timeout, final String password, |
||||
final int database) { |
||||
this(masterName, sentinels, poolConfig, timeout, timeout, password, database); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, int timeout, final String password, |
||||
final int database, final String clientName) { |
||||
this(masterName, sentinels, poolConfig, timeout, timeout, password, database, clientName); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, final int timeout, final int soTimeout, |
||||
final String password, final int database) { |
||||
this(masterName, sentinels, poolConfig, timeout, soTimeout, password, database, null); |
||||
} |
||||
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels, |
||||
final GenericObjectPoolConfig poolConfig, final int connectionTimeout, final int soTimeout, |
||||
final String password, final int database, final String clientName) { |
||||
this.poolConfig = poolConfig; |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
this.password = password; |
||||
this.database = database; |
||||
this.clientName = clientName; |
||||
|
||||
HostAndPort master = initSentinels(sentinels, masterName); |
||||
initPool(master); |
||||
} |
||||
|
||||
@Override |
||||
public void destroy() { |
||||
for (MasterListener m : masterListeners) { |
||||
m.shutdown(); |
||||
} |
||||
|
||||
super.destroy(); |
||||
} |
||||
|
||||
public HostAndPort getCurrentHostMaster() { |
||||
return currentHostMaster; |
||||
} |
||||
|
||||
private void initPool(HostAndPort master) { |
||||
if (!master.equals(currentHostMaster)) { |
||||
currentHostMaster = master; |
||||
if (factory == null) { |
||||
factory = new JedisFactory(master.getHost(), master.getPort(), connectionTimeout, |
||||
soTimeout, password, database, clientName); |
||||
initPool(poolConfig, factory); |
||||
} else { |
||||
factory.setHostAndPort(currentHostMaster); |
||||
// although we clear the pool, we still have to check the
|
||||
// returned object
|
||||
// in getResource, this call only clears idle instances, not
|
||||
// borrowed instances
|
||||
internalPool.clear(); |
||||
} |
||||
|
||||
log.info("Created JedisPool to master at " + master); |
||||
} |
||||
} |
||||
|
||||
private HostAndPort initSentinels(Set<String> sentinels, final String masterName) { |
||||
|
||||
HostAndPort master = null; |
||||
boolean sentinelAvailable = false; |
||||
|
||||
log.info("Trying to find master from available Sentinels..."); |
||||
|
||||
for (String sentinel : sentinels) { |
||||
final HostAndPort hap = HostAndPort.parseString(sentinel); |
||||
|
||||
log.debug("Connecting to Sentinel {}", hap); |
||||
|
||||
Jedis jedis = null; |
||||
try { |
||||
jedis = new Jedis(hap); |
||||
|
||||
List<String> masterAddr = jedis.sentinelGetMasterAddrByName(masterName); |
||||
|
||||
// connected to sentinel...
|
||||
sentinelAvailable = true; |
||||
|
||||
if (masterAddr == null || masterAddr.size() != 2) { |
||||
log.warn("Can not get master addr, master name: {}. Sentinel: {}", masterName, hap); |
||||
continue; |
||||
} |
||||
|
||||
master = toHostAndPort(masterAddr); |
||||
log.debug("Found Redis master at {}", master); |
||||
break; |
||||
} catch (JedisException e) { |
||||
// resolves #1036, it should handle JedisException there's another chance
|
||||
// of raising JedisDataException
|
||||
log.warn( |
||||
"Cannot get master address from sentinel running @ {}. Reason: {}. Trying next one.", hap, |
||||
e.toString()); |
||||
} finally { |
||||
if (jedis != null) { |
||||
jedis.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (master == null) { |
||||
if (sentinelAvailable) { |
||||
// can connect to sentinel, but master name seems to not
|
||||
// monitored
|
||||
throw new JedisException("Can connect to sentinel, but " + masterName |
||||
+ " seems to be not monitored..."); |
||||
} else { |
||||
throw new JedisConnectionException("All sentinels down, cannot determine where is " |
||||
+ masterName + " master is running..."); |
||||
} |
||||
} |
||||
|
||||
log.info("Redis master running at " + master + ", starting Sentinel listeners..."); |
||||
|
||||
for (String sentinel : sentinels) { |
||||
final HostAndPort hap = HostAndPort.parseString(sentinel); |
||||
MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort()); |
||||
// whether MasterListener threads are alive or not, process can be stopped
|
||||
masterListener.setDaemon(true); |
||||
masterListeners.add(masterListener); |
||||
masterListener.start(); |
||||
} |
||||
|
||||
return master; |
||||
} |
||||
|
||||
private HostAndPort toHostAndPort(List<String> getMasterAddrByNameResult) { |
||||
String host = getMasterAddrByNameResult.get(0); |
||||
int port = Integer.parseInt(getMasterAddrByNameResult.get(1)); |
||||
|
||||
return new HostAndPort(host, port); |
||||
} |
||||
|
||||
@Override |
||||
public Jedis getResource() { |
||||
while (true) { |
||||
Jedis jedis = super.getResource(); |
||||
jedis.setDataSource(this); |
||||
|
||||
// get a reference because it can change concurrently
|
||||
final HostAndPort master = currentHostMaster; |
||||
final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient() |
||||
.getPort()); |
||||
|
||||
if (master.equals(connection)) { |
||||
// connected to the correct master
|
||||
return jedis; |
||||
} else { |
||||
returnBrokenResource(jedis); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void returnBrokenResource(final Jedis resource) { |
||||
if (resource != null) { |
||||
returnBrokenResourceObject(resource); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void returnResource(final Jedis resource) { |
||||
if (resource != null) { |
||||
resource.resetState(); |
||||
returnResourceObject(resource); |
||||
} |
||||
} |
||||
|
||||
protected class MasterListener extends Thread { |
||||
|
||||
protected String masterName; |
||||
protected String host; |
||||
protected int port; |
||||
protected long subscribeRetryWaitTimeMillis = 5000; |
||||
protected volatile Jedis j; |
||||
protected AtomicBoolean running = new AtomicBoolean(false); |
||||
|
||||
protected MasterListener() { |
||||
} |
||||
|
||||
public MasterListener(String masterName, String host, int port) { |
||||
super(String.format("MasterListener-%s-[%s:%d]", masterName, host, port)); |
||||
this.masterName = masterName; |
||||
this.host = host; |
||||
this.port = port; |
||||
} |
||||
|
||||
public MasterListener(String masterName, String host, int port, |
||||
long subscribeRetryWaitTimeMillis) { |
||||
this(masterName, host, port); |
||||
this.subscribeRetryWaitTimeMillis = subscribeRetryWaitTimeMillis; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
|
||||
running.set(true); |
||||
|
||||
while (running.get()) { |
||||
|
||||
j = new Jedis(host, port); |
||||
|
||||
try { |
||||
// double check that it is not being shutdown
|
||||
if (!running.get()) { |
||||
break; |
||||
} |
||||
|
||||
/* |
||||
* Added code for active refresh |
||||
*/ |
||||
List<String> masterAddr = j.sentinelGetMasterAddrByName(masterName); |
||||
if (masterAddr == null || masterAddr.size() != 2) { |
||||
log.warn("Can not get master addr, master name: {}. Sentinel: {}:{}.",masterName,host,port); |
||||
}else{ |
||||
initPool(toHostAndPort(masterAddr)); |
||||
} |
||||
|
||||
j.subscribe(new JedisPubSub() { |
||||
@Override |
||||
public void onMessage(String channel, String message) { |
||||
log.debug("Sentinel {}:{} published: {}.", host, port, message); |
||||
|
||||
String[] switchMasterMsg = message.split(" "); |
||||
|
||||
if (switchMasterMsg.length > 3) { |
||||
|
||||
if (masterName.equals(switchMasterMsg[0])) { |
||||
initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4]))); |
||||
} else { |
||||
log.debug( |
||||
"Ignoring message on +switch-master for master name {}, our master name is {}", |
||||
switchMasterMsg[0], masterName); |
||||
} |
||||
|
||||
} else { |
||||
log.error( |
||||
"Invalid message received on Sentinel {}:{} on channel +switch-master: {}", host, |
||||
port, message); |
||||
} |
||||
} |
||||
}, "+switch-master"); |
||||
|
||||
} catch (JedisException e) { |
||||
|
||||
if (running.get()) { |
||||
log.error("Lost connection to Sentinel at {}:{}. Sleeping 5000ms and retrying.", host, |
||||
port, e); |
||||
try { |
||||
Thread.sleep(subscribeRetryWaitTimeMillis); |
||||
} catch (InterruptedException e1) { |
||||
log.error("Sleep interrupted: ", e1); |
||||
} |
||||
} else { |
||||
log.debug("Unsubscribing from Sentinel at {}:{}", host, port); |
||||
} |
||||
} finally { |
||||
j.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void shutdown() { |
||||
try { |
||||
log.debug("Shutting down listener on {}:{}", host, port); |
||||
running.set(false); |
||||
// This isn't good, the Jedis object is not thread safe
|
||||
if (j != null) { |
||||
j.disconnect(); |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("Caught exception while shutting down: ", e); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,252 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.net.URI; |
||||
|
||||
import javax.net.ssl.HostnameVerifier; |
||||
import javax.net.ssl.SSLParameters; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.InvalidURIException; |
||||
import com.fr.third.redis.clients.jedis.util.JedisURIHelper; |
||||
import com.fr.third.redis.clients.jedis.util.ShardInfo; |
||||
import com.fr.third.redis.clients.jedis.util.Sharded; |
||||
|
||||
public class JedisShardInfo extends ShardInfo<Jedis> { |
||||
|
||||
private int connectionTimeout; |
||||
private int soTimeout; |
||||
private String host; |
||||
private int port; |
||||
private String password = null; |
||||
private String name = null; |
||||
// Default Redis DB
|
||||
private int db = 0; |
||||
private boolean ssl; |
||||
private SSLSocketFactory sslSocketFactory; |
||||
private SSLParameters sslParameters; |
||||
private HostnameVerifier hostnameVerifier; |
||||
|
||||
public JedisShardInfo(String host) { |
||||
super(Sharded.DEFAULT_WEIGHT); |
||||
URI uri = URI.create(host); |
||||
if (JedisURIHelper.isValid(uri)) { |
||||
this.host = uri.getHost(); |
||||
this.port = uri.getPort(); |
||||
this.password = JedisURIHelper.getPassword(uri); |
||||
this.db = JedisURIHelper.getDBIndex(uri); |
||||
this.ssl = JedisURIHelper.isRedisSSLScheme(uri); |
||||
} else { |
||||
this.host = host; |
||||
this.port = Protocol.DEFAULT_PORT; |
||||
} |
||||
} |
||||
|
||||
public JedisShardInfo(String host, SSLSocketFactory sslSocketFactory, |
||||
SSLParameters sslParameters, HostnameVerifier hostnameVerifier) { |
||||
this(host); |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, String name) { |
||||
this(host, Protocol.DEFAULT_PORT, name); |
||||
} |
||||
|
||||
public JedisShardInfo(HostAndPort hp) { |
||||
this(hp.getHost(), hp.getPort()); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, boolean ssl) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT, ssl); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, boolean ssl, SSLSocketFactory sslSocketFactory, |
||||
SSLParameters sslParameters, HostnameVerifier hostnameVerifier) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT, ssl, sslSocketFactory, sslParameters, |
||||
hostnameVerifier); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, String name) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT, name); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, String name, boolean ssl) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT, name, ssl); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, String name, boolean ssl, SSLSocketFactory sslSocketFactory, |
||||
SSLParameters sslParameters, HostnameVerifier hostnameVerifier) { |
||||
this(host, port, Protocol.DEFAULT_TIMEOUT, name, ssl, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout) { |
||||
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout, boolean ssl) { |
||||
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT, ssl); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout, boolean ssl, |
||||
SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT, ssl, sslSocketFactory, |
||||
sslParameters, hostnameVerifier); |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout, String name) { |
||||
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout, String name, boolean ssl) { |
||||
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT, ssl); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int timeout, String name, boolean ssl, |
||||
SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this(host, port, timeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int connectionTimeout, int soTimeout, int weight) { |
||||
super(weight); |
||||
this.host = host; |
||||
this.port = port; |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int connectionTimeout, int soTimeout, int weight, |
||||
boolean ssl) { |
||||
super(weight); |
||||
this.host = host; |
||||
this.port = port; |
||||
this.connectionTimeout = connectionTimeout; |
||||
this.soTimeout = soTimeout; |
||||
this.ssl = ssl; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, int port, int connectionTimeout, int soTimeout, int weight, |
||||
boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this(host, port, connectionTimeout, soTimeout, weight, ssl); |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, String name, int port, int timeout, int weight) { |
||||
this(host, port, timeout, timeout, weight); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, String name, int port, int timeout, int weight, boolean ssl) { |
||||
this(host, port, timeout, timeout, weight, ssl); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(String host, String name, int port, int timeout, int weight, |
||||
boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this(host, port, timeout, timeout, weight, ssl, sslSocketFactory, sslParameters, hostnameVerifier); |
||||
this.name = name; |
||||
} |
||||
|
||||
public JedisShardInfo(URI uri) { |
||||
super(Sharded.DEFAULT_WEIGHT); |
||||
if (!JedisURIHelper.isValid(uri)) { |
||||
throw new InvalidURIException(String.format( |
||||
"Cannot open Redis connection due invalid URI. %s", uri.toString())); |
||||
} |
||||
|
||||
this.host = uri.getHost(); |
||||
this.port = uri.getPort(); |
||||
this.password = JedisURIHelper.getPassword(uri); |
||||
this.db = JedisURIHelper.getDBIndex(uri); |
||||
this.ssl = JedisURIHelper.isRedisSSLScheme(uri); |
||||
} |
||||
|
||||
public JedisShardInfo(URI uri, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, |
||||
HostnameVerifier hostnameVerifier) { |
||||
this(uri); |
||||
this.sslSocketFactory = sslSocketFactory; |
||||
this.sslParameters = sslParameters; |
||||
this.hostnameVerifier = hostnameVerifier; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return host + ":" + port + "*" + getWeight(); |
||||
} |
||||
|
||||
public String getHost() { |
||||
return host; |
||||
} |
||||
|
||||
public int getPort() { |
||||
return port; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String auth) { |
||||
this.password = auth; |
||||
} |
||||
|
||||
public int getConnectionTimeout() { |
||||
return connectionTimeout; |
||||
} |
||||
|
||||
public void setConnectionTimeout(int connectionTimeout) { |
||||
this.connectionTimeout = connectionTimeout; |
||||
} |
||||
|
||||
public int getSoTimeout() { |
||||
return soTimeout; |
||||
} |
||||
|
||||
public void setSoTimeout(int soTimeout) { |
||||
this.soTimeout = soTimeout; |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public int getDb() { |
||||
return db; |
||||
} |
||||
|
||||
public boolean getSsl() { |
||||
return ssl; |
||||
} |
||||
|
||||
public SSLSocketFactory getSslSocketFactory() { |
||||
return sslSocketFactory; |
||||
} |
||||
|
||||
public SSLParameters getSslParameters() { |
||||
return sslParameters; |
||||
} |
||||
|
||||
public HostnameVerifier getHostnameVerifier() { |
||||
return hostnameVerifier; |
||||
} |
||||
|
||||
@Override |
||||
public Jedis createResource() { |
||||
return new Jedis(this); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,82 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException; |
||||
|
||||
public class JedisSlotBasedConnectionHandler extends JedisClusterConnectionHandler { |
||||
|
||||
public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes, |
||||
final GenericObjectPoolConfig poolConfig, int timeout) { |
||||
this(nodes, poolConfig, timeout, timeout); |
||||
} |
||||
|
||||
public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes, |
||||
final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) { |
||||
super(nodes, poolConfig, connectionTimeout, soTimeout, null); |
||||
} |
||||
|
||||
public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes, GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout, String password) { |
||||
super(nodes, poolConfig, connectionTimeout, soTimeout, password); |
||||
} |
||||
|
||||
public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes, GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout, String password, String clientName) { |
||||
super(nodes, poolConfig, connectionTimeout, soTimeout, password, clientName); |
||||
} |
||||
|
||||
@Override |
||||
public Jedis getConnection() { |
||||
// In antirez's redis-rb-cluster implementation,
|
||||
// getRandomConnection always return valid connection (able to
|
||||
// ping-pong)
|
||||
// or exception if all connections are invalid
|
||||
|
||||
List<JedisPool> pools = cache.getShuffledNodesPool(); |
||||
|
||||
for (JedisPool pool : pools) { |
||||
Jedis jedis = null; |
||||
try { |
||||
jedis = pool.getResource(); |
||||
|
||||
if (jedis == null) { |
||||
continue; |
||||
} |
||||
|
||||
String result = jedis.ping(); |
||||
|
||||
if (result.equalsIgnoreCase("pong")) return jedis; |
||||
|
||||
jedis.close(); |
||||
} catch (JedisException ex) { |
||||
if (jedis != null) { |
||||
jedis.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
throw new JedisNoReachableClusterNodeException("No reachable node in cluster"); |
||||
} |
||||
|
||||
@Override |
||||
public Jedis getConnectionFromSlot(int slot) { |
||||
JedisPool connectionPool = cache.getSlotPool(slot); |
||||
if (connectionPool != null) { |
||||
// It can't guaranteed to get valid connection because of node
|
||||
// assignment
|
||||
return connectionPool.getResource(); |
||||
} else { |
||||
renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
|
||||
connectionPool = cache.getSlotPool(slot); |
||||
if (connectionPool != null) { |
||||
return connectionPool.getResource(); |
||||
} else { |
||||
//no choice, fallback to new connection to random node
|
||||
return getConnection(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public enum ListPosition { |
||||
BEFORE, AFTER; |
||||
public final byte[] raw; |
||||
|
||||
private ListPosition() { |
||||
raw = SafeEncoder.encode(name()); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
public class Module { |
||||
private String name; |
||||
private int version; |
||||
|
||||
public Module(String name, int version) { |
||||
this.name = name; |
||||
this.version = version; |
||||
} |
||||
|
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public int getVersion() { |
||||
return version; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (o == null || getClass() != o.getClass()) return false; |
||||
|
||||
Module module = (Module) o; |
||||
|
||||
if (version != module.version) return false; |
||||
return !(name != null ? !name.equals(module.name) : module.name != null); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = name != null ? name.hashCode() : 0; |
||||
result = 31 * result + version; |
||||
return result; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,692 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.commands.*; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
public abstract class MultiKeyPipelineBase extends PipelineBase implements |
||||
MultiKeyBinaryRedisPipeline, MultiKeyCommandsPipeline, ClusterPipeline, |
||||
BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline, BasicRedisPipeline { |
||||
|
||||
protected Client client = null; |
||||
|
||||
@Override |
||||
public Response<List<String>> brpop(String... args) { |
||||
client.brpop(args); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
public Response<List<String>> brpop(int timeout, String... keys) { |
||||
client.brpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<String>> blpop(String... args) { |
||||
client.blpop(args); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
public Response<List<String>> blpop(int timeout, String... keys) { |
||||
client.blpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
public Response<Map<String, String>> blpopMap(int timeout, String... keys) { |
||||
client.blpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_MAP); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<byte[]>> brpop(byte[]... args) { |
||||
client.brpop(args); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); |
||||
} |
||||
|
||||
public Response<List<String>> brpop(int timeout, byte[]... keys) { |
||||
client.brpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
public Response<Map<String, String>> brpopMap(int timeout, String... keys) { |
||||
client.blpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_MAP); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<byte[]>> blpop(byte[]... args) { |
||||
client.blpop(args); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); |
||||
} |
||||
|
||||
public Response<List<String>> blpop(int timeout, byte[]... keys) { |
||||
client.blpop(timeout, keys); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> del(String... keys) { |
||||
client.del(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> del(byte[]... keys) { |
||||
client.del(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> unlink(String... keys) { |
||||
client.unlink(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> unlink(byte[]... keys) { |
||||
client.unlink(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> exists(String... keys) { |
||||
client.exists(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> exists(byte[]... keys) { |
||||
client.exists(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<String>> keys(String pattern) { |
||||
getClient(pattern).keys(pattern); |
||||
return getResponse(BuilderFactory.STRING_SET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<byte[]>> keys(byte[] pattern) { |
||||
getClient(pattern).keys(pattern); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<String>> mget(String... keys) { |
||||
client.mget(keys); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<byte[]>> mget(byte[]... keys) { |
||||
client.mget(keys); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> mset(String... keysvalues) { |
||||
client.mset(keysvalues); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> mset(byte[]... keysvalues) { |
||||
client.mset(keysvalues); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> msetnx(String... keysvalues) { |
||||
client.msetnx(keysvalues); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> msetnx(byte[]... keysvalues) { |
||||
client.msetnx(keysvalues); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> rename(String oldkey, String newkey) { |
||||
client.rename(oldkey, newkey); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> rename(byte[] oldkey, byte[] newkey) { |
||||
client.rename(oldkey, newkey); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> renamenx(String oldkey, String newkey) { |
||||
client.renamenx(oldkey, newkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> renamenx(byte[] oldkey, byte[] newkey) { |
||||
client.renamenx(oldkey, newkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> rpoplpush(String srckey, String dstkey) { |
||||
client.rpoplpush(srckey, dstkey); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<byte[]> rpoplpush(byte[] srckey, byte[] dstkey) { |
||||
client.rpoplpush(srckey, dstkey); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<String>> sdiff(String... keys) { |
||||
client.sdiff(keys); |
||||
return getResponse(BuilderFactory.STRING_SET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<byte[]>> sdiff(byte[]... keys) { |
||||
client.sdiff(keys); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sdiffstore(String dstkey, String... keys) { |
||||
client.sdiffstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sdiffstore(byte[] dstkey, byte[]... keys) { |
||||
client.sdiffstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<String>> sinter(String... keys) { |
||||
client.sinter(keys); |
||||
return getResponse(BuilderFactory.STRING_SET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<byte[]>> sinter(byte[]... keys) { |
||||
client.sinter(keys); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sinterstore(String dstkey, String... keys) { |
||||
client.sinterstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sinterstore(byte[] dstkey, byte[]... keys) { |
||||
client.sinterstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> smove(String srckey, String dstkey, String member) { |
||||
client.smove(srckey, dstkey, member); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member) { |
||||
client.smove(srckey, dstkey, member); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sort(String key, SortingParams sortingParameters, String dstkey) { |
||||
client.sort(key, sortingParameters, dstkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sort(byte[] key, SortingParams sortingParameters, byte[] dstkey) { |
||||
client.sort(key, sortingParameters, dstkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sort(String key, String dstkey) { |
||||
client.sort(key, dstkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sort(byte[] key, byte[] dstkey) { |
||||
client.sort(key, dstkey); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<String>> sunion(String... keys) { |
||||
client.sunion(keys); |
||||
return getResponse(BuilderFactory.STRING_SET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Set<byte[]>> sunion(byte[]... keys) { |
||||
client.sunion(keys); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sunionstore(String dstkey, String... keys) { |
||||
client.sunionstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> sunionstore(byte[] dstkey, byte[]... keys) { |
||||
client.sunionstore(dstkey, keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> watch(String... keys) { |
||||
client.watch(keys); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> watch(byte[]... keys) { |
||||
client.watch(keys); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zinterstore(String dstkey, String... sets) { |
||||
client.zinterstore(dstkey, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zinterstore(byte[] dstkey, byte[]... sets) { |
||||
client.zinterstore(dstkey, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zinterstore(String dstkey, ZParams params, String... sets) { |
||||
client.zinterstore(dstkey, params, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zinterstore(byte[] dstkey, ZParams params, byte[]... sets) { |
||||
client.zinterstore(dstkey, params, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zunionstore(String dstkey, String... sets) { |
||||
client.zunionstore(dstkey, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zunionstore(byte[] dstkey, byte[]... sets) { |
||||
client.zunionstore(dstkey, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zunionstore(String dstkey, ZParams params, String... sets) { |
||||
client.zunionstore(dstkey, params, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> zunionstore(byte[] dstkey, ZParams params, byte[]... sets) { |
||||
client.zunionstore(dstkey, params, sets); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> bgrewriteaof() { |
||||
client.bgrewriteaof(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> bgsave() { |
||||
client.bgsave(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<String>> configGet(String pattern) { |
||||
client.configGet(pattern); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> configSet(String parameter, String value) { |
||||
client.configSet(parameter, value); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> brpoplpush(String source, String destination, int timeout) { |
||||
client.brpoplpush(source, destination, timeout); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<byte[]> brpoplpush(byte[] source, byte[] destination, int timeout) { |
||||
client.brpoplpush(source, destination, timeout); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> configResetStat() { |
||||
client.configResetStat(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> save() { |
||||
client.save(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> lastsave() { |
||||
client.lastsave(); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> publish(String channel, String message) { |
||||
client.publish(channel, message); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> publish(byte[] channel, byte[] message) { |
||||
client.publish(channel, message); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> randomKey() { |
||||
client.randomKey(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<byte[]> randomKeyBinary() { |
||||
client.randomKey(); |
||||
return getResponse(BuilderFactory.BYTE_ARRAY); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> flushDB() { |
||||
client.flushDB(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> flushAll() { |
||||
client.flushAll(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> info() { |
||||
client.info(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
public Response<String> info(final String section) { |
||||
client.info(section); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> dbSize() { |
||||
client.dbSize(); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> shutdown() { |
||||
client.shutdown(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> ping() { |
||||
client.ping(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> select(int index) { |
||||
client.select(index); |
||||
Response<String> response = getResponse(BuilderFactory.STRING); |
||||
client.setDb(index); |
||||
|
||||
return response; |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> swapDB(int index1, int index2) { |
||||
client.swapDB(index1, index2); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { |
||||
client.bitop(op, destKey, srcKeys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> bitop(BitOP op, String destKey, String... srcKeys) { |
||||
client.bitop(op, destKey, srcKeys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterNodes() { |
||||
client.clusterNodes(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterMeet(final String ip, final int port) { |
||||
client.clusterMeet(ip, port); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterAddSlots(final int... slots) { |
||||
client.clusterAddSlots(slots); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterDelSlots(final int... slots) { |
||||
client.clusterDelSlots(slots); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterInfo() { |
||||
client.clusterInfo(); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<String>> clusterGetKeysInSlot(final int slot, final int count) { |
||||
client.clusterGetKeysInSlot(slot, count); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterSetSlotNode(final int slot, final String nodeId) { |
||||
client.clusterSetSlotNode(slot, nodeId); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterSetSlotMigrating(final int slot, final String nodeId) { |
||||
client.clusterSetSlotMigrating(slot, nodeId); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> clusterSetSlotImporting(final int slot, final String nodeId) { |
||||
client.clusterSetSlotImporting(slot, nodeId); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(String script) { |
||||
return this.eval(script, 0, new String[0]); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(String script, List<String> keys, List<String> args) { |
||||
String[] argv = Jedis.getParams(keys, args); |
||||
return this.eval(script, keys.size(), argv); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(String script, int keyCount, String... params) { |
||||
getClient(script).eval(script, keyCount, params); |
||||
return getResponse(BuilderFactory.EVAL_RESULT); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(String sha1) { |
||||
return this.evalsha(sha1, 0, new String[0]); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(String sha1, List<String> keys, List<String> args) { |
||||
String[] argv = Jedis.getParams(keys, args); |
||||
return this.evalsha(sha1, keys.size(), argv); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(String sha1, int keyCount, String... params) { |
||||
getClient(sha1).evalsha(sha1, keyCount, params); |
||||
return getResponse(BuilderFactory.EVAL_RESULT); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(byte[] script) { |
||||
return this.eval(script, 0); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(byte[] script, byte[] keyCount, byte[]... params) { |
||||
getClient(script).eval(script, keyCount, params); |
||||
return getResponse(BuilderFactory.EVAL_BINARY_RESULT); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(byte[] script, List<byte[]> keys, List<byte[]> args) { |
||||
byte[][] argv = BinaryJedis.getParamsWithBinary(keys, args); |
||||
return this.eval(script, keys.size(), argv); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> eval(byte[] script, int keyCount, byte[]... params) { |
||||
getClient(script).eval(script, keyCount, params); |
||||
return getResponse(BuilderFactory.EVAL_BINARY_RESULT); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(byte[] sha1) { |
||||
return this.evalsha(sha1, 0); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args) { |
||||
byte[][] argv = BinaryJedis.getParamsWithBinary(keys, args); |
||||
return this.evalsha(sha1, keys.size(), argv); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Object> evalsha(byte[] sha1, int keyCount, byte[]... params) { |
||||
getClient(sha1).evalsha(sha1, keyCount, params); |
||||
return getResponse(BuilderFactory.EVAL_BINARY_RESULT); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> pfcount(String... keys) { |
||||
client.pfcount(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> pfcount(final byte[]... keys) { |
||||
client.pfcount(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> pfmerge(byte[] destkey, byte[]... sourcekeys) { |
||||
client.pfmerge(destkey, sourcekeys); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> pfmerge(String destkey, String... sourcekeys) { |
||||
client.pfmerge(destkey, sourcekeys); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<String>> time() { |
||||
client.time(); |
||||
return getResponse(BuilderFactory.STRING_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> touch(String... keys) { |
||||
client.touch(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<Long> touch(byte[]... keys) { |
||||
client.touch(keys); |
||||
return getResponse(BuilderFactory.LONG); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> moduleUnload(String name) { |
||||
client.moduleUnload(name); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
@Override |
||||
public Response<List<Module>> moduleList() { |
||||
client.moduleList(); |
||||
return getResponse(BuilderFactory.MODULE_LIST); |
||||
} |
||||
|
||||
@Override |
||||
public Response<String> moduleLoad(String path) { |
||||
client.moduleLoad(path); |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,160 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisDataException; |
||||
|
||||
public class Pipeline extends MultiKeyPipelineBase implements Closeable { |
||||
|
||||
private MultiResponseBuilder currentMulti; |
||||
|
||||
private class MultiResponseBuilder extends Builder<List<Object>> { |
||||
private List<Response<?>> responses = new ArrayList<Response<?>>(); |
||||
|
||||
@Override |
||||
public List<Object> build(Object data) { |
||||
@SuppressWarnings("unchecked") |
||||
List<Object> list = (List<Object>) data; |
||||
List<Object> values = new ArrayList<Object>(); |
||||
|
||||
if (list.size() != responses.size()) { |
||||
throw new JedisDataException("Expected data size " + responses.size() + " but was " |
||||
+ list.size()); |
||||
} |
||||
|
||||
for (int i = 0; i < list.size(); i++) { |
||||
Response<?> response = responses.get(i); |
||||
response.set(list.get(i)); |
||||
Object builtResponse; |
||||
try { |
||||
builtResponse = response.get(); |
||||
} catch (JedisDataException e) { |
||||
builtResponse = e; |
||||
} |
||||
values.add(builtResponse); |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
public void setResponseDependency(Response<?> dependency) { |
||||
for (Response<?> response : responses) { |
||||
response.setDependency(dependency); |
||||
} |
||||
} |
||||
|
||||
public void addResponse(Response<?> response) { |
||||
responses.add(response); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected <T> Response<T> getResponse(Builder<T> builder) { |
||||
if (currentMulti != null) { |
||||
super.getResponse(BuilderFactory.STRING); // Expected QUEUED
|
||||
|
||||
Response<T> lr = new Response<T>(builder); |
||||
currentMulti.addResponse(lr); |
||||
return lr; |
||||
} else { |
||||
return super.getResponse(builder); |
||||
} |
||||
} |
||||
|
||||
public void setClient(Client client) { |
||||
this.client = client; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(byte[] key) { |
||||
return client; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(String key) { |
||||
return client; |
||||
} |
||||
|
||||
public void clear() { |
||||
if (isInMulti()) { |
||||
discard(); |
||||
} |
||||
|
||||
sync(); |
||||
} |
||||
|
||||
public boolean isInMulti() { |
||||
return currentMulti != null; |
||||
} |
||||
|
||||
/** |
||||
* Synchronize pipeline by reading all responses. This operation close the pipeline. In order to |
||||
* get return values from pipelined commands, capture the different Response<?> of the |
||||
* commands you execute. |
||||
*/ |
||||
public void sync() { |
||||
if (getPipelinedResponseLength() > 0) { |
||||
List<Object> unformatted = client.getMany(getPipelinedResponseLength()); |
||||
for (Object o : unformatted) { |
||||
generateResponse(o); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Synchronize pipeline by reading all responses. This operation close the pipeline. Whenever |
||||
* possible try to avoid using this version and use Pipeline.sync() as it won't go through all the |
||||
* responses and generate the right response type (usually it is a waste of time). |
||||
* @return A list of all the responses in the order you executed them. |
||||
*/ |
||||
public List<Object> syncAndReturnAll() { |
||||
if (getPipelinedResponseLength() > 0) { |
||||
List<Object> unformatted = client.getMany(getPipelinedResponseLength()); |
||||
List<Object> formatted = new ArrayList<Object>(); |
||||
for (Object o : unformatted) { |
||||
try { |
||||
formatted.add(generateResponse(o).get()); |
||||
} catch (JedisDataException e) { |
||||
formatted.add(e); |
||||
} |
||||
} |
||||
return formatted; |
||||
} else { |
||||
return java.util.Collections.<Object> emptyList(); |
||||
} |
||||
} |
||||
|
||||
public Response<String> discard() { |
||||
if (currentMulti == null) throw new JedisDataException("DISCARD without MULTI"); |
||||
client.discard(); |
||||
currentMulti = null; |
||||
return getResponse(BuilderFactory.STRING); |
||||
} |
||||
|
||||
public Response<List<Object>> exec() { |
||||
if (currentMulti == null) throw new JedisDataException("EXEC without MULTI"); |
||||
|
||||
client.exec(); |
||||
Response<List<Object>> response = super.getResponse(currentMulti); |
||||
currentMulti.setResponseDependency(response); |
||||
currentMulti = null; |
||||
return response; |
||||
} |
||||
|
||||
public Response<String> multi() { |
||||
if (currentMulti != null) throw new JedisDataException("MULTI calls can not be nested"); |
||||
|
||||
client.multi(); |
||||
Response<String> response = getResponse(BuilderFactory.STRING); // Expecting
|
||||
// OK
|
||||
currentMulti = new MultiResponseBuilder(); |
||||
return response; |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
clear(); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,281 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Locale; |
||||
|
||||
import com.fr.third.redis.clients.jedis.commands.ProtocolCommand; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisAskDataException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisBusyException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisClusterException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisConnectionException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisDataException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisMovedDataException; |
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisNoScriptException; |
||||
import com.fr.third.redis.clients.jedis.util.RedisInputStream; |
||||
import com.fr.third.redis.clients.jedis.util.RedisOutputStream; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public final class Protocol { |
||||
|
||||
private static final String ASK_RESPONSE = "ASK"; |
||||
private static final String MOVED_RESPONSE = "MOVED"; |
||||
private static final String CLUSTERDOWN_RESPONSE = "CLUSTERDOWN"; |
||||
private static final String BUSY_RESPONSE = "BUSY"; |
||||
private static final String NOSCRIPT_RESPONSE = "NOSCRIPT"; |
||||
|
||||
public static final String DEFAULT_HOST = "localhost"; |
||||
public static final int DEFAULT_PORT = 6379; |
||||
public static final int DEFAULT_SENTINEL_PORT = 26379; |
||||
public static final int DEFAULT_TIMEOUT = 2000; |
||||
public static final int DEFAULT_DATABASE = 0; |
||||
|
||||
public static final String CHARSET = "UTF-8"; |
||||
|
||||
public static final byte DOLLAR_BYTE = '$'; |
||||
public static final byte ASTERISK_BYTE = '*'; |
||||
public static final byte PLUS_BYTE = '+'; |
||||
public static final byte MINUS_BYTE = '-'; |
||||
public static final byte COLON_BYTE = ':'; |
||||
|
||||
public static final String SENTINEL_MASTERS = "masters"; |
||||
public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name"; |
||||
public static final String SENTINEL_RESET = "reset"; |
||||
public static final String SENTINEL_SLAVES = "slaves"; |
||||
public static final String SENTINEL_FAILOVER = "failover"; |
||||
public static final String SENTINEL_MONITOR = "monitor"; |
||||
public static final String SENTINEL_REMOVE = "remove"; |
||||
public static final String SENTINEL_SET = "set"; |
||||
|
||||
public static final String CLUSTER_NODES = "nodes"; |
||||
public static final String CLUSTER_MEET = "meet"; |
||||
public static final String CLUSTER_RESET = "reset"; |
||||
public static final String CLUSTER_ADDSLOTS = "addslots"; |
||||
public static final String CLUSTER_DELSLOTS = "delslots"; |
||||
public static final String CLUSTER_INFO = "info"; |
||||
public static final String CLUSTER_GETKEYSINSLOT = "getkeysinslot"; |
||||
public static final String CLUSTER_SETSLOT = "setslot"; |
||||
public static final String CLUSTER_SETSLOT_NODE = "node"; |
||||
public static final String CLUSTER_SETSLOT_MIGRATING = "migrating"; |
||||
public static final String CLUSTER_SETSLOT_IMPORTING = "importing"; |
||||
public static final String CLUSTER_SETSLOT_STABLE = "stable"; |
||||
public static final String CLUSTER_FORGET = "forget"; |
||||
public static final String CLUSTER_FLUSHSLOT = "flushslots"; |
||||
public static final String CLUSTER_KEYSLOT = "keyslot"; |
||||
public static final String CLUSTER_COUNTKEYINSLOT = "countkeysinslot"; |
||||
public static final String CLUSTER_SAVECONFIG = "saveconfig"; |
||||
public static final String CLUSTER_REPLICATE = "replicate"; |
||||
public static final String CLUSTER_SLAVES = "slaves"; |
||||
public static final String CLUSTER_FAILOVER = "failover"; |
||||
public static final String CLUSTER_SLOTS = "slots"; |
||||
public static final String PUBSUB_CHANNELS = "channels"; |
||||
public static final String PUBSUB_NUMSUB = "numsub"; |
||||
public static final String PUBSUB_NUM_PAT = "numpat"; |
||||
|
||||
public static final byte[] BYTES_TRUE = toByteArray(1); |
||||
public static final byte[] BYTES_FALSE = toByteArray(0); |
||||
|
||||
public static final byte[] POSITIVE_INFINITY_BYTES = "+inf".getBytes(); |
||||
public static final byte[] NEGATIVE_INFINITY_BYTES = "-inf".getBytes(); |
||||
|
||||
private Protocol() { |
||||
// this prevent the class from instantiation
|
||||
} |
||||
|
||||
public static void sendCommand(final RedisOutputStream os, final ProtocolCommand command, |
||||
final byte[]... args) { |
||||
sendCommand(os, command.getRaw(), args); |
||||
} |
||||
|
||||
private static void sendCommand(final RedisOutputStream os, final byte[] command, |
||||
final byte[]... args) { |
||||
try { |
||||
os.write(ASTERISK_BYTE); |
||||
os.writeIntCrLf(args.length + 1); |
||||
os.write(DOLLAR_BYTE); |
||||
os.writeIntCrLf(command.length); |
||||
os.write(command); |
||||
os.writeCrLf(); |
||||
|
||||
for (final byte[] arg : args) { |
||||
os.write(DOLLAR_BYTE); |
||||
os.writeIntCrLf(arg.length); |
||||
os.write(arg); |
||||
os.writeCrLf(); |
||||
} |
||||
} catch (IOException e) { |
||||
throw new JedisConnectionException(e); |
||||
} |
||||
} |
||||
|
||||
private static void processError(final RedisInputStream is) { |
||||
String message = is.readLine(); |
||||
// TODO: I'm not sure if this is the best way to do this.
|
||||
// Maybe Read only first 5 bytes instead?
|
||||
if (message.startsWith(MOVED_RESPONSE)) { |
||||
String[] movedInfo = parseTargetHostAndSlot(message); |
||||
throw new JedisMovedDataException(message, new HostAndPort(movedInfo[1], |
||||
Integer.parseInt(movedInfo[2])), Integer.parseInt(movedInfo[0])); |
||||
} else if (message.startsWith(ASK_RESPONSE)) { |
||||
String[] askInfo = parseTargetHostAndSlot(message); |
||||
throw new JedisAskDataException(message, new HostAndPort(askInfo[1], |
||||
Integer.parseInt(askInfo[2])), Integer.parseInt(askInfo[0])); |
||||
} else if (message.startsWith(CLUSTERDOWN_RESPONSE)) { |
||||
throw new JedisClusterException(message); |
||||
} else if (message.startsWith(BUSY_RESPONSE)) { |
||||
throw new JedisBusyException(message); |
||||
} else if (message.startsWith(NOSCRIPT_RESPONSE) ) { |
||||
throw new JedisNoScriptException(message); |
||||
} |
||||
throw new JedisDataException(message); |
||||
} |
||||
|
||||
public static String readErrorLineIfPossible(RedisInputStream is) { |
||||
final byte b = is.readByte(); |
||||
// if buffer contains other type of response, just ignore.
|
||||
if (b != MINUS_BYTE) { |
||||
return null; |
||||
} |
||||
return is.readLine(); |
||||
} |
||||
|
||||
private static String[] parseTargetHostAndSlot(String clusterRedirectResponse) { |
||||
String[] response = new String[3]; |
||||
String[] messageInfo = clusterRedirectResponse.split(" "); |
||||
String[] targetHostAndPort = HostAndPort.extractParts(messageInfo[2]); |
||||
response[0] = messageInfo[1]; |
||||
response[1] = targetHostAndPort[0]; |
||||
response[2] = targetHostAndPort[1]; |
||||
return response; |
||||
} |
||||
|
||||
private static Object process(final RedisInputStream is) { |
||||
|
||||
final byte b = is.readByte(); |
||||
if (b == PLUS_BYTE) { |
||||
return processStatusCodeReply(is); |
||||
} else if (b == DOLLAR_BYTE) { |
||||
return processBulkReply(is); |
||||
} else if (b == ASTERISK_BYTE) { |
||||
return processMultiBulkReply(is); |
||||
} else if (b == COLON_BYTE) { |
||||
return processInteger(is); |
||||
} else if (b == MINUS_BYTE) { |
||||
processError(is); |
||||
return null; |
||||
} else { |
||||
throw new JedisConnectionException("Unknown reply: " + (char) b); |
||||
} |
||||
} |
||||
|
||||
private static byte[] processStatusCodeReply(final RedisInputStream is) { |
||||
return is.readLineBytes(); |
||||
} |
||||
|
||||
private static byte[] processBulkReply(final RedisInputStream is) { |
||||
final int len = is.readIntCrLf(); |
||||
if (len == -1) { |
||||
return null; |
||||
} |
||||
|
||||
final byte[] read = new byte[len]; |
||||
int offset = 0; |
||||
while (offset < len) { |
||||
final int size = is.read(read, offset, (len - offset)); |
||||
if (size == -1) throw new JedisConnectionException( |
||||
"It seems like server has closed the connection."); |
||||
offset += size; |
||||
} |
||||
|
||||
// read 2 more bytes for the command delimiter
|
||||
is.readByte(); |
||||
is.readByte(); |
||||
|
||||
return read; |
||||
} |
||||
|
||||
private static Long processInteger(final RedisInputStream is) { |
||||
return is.readLongCrLf(); |
||||
} |
||||
|
||||
private static List<Object> processMultiBulkReply(final RedisInputStream is) { |
||||
final int num = is.readIntCrLf(); |
||||
if (num == -1) { |
||||
return null; |
||||
} |
||||
final List<Object> ret = new ArrayList<Object>(num); |
||||
for (int i = 0; i < num; i++) { |
||||
try { |
||||
ret.add(process(is)); |
||||
} catch (JedisDataException e) { |
||||
ret.add(e); |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
public static Object read(final RedisInputStream is) { |
||||
return process(is); |
||||
} |
||||
|
||||
public static final byte[] toByteArray(final boolean value) { |
||||
return value ? BYTES_TRUE : BYTES_FALSE; |
||||
} |
||||
|
||||
public static final byte[] toByteArray(final int value) { |
||||
return SafeEncoder.encode(String.valueOf(value)); |
||||
} |
||||
|
||||
public static final byte[] toByteArray(final long value) { |
||||
return SafeEncoder.encode(String.valueOf(value)); |
||||
} |
||||
|
||||
public static final byte[] toByteArray(final double value) { |
||||
if (value == Double.POSITIVE_INFINITY) { |
||||
return POSITIVE_INFINITY_BYTES; |
||||
} else if (value == Double.NEGATIVE_INFINITY) { |
||||
return NEGATIVE_INFINITY_BYTES; |
||||
} else { |
||||
return SafeEncoder.encode(String.valueOf(value)); |
||||
} |
||||
} |
||||
|
||||
public static enum Command implements ProtocolCommand { |
||||
PING, SET, GET, QUIT, EXISTS, DEL, UNLINK, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, |
||||
DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, |
||||
DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, |
||||
HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, |
||||
RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, |
||||
SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, |
||||
ZREVRANGE, ZCARD, ZSCORE, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, |
||||
SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, ZCOUNT, ZRANGEBYSCORE, |
||||
ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, ZLEXCOUNT, |
||||
ZRANGEBYLEX, ZREVRANGEBYLEX, ZREMRANGEBYLEX, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, |
||||
INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, |
||||
SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, |
||||
SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, |
||||
SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, PFADD, PFCOUNT, PFMERGE, READONLY, GEOADD, GEODIST, |
||||
GEOHASH, GEOPOS, GEORADIUS, GEORADIUSBYMEMBER, MODULE, BITFIELD, HSTRLEN, TOUCH, SWAPDB; |
||||
|
||||
private final byte[] raw; |
||||
|
||||
Command() { |
||||
raw = SafeEncoder.encode(this.name()); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] getRaw() { |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
public static enum Keyword { |
||||
AGGREGATE, ALPHA, ASC, BY, DESC, GET, LIMIT, MESSAGE, NO, NOSORT, PMESSAGE, PSUBSCRIBE, PUNSUBSCRIBE, OK, ONE, QUEUED, SET, STORE, SUBSCRIBE, UNSUBSCRIBE, WEIGHTS, WITHSCORES, RESETSTAT, REWRITE, RESET, FLUSH, EXISTS, LOAD, KILL, LEN, REFCOUNT, ENCODING, IDLETIME, GETNAME, SETNAME, LIST, MATCH, COUNT, PING, PONG, UNLOAD; |
||||
public final byte[] raw; |
||||
|
||||
Keyword() { |
||||
raw = SafeEncoder.encode(this.name().toLowerCase(Locale.ENGLISH)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.LinkedList; |
||||
import java.util.Queue; |
||||
|
||||
public class Queable { |
||||
private Queue<Response<?>> pipelinedResponses = new LinkedList<Response<?>>(); |
||||
|
||||
protected void clean() { |
||||
pipelinedResponses.clear(); |
||||
} |
||||
|
||||
protected Response<?> generateResponse(Object data) { |
||||
Response<?> response = pipelinedResponses.poll(); |
||||
if (response != null) { |
||||
response.set(data); |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
protected <T> Response<T> getResponse(Builder<T> builder) { |
||||
Response<T> lr = new Response<T>(builder); |
||||
pipelinedResponses.add(lr); |
||||
return lr; |
||||
} |
||||
|
||||
protected boolean hasPipelinedResponse() { |
||||
return !pipelinedResponses.isEmpty(); |
||||
} |
||||
|
||||
protected int getPipelinedResponseLength() { |
||||
return pipelinedResponses.size(); |
||||
} |
||||
} |
@ -0,0 +1,77 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisDataException; |
||||
|
||||
public class Response<T> { |
||||
protected T response = null; |
||||
protected JedisDataException exception = null; |
||||
|
||||
private boolean building = false; |
||||
private boolean built = false; |
||||
private boolean set = false; |
||||
|
||||
private Builder<T> builder; |
||||
private Object data; |
||||
private Response<?> dependency = null; |
||||
|
||||
public Response(Builder<T> b) { |
||||
this.builder = b; |
||||
} |
||||
|
||||
public void set(Object data) { |
||||
this.data = data; |
||||
set = true; |
||||
} |
||||
|
||||
public T get() { |
||||
// if response has dependency response and dependency is not built,
|
||||
// build it first and no more!!
|
||||
if (dependency != null && dependency.set && !dependency.built) { |
||||
dependency.build(); |
||||
} |
||||
if (!set) { |
||||
throw new JedisDataException( |
||||
"Please close pipeline or multi block before calling this method."); |
||||
} |
||||
if (!built) { |
||||
build(); |
||||
} |
||||
if (exception != null) { |
||||
throw exception; |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
public void setDependency(Response<?> dependency) { |
||||
this.dependency = dependency; |
||||
} |
||||
|
||||
private void build() { |
||||
// check build state to prevent recursion
|
||||
if (building) { |
||||
return; |
||||
} |
||||
|
||||
building = true; |
||||
try { |
||||
if (data != null) { |
||||
if (data instanceof JedisDataException) { |
||||
exception = (JedisDataException) data; |
||||
} else { |
||||
response = builder.build(data); |
||||
} |
||||
} |
||||
|
||||
data = null; |
||||
} finally { |
||||
building = false; |
||||
built = true; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Response " + builder.toString(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,78 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.COUNT; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.MATCH; |
||||
|
||||
import com.fr.third.redis.clients.jedis.Protocol.Keyword; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.EnumMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class ScanParams { |
||||
|
||||
private final Map<Keyword, ByteBuffer> params = new EnumMap<Keyword, ByteBuffer>(Keyword.class); |
||||
|
||||
public final static String SCAN_POINTER_START = String.valueOf(0); |
||||
public final static byte[] SCAN_POINTER_START_BINARY = SafeEncoder.encode(SCAN_POINTER_START); |
||||
|
||||
public ScanParams match(final byte[] pattern) { |
||||
params.put(MATCH, ByteBuffer.wrap(pattern)); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* @see <a href="https://redis.io/commands/scan#the-match-option">MATCH option in Redis documentation</a> |
||||
*/ |
||||
public ScanParams match(final String pattern) { |
||||
params.put(MATCH, ByteBuffer.wrap(SafeEncoder.encode(pattern))); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* @see <a href="https://redis.io/commands/scan#the-count-option">COUNT option in Redis documentation</a> |
||||
*/ |
||||
public ScanParams count(final Integer count) { |
||||
params.put(COUNT, ByteBuffer.wrap(Protocol.toByteArray(count))); |
||||
return this; |
||||
} |
||||
|
||||
public Collection<byte[]> getParams() { |
||||
List<byte[]> paramsList = new ArrayList<byte[]>(params.size()); |
||||
for (Map.Entry<Keyword, ByteBuffer> param : params.entrySet()) { |
||||
paramsList.add(param.getKey().raw); |
||||
paramsList.add(param.getValue().array()); |
||||
} |
||||
return Collections.unmodifiableCollection(paramsList); |
||||
} |
||||
|
||||
byte[] binaryMatch() { |
||||
if (params.containsKey(MATCH)) { |
||||
return params.get(MATCH).array(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
String match() { |
||||
if (params.containsKey(MATCH)) { |
||||
return new String(params.get(MATCH).array()); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
Integer count() { |
||||
if (params.containsKey(COUNT)) { |
||||
return params.get(COUNT).getInt(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class ScanResult<T> { |
||||
private byte[] cursor; |
||||
private List<T> results; |
||||
|
||||
public ScanResult(String cursor, List<T> results) { |
||||
this(SafeEncoder.encode(cursor), results); |
||||
} |
||||
|
||||
public ScanResult(byte[] cursor, List<T> results) { |
||||
this.cursor = cursor; |
||||
this.results = results; |
||||
} |
||||
|
||||
/** |
||||
* Returns the new value of the cursor |
||||
* @return the new cursor value. {@link ScanParams#SCAN_POINTER_START} when a complete iteration has finished |
||||
*/ |
||||
public String getCursor() { |
||||
return SafeEncoder.encode(cursor); |
||||
} |
||||
|
||||
/** |
||||
* Is the iteration complete. I.e. was the complete dataset scanned. |
||||
* |
||||
* @return true if the iteration is complete |
||||
*/ |
||||
public boolean isCompleteIteration() { |
||||
return ScanParams.SCAN_POINTER_START.equals(getCursor()); |
||||
} |
||||
|
||||
public byte[] getCursorAsBytes() { |
||||
return cursor; |
||||
} |
||||
|
||||
/** |
||||
* The scan results from the current call. |
||||
* @return the scan results |
||||
*/ |
||||
public List<T> getResult() { |
||||
return results; |
||||
} |
||||
} |
@ -0,0 +1,934 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Map.Entry; |
||||
import java.util.Set; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.fr.third.redis.clients.jedis.commands.JedisCommands; |
||||
import com.fr.third.redis.clients.jedis.params.GeoRadiusParam; |
||||
import com.fr.third.redis.clients.jedis.params.SetParams; |
||||
import com.fr.third.redis.clients.jedis.params.ZAddParams; |
||||
import com.fr.third.redis.clients.jedis.params.ZIncrByParams; |
||||
import com.fr.third.redis.clients.jedis.util.Hashing; |
||||
|
||||
public class ShardedJedis extends BinaryShardedJedis implements JedisCommands, Closeable { |
||||
|
||||
protected ShardedJedisPool dataSource = null; |
||||
|
||||
public ShardedJedis(List<JedisShardInfo> shards) { |
||||
super(shards); |
||||
} |
||||
|
||||
public ShardedJedis(List<JedisShardInfo> shards, Hashing algo) { |
||||
super(shards, algo); |
||||
} |
||||
|
||||
public ShardedJedis(List<JedisShardInfo> shards, Pattern keyTagPattern) { |
||||
super(shards, keyTagPattern); |
||||
} |
||||
|
||||
public ShardedJedis(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) { |
||||
super(shards, algo, keyTagPattern); |
||||
} |
||||
|
||||
@Override |
||||
public String set(final String key, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.set(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public String set(final String key, final String value, SetParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.set(key, value, params); |
||||
} |
||||
|
||||
@Override |
||||
public String get(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.get(key); |
||||
} |
||||
|
||||
@Override |
||||
public String echo(final String string) { |
||||
Jedis j = getShard(string); |
||||
return j.echo(string); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean exists(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.exists(key); |
||||
} |
||||
|
||||
@Override |
||||
public String type(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.type(key); |
||||
} |
||||
|
||||
@Override |
||||
public byte[] dump(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.dump(key); |
||||
} |
||||
|
||||
@Override |
||||
public String restore(final String key, final int ttl, final byte[] serializedValue) { |
||||
Jedis j = getShard(key); |
||||
return j.restore(key, ttl, serializedValue); |
||||
} |
||||
|
||||
@Override |
||||
public Long expire(final String key, final int seconds) { |
||||
Jedis j = getShard(key); |
||||
return j.expire(key, seconds); |
||||
} |
||||
|
||||
@Override |
||||
public Long pexpire(final String key, final long milliseconds) { |
||||
Jedis j = getShard(key); |
||||
return j.pexpire(key, milliseconds); |
||||
} |
||||
|
||||
@Override |
||||
public Long expireAt(final String key, final long unixTime) { |
||||
Jedis j = getShard(key); |
||||
return j.expireAt(key, unixTime); |
||||
} |
||||
|
||||
@Override |
||||
public Long pexpireAt(final String key, final long millisecondsTimestamp) { |
||||
Jedis j = getShard(key); |
||||
return j.pexpireAt(key, millisecondsTimestamp); |
||||
} |
||||
|
||||
@Override |
||||
public Long ttl(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.ttl(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long pttl(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.pttl(key); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean setbit(final String key, final long offset, boolean value) { |
||||
Jedis j = getShard(key); |
||||
return j.setbit(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean setbit(final String key, final long offset, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.setbit(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean getbit(final String key, final long offset) { |
||||
Jedis j = getShard(key); |
||||
return j.getbit(key, offset); |
||||
} |
||||
|
||||
@Override |
||||
public Long setrange(final String key, final long offset, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.setrange(key, offset, value); |
||||
} |
||||
|
||||
@Override |
||||
public String getrange(final String key, final long startOffset, final long endOffset) { |
||||
Jedis j = getShard(key); |
||||
return j.getrange(key, startOffset, endOffset); |
||||
} |
||||
|
||||
@Override |
||||
public String getSet(final String key, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.getSet(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long setnx(final String key, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.setnx(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public String setex(final String key, final int seconds, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.setex(key, seconds, value); |
||||
} |
||||
|
||||
@Override |
||||
public String psetex(final String key, final long milliseconds, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.psetex(key, milliseconds, value); |
||||
} |
||||
|
||||
public List<String> blpop(final String arg) { |
||||
Jedis j = getShard(arg); |
||||
return j.blpop(arg); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> blpop(final int timeout, final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.blpop(timeout, key); |
||||
} |
||||
|
||||
public List<String> brpop(final String arg) { |
||||
Jedis j = getShard(arg); |
||||
return j.brpop(arg); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> brpop(final int timeout, final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.brpop(timeout, key); |
||||
} |
||||
|
||||
@Override |
||||
public Long decrBy(final String key, final long decrement) { |
||||
Jedis j = getShard(key); |
||||
return j.decrBy(key, decrement); |
||||
} |
||||
|
||||
@Override |
||||
public Long decr(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.decr(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long incrBy(final String key, final long increment) { |
||||
Jedis j = getShard(key); |
||||
return j.incrBy(key, increment); |
||||
} |
||||
|
||||
@Override |
||||
public Double incrByFloat(final String key, final double increment) { |
||||
Jedis j = getShard(key); |
||||
return j.incrByFloat(key, increment); |
||||
} |
||||
|
||||
@Override |
||||
public Long incr(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.incr(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long append(final String key, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.append(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public String substr(final String key, final int start, final int end) { |
||||
Jedis j = getShard(key); |
||||
return j.substr(key, start, end); |
||||
} |
||||
|
||||
@Override |
||||
public Long hset(final String key, final String field, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.hset(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long hset(final String key, final Map<String, String> hash) { |
||||
Jedis j = getShard(key); |
||||
return j.hset(key, hash); |
||||
} |
||||
|
||||
@Override |
||||
public String hget(final String key, final String field) { |
||||
Jedis j = getShard(key); |
||||
return j.hget(key, field); |
||||
} |
||||
|
||||
@Override |
||||
public Long hsetnx(final String key, final String field, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.hsetnx(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public String hmset(final String key, final Map<String, String> hash) { |
||||
Jedis j = getShard(key); |
||||
return j.hmset(key, hash); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> hmget(final String key, String... fields) { |
||||
Jedis j = getShard(key); |
||||
return j.hmget(key, fields); |
||||
} |
||||
|
||||
@Override |
||||
public Long hincrBy(final String key, final String field, final long value) { |
||||
Jedis j = getShard(key); |
||||
return j.hincrBy(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Double hincrByFloat(final String key, final String field, final double value) { |
||||
Jedis j = getShard(key); |
||||
return j.hincrByFloat(key, field, value); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean hexists(final String key, final String field) { |
||||
Jedis j = getShard(key); |
||||
return j.hexists(key, field); |
||||
} |
||||
|
||||
@Override |
||||
public Long del(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.del(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long unlink(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.unlink(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long hdel(final String key, String... fields) { |
||||
Jedis j = getShard(key); |
||||
return j.hdel(key, fields); |
||||
} |
||||
|
||||
@Override |
||||
public Long hlen(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.hlen(key); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> hkeys(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.hkeys(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> hvals(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.hvals(key); |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, String> hgetAll(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.hgetAll(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long rpush(final String key, String... strings) { |
||||
Jedis j = getShard(key); |
||||
return j.rpush(key, strings); |
||||
} |
||||
|
||||
@Override |
||||
public Long lpush(final String key, String... strings) { |
||||
Jedis j = getShard(key); |
||||
return j.lpush(key, strings); |
||||
} |
||||
|
||||
@Override |
||||
public Long lpushx(final String key, String... string) { |
||||
Jedis j = getShard(key); |
||||
return j.lpushx(key, string); |
||||
} |
||||
|
||||
@Override |
||||
public Long strlen(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.strlen(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long move(final String key, final int dbIndex) { |
||||
Jedis j = getShard(key); |
||||
return j.move(key, dbIndex); |
||||
} |
||||
|
||||
@Override |
||||
public Long rpushx(final String key, String... string) { |
||||
Jedis j = getShard(key); |
||||
return j.rpushx(key, string); |
||||
} |
||||
|
||||
@Override |
||||
public Long persist(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.persist(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long llen(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.llen(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> lrange(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.lrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public String ltrim(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.ltrim(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public String lindex(final String key, final long index) { |
||||
Jedis j = getShard(key); |
||||
return j.lindex(key, index); |
||||
} |
||||
|
||||
@Override |
||||
public String lset(final String key, final long index, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.lset(key, index, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long lrem(final String key, final long count, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.lrem(key, count, value); |
||||
} |
||||
|
||||
@Override |
||||
public String lpop(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.lpop(key); |
||||
} |
||||
|
||||
@Override |
||||
public String rpop(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.rpop(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long sadd(final String key, String... members) { |
||||
Jedis j = getShard(key); |
||||
return j.sadd(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> smembers(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.smembers(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long srem(final String key, String... members) { |
||||
Jedis j = getShard(key); |
||||
return j.srem(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public String spop(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.spop(key); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> spop(final String key, final long count) { |
||||
Jedis j = getShard(key); |
||||
return j.spop(key, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long scard(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.scard(key); |
||||
} |
||||
|
||||
@Override |
||||
public Boolean sismember(final String key, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.sismember(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public String srandmember(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.srandmember(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> srandmember(final String key, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.srandmember(key, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final String key, final double score, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, score, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final String key, final double score, final String member, final ZAddParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, score, member, params); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final String key, final Map<String, Double> scoreMembers) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, scoreMembers); |
||||
} |
||||
|
||||
@Override |
||||
public Long zadd(final String key, final Map<String, Double> scoreMembers, final ZAddParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zadd(key, scoreMembers, params); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrange(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrem(final String key, String... members) { |
||||
Jedis j = getShard(key); |
||||
return j.zrem(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public Double zincrby(final String key, final double increment, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.zincrby(key, increment, member); |
||||
} |
||||
|
||||
@Override |
||||
public Double zincrby(final String key, final double increment, final String member, ZIncrByParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zincrby(key, increment, member, params); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrank(final String key, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.zrank(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long zrevrank(final String key, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrank(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrange(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrange(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeWithScores(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeWithScores(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeWithScores(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeWithScores(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcard(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.zcard(key); |
||||
} |
||||
|
||||
@Override |
||||
public Double zscore(final String key, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.zscore(key, member); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> sort(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.sort(key); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> sort(final String key, final SortingParams sortingParameters) { |
||||
Jedis j = getShard(key); |
||||
return j.sort(key, sortingParameters); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcount(final String key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zcount(final String key, final String min, final String max) { |
||||
Jedis j = getShard(key); |
||||
return j.zcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByScore(final String key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByScore(final String key, final double max, final double min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByScore(final String key, final double min, final double max, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByScore(final String key, final double max, final double min, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max, final double min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double max, final double min, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByScore(final String key, final String min, final String max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByScore(final String key, final String max, final String min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByScore(final String key, final String min, final String max, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScore(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByScore(final String key, final String max, final String min, final int offset, final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScore(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max, final String min) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrangeByScoreWithScores(final String key, final String min, final String max, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrangeByScoreWithScores(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<Tuple> zrevrangeByScoreWithScores(final String key, final String max, final String min, final int offset, |
||||
final int count) { |
||||
Jedis j = getShard(key); |
||||
return j.zrevrangeByScoreWithScores(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByRank(final String key, final long start, final long stop) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByRank(key, start, stop); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByScore(final String key, final double min, final double max) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByScore(final String key, final String min, final String max) { |
||||
Jedis j = getShard(key); |
||||
return j.zremrangeByScore(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long zlexcount(final String key, final String min, final String max) { |
||||
return getShard(key).zlexcount(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByLex(final String key, final String min, final String max) { |
||||
return getShard(key).zrangeByLex(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrangeByLex(final String key, final String min, final String max, |
||||
final int offset, final int count) { |
||||
return getShard(key).zrangeByLex(key, min, max, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByLex(final String key, final String max, final String min) { |
||||
return getShard(key).zrevrangeByLex(key, max, min); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> zrevrangeByLex(final String key, final String max, final String min, final int offset, final int count) { |
||||
return getShard(key).zrevrangeByLex(key, max, min, offset, count); |
||||
} |
||||
|
||||
@Override |
||||
public Long zremrangeByLex(final String key, final String min, final String max) { |
||||
return getShard(key).zremrangeByLex(key, min, max); |
||||
} |
||||
|
||||
@Override |
||||
public Long linsert(final String key, final ListPosition where, final String pivot, final String value) { |
||||
Jedis j = getShard(key); |
||||
return j.linsert(key, where, pivot, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitcount(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.bitcount(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitcount(final String key, final long start, final long end) { |
||||
Jedis j = getShard(key); |
||||
return j.bitcount(key, start, end); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitpos(final String key, final boolean value) { |
||||
Jedis j = getShard(key); |
||||
return j.bitpos(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public Long bitpos(final String key, boolean value, final BitPosParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.bitpos(key, value, params); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Entry<String, String>> hscan(final String key, final String cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.hscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Entry<String, String>> hscan(final String key, final String cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.hscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<String> sscan(final String key, final String cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.sscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Tuple> zscan(final String key, final String cursor) { |
||||
Jedis j = getShard(key); |
||||
return j.zscan(key, cursor); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<Tuple> zscan(final String key, final String cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.zscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public ScanResult<String> sscan(final String key, final String cursor, final ScanParams params) { |
||||
Jedis j = getShard(key); |
||||
return j.sscan(key, cursor, params); |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
if (dataSource != null) { |
||||
boolean broken = false; |
||||
|
||||
for (Jedis jedis : getAllShards()) { |
||||
if (jedis.getClient().isBroken()) { |
||||
broken = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (broken) { |
||||
dataSource.returnBrokenResource(this); |
||||
} else { |
||||
dataSource.returnResource(this); |
||||
} |
||||
|
||||
} else { |
||||
disconnect(); |
||||
} |
||||
} |
||||
|
||||
public void setDataSource(ShardedJedisPool shardedJedisPool) { |
||||
this.dataSource = shardedJedisPool; |
||||
} |
||||
|
||||
public void resetState() { |
||||
for (Jedis jedis : getAllShards()) { |
||||
jedis.resetState(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Long pfadd(final String key, final String... elements) { |
||||
Jedis j = getShard(key); |
||||
return j.pfadd(key, elements); |
||||
} |
||||
|
||||
@Override |
||||
public long pfcount(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.pfcount(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long touch(final String key) { |
||||
Jedis j = getShard(key); |
||||
return j.touch(key); |
||||
} |
||||
|
||||
@Override |
||||
public Long geoadd(final String key, final double longitude, final double latitude, final String member) { |
||||
Jedis j = getShard(key); |
||||
return j.geoadd(key, longitude, latitude, member); |
||||
} |
||||
|
||||
@Override |
||||
public Long geoadd(final String key, final Map<String, GeoCoordinate> memberCoordinateMap) { |
||||
Jedis j = getShard(key); |
||||
return j.geoadd(key, memberCoordinateMap); |
||||
} |
||||
|
||||
@Override |
||||
public Double geodist(final String key, final String member1, final String member2) { |
||||
Jedis j = getShard(key); |
||||
return j.geodist(key, member1, member2); |
||||
} |
||||
|
||||
@Override |
||||
public Double geodist(final String key, final String member1, final String member2, final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.geodist(key, member1, member2, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> geohash(final String key, final String... members) { |
||||
Jedis j = getShard(key); |
||||
return j.geohash(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoCoordinate> geopos(final String key, final String... members) { |
||||
Jedis j = getShard(key); |
||||
return j.geopos(key, members); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadius(final String key, final double longitude, final double latitude, |
||||
final double radius, final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.georadius(key, longitude, latitude, radius, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadius(final String key, final double longitude, final double latitude, |
||||
final double radius, final GeoUnit unit, final GeoRadiusParam param) { |
||||
Jedis j = getShard(key); |
||||
return j.georadius(key, longitude, latitude, radius, unit, param); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadiusByMember(final String key, final String member, final double radius, |
||||
final GeoUnit unit) { |
||||
Jedis j = getShard(key); |
||||
return j.georadiusByMember(key, member, radius, unit); |
||||
} |
||||
|
||||
@Override |
||||
public List<GeoRadiusResponse> georadiusByMember(final String key, final String member, final double radius, |
||||
final GeoUnit unit, final GeoRadiusParam param) { |
||||
Jedis j = getShard(key); |
||||
return j.georadiusByMember(key, member, radius, unit, param); |
||||
} |
||||
|
||||
@Override |
||||
public List<Long> bitfield(final String key, final String... arguments) { |
||||
Jedis j = getShard(key); |
||||
return j.bitfield(key, arguments); |
||||
} |
||||
|
||||
@Override |
||||
public Long hstrlen(final String key, final String field) { |
||||
Jedis j = getShard(key); |
||||
return j.hstrlen(key, field); |
||||
} |
||||
} |
@ -0,0 +1,77 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Queue; |
||||
|
||||
public class ShardedJedisPipeline extends PipelineBase { |
||||
private BinaryShardedJedis jedis; |
||||
private List<FutureResult> results = new ArrayList<FutureResult>(); |
||||
private Queue<Client> clients = new LinkedList<Client>(); |
||||
|
||||
private static class FutureResult { |
||||
private Client client; |
||||
|
||||
public FutureResult(Client client) { |
||||
this.client = client; |
||||
} |
||||
|
||||
public Object get() { |
||||
return client.getOne(); |
||||
} |
||||
} |
||||
|
||||
public void setShardedJedis(BinaryShardedJedis jedis) { |
||||
this.jedis = jedis; |
||||
} |
||||
|
||||
public List<Object> getResults() { |
||||
List<Object> r = new ArrayList<Object>(); |
||||
for (FutureResult fr : results) { |
||||
r.add(fr.get()); |
||||
} |
||||
return r; |
||||
} |
||||
|
||||
/** |
||||
* Syncronize pipeline by reading all responses. This operation closes the pipeline. In order to |
||||
* get return values from pipelined commands, capture the different Response<?> of the |
||||
* commands you execute. |
||||
*/ |
||||
public void sync() { |
||||
for (Client client : clients) { |
||||
generateResponse(client.getOne()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Syncronize pipeline by reading all responses. This operation closes the pipeline. Whenever |
||||
* possible try to avoid using this version and use ShardedJedisPipeline.sync() as it won't go |
||||
* through all the responses and generate the right response type (usually it is a waste of time). |
||||
* @return A list of all the responses in the order you executed them. |
||||
*/ |
||||
public List<Object> syncAndReturnAll() { |
||||
List<Object> formatted = new ArrayList<Object>(); |
||||
for (Client client : clients) { |
||||
formatted.add(generateResponse(client.getOne()).get()); |
||||
} |
||||
return formatted; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(String key) { |
||||
Client client = jedis.getShard(key).getClient(); |
||||
clients.add(client); |
||||
results.add(new FutureResult(client)); |
||||
return client; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(byte[] key) { |
||||
Client client = jedis.getShard(key).getClient(); |
||||
clients.add(client); |
||||
results.add(new FutureResult(client)); |
||||
return client; |
||||
} |
||||
} |
@ -0,0 +1,120 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.List; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.fr.third.org.apache.commons.pool2.PooledObject; |
||||
import com.fr.third.org.apache.commons.pool2.PooledObjectFactory; |
||||
import com.fr.third.org.apache.commons.pool2.impl.DefaultPooledObject; |
||||
import com.fr.third.org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.Hashing; |
||||
import com.fr.third.redis.clients.jedis.util.Pool; |
||||
|
||||
public class ShardedJedisPool extends Pool<ShardedJedis> { |
||||
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards) { |
||||
this(poolConfig, shards, Hashing.MURMUR_HASH); |
||||
} |
||||
|
||||
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards, |
||||
Hashing algo) { |
||||
this(poolConfig, shards, algo, null); |
||||
} |
||||
|
||||
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards, |
||||
Pattern keyTagPattern) { |
||||
this(poolConfig, shards, Hashing.MURMUR_HASH, keyTagPattern); |
||||
} |
||||
|
||||
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards, |
||||
Hashing algo, Pattern keyTagPattern) { |
||||
super(poolConfig, new ShardedJedisFactory(shards, algo, keyTagPattern)); |
||||
} |
||||
|
||||
@Override |
||||
public ShardedJedis getResource() { |
||||
ShardedJedis jedis = super.getResource(); |
||||
jedis.setDataSource(this); |
||||
return jedis; |
||||
} |
||||
|
||||
@Override |
||||
protected void returnBrokenResource(final ShardedJedis resource) { |
||||
if (resource != null) { |
||||
returnBrokenResourceObject(resource); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void returnResource(final ShardedJedis resource) { |
||||
if (resource != null) { |
||||
resource.resetState(); |
||||
returnResourceObject(resource); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* PoolableObjectFactory custom impl. |
||||
*/ |
||||
private static class ShardedJedisFactory implements PooledObjectFactory<ShardedJedis> { |
||||
private List<JedisShardInfo> shards; |
||||
private Hashing algo; |
||||
private Pattern keyTagPattern; |
||||
|
||||
public ShardedJedisFactory(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) { |
||||
this.shards = shards; |
||||
this.algo = algo; |
||||
this.keyTagPattern = keyTagPattern; |
||||
} |
||||
|
||||
@Override |
||||
public PooledObject<ShardedJedis> makeObject() throws Exception { |
||||
ShardedJedis jedis = new ShardedJedis(shards, algo, keyTagPattern); |
||||
return new DefaultPooledObject<ShardedJedis>(jedis); |
||||
} |
||||
|
||||
@Override |
||||
public void destroyObject(PooledObject<ShardedJedis> pooledShardedJedis) throws Exception { |
||||
final ShardedJedis shardedJedis = pooledShardedJedis.getObject(); |
||||
for (Jedis jedis : shardedJedis.getAllShards()) { |
||||
if (jedis.isConnected()) { |
||||
try { |
||||
try { |
||||
jedis.quit(); |
||||
} catch (Exception e) { |
||||
|
||||
} |
||||
jedis.disconnect(); |
||||
} catch (Exception e) { |
||||
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean validateObject(PooledObject<ShardedJedis> pooledShardedJedis) { |
||||
try { |
||||
ShardedJedis jedis = pooledShardedJedis.getObject(); |
||||
for (Jedis shard : jedis.getAllShards()) { |
||||
if (!shard.ping().equals("PONG")) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} catch (Exception ex) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void activateObject(PooledObject<ShardedJedis> p) throws Exception { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void passivateObject(PooledObject<ShardedJedis> p) throws Exception { |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,159 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.ALPHA; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.ASC; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.BY; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.DESC; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.GET; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.LIMIT; |
||||
import static com.fr.third.redis.clients.jedis.Protocol.Keyword.NOSORT; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
/** |
||||
* Builder Class for {@link Jedis#sort(String, SortingParams) SORT} Parameters. |
||||
*/ |
||||
public class SortingParams { |
||||
private List<byte[]> params = new ArrayList<byte[]>(); |
||||
|
||||
/** |
||||
* Sort by weight in keys. |
||||
* <p> |
||||
* Takes a pattern that is used in order to generate the key names of the weights used for |
||||
* sorting. Weight key names are obtained substituting the first occurrence of * with the actual |
||||
* value of the elements on the list. |
||||
* <p> |
||||
* The pattern for a normal key/value pair is "field*" and for a value in a hash |
||||
* "field*->fieldname". |
||||
* @param pattern |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams by(final String pattern) { |
||||
return by(SafeEncoder.encode(pattern)); |
||||
} |
||||
|
||||
/** |
||||
* Sort by weight in keys. |
||||
* <p> |
||||
* Takes a pattern that is used in order to generate the key names of the weights used for |
||||
* sorting. Weight key names are obtained substituting the first occurrence of * with the actual |
||||
* value of the elements on the list. |
||||
* <p> |
||||
* The pattern for a normal key/value pair is "field*" and for a value in a hash |
||||
* "field*->fieldname". |
||||
* @param pattern |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams by(final byte[] pattern) { |
||||
params.add(BY.raw); |
||||
params.add(pattern); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* No sorting. |
||||
* <p> |
||||
* This is useful if you want to retrieve a external key (using {@link #get(String...) GET}) but |
||||
* you don't want the sorting overhead. |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams nosort() { |
||||
params.add(BY.raw); |
||||
params.add(NOSORT.raw); |
||||
return this; |
||||
} |
||||
|
||||
public Collection<byte[]> getParams() { |
||||
return Collections.unmodifiableCollection(params); |
||||
} |
||||
|
||||
/** |
||||
* Get the Sorting in Descending Order. |
||||
* @return the sortingParams Object |
||||
*/ |
||||
public SortingParams desc() { |
||||
params.add(DESC.raw); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Get the Sorting in Ascending Order. This is the default order. |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams asc() { |
||||
params.add(ASC.raw); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Limit the Numbers of returned Elements. |
||||
* @param start is zero based |
||||
* @param count |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams limit(final int start, final int count) { |
||||
params.add(LIMIT.raw); |
||||
params.add(Protocol.toByteArray(start)); |
||||
params.add(Protocol.toByteArray(count)); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sort lexicographicaly. Note that Redis is utf-8 aware assuming you set the right value for the |
||||
* LC_COLLATE environment variable. |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams alpha() { |
||||
params.add(ALPHA.raw); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Retrieving external keys from the result of the search. |
||||
* <p> |
||||
* Takes a pattern that is used in order to generate the key names of the result of sorting. The |
||||
* key names are obtained substituting the first occurrence of * with the actual value of the |
||||
* elements on the list. |
||||
* <p> |
||||
* The pattern for a normal key/value pair is "field*" and for a value in a hash |
||||
* "field*->fieldname". |
||||
* <p> |
||||
* To get the list itself use the char # as pattern. |
||||
* @param patterns |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams get(String... patterns) { |
||||
for (final String pattern : patterns) { |
||||
params.add(GET.raw); |
||||
params.add(SafeEncoder.encode(pattern)); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Retrieving external keys from the result of the search. |
||||
* <p> |
||||
* Takes a pattern that is used in order to generate the key names of the result of sorting. The |
||||
* key names are obtained substituting the first occurrence of * with the actual value of the |
||||
* elements on the list. |
||||
* <p> |
||||
* The pattern for a normal key/value pair is "field*" and for a value in a hash |
||||
* "field*->fieldname". |
||||
* <p> |
||||
* To get the list itself use the char # as pattern. |
||||
* @param patterns |
||||
* @return the SortingParams Object |
||||
*/ |
||||
public SortingParams get(byte[]... patterns) { |
||||
for (final byte[] pattern : patterns) { |
||||
params.add(GET.raw); |
||||
params.add(pattern); |
||||
} |
||||
return this; |
||||
} |
||||
} |
@ -0,0 +1,94 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.io.Closeable; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.redis.clients.jedis.exceptions.JedisDataException; |
||||
|
||||
/** |
||||
* Transaction is nearly identical to Pipeline, only differences are the multi/discard behaviors |
||||
*/ |
||||
public class Transaction extends MultiKeyPipelineBase implements Closeable { |
||||
|
||||
protected boolean inTransaction = true; |
||||
|
||||
protected Transaction() { |
||||
// client will be set later in transaction block
|
||||
} |
||||
|
||||
public Transaction(final Client client) { |
||||
this.client = client; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(String key) { |
||||
return client; |
||||
} |
||||
|
||||
@Override |
||||
protected Client getClient(byte[] key) { |
||||
return client; |
||||
} |
||||
|
||||
public void clear() { |
||||
if (inTransaction) { |
||||
discard(); |
||||
} |
||||
} |
||||
|
||||
public List<Object> exec() { |
||||
// Discard QUEUED or ERROR
|
||||
client.getMany(getPipelinedResponseLength()); |
||||
client.exec(); |
||||
inTransaction = false; |
||||
|
||||
List<Object> unformatted = client.getObjectMultiBulkReply(); |
||||
if (unformatted == null) { |
||||
return null; |
||||
} |
||||
List<Object> formatted = new ArrayList<Object>(); |
||||
for (Object o : unformatted) { |
||||
try { |
||||
formatted.add(generateResponse(o).get()); |
||||
} catch (JedisDataException e) { |
||||
formatted.add(e); |
||||
} |
||||
} |
||||
return formatted; |
||||
} |
||||
|
||||
public List<Response<?>> execGetResponse() { |
||||
// Discard QUEUED or ERROR
|
||||
client.getMany(getPipelinedResponseLength()); |
||||
client.exec(); |
||||
inTransaction = false; |
||||
|
||||
List<Object> unformatted = client.getObjectMultiBulkReply(); |
||||
if (unformatted == null) { |
||||
return null; |
||||
} |
||||
List<Response<?>> response = new ArrayList<Response<?>>(); |
||||
for (Object o : unformatted) { |
||||
response.add(generateResponse(o)); |
||||
} |
||||
return response; |
||||
} |
||||
|
||||
public String discard() { |
||||
client.getMany(getPipelinedResponseLength()); |
||||
client.discard(); |
||||
inTransaction = false; |
||||
clean(); |
||||
return client.getStatusCodeReply(); |
||||
} |
||||
|
||||
public void setClient(Client client) { |
||||
this.client = client; |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
clear(); |
||||
} |
||||
} |
@ -0,0 +1,80 @@
|
||||
package com.fr.third.redis.clients.jedis; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Objects; |
||||
|
||||
import com.fr.third.redis.clients.jedis.util.ByteArrayComparator; |
||||
import com.fr.third.redis.clients.jedis.util.SafeEncoder; |
||||
|
||||
public class Tuple implements Comparable<Tuple> { |
||||
private byte[] element; |
||||
private Double score; |
||||
|
||||
public Tuple(String element, Double score) { |
||||
this(SafeEncoder.encode(element), score); |
||||
} |
||||
|
||||
public Tuple(byte[] element, Double score) { |
||||
super(); |
||||
this.element = element; |
||||
this.score = score; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result; |
||||
if (null != element) { |
||||
for (final byte b : element) { |
||||
result = prime * result + b; |
||||
} |
||||
} |
||||
long temp = Double.doubleToLongBits(score); |
||||
result = prime * result + (int) (temp ^ (temp >>> 32)); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) return true; |
||||
if (obj == null) return false; |
||||
if (getClass() != obj.getClass()) return false; |
||||
Tuple other = (Tuple) obj; |
||||
if (!Arrays.equals(element, other.element)) return false; |
||||
return Objects.equals(score, other.score); |
||||
} |
||||
|
||||
@Override |
||||
public int compareTo(Tuple other) { |
||||
return compare(this, other); |
||||
} |
||||
|
||||
public static int compare(Tuple t1, Tuple t2) { |
||||
int compScore = Double.compare(t1.score, t2.score); |
||||
if(compScore != 0) return compScore; |
||||
|
||||
return ByteArrayComparator.compare(t1.element, t2.element); |
||||
} |
||||
|
||||
public String getElement() { |
||||
if (null != element) { |
||||
return SafeEncoder.encode(element); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public byte[] getBinaryElement() { |
||||
return element; |
||||
} |
||||
|
||||
public double getScore() { |
||||
return score; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return '[' + SafeEncoder.encode(element) + ',' + score + ']'; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue