protected virtual async Task ConsumeCharsAsync(DataStressReader reader, int i, CancellationToken token, Random rnd) { char[] buffer = new char[255]; if (rnd.NextBool()) { // Read with GetChars reader.GetChars(i, rnd.Next(20), buffer, rnd.Next(20), rnd.Next(200)); } else if (reader.GetProviderSpecificFieldType(i) == typeof(SqlXml)) { // SqlClient only: Xml is read by XmlReader DataStressXmlReader xmlReader = reader.GetXmlReader(i); xmlReader.Read(); } else { // Read with TextReader DataStressTextReader textReader = reader.GetTextReader(i); if (rnd.NextBool()) { textReader.Peek(); } await textReader.ReadSyncOrAsync(buffer, rnd.Next(20), rnd.Next(200), rnd); if (rnd.NextBool()) { textReader.Peek(); } } }
/// <summary> /// Utility function to consume a single row of a reader in a random fashion after Read/ReadAsync has been invoked. /// </summary> protected virtual async Task ConsumeRowAsync(DataStressReader reader, bool sequentialAccess, CancellationToken token, Random rnd) { for (int i = 0; i < reader.FieldCount; i++) { if (rnd.Next(10) == 0) { break; // stop reading from this row } if (rnd.Next(2) == 0) { continue; // skip this field } bool hasBeenRead = false; // If the field is not null, we can optionally use streaming API if ((!await reader.IsDBNullSyncOrAsync(i, token, rnd)) && (rnd.NextBool())) { Type t = reader.GetFieldType(i); if (t == typeof(byte[])) { await ConsumeBytesAsync(reader, i, token, rnd); hasBeenRead = true; } else if (t == typeof(string)) { await ConsumeCharsAsync(reader, i, token, rnd); hasBeenRead = true; } } // If the field has not yet been read, or if it is non-sequential then we can re-read it if ((!hasBeenRead) || (!sequentialAccess)) { if (!await reader.IsDBNullSyncOrAsync(i, token, rnd)) { // Field value is not null, we can use new GetFieldValue<T> methods await reader.GetValueSyncOrAsync(i, token, rnd); } else { // Field value is null, we have to use old GetValue method reader.GetValue(i); } } // Do IsDBNull check again with 50% probability if (rnd.NextBool()) { await reader.IsDBNullSyncOrAsync(i, token, rnd); } } }
/// <summary> /// Utility function to consume a reader in a random fashion /// </summary> protected virtual async Task ConsumeReaderAsync(DataStressReader reader, bool sequentialAccess, CancellationToken token, Random rnd) { // Close 1/10 of readers while they are reading Task closeTask = null; if (AllowReaderCloseDuringReadAsync() && rnd.NextBool(0.1)) { // Begin closing now on another thread closeTask = reader.CloseAsync(); } try { do { while (await reader.ReadSyncOrAsync(token, rnd)) { // Optionally stop reading the current result set if (rnd.NextBool(0.1)) { break; } // Read the current row await ConsumeRowAsync(reader, sequentialAccess, token, rnd); } // Executing NextResult only 50% of the time if (rnd.NextBool()) { break; } } while (await reader.NextResultSyncOrAsync(token, rnd)); } catch (Exception e) { if (closeTask != null && IsReaderClosedException(e)) { // Catch reader closed exception } else { throw; } } finally { if (closeTask != null) { AsyncUtils.WaitAndUnwrapException(closeTask); } } }
protected virtual async Task ConsumeBytesAsync(DataStressReader reader, int i, CancellationToken token, Random rnd) { byte[] buffer = new byte[255]; if (rnd.NextBool()) { // We can optionally use GetBytes reader.GetBytes(i, rnd.Next(20), buffer, rnd.Next(20), rnd.Next(200)); } else if (reader.GetName(i) != "timestamp_FLD") { // Timestamp appears to be binary, but cannot be read by Stream DataStressStream stream = reader.GetStream(i); await stream.ReadSyncOrAsync(buffer, rnd.Next(20), rnd.Next(200), token, rnd); } else { // It is timestamp column, so read it later with GetValueSyncOrAsync await reader.GetValueSyncOrAsync(i, token, rnd); } }
public DataStressXmlReader(XmlReader xmlReader, DataStressReader reader) { _xmlReader = xmlReader; _reader = reader; }
public DataStressTextReader(TextReader textReader, DataStressReader reader) { _textReader = textReader; _reader = reader; }
public DataStressStream(Stream stream, DataStressReader reader) { _stream = stream; _reader = reader; }
protected async virtual Task CommandExecuteAsync(Random rnd, DbCommand com, bool query) { CancellationTokenSource cts = null; // Cancel 1/10 commands Task cancelTask = null; bool cancelCommand = rnd.NextBool(0.1); if (cancelCommand) { if (rnd.NextBool()) { // Use DbCommand.Cancel cancelTask = Task.Run(() => CommandCancel(com)); } else { // Use CancellationTokenSource if (cts == null) { cts = new CancellationTokenSource(); } cancelTask = Task.Run(() => cts.Cancel()); } } // Get the CancellationToken CancellationToken token = (cts != null) ? cts.Token : CancellationToken.None; DataStressReader reader = null; try { if (query) { CommandBehavior commandBehavior = CommandBehavior.Default; if (rnd.NextBool(0.5)) { commandBehavior |= CommandBehavior.SequentialAccess; } if (rnd.NextBool(0.25)) { commandBehavior |= CommandBehavior.KeyInfo; } if (rnd.NextBool(0.1)) { commandBehavior |= CommandBehavior.SchemaOnly; } // Get the reader reader = new DataStressReader(await com.ExecuteReaderSyncOrAsync(commandBehavior, token, rnd)); // Consume the reader's data await ConsumeReaderAsync(reader, commandBehavior.HasFlag(CommandBehavior.SequentialAccess), token, rnd); } else { await com.ExecuteNonQuerySyncOrAsync(token, rnd); } } catch (Exception e) { if (cancelCommand && IsCommandCancelledException(e)) { // Catch command canceled exception } else { throw; } } finally { if (cancelTask != null) { AsyncUtils.WaitAndUnwrapException(cancelTask); } if (reader != null && ShouldCloseDataReader()) { reader.Close(); } } }