Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 65 additions & 46 deletions PushSharp.Apple/ApnsConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public void Send (CompletableApnsNotification notification)

notifications.Enqueue (notification);

var currentIsSendBatchRunning = Interlocked.CompareExchange(ref isSendBatchRunning, 0, 0);
if (currentIsSendBatchRunning == 1)
return;

if (notifications.Count >= Configuration.InternalBatchSize) {

// Make the timer fire immediately and send a batch off
Expand All @@ -104,75 +108,90 @@ public void Send (CompletableApnsNotification notification)

long batchId = 0;

int isSendBatchRunning;

async Task SendBatch ()
{
batchId++;
if (batchId >= long.MaxValue)
batchId = 1;

// Pause the timer
timerBatchWait.Change (Timeout.Infinite, Timeout.Infinite);

if (notifications.Count <= 0)
var currentIsSendBatchRunning = Interlocked.CompareExchange(ref isSendBatchRunning, 1, 0);
if (currentIsSendBatchRunning == 1)
return;

// Let's store the batch items to send internally
var toSend = new List<CompletableApnsNotification> ();
try
{
batchId++;
if (batchId >= long.MaxValue)
batchId = 1;

while (notifications.Count > 0 && toSend.Count < Configuration.InternalBatchSize) {
var n = notifications.Dequeue ();
toSend.Add (n);
}
// Pause the timer
timerBatchWait.Change(Timeout.Infinite, Timeout.Infinite);

if (notifications.Count <= 0)
return;

Log.Info ("APNS-Client[{0}]: Sending Batch ID={1}, Count={2}", id, batchId, toSend.Count);
// Let's store the batch items to send internally
var toSend = new List<CompletableApnsNotification>();

try {
lock (notificationBatchQueueLock) {
while (notifications.Count > 0 && toSend.Count < Configuration.InternalBatchSize) {
var n = notifications.Dequeue();
toSend.Add(n);
}
}

var data = createBatch (toSend);

if (data != null && data.Length > 0) {
Log.Info("APNS-Client[{0}]: Sending Batch ID={1}, Count={2}", id, batchId, toSend.Count);

for (var i = 0; i <= Configuration.InternalBatchFailureRetryCount; i++) {
try {

await connectingSemaphore.WaitAsync ();
var data = createBatch(toSend);

try {
// See if we need to connect
if (!socketCanWrite () || i > 0)
await connect ();
} finally {
connectingSemaphore.Release ();
}

try {
await networkStream.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
break;
} catch (Exception ex) when (i != Configuration.InternalBatchFailureRetryCount) {
Log.Info("APNS-CLIENT[{0}]: Retrying Batch: Batch ID={1}, Error={2}", id, batchId, ex);
if (data != null && data.Length > 0) {

for (var i = 0; i <= Configuration.InternalBatchFailureRetryCount; i++)
{

await connectingSemaphore.WaitAsync();

try {
// See if we need to connect
if (!socketCanWrite() || i > 0)
await connect();
} finally {
connectingSemaphore.Release();
}

try {
await networkStream.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
break;
} catch (Exception ex) when (i != Configuration.InternalBatchFailureRetryCount) {
Log.Info("APNS-CLIENT[{0}]: Retrying Batch: Batch ID={1}, Error={2}", id, batchId, ex);
}
}

foreach (var n in toSend)
sent.Add(new SentNotification(n));
}

} catch (Exception ex) {
Log.Error("APNS-CLIENT[{0}]: Send Batch Error: Batch ID={1}, Error={2}", id, batchId, ex);
foreach (var n in toSend)
sent.Add (new SentNotification (n));
n.CompleteFailed(new ApnsNotificationException(ApnsNotificationErrorStatusCode.ConnectionError,
n.Notification, ex));
}

} catch (Exception ex) {
Log.Error ("APNS-CLIENT[{0}]: Send Batch Error: Batch ID={1}, Error={2}", id, batchId, ex);
foreach (var n in toSend)
n.CompleteFailed (new ApnsNotificationException (ApnsNotificationErrorStatusCode.ConnectionError, n.Notification, ex));
}
Log.Info("APNS-Client[{0}]: Sent Batch, waiting for possible response...", id);

Log.Info ("APNS-Client[{0}]: Sent Batch, waiting for possible response...", id);
try {
await Reader();
} catch (Exception ex) {
Log.Error("APNS-Client[{0}]: Reader Exception: {1}", id, ex);
}

try {
await Reader ();
} catch (Exception ex) {
Log.Error ("APNS-Client[{0}]: Reader Exception: {1}", id, ex);
Log.Info("APNS-Client[{0}]: Done Reading for Batch ID={1}, reseting batch timer...", id, batchId);
} finally {
Interlocked.Exchange(ref isSendBatchRunning, 0);
}

Log.Info ("APNS-Client[{0}]: Done Reading for Batch ID={1}, reseting batch timer...", id, batchId);

// Restart the timer for the next batch
timerBatchWait.Change (Configuration.InternalBatchingWaitPeriod, Timeout.InfiniteTimeSpan);
}
Expand Down
37 changes: 32 additions & 5 deletions PushSharp.Core/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ public static class Log
static List<ILogger> loggers { get; set; }
static Dictionary<CounterToken, Stopwatch> counters;

static Log ()
static Log()
{
counters = new Dictionary<CounterToken, Stopwatch> ();
loggers = new List<ILogger> ();

AddLogger (new ConsoleLogger ());
counters = new Dictionary<CounterToken, Stopwatch>();
loggers = new List<ILogger>();
#if DEBUG
AddLogger(new DebugLogger());
#endif
}

public static void AddLogger (ILogger logger)
Expand Down Expand Up @@ -153,5 +154,31 @@ public void Write (LogLevel level, string msg, params object[] args)
}
}
}

public class DebugLogger : ILogger
{
public void Write(LogLevel level, string msg, params object[] args)
{
var s = msg;

if (args != null && args.Length > 0)
s = string.Format(msg, args);

var d = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ttt");

switch (level)
{
case LogLevel.Info:
System.Diagnostics.Debug.WriteLine(d + " [INFO] " + s);
break;
case LogLevel.Debug:
System.Diagnostics.Debug.WriteLine(d + " [DEBUG] " + s);
break;
case LogLevel.Error:
System.Diagnostics.Debug.WriteLine(d + " [ERROR] " + s);
break;
}
}
}
}