private void PrepareForNewDocumentParse(BlittableJsonDocumentBuilder.UsageMode mode, string debugTag) { _parser.NewDocument(); _writer.Renew(debugTag, mode); _writer.ReadObjectDocument(); _context.CachedProperties.NewDocument(); }
private async Task ListenForCommands() { await _clusterDashboardNotifications.EnsureWatcher(); // in current impl cluster dashboard senders talk to a single watcher using (_readContext.GetMemoryBuffer(out JsonOperationContext.MemoryBuffer segment1)) using (_readContext.GetMemoryBuffer(out JsonOperationContext.MemoryBuffer segment2)) { try { var segments = new[] { segment1, segment2 }; int index = 0; var receiveAsync = _webSocket.ReceiveAsync(segments[index].Memory.Memory, _resourceShutdown); var jsonParserState = new JsonParserState(); using (var parser = new UnmanagedJsonParser(_readContext, jsonParserState, "cluster-dashboard")) { var result = await receiveAsync; _resourceShutdown.ThrowIfCancellationRequested(); parser.SetBuffer(segments[index], 0, result.Count); index++; receiveAsync = _webSocket.ReceiveAsync(segments[index].Memory.Memory, _resourceShutdown); while (true) { using (var builder = new BlittableJsonDocumentBuilder(_readContext, BlittableJsonDocumentBuilder.UsageMode.None, "cluster-dashboard", parser, jsonParserState)) { parser.NewDocument(); builder.ReadObjectDocument(); while (builder.Read() == false) { result = await receiveAsync; _resourceShutdown.ThrowIfCancellationRequested(); parser.SetBuffer(segments[index], 0, result.Count); if (++index >= segments.Length) { index = 0; } receiveAsync = _webSocket.ReceiveAsync(segments[index].Memory.Memory, _resourceShutdown); } builder.FinalizeDocument(); using (var reader = builder.CreateReader()) { await HandleCommand(reader); } } } } } catch (IOException ex) { /* Client was disconnected, write to log */ if (Logger.IsInfoEnabled) { Logger.Info("Client was disconnected", ex); } } catch (Exception ex) { // if we received close from the client, we want to ignore it and close the websocket (dispose does it) if (ex is WebSocketException webSocketException && webSocketException.WebSocketErrorCode == WebSocketError.InvalidState && _webSocket.State == WebSocketState.CloseReceived) { // ignore }
private async Task HandleConnection(WebSocket webSocket, JsonOperationContext context) { // this flag can be used to detect if server was restarted between changes connections on client side var sendStartTime = GetBoolValueQueryString("sendServerStartTime", false).GetValueOrDefault(false); var throttleConnection = GetBoolValueQueryString("throttleConnection", false).GetValueOrDefault(false); var connection = new NotificationsClientConnection(webSocket, Database); Database.Notifications.Connect(connection); var sendTask = connection.StartSendingNotifications(sendStartTime, throttleConnection); var debugTag = "changes/" + connection.Id; JsonOperationContext.ManagedPinnedBuffer segment1, segment2; using (context.GetManagedBuffer(out segment1)) using (context.GetManagedBuffer(out segment2)) { try { var segments = new[] { segment1, segment2 }; int index = 0; var receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); var jsonParserState = new JsonParserState(); using (var parser = new UnmanagedJsonParser(context, jsonParserState, debugTag)) { var result = await receiveAsync; parser.SetBuffer(segments[index], result.Count); index++; receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); while (true) { using (var builder = new BlittableJsonDocumentBuilder(context, BlittableJsonDocumentBuilder.UsageMode.None, debugTag, parser, jsonParserState)) { parser.NewDocument(); builder.ReadObjectDocument(); while (builder.Read() == false) { result = await receiveAsync; parser.SetBuffer(segments[index], result.Count); if (++index >= segments.Length) { index = 0; } receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); } builder.FinalizeDocument(); using (var reader = builder.CreateReader()) { string command, commandParameter; if (reader.TryGet("Command", out command) == false) { throw new ArgumentNullException(nameof(command), "Command argument is mandatory"); } reader.TryGet("Param", out commandParameter); connection.HandleCommand(command, commandParameter); int commandId; if (reader.TryGet("CommandId", out commandId)) { connection.Confirm(commandId); } } } } } } catch (IOException ex) { /* Client was disconnected, write to log */ if (Logger.IsInfoEnabled) { Logger.Info("Client was disconnected", ex); } } finally { Database.Notifications.Disconnect(connection.Id); } } await sendTask; }
private async Task HandleConnection(WebSocket webSocket, JsonOperationContext context) { var fromStudio = GetBoolValueQueryString(StudioMarker, false) ?? false; var throttleConnection = GetBoolValueQueryString("throttleConnection", false).GetValueOrDefault(false); var connection = new ChangesClientConnection(webSocket, Database, fromStudio); Database.Changes.Connect(connection); var sendTask = connection.StartSendingNotifications(throttleConnection); var debugTag = "changes/" + connection.Id; using (context.GetManagedBuffer(out JsonOperationContext.ManagedPinnedBuffer segment1)) using (context.GetManagedBuffer(out JsonOperationContext.ManagedPinnedBuffer segment2)) { try { var segments = new[] { segment1, segment2 }; int index = 0; var receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); var jsonParserState = new JsonParserState(); using (var parser = new UnmanagedJsonParser(context, jsonParserState, debugTag)) { var result = await receiveAsync; Database.DatabaseShutdown.ThrowIfCancellationRequested(); parser.SetBuffer(segments[index], 0, result.Count); index++; receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); while (true) { using (var builder = new BlittableJsonDocumentBuilder(context, BlittableJsonDocumentBuilder.UsageMode.None, debugTag, parser, jsonParserState)) { parser.NewDocument(); builder.ReadObjectDocument(); while (builder.Read() == false) { result = await receiveAsync; Database.DatabaseShutdown.ThrowIfCancellationRequested(); parser.SetBuffer(segments[index], 0, result.Count); if (++index >= segments.Length) { index = 0; } receiveAsync = webSocket.ReceiveAsync(segments[index].Buffer, Database.DatabaseShutdown); } builder.FinalizeDocument(); using (var reader = builder.CreateReader()) { if (reader.TryGet("Command", out string command) == false) { throw new ArgumentNullException(nameof(command), "Command argument is mandatory"); } reader.TryGet("Param", out string commandParameter); reader.TryGet("Params", out BlittableJsonReaderArray commandParameters); connection.HandleCommand(command, commandParameter, commandParameters); if (reader.TryGet("CommandId", out int commandId)) { connection.Confirm(commandId); } } } } } } catch (IOException ex) { /* Client was disconnected, write to log */ if (Logger.IsInfoEnabled) { Logger.Info("Client was disconnected", ex); } } catch { #pragma warning disable 4014 sendTask.IgnoreUnobservedExceptions(); #pragma warning restore 4014 throw; } finally { Database.Changes.Disconnect(connection.Id); } } await sendTask; }