Skip to content

Commit

Permalink
Fix 'out of range in dynamic array' error in Task::toJson (facebookin…
Browse files Browse the repository at this point in the history
…cubator#8735)

Summary:
Task::toJson used to create folly::dynamic::array for drivers and access non-existing
elements via [index]. That resulted in 'out of range in dynamic array' errors.

Fix is to use folly::dynamic::object.

Fixes prestodb/presto#21917

Pull Request resolved: facebookincubator#8735

Reviewed By: spershin

Differential Revision: D53727317

Pulled By: mbasmanova

fbshipit-source-id: afcfd490fd44d67b78c0b70b3f557a179fddd123
  • Loading branch information
mbasmanova authored and facebook-github-bot committed Feb 14, 2024
1 parent f0583e7 commit dec4c44
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
11 changes: 5 additions & 6 deletions velox/exec/Task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2154,14 +2154,13 @@ folly::dynamic Task::toJson() const {
obj["plan"] = planFragment_.planNode->toString(true, true);
}

folly::dynamic driverObj = folly::dynamic::array;
int index = 0;
for (auto& driver : drivers_) {
if (driver) {
driverObj[index++] = driver->toJson();
folly::dynamic drivers = folly::dynamic::object;
for (auto i = 0; i < drivers_.size(); ++i) {
if (drivers_[i] != nullptr) {
drivers[i] = drivers_[i]->toJson();
}
}
obj["drivers"] = driverObj;
obj["drivers"] = drivers;

if (auto buffers = bufferManager_.lock()) {
if (auto buffer = buffers->getBufferIfExists(taskId_)) {
Expand Down
42 changes: 33 additions & 9 deletions velox/exec/tests/TaskTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,14 +502,7 @@ class TaskTest : public HiveConnectorTestBase {
}
};

TEST_F(TaskTest, wrongPlanNodeForSplit) {
auto connectorSplit = std::make_shared<connector::hive::HiveConnectorSplit>(
"test",
"file:/tmp/abc",
facebook::velox::dwio::common::FileFormat::DWRF,
0,
100);

TEST_F(TaskTest, toJson) {
auto plan = PlanBuilder()
.tableScan(ROW({"a", "b"}, {INTEGER(), DOUBLE()}))
.project({"a * a", "b + b"})
Expand All @@ -525,11 +518,42 @@ TEST_F(TaskTest, wrongPlanNodeForSplit) {
task->toString(), "{Task task-1 (task-1)Plan: -- Project\n\n drivers:\n");
ASSERT_EQ(
folly::toPrettyJson(task->toJson()),
"{\n \"concurrentSplitGroups\": 1,\n \"drivers\": [],\n \"exchangeClientByPlanNode\": {},\n \"groupedPartitionedOutput\": false,\n \"id\": \"task-1\",\n \"noMoreOutputBuffers\": false,\n \"numDriversPerSplitGroup\": 0,\n \"numDriversUngrouped\": 0,\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numRunningSplitGroups\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"onThreadSince\": \"0\",\n \"partitionedOutputConsumed\": false,\n \"pauseRequested\": false,\n \"plan\": \"-- Project[expressions: (p0:INTEGER, multiply(ROW[\\\"a\\\"],ROW[\\\"a\\\"])), (p1:DOUBLE, plus(ROW[\\\"b\\\"],ROW[\\\"b\\\"]))] -> p0:INTEGER, p1:DOUBLE\\n -- TableScan[table: hive_table] -> a:INTEGER, b:DOUBLE\\n\",\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}");
"{\n \"concurrentSplitGroups\": 1,\n \"drivers\": {},\n \"exchangeClientByPlanNode\": {},\n \"groupedPartitionedOutput\": false,\n \"id\": \"task-1\",\n \"noMoreOutputBuffers\": false,\n \"numDriversPerSplitGroup\": 0,\n \"numDriversUngrouped\": 0,\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numRunningSplitGroups\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"onThreadSince\": \"0\",\n \"partitionedOutputConsumed\": false,\n \"pauseRequested\": false,\n \"plan\": \"-- Project[expressions: (p0:INTEGER, multiply(ROW[\\\"a\\\"],ROW[\\\"a\\\"])), (p1:DOUBLE, plus(ROW[\\\"b\\\"],ROW[\\\"b\\\"]))] -> p0:INTEGER, p1:DOUBLE\\n -- TableScan[table: hive_table] -> a:INTEGER, b:DOUBLE\\n\",\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}");
ASSERT_EQ(
folly::toPrettyJson(task->toShortJson()),
"{\n \"id\": \"task-1\",\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"pauseRequested\": false,\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}");

task->start(2);

ASSERT_NO_THROW(task->toJson());
ASSERT_NO_THROW(task->toShortJson());

task->noMoreSplits("0");
waitForTaskCompletion(task.get());

ASSERT_NO_THROW(task->toJson());
ASSERT_NO_THROW(task->toShortJson());
}

TEST_F(TaskTest, wrongPlanNodeForSplit) {
auto connectorSplit = std::make_shared<connector::hive::HiveConnectorSplit>(
"test",
"file:/tmp/abc",
facebook::velox::dwio::common::FileFormat::DWRF,
0,
100);

auto plan = PlanBuilder()
.tableScan(ROW({"a", "b"}, {INTEGER(), DOUBLE()}))
.project({"a * a", "b + b"})
.planFragment();

auto task = Task::create(
"task-1",
std::move(plan),
0,
std::make_shared<core::QueryCtx>(driverExecutor_.get()));

// Add split for the source node.
task->addSplit("0", exec::Split(folly::copy(connectorSplit)));

Expand Down

0 comments on commit dec4c44

Please sign in to comment.