Skip to content

Commit

Permalink
Close Issue #742 (#761)
Browse files Browse the repository at this point in the history
Fixes #742

* Remove SocketTimeout options from iOS and Android since Xamarin doesn't provide a reasonable way to support it at this time

* Huge performance win by redoing the Batcher reduplication
  • Loading branch information
borrrden authored Oct 11, 2016
1 parent 5cfe25b commit 7e82825
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 15 deletions.
3 changes: 0 additions & 3 deletions src/Couchbase.Lite.Android/Couchbase.Lite.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@
<HintPath>..\packages\Stateless.2.5.53.0\lib\portable-net40+sl50+win+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Stateless.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest">
<HintPath>..\..\vendor\Mono\System.Net.Http.WebRequest.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
Expand Down
1 change: 1 addition & 0 deletions src/Couchbase.Lite.Shared/Couchbase.Lite.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Linq\MapReduceQueryProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Linq\NotSupportedExpressionVisitor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Replication\ExceptionResolver.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Util\UniqueQueue.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)View\" />
Expand Down
11 changes: 5 additions & 6 deletions src/Couchbase.Lite.Shared/Replication/Batcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ internal class Batcher<T>
private bool _scheduled;
private DateTime _lastProcessedTime;
private CancellationTokenSource _cancellationSource;
private ConcurrentQueue<T> _inbox = new ConcurrentQueue<T>();
private UniqueQueue<T> _inbox = new UniqueQueue<T>();

private object _scheduleLocker = new object();

Expand Down Expand Up @@ -137,10 +137,8 @@ public int QueueObjects(IList<T> objects)
Log.To.NoDomain.V(TAG, "QueueObjects called with {0} objects", objects.Count);
int added = 0;
foreach (var obj in objects) {
if (!_inbox.Contains (obj)) {
added++;
_inbox.Enqueue (obj);
}
added++;
_inbox.Enqueue(obj);
}

ScheduleWithDelay(DelayToUse());
Expand Down Expand Up @@ -188,7 +186,8 @@ internal void Clear()
Unschedule();

var itemCount = _inbox.Count;
_inbox = new ConcurrentQueue<T>();
Misc.SafeDispose(ref _inbox);
_inbox = new UniqueQueue<T>();

Log.To.NoDomain.D(TAG, "Discarded {0} items", itemCount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,18 @@ internal static void SetupSslCallback()
/// </summary>
internal HttpMessageHandler BuildHandlerPipeline (CookieStore store, IRetryStrategy retryStrategy)
{
#if __MOBILE__
var handler = new HttpClientHandler {
CookieContainer = store,
UseCookies = true
};
#else
var handler = new WebRequestHandler {
CookieContainer = store,
UseCookies = true,
ReadWriteTimeout = (int)SocketTimeout.TotalMilliseconds
};

// For now, we are not using the client cert for identity verification, just to
// satisfy Mono so it doesn't matter if the user doesn't choose it.
//handler.ClientCertificates.Add(SSLGenerator.GetOrCreateClientCert());
#endif

if(handler.SupportsAutomaticDecompression) {
handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
Expand Down
4 changes: 2 additions & 2 deletions src/Couchbase.Lite.Shared/Replication/ReplicationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ public sealed class ReplicationOptions
/// Gets or sets the socket timeout for requests during
/// the replication process (i.e. if the client cannot
/// read data from the server response for longer than
/// X it is considered timed out)
/// X it is considered timed out). This property is not supported
/// on Xamarin.iOS and Xamarin.Android
/// </summary>
/// <value>The socket timeout.</value>
public TimeSpan SocketTimeout { get; set; }

/// <summary>
Expand Down
99 changes: 99 additions & 0 deletions src/Couchbase.Lite.Shared/Util/UniqueQueue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// UniqueList.cs
//
// Author:
// Jim Borden <[email protected]>
//
// Copyright (c) 2016 Couchbase, Inc All rights reserved.
//
// 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.
//
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;

namespace Couchbase.Lite.Util
{
internal sealed class UniqueQueue<T> : IDisposable
{
private readonly Queue<T> _queue = new Queue<T>();
private readonly HashSet<T> _used = new HashSet<T>();
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

public int Count
{
get {
_lock.EnterReadLock();
try {
return _queue.Count;
} finally {
_lock.ExitReadLock();
}
}
}

public UniqueQueue()
{
}

public void Enqueue(T obj)
{
_lock.EnterWriteLock();
try {
if(_used.Contains(obj)) {
return;
}

_used.Add(obj);
_queue.Enqueue(obj);
} finally {
_lock.ExitWriteLock();
}
}

public T Dequeue()
{
_lock.EnterWriteLock();
try {
var retVal = _queue.Dequeue();
_used.Remove(retVal);
return retVal;
} finally {
_lock.ExitWriteLock();
}
}

public bool TryDequeue(out T obj)
{
_lock.EnterWriteLock();
try {
obj = default(T);
if(_queue.Count == 0) {
return false;
}

obj = _queue.Dequeue();
_used.Remove(obj);
return true;
} finally {
_lock.ExitWriteLock();
}
}

public void Dispose()
{
_lock.Dispose();
}
}
}

0 comments on commit 7e82825

Please sign in to comment.