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