mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-22 12:02:05 +01:00
Add BundleAndDeferCallback to smack-tcp
This commit is contained in:
parent
aa8daba1cf
commit
d415661e35
3 changed files with 144 additions and 0 deletions
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2015 Florian Schmaus
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.tcp;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
||||||
|
public class BundleAndDefer {
|
||||||
|
|
||||||
|
private final AtomicBoolean isStopped;
|
||||||
|
|
||||||
|
BundleAndDefer(AtomicBoolean isStopped) {
|
||||||
|
this.isStopped = isStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopCurrentBundleAndDefer() {
|
||||||
|
synchronized (isStopped) {
|
||||||
|
if (isStopped.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isStopped.set(true);
|
||||||
|
isStopped.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2015 Florian Schmaus
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smack.tcp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is used to get the current value of the period in which Smack does bundle and defer
|
||||||
|
* outgoing stanzas.
|
||||||
|
* <p>
|
||||||
|
* Smack will bundle and defer stanzas if the connection is authenticated, the send queue is empty
|
||||||
|
* and if a bundle and defer callback is set, either via
|
||||||
|
* {@link XMPPTCPConnection#setDefaultBundleAndDeferCallback(BundleAndDeferCallback)} or
|
||||||
|
* {@link XMPPTCPConnection#setBundleandDeferCallback(BundleAndDeferCallback)}, and
|
||||||
|
* {@link #getBundleAndDeferMillis(BundleAndDefer)} returns a positive value. In a mobile environment, bundling
|
||||||
|
* and deferring outgoing stanzas may reduce battery consumption. It heavily depends on the
|
||||||
|
* environment, but recommend values for the bundle and defer period range from 20-60 seconds. But
|
||||||
|
* keep in mind that longer periods decrease the realtime aspect of Smack.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Smack will invoke the callback when it needs to know the length of the bundle and defer period.
|
||||||
|
* If {@link #getBundleAndDeferMillis(BundleAndDefer)} returns 0 or a negative value, then the
|
||||||
|
* stanzas will send immediately. You can also prematurely abort the bundling of stanzas by calling
|
||||||
|
* {@link BundleAndDefer#stopCurrentBundleAndDefer()}.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface BundleAndDeferCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bundle and defer period used by Smack in milliseconds.
|
||||||
|
*
|
||||||
|
* @param bundleAndDefer used to premature abort bundle and defer.
|
||||||
|
* @return the bundle and defer period in milliseconds.
|
||||||
|
*/
|
||||||
|
public int getBundleAndDeferMillis(BundleAndDefer bundleAndDefer);
|
||||||
|
|
||||||
|
}
|
|
@ -125,6 +125,7 @@ import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -184,6 +185,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
private final SynchronizationPoint<XMPPException> compressSyncPoint = new SynchronizationPoint<XMPPException>(
|
private final SynchronizationPoint<XMPPException> compressSyncPoint = new SynchronizationPoint<XMPPException>(
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
private static BundleAndDeferCallback defaultBundleAndDeferCallback;
|
||||||
|
|
||||||
|
private BundleAndDeferCallback bundleAndDeferCallback = defaultBundleAndDeferCallback;
|
||||||
|
|
||||||
private static boolean useSmDefault = false;
|
private static boolean useSmDefault = false;
|
||||||
|
|
||||||
private static boolean useSmResumptionDefault = true;
|
private static boolean useSmResumptionDefault = true;
|
||||||
|
@ -1269,6 +1274,30 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a local version of the bundle and defer callback, in case it's unset
|
||||||
|
// between the null check and the method invocation
|
||||||
|
final BundleAndDeferCallback localBundleAndDeferCallback = bundleAndDeferCallback;
|
||||||
|
// If the preconditions are given (e.g. bundleAndDefer callback is set, queue is
|
||||||
|
// empty), then we could wait a bit for further stanzas attempting to decrease
|
||||||
|
// our energy consumption
|
||||||
|
if (localBundleAndDeferCallback != null && isAuthenticated() && queue.isEmpty()) {
|
||||||
|
final AtomicBoolean bundlingAndDeferringStopped = new AtomicBoolean();
|
||||||
|
final int bundleAndDeferMillis = localBundleAndDeferCallback.getBundleAndDeferMillis(new BundleAndDefer(
|
||||||
|
bundlingAndDeferringStopped));
|
||||||
|
if (bundleAndDeferMillis > 0) {
|
||||||
|
long remainingWait = bundleAndDeferMillis;
|
||||||
|
final long waitStart = System.currentTimeMillis();
|
||||||
|
synchronized (bundlingAndDeferringStopped) {
|
||||||
|
while (!bundlingAndDeferringStopped.get() && remainingWait > 0) {
|
||||||
|
bundlingAndDeferringStopped.wait(remainingWait);
|
||||||
|
remainingWait = bundleAndDeferMillis
|
||||||
|
- (System.currentTimeMillis() - waitStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Stanza packet = null;
|
Stanza packet = null;
|
||||||
if (element instanceof Stanza) {
|
if (element instanceof Stanza) {
|
||||||
packet = (Stanza) element;
|
packet = (Stanza) element;
|
||||||
|
@ -1709,4 +1738,31 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
|
|
||||||
serverHandledStanzasCount = handledCount;
|
serverHandledStanzasCount = handledCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default bundle and defer callback used for new connections.
|
||||||
|
*
|
||||||
|
* @param defaultBundleAndDeferCallback
|
||||||
|
* @see BundleAndDeferCallback
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public static void setDefaultBundleAndDeferCallback(BundleAndDeferCallback defaultBundleAndDeferCallback) {
|
||||||
|
XMPPTCPConnection.defaultBundleAndDeferCallback = defaultBundleAndDeferCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the bundle and defer callback used for this connection.
|
||||||
|
* <p>
|
||||||
|
* You can use <code>null</code> as argument to reset the callback. Outgoing stanzas will then
|
||||||
|
* no longer get deferred.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param bundleAndDeferCallback the callback or <code>null</code>.
|
||||||
|
* @see BundleAndDeferCallback
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public void setBundleandDeferCallback(BundleAndDeferCallback bundleAndDeferCallback) {
|
||||||
|
this.bundleAndDeferCallback = bundleAndDeferCallback;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue