David Ribeiro Alves has posted comments on this change. Change subject: WIP: [integration tests] scan inconsistency test ......................................................................
Patch Set 1: (6 comments) http://gerrit.cloudera.org:8080/#/c/5084/1/src/kudu/integration-tests/consistent-scan-test.cc File src/kudu/integration-tests/consistent-scan-test.cc: PS1, Line 48: class ConsistentScanTest : public KuduTest { It would be great to have a way to have each specific test start a cluster a certain way. For certain tests multiple tablets of one replica are ideal, for other we need a single tablet with multiple replicas. A helper method like StartCluster(int num_tablets, int num_replicas) would be helpful. PS1, Line 48: ConsistentScanTest Like we had discussed yesterday and like Todd suggested ConsistencyITest would be a better name for the class/test. PS1, Line 80: ExternalMiniClusterOptions In most of the cases I can think of we need a MiniCluster, not an ExternalMIniCluster, so that we can skew the clock. Maybe worth pondering if we'll need a test that stops/kills servers in which case having the option to choose between the two would be best. PS1, Line 84: // Creates a table with the specified name and replication factor. : void CreateTable(const string& table_name, int num_replicas, : shared_ptr<KuduTable>* table) { : // Using range partitions with high split value for the key -- this is : // to keep the contents of the table primarily at one tablet server. : unique_ptr<KuduPartialRow> split_row(schema_.NewRow()); : ASSERT_OK(split_row->SetInt32(0, 8)); : : unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator()); : ASSERT_OK(table_creator->table_name(table_name) : .schema(&schema_) : .add_range_partition_split(split_row.release()) : .set_range_partition_columns({ key_column_name_ }) : .num_replicas(num_replicas) : .Create()); : ASSERT_OK(client_->OpenTable(table_name, table)); : } Worth looking into other itests to see if we can reuse some of the setup/helpers there. TabletHistoryGcITest or RaftConsensusITest come to mind PS1, Line 102: unique_ptr<KuduInsert> BuildTestRow(KuduTable* table, int index) { : unique_ptr<KuduInsert> insert(table->NewInsert()); : KuduPartialRow* row = insert->mutable_row(); : CHECK_OK(row->SetInt32(0, index)); : CHECK_OK(row->SetInt32(1, index * 2)); : CHECK_OK(row->SetStringCopy(2, Slice(StringPrintf("hello %d", index)))); : return insert; : } : : // Inserts given number of tests rows into the default test table : // in the context of the specified session. : Status InsertTestRows(KuduSession* session, InsertFlushOptions flush_opt, : int num_rows, int first_row = 0) { : RETURN_NOT_OK(session->SetFlushMode(KuduSession::AUTO_FLUSH_BACKGROUND)); : session->SetTimeoutMillis(60000); : for (int i = first_row; i < num_rows + first_row; ++i) { : unique_ptr<KuduInsert> insert(BuildTestRow(table_.get(), i)); : RETURN_NOT_OK(session->Apply(insert.release())); : } : if (flush_opt == OPT_FLUSH) { : RETURN_NOT_OK(session->Flush()); : } : return Status::OK(); : } : : Status GetRowCount(KuduClient::ReplicaSelection replica_selection, : KuduScanner::ReadMode read_mode, : size_t* row_count) { : KuduScanner scanner(table_.get()); : RETURN_NOT_OK(scanner.SetReadMode(read_mode)); : RETURN_NOT_OK(scanner.SetSelection(replica_selection)); : // KUDU-1656: there might be timeouts, so re-try the operations to : // avoid test flakiness. : Status row_count_status; : size_t actual_row_count = 0; : for (size_t i = 0; i < 3; ++i) { : row_count_status = scanner.Open(); : if (!row_count_status.ok()) { : if (row_count_status.IsTimedOut()) { : // Start the row count over again. : continue; : } : RETURN_NOT_OK(row_count_status); : } : size_t count = 0; : while (scanner.HasMoreRows()) { : KuduScanBatch batch; : row_count_status = scanner.NextBatch(&batch); : if (!row_count_status.ok()) { : if (row_count_status.IsTimedOut()) { : // Break the NextBatch() cycle and start row count over again. : break; : } : RETURN_NOT_OK(row_count_status); : } : count += batch.NumRows(); : } : if (row_count_status.ok()) { : // Success: stop the retry cycle. : actual_row_count = count; : break; : } : } : RETURN_NOT_OK(row_count_status); : if (row_count) { : *row_count = actual_row_count; : } : return Status::OK(); : } same PS1, Line 193: TEST_F(ConsistentScanTest, DISABLED_TwoReadsAfterWrite) { I think the cleanest to test scan response timestamp propagation is to do the following: - Start two mini cluster tservers and create a table with two tablets ({a, b} order matters), single replica. - Set the flag to use the mock wall clock. - Advance the clock in tablet a's tserver by some amount - Write a row to tablet a, discard the client. - With a new client, read the row from tablet a (snapshot read, no assigned timestamp), then write a row to tablet b. Take note of write timestamp. Discard the client. Now Scan both tablets at the timestamp of the write to tablet b. Since b followed a (quite literally, we scanned a before writing b). We should see both rows, but because we didn't propagate the timestamp from a's scan to b's write that shouldn't be the case. -- To view, visit http://gerrit.cloudera.org:8080/5084 To unsubscribe, visit http://gerrit.cloudera.org:8080/settings Gerrit-MessageType: comment Gerrit-Change-Id: I88e0d4e244be8abcef18e0b8317bacfa9bf272cb Gerrit-PatchSet: 1 Gerrit-Project: kudu Gerrit-Branch: master Gerrit-Owner: Alexey Serbin <aser...@cloudera.com> Gerrit-Reviewer: Alexey Serbin <aser...@cloudera.com> Gerrit-Reviewer: David Ribeiro Alves <dral...@apache.org> Gerrit-Reviewer: Kudu Jenkins Gerrit-Reviewer: Tidy Bot Gerrit-Reviewer: Todd Lipcon <t...@apache.org> Gerrit-HasComments: Yes