/Users/deen/code/yugabyte-db/src/yb/tablet/tablet-test-base.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include "yb/tablet/tablet-test-base.h" |
15 | | |
16 | | namespace yb { |
17 | | namespace tablet { |
18 | | |
19 | 6 | Schema StringKeyTestSetup::CreateSchema() { |
20 | 6 | return Schema({ ColumnSchema("key", STRING, false, true), |
21 | 6 | ColumnSchema("key_idx", INT32), |
22 | 6 | ColumnSchema("val", INT32) }, |
23 | 6 | 1); |
24 | 6 | } |
25 | | |
26 | 4.51k | void StringKeyTestSetup::BuildRowKey(QLWriteRequestPB *req, int64_t key_idx) { |
27 | | // This is called from multiple threads, so can't move this buffer |
28 | | // to be a class member. However, it's likely to get inlined anyway |
29 | | // and loop-hosted. |
30 | 4.51k | char buf[256]; |
31 | 4.51k | FormatKey(buf, sizeof(buf), key_idx); |
32 | 4.51k | QLAddStringHashValue(req, buf); |
33 | 4.51k | } |
34 | | |
35 | 4.00k | void StringKeyTestSetup::BuildRow(QLWriteRequestPB *req, int32_t key_idx, int32_t val) { |
36 | 4.00k | BuildRowKey(req, key_idx); |
37 | 4.00k | QLAddInt32ColumnValue(req, kFirstColumnId + 1, key_idx); |
38 | 4.00k | QLAddInt32ColumnValue(req, kFirstColumnId + 2, val); |
39 | 4.00k | } |
40 | | |
41 | 4.51k | void StringKeyTestSetup::FormatKey(char *buf, size_t buf_size, int64_t key_idx) { |
42 | 4.51k | snprintf(buf, buf_size, "hello %" PRId64, key_idx); |
43 | 4.51k | } |
44 | | |
45 | 2 | string StringKeyTestSetup::FormatDebugRow(int64_t key_idx, int32_t val, bool updated) { |
46 | 2 | char buf[256]; |
47 | 2 | FormatKey(buf, sizeof(buf), key_idx); |
48 | | |
49 | 2 | return strings::Substitute( |
50 | 2 | "{ string_value: \"$0\" int32_value: $1 int32_value: $2 }", |
51 | 2 | buf, key_idx, val); |
52 | 2 | } |
53 | | |
54 | 6 | uint32_t StringKeyTestSetup::GetMaxRows() { |
55 | 6 | return std::numeric_limits<uint32_t>::max() - 1; |
56 | 6 | } |
57 | | |
58 | 0 | Schema CompositeKeyTestSetup::CreateSchema() { |
59 | 0 | return Schema({ ColumnSchema("key1", STRING, false, true), |
60 | 0 | ColumnSchema("key2", INT32, false, true), |
61 | 0 | ColumnSchema("key_idx", INT32), |
62 | 0 | ColumnSchema("val", INT32) }, |
63 | 0 | 2); |
64 | 0 | } |
65 | | |
66 | 0 | void CompositeKeyTestSetup::FormatKey(char *buf, size_t buf_size, int64_t key_idx) { |
67 | 0 | snprintf(buf, buf_size, "hello %" PRId64, key_idx); |
68 | 0 | } |
69 | | |
70 | 0 | string CompositeKeyTestSetup::FormatDebugRow(int64_t key_idx, int32_t val, bool updated) { |
71 | 0 | char buf[256]; |
72 | 0 | FormatKey(buf, sizeof(buf), key_idx); |
73 | 0 | return strings::Substitute( |
74 | 0 | "(string key1=$0, int32 key2=$1, int32 val=$2, int32 val=$3)", |
75 | 0 | buf, key_idx, key_idx, val); |
76 | 0 | } |
77 | | |
78 | | // Slices can be arbitrarily large |
79 | | // but in practice tests won't overflow a uint64_t |
80 | 0 | uint32_t CompositeKeyTestSetup::GetMaxRows() { |
81 | 0 | return std::numeric_limits<uint32_t>::max() - 1; |
82 | 0 | } |
83 | | |
84 | | void TabletTestPreBase::InsertTestRows(int32_t first_row, |
85 | | int32_t count, |
86 | | int32_t val, |
87 | 18 | TimeSeries *ts) { |
88 | 18 | LocalTabletWriter writer(tablet().get()); |
89 | | |
90 | 18 | uint64_t inserted_since_last_report = 0; |
91 | 17.1k | for (int32_t i = first_row; i < first_row + count; i++17.1k ) { |
92 | 17.1k | QLWriteRequestPB req; |
93 | 17.1k | BuildRow(&req, i, val); |
94 | 17.1k | CHECK_OK(writer.Write(&req)); |
95 | | |
96 | 17.1k | if ((inserted_since_last_report++ > 100) && ts10.8k ) { |
97 | 46 | ts->AddValue(static_cast<double>(inserted_since_last_report)); |
98 | 46 | inserted_since_last_report = 0; |
99 | 46 | } |
100 | 17.1k | } |
101 | | |
102 | 18 | if (ts) { |
103 | 6 | ts->AddValue(static_cast<double>(inserted_since_last_report)); |
104 | 6 | } |
105 | 18 | } |
106 | | |
107 | | CHECKED_STATUS TabletTestPreBase::InsertTestRow(LocalTabletWriter* writer, |
108 | | int32_t key_idx, |
109 | 5.16k | int32_t val) { |
110 | 5.16k | QLWriteRequestPB req; |
111 | 5.16k | req.set_type(QLWriteRequestPB::QL_STMT_INSERT); |
112 | 5.16k | BuildRow(&req, key_idx, val); |
113 | 5.16k | return writer->Write(&req); |
114 | 5.16k | } |
115 | | |
116 | | CHECKED_STATUS TabletTestPreBase::UpdateTestRow(LocalTabletWriter* writer, |
117 | | int32_t key_idx, |
118 | 2.49k | int32_t new_val) { |
119 | 2.49k | QLWriteRequestPB req; |
120 | 2.49k | req.set_type(QLWriteRequestPB::QL_STMT_UPDATE); |
121 | 2.49k | BuildRowKey(&req, key_idx); |
122 | | // select the col to update (the third if there is only one key |
123 | | // or the fourth if there are two col keys). |
124 | 2.49k | QLAddInt32ColumnValue(&req, kFirstColumnId + (schema_.num_key_columns() == 1 ? 2 : 30 ), new_val); |
125 | 2.49k | return writer->Write(&req); |
126 | 2.49k | } |
127 | | |
128 | 100 | CHECKED_STATUS TabletTestPreBase::UpdateTestRowToNull(LocalTabletWriter* writer, int32_t key_idx) { |
129 | 100 | QLWriteRequestPB req; |
130 | 100 | req.set_type(QLWriteRequestPB::QL_STMT_UPDATE); |
131 | 100 | BuildRowKey(&req, key_idx); |
132 | 100 | QLAddNullColumnValue(&req, kFirstColumnId + (schema_.num_key_columns() == 1 ? 2 : 30 )); |
133 | 100 | return writer->Write(&req); |
134 | 100 | } |
135 | | |
136 | 0 | CHECKED_STATUS TabletTestPreBase::DeleteTestRow(LocalTabletWriter* writer, int32_t key_idx) { |
137 | 0 | QLWriteRequestPB req; |
138 | 0 | req.set_type(QLWriteRequestPB::QL_STMT_DELETE); |
139 | 0 | BuildRowKey(&req, key_idx); |
140 | 0 | return writer->Write(&req); |
141 | 0 | } |
142 | | |
143 | 6 | void TabletTestPreBase::VerifyTestRows(int32_t first_row, int32_t expected_count) { |
144 | 6 | auto iter = tablet()->NewRowIterator(client_schema_); |
145 | 6 | ASSERT_OK(iter); |
146 | | |
147 | 6 | if (expected_count > INT_MAX) { |
148 | 0 | LOG(INFO) << "Not checking rows for duplicates -- duplicates expected since " |
149 | 0 | << "there were more than " << INT_MAX << " rows inserted."; |
150 | 0 | return; |
151 | 0 | } |
152 | | |
153 | | // Keep a bitmap of which rows have been seen from the requested |
154 | | // range. |
155 | 6 | std::vector<bool> seen_rows; |
156 | 6 | seen_rows.resize(expected_count); |
157 | | |
158 | 6 | QLTableRow row; |
159 | 6 | QLValue value; |
160 | 5.12k | while (ASSERT_RESULT((**iter).HasNext())) { |
161 | 5.12k | ASSERT_OK_FAST((**iter).NextRow(&row)); |
162 | | |
163 | 5.12k | if (VLOG_IS_ON(2)) { |
164 | 0 | VLOG(2) << "Fetched row: " << row.ToString(); |
165 | 0 | } |
166 | | |
167 | 5.12k | ASSERT_OK(row.GetValue(schema_.column_id(1), &value)); |
168 | 5.12k | int32_t key_idx = value.int32_value(); |
169 | 5.12k | if (key_idx >= first_row && key_idx < first_row + expected_count) { |
170 | 5.12k | size_t rel_idx = key_idx - first_row; |
171 | 5.12k | if (seen_rows[rel_idx]) { |
172 | 0 | FAIL() << "Saw row " << key_idx << " twice!\n" |
173 | 0 | << "Row: " << row.ToString(); |
174 | 0 | } |
175 | 5.12k | seen_rows[rel_idx] = true; |
176 | 5.12k | } |
177 | 5.12k | } |
178 | | |
179 | | // Verify that all the rows were seen. |
180 | 5.13k | for (int i = 0; 6 i < expected_count; i++5.12k ) { |
181 | 10.2k | ASSERT_EQ(true, seen_rows[i]) << "Never saw row: " << (i + first_row); |
182 | 5.12k | } |
183 | 6 | LOG(INFO) << "Successfully verified " << expected_count << "rows"; |
184 | 6 | } |
185 | | |
186 | 18 | CHECKED_STATUS TabletTestPreBase::IterateToStringList(vector<string> *out) { |
187 | | // TODO(dtxn) pass correct transaction ID if needed |
188 | 18 | auto iter = this->tablet()->NewRowIterator(this->client_schema_); |
189 | 18 | RETURN_NOT_OK(iter); |
190 | 18 | return yb::tablet::IterateToStringList(iter->get(), out); |
191 | 18 | } |
192 | | |
193 | 24 | uint32_t TabletTestPreBase::ClampRowCount(uint32_t proposal) const { |
194 | 24 | if (max_rows_ < proposal) { |
195 | 4 | LOG(WARNING) << "Clamping max rows to " << max_rows_ << " to prevent overflow"; |
196 | 4 | return max_rows_; |
197 | 4 | } |
198 | 20 | return proposal; |
199 | 24 | } |
200 | | |
201 | | } // namespace tablet |
202 | | } // namespace yb |