예제 #1
0
    /// <summary>
    /// Applies a list of operations and returns the final change type for each key.
    /// </summary>
    private async Task <Dictionary <int, RowOperation> > ApplyOperationsAsync(
        KuduClient client, List <KuduOperation> operations)
    {
        var results = new Dictionary <int, RowOperation>();

        // If there are no operations, return early.
        if (operations.Count == 0)
        {
            return(results);
        }

        // On some runs, wait long enough to flush at the start.
        if (_random.NextBool())
        {
            await Task.Delay(2000);
        }

        // Pick an int as a flush indicator so we flush once on average while applying operations.
        int flushInt = _random.Next(operations.Count);

        foreach (var operation in operations)
        {
            // On some runs, wait long enough to flush while applying operations.
            if (_random.Next(operations.Count) == flushInt)
            {
                await Task.Delay(2000);
            }

            await client.WriteAsync(new[] { operation });

            results[operation.GetInt32(0)] = operation.Operation;
        }

        return(results);
    }
예제 #2
0
    /// <summary>
    /// Load a table of default schema with the specified number of records, in ascending key order.
    /// </summary>
    public static async Task LoadDefaultTableAsync(KuduClient client, KuduTable table, int numRows)
    {
        var rows = Enumerable.Range(0, numRows)
                   .Select(i => CreateBasicSchemaInsert(table, i));

        await client.WriteAsync(rows);
    }
예제 #3
0
    private async Task SendAsync(List <KuduOperation> queue)
    {
        try
        {
            await _client.WriteAsync(queue, _options.ExternalConsistencyMode, _txnId)
            .ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            _logger.ExceptionFlushingSessionData(ex, queue.Count, _txnId);

            var exceptionHandler = _options.ExceptionHandler;
            if (exceptionHandler is not null)
            {
                var queueCopy        = new List <KuduOperation>(queue);
                var exceptionContext = new SessionExceptionContext(ex, queueCopy);

                try
                {
                    await exceptionHandler(exceptionContext).ConfigureAwait(false);
                }
                catch { }
            }
        }
    }
예제 #4
0
    public async Task TestInsertIgnoreAfterInsertHasNoRowError()
    {
        var builder = ClientTestUtil.GetBasicSchema()
                      .SetTableName(nameof(TestInsertIgnoreAfterInsertHasNoRowError));

        var table = await _client.CreateTableAsync(builder);

        var rows = new[]
        {
            ClientTestUtil.CreateBasicSchemaInsert(table, 1),
            ClientTestUtil.CreateBasicSchemaUpsert(table, 1, 1, false),
            ClientTestUtil.CreateBasicSchemaInsertIgnore(table, 1)
        };

        await _client.WriteAsync(rows);

        var rowStrings = await ClientTestUtil.ScanTableToStringsAsync(_client, table);

        var rowString = Assert.Single(rowStrings);

        Assert.Equal(
            "INT32 key=1, INT32 column1_i=1, INT32 column2_i=3, " +
            "STRING column3_s=a string, BOOL column4_b=True", rowString);
    }
예제 #5
0
    public async Task TestConstructorWithProperties()
    {
        var builder = new TableBuilder(nameof(TestConstructorWithProperties))
                      .AddColumn("Key", KuduType.Int32, opt => opt.Key(true))
                      .AddColumn("Column1", KuduType.String, opt => opt.Nullable(false))
                      .AddColumn("Column2", KuduType.Int32, opt => opt.Nullable(false))
                      .AddColumn("Column3", KuduType.String, opt => opt.Nullable(false));

        var values = new[]
        {
            new MixedRecord(1, "val-1")
            {
                Column2 = 100, Column3 = "val-2"
            },
            new MixedRecord(2, "val-3")
            {
                Column2 = 200, Column3 = "val-4"
            }
        };

        var table = await _client.CreateTableAsync(builder);

        var rowsToInsert = values.Select(value =>
        {
            var insert = table.NewInsert();
            insert.SetInt32("Key", value.Key);
            insert.SetString("Column1", value.Column1);
            insert.SetInt32("Column2", value.Column2);
            insert.SetString("Column3", value.Column3);
            return(insert);
        });

        await _client.WriteAsync(rowsToInsert);

        var rows = await ScanAsync <MixedRecord>(table);

        Assert.Equal(values, rows);
    }
    public async Task InitializeAsync()
    {
        _harness = await new MiniKuduClusterBuilder().BuildHarnessAsync();
        _client  = _harness.CreateClient();

        var builder = ClientTestUtil.GetBasicSchema()
                      .SetTableName("ScannerFaultToleranceTests")
                      .AddHashPartitions(_numTablets, "key");

        _table = await _client.CreateTableAsync(builder);

        var random = new Random();

        _keys = new HashSet <int>();
        while (_keys.Count < _numRows)
        {
            _keys.Add(random.Next());
        }

        var rows = _keys
                   .Select((key, i) =>
        {
            var insert = _table.NewInsert();
            insert.SetInt32(0, key);
            insert.SetInt32(1, i);
            insert.SetInt32(2, i++);
            insert.SetString(3, DataGenerator.RandomString(1024, random));
            insert.SetBool(4, true);

            return(insert);
        })
                   .Chunk(1000);

        foreach (var batch in rows)
        {
            await _client.WriteAsync(batch);
        }
    }
예제 #7
0
    public async Task TestAllPrimaryKeyTypes()
    {
        var tableBuilder = new TableBuilder(nameof(TestAllPrimaryKeyTypes))
                           .AddColumn("int8", KuduType.Int8, opt => opt.Key(true))
                           .AddColumn("int16", KuduType.Int16, opt => opt.Key(true))
                           .AddColumn("int32", KuduType.Int32, opt => opt.Key(true))
                           .AddColumn("int64", KuduType.Int64, opt => opt.Key(true))
                           .AddColumn("string", KuduType.String, opt => opt.Key(true))
                           .AddColumn("binary", KuduType.Binary, opt => opt.Key(true))
                           .AddColumn("timestamp", KuduType.UnixtimeMicros, opt => opt.Key(true))
                           .AddColumn("decimal32", KuduType.Decimal32, opt => opt.Key(true)
                                      .DecimalAttributes(DecimalUtil.MaxDecimal32Precision, 0))
                           .AddColumn("decimal64", KuduType.Decimal64, opt => opt.Key(true)
                                      .DecimalAttributes(DecimalUtil.MaxDecimal64Precision, 0))
                           .AddColumn("decimal128", KuduType.Decimal128, opt => opt.Key(true)
                                      .DecimalAttributes(DecimalUtil.MaxDecimal128Precision, 0))
                           .AddColumn("varchar", KuduType.Varchar, opt => opt.Key(true)
                                      .VarcharAttributes(10))
                           .AddColumn("date", KuduType.Date, opt => opt.Key(true))
                           .AddColumn("bool", KuduType.Bool)      // not primary key type
                           .AddColumn("float", KuduType.Float)    // not primary key type
                           .AddColumn("double", KuduType.Double); // not primary key type

        var table = await _client.CreateTableAsync(tableBuilder);

        var insert = table.NewInsert();

        insert.SetSByte("int8", 1);
        insert.SetInt16("int16", 2);
        insert.SetInt32("int32", 3);
        insert.SetInt64("int64", 4);
        insert.SetString("string", "foo");
        insert.SetBinary("binary", "bar".ToUtf8ByteArray());
        insert.SetInt64("timestamp", 6);
        insert.SetDecimal("decimal32", DecimalUtil.MaxUnscaledDecimal32);
        insert.SetDecimal("decimal64", DecimalUtil.MaxUnscaledDecimal64);
        insert.SetDecimal("decimal128", decimal.Truncate(decimal.MaxValue));
        insert.SetString("varchar", "varchar bar");
        insert.SetDateTime("date", EpochTime.FromUnixTimeDays(0));
        insert.SetBool("bool", true);
        insert.SetFloat("float", 7.8f);
        insert.SetDouble("double", 9.9);

        await _client.WriteAsync(new[] { insert });

        var scanner = _client.NewScanBuilder(table).Build();

        var scannedRows = 0;

        await foreach (var resultSet in scanner)
        {
            foreach (var row in resultSet)
            {
                scannedRows++;
                Assert.Equal(1, row.GetSByte("int8"));
                Assert.Equal(2, row.GetInt16("int16"));
                Assert.Equal(3, row.GetInt32("int32"));
                Assert.Equal(4, row.GetInt64("int64"));
                Assert.Equal("foo", row.GetString("string"));
                Assert.Equal("bar".ToUtf8ByteArray(), row.GetBinary("binary"));
                Assert.Equal(6, row.GetInt64("timestamp"));
                Assert.Equal(DecimalUtil.MaxUnscaledDecimal32, row.GetDecimal("decimal32"));
                Assert.Equal(DecimalUtil.MaxUnscaledDecimal64, row.GetDecimal("decimal64"));
                Assert.Equal(decimal.Truncate(decimal.MaxValue), row.GetDecimal("decimal128"));
                Assert.Equal("varchar ba", row.GetString("varchar"));
                Assert.Equal(0, row.GetInt32("date"));
                Assert.True(row.GetBool("bool"));
                Assert.Equal(7.8f, row.GetFloat("float"));
                Assert.Equal(9.9, row.GetDouble("double"));
            }
        }

        Assert.Equal(1, scannedRows);
    }
예제 #8
0
    public async Task TestScanTokenWithWrongUuidSerialization()
    {
        int buckets = 8;
        var builder = ClientTestUtil.CreateManyStringsSchema()
                      .SetTableName(_tableName)
                      .AddHashPartitions(buckets, "key");

        var table = await _client.CreateTableAsync(builder);

        int totalRows = 100;
        var inserts   = Enumerable.Range(0, totalRows).Select(i =>
        {
            var insert = table.NewInsert();
            insert.SetString("key", $"key_{i:00}");
            insert.SetString("c1", $"c1_{i}");
            insert.SetString("c2", $"c2_{i}");
            return(insert);
        });

        await _client.WriteAsync(inserts);

        var tokens = await _client.NewScanTokenBuilder(table)
                     .SetEmptyProjection()
                     .IncludeTableMetadata(true)
                     .IncludeTabletMetadata(true)
                     .BuildAsync();

        Assert.Equal(buckets, tokens.Count);

        // Create a new client, open the newly created kudu table, and new scanners.
        await using var newClient = _harness.CreateClient();
        var newTable = await newClient.OpenTableAsync(_tableName);

        var tabletIds = new List <string>();
        var scanners  = new List <KuduScanner>();

        foreach (var token in tokens)
        {
            tabletIds.Add(token.Tablet.TabletId);

            var scanBuilder = await newClient.NewScanBuilderFromTokenAsync(token);

            scanners.Add(scanBuilder.Build());
        }

        // Step down all tablet leaders.
        var masters = string.Join(',', _harness.GetMasterServers());

        foreach (var tabletId in tabletIds)
        {
            await MiniKuduCluster.RunKuduToolAsync(
                "tablet",
                "leader_step_down",
                masters,
                tabletId);

            await Task.Delay(1000);
        }

        // Delete all rows first through the new client.
        var deletes = Enumerable.Range(0, totalRows).Select(i =>
        {
            var delete = table.NewDelete();
            delete.SetString("key", $"key_{i:00}");
            return(delete);
        });

        await newClient.WriteAsync(deletes);

        // Insert all rows again through the new client.
        var newInserts = Enumerable.Range(0, totalRows).Select(i =>
        {
            var insert = table.NewInsert();
            insert.SetString("key", $"key_{i:00}");
            insert.SetString("c1", $"c1_{i}");
            insert.SetString("c2", $"c2_{i}");
            return(insert);
        });

        await newClient.WriteAsync(newInserts);

        // Verify all the row count.
        long rowCount = 0;

        foreach (var scanner in scanners)
        {
            rowCount += await scanner.CountAsync();
        }

        Assert.Equal(totalRows, rowCount);
    }