public async Task <T> RunAsync <T>(IQueryConverter queryConverter, IScalarQuery <T> queryObject, CancellationToken cancellationToken) { var query = new Spec.Query(); query.token = GetNextToken(); query.type = Spec.Query.QueryType.START; query.query = queryObject.GenerateTerm(queryConverter); var response = await InternalRunQuery(query, cancellationToken); switch (response.type) { case Response.ResponseType.SUCCESS_SEQUENCE: case Response.ResponseType.SUCCESS_ATOM: if (response.response.Count != 1) { throw new RethinkDbRuntimeException(String.Format("Expected 1 object, received {0}", response.response.Count)); } return(queryConverter.Get <T>().ConvertDatum(response.response[0])); case Response.ResponseType.CLIENT_ERROR: case Response.ResponseType.COMPILE_ERROR: throw new RethinkDbInternalErrorException("Client error: " + response.response[0].r_str); case Response.ResponseType.RUNTIME_ERROR: throw new RethinkDbRuntimeException("Runtime error: " + response.response[0].r_str); default: throw new RethinkDbInternalErrorException("Unhandled response type: " + response.type); } }
public void Reset() { query = null; lastResponse = null; lastResponseIndex = 0; disposed = false; }
internal async Task <Response> InternalRunQuery(Spec.Query query, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <Response>(); tokenResponse[query.token] = tcs; DateTime start = DateTime.UtcNow; Logger.Debug("InternalRunQuery: beginning process of transmitting query w/ token {0}", query.token); bool pastSpinLock = false; Action abortToken = () => { DateTime timeout = DateTime.UtcNow; if (!pastSpinLock) { Logger.Warning( "Query token {0} timed out after {1}; usually this happens because of a query timeout, but, query never acquired write lock on the connection in before timing out. Write lock is currently held by query token {2}.", query.token, timeout - start, writeTokenLock); } else { Logger.Warning( "Query token {0} timed out after {1} because CancellationToken was triggered; usually this happens because of a query timeout.", query.token, timeout - start); } if (tokenResponse.Remove(query.token)) { tcs.SetCanceled(); } }; using (cancellationToken.Register(abortToken)) { // Put query.token into writeTokenLock if writeTokenLock is 0 (ie. unlocked). If it's not 0, // spin-lock on the compare exchange. while (Interlocked.CompareExchange(ref writeTokenLock, query.token, 0) != 0) { ; } try { Logger.Debug("InternalRunQuery: acquired write lock for query token {0}", query.token); pastSpinLock = true; Logger.Debug("InternalRunQuery: writing query token {0}", query.token); await Protocol.WriteQueryToStream(stream, Logger, query, cancellationToken); } finally { // Revert writeTokenLock to 0. writeTokenLock = 0; } Logger.Debug("InternalRunQuery: waiting for response for query token {0}", query.token); return(await tcs.Task); } }
internal async Task <Response> InternalRunQuery(Spec.Query query, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <Response>(); tokenResponse[query.token] = tcs; Action abortToken = () => { Logger.Warning("Query token {0} timed out after {1}", query.token, this.QueryTimeout); if (tokenResponse.Remove(query.token)) { tcs.SetCanceled(); } }; using (cancellationToken.Register(abortToken)) { using (var memoryBuffer = new MemoryStream(1024)) { Serializer.Serialize(memoryBuffer, query); var data = memoryBuffer.ToArray(); var header = BitConverter.GetBytes(data.Length); if (!BitConverter.IsLittleEndian) { Array.Reverse(header, 0, header.Length); } // Put query.token into writeTokenLock if writeTokenLock is 0 (ie. unlocked). If it's not 0, // spin-lock on the compare exchange. while (Interlocked.CompareExchange(ref writeTokenLock, (long)query.token, 0) != 0) { ; } try { Logger.Debug("Writing packet, {0} bytes", data.Length); await stream.WriteAsync(header, 0, header.Length, cancellationToken); await stream.WriteAsync(data, 0, data.Length, cancellationToken); } finally { // Revert writeTokenLock to 0. writeTokenLock = 0; } } return(await tcs.Task); } }
public async Task <bool> MoveNext(CancellationToken cancellationToken) { if (disposed) { throw new ObjectDisposedException(GetType().FullName); } if (lastResponse == null) { query = new Spec.Query(); query.token = connection.GetNextToken(); connection.Logger.Debug("QueryEnumerator: Token {0} is assigned to query {1}", query.token, queryObject); query.type = Spec.Query.QueryType.START; query.query = this.queryObject.GenerateTerm(queryConverter); await ReissueQuery(cancellationToken); } if (lastResponseIndex < (LoadedRecordCount() - 1)) { lastResponseIndex += 1; return(true); } if (lastResponse.type == Response.ResponseType.SUCCESS_SEQUENCE || lastResponse.type == Response.ResponseType.SUCCESS_ATOM) { return(false); } else if (lastResponse.type == Response.ResponseType.SUCCESS_PARTIAL || lastResponse.type == (Response.ResponseType) 5) { query.type = RethinkDb.Spec.Query.QueryType.CONTINUE; query.query = null; await ReissueQuery(cancellationToken); return(await MoveNext(cancellationToken)); } else { throw new RethinkDbInternalErrorException("Unreachable code; ReissueQuery should prevent reaching this condition"); } }
internal async Task <Response> InternalRunQuery(Spec.Query query, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <Response>(); tokenResponse[query.token] = tcs; Action abortToken = () => { Logger.Warning("Query token {0} timed out after {1}", query.token, this.QueryTimeout); if (tokenResponse.Remove(query.token)) { tcs.SetCanceled(); } }; using (cancellationToken.Register(abortToken)) { // Put query.token into writeTokenLock if writeTokenLock is 0 (ie. unlocked). If it's not 0, // spin-lock on the compare exchange. while (Interlocked.CompareExchange(ref writeTokenLock, query.token, 0) != 0) { ; } try { await Protocol.WriteQueryToStream(stream, Logger, query, cancellationToken); } finally { // Revert writeTokenLock to 0. writeTokenLock = 0; } return(await tcs.Task); } }