Skip to content

Commit

Permalink
Use transactions to determine the read/write data to use
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminwinger committed Aug 23, 2023
1 parent 45a2de9 commit 4c9f231
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 36 deletions.
5 changes: 3 additions & 2 deletions src/include/storage/store/property_statistics.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "common/types/types.h"
#include "transaction/transaction.h"

namespace kuzu {
namespace storage {
Expand Down Expand Up @@ -34,8 +35,8 @@ class RWPropertyStats {

static RWPropertyStats empty() { return RWPropertyStats(nullptr, 0, 0); }

bool mayHaveNull();
void setHasNull();
bool mayHaveNull(const transaction::Transaction& transaction);
void setHasNull(const transaction::Transaction& transaction);

private:
TablesStatistics* tablesStatistics;
Expand Down
30 changes: 15 additions & 15 deletions src/include/storage/store/table_statistics.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,27 @@ class TablesStatistics {
->getNumTuples();
}

PropertyStatistics& getWritePropertyStatisticsForTable(
common::table_id_t tableID, common::property_id_t propertyID) {
initTableStatisticPerTableForWriteTrxIfNecessary();
auto tableStatistics =
tablesStatisticsContentForWriteTrx->tableStatisticPerTable.at(tableID).get();
return tableStatistics->getPropertyStatistics(propertyID);
}

inline PropertyStatistics* getReadPropertyStatisticsForTable(
common::table_id_t tableID, common::property_id_t propertyID) {
auto readResult =
tablesStatisticsContentForReadOnlyTrx->tableStatisticPerTable.find(tableID);
if (readResult != tablesStatisticsContentForReadOnlyTrx->tableStatisticPerTable.end()) {
return &(readResult->second->getPropertyStatistics(propertyID));
inline PropertyStatistics& getPropertyStatisticsForTable(
const transaction::Transaction& transaction, common::table_id_t tableID,
common::property_id_t propertyID) {
if (transaction.isReadOnly()) {
assert(tablesStatisticsContentForReadOnlyTrx->tableStatisticPerTable.contains(tableID));
auto tableStatistics =
tablesStatisticsContentForReadOnlyTrx->tableStatisticPerTable.at(tableID).get();
return tableStatistics->getPropertyStatistics(propertyID);
} else {
initTableStatisticPerTableForWriteTrxIfNecessary();
assert(tablesStatisticsContentForWriteTrx->tableStatisticPerTable.contains(tableID));
auto tableStatistics =
tablesStatisticsContentForWriteTrx->tableStatisticPerTable.at(tableID).get();
return tableStatistics->getPropertyStatistics(propertyID);
}
return nullptr;
}

void setPropertyStatisticsForTable(
common::table_id_t tableID, common::property_id_t propertyID, PropertyStatistics stats) {
initTableStatisticPerTableForWriteTrxIfNecessary();
assert(tablesStatisticsContentForWriteTrx->tableStatisticPerTable.contains(tableID));
auto tableStatistics =
tablesStatisticsContentForWriteTrx->tableStatisticPerTable.at(tableID).get();
tableStatistics->setPropertyStatistics(propertyID, stats);
Expand Down
1 change: 1 addition & 0 deletions src/include/transaction/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Transaction {
};

static Transaction DUMMY_READ_TRANSACTION = Transaction(TransactionType::READ_ONLY);
static Transaction DUMMY_WRITE_TRANSACTION = Transaction(TransactionType::WRITE);

} // namespace transaction
} // namespace kuzu
15 changes: 8 additions & 7 deletions src/storage/store/node_column.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "storage/store/struct_node_column.h"
#include "storage/store/table_statistics.h"
#include "storage/store/var_list_node_column.h"
#include "transaction/transaction.h"

using namespace kuzu::catalog;
using namespace kuzu::common;
Expand Down Expand Up @@ -438,7 +439,7 @@ NullNodeColumn::NullNodeColumn(page_idx_t metaDAHPageIdx, BMFileHandle* dataFH,

void NullNodeColumn::scan(
Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) {
if (propertyStatistics.mayHaveNull()) {
if (propertyStatistics.mayHaveNull(*transaction)) {
scanInternal(transaction, nodeIDVector, resultVector);
} else {
resultVector->setAllNonNull();
Expand All @@ -448,7 +449,7 @@ void NullNodeColumn::scan(
void NullNodeColumn::scan(transaction::Transaction* transaction, node_group_idx_t nodeGroupIdx,
offset_t startOffsetInGroup, offset_t endOffsetInGroup, ValueVector* resultVector,
uint64_t offsetInVector) {
if (propertyStatistics.mayHaveNull()) {
if (propertyStatistics.mayHaveNull(*transaction)) {
NodeColumn::scan(transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup,
resultVector, offsetInVector);
} else {
Expand All @@ -457,7 +458,7 @@ void NullNodeColumn::scan(transaction::Transaction* transaction, node_group_idx_
}

void NullNodeColumn::scan(node_group_idx_t nodeGroupIdx, ColumnChunk* columnChunk) {
if (propertyStatistics.mayHaveNull()) {
if (propertyStatistics.mayHaveNull(DUMMY_WRITE_TRANSACTION)) {
NodeColumn::scan(nodeGroupIdx, columnChunk);
} else {
static_cast<NullColumnChunk*>(columnChunk)->resetNullBuffer();
Expand All @@ -466,7 +467,7 @@ void NullNodeColumn::scan(node_group_idx_t nodeGroupIdx, ColumnChunk* columnChun

void NullNodeColumn::lookup(
Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) {
if (propertyStatistics.mayHaveNull()) {
if (propertyStatistics.mayHaveNull(*transaction)) {
lookupInternal(transaction, nodeIDVector, resultVector);
} else {
for (auto i = 0ul; i < nodeIDVector->state->selVector->selectedSize; i++) {
Expand All @@ -483,15 +484,15 @@ page_idx_t NullNodeColumn::append(
metadataDA->update(nodeGroupIdx,
MainColumnChunkMetadata{startPageIdx, numPagesFlushed, columnChunk->getNumValues()});
if (static_cast<NullColumnChunk*>(columnChunk)->mayHaveNull()) {
propertyStatistics.setHasNull();
propertyStatistics.setHasNull(DUMMY_WRITE_TRANSACTION);
}
return numPagesFlushed;
}

void NullNodeColumn::setNull(offset_t nodeOffset) {
auto walPageInfo = createWALVersionOfPageForValue(nodeOffset);
try {
propertyStatistics.setHasNull();
propertyStatistics.setHasNull(DUMMY_WRITE_TRANSACTION);
NullMask::setNull((uint64_t*)walPageInfo.frame, walPageInfo.posInPage, true);
} catch (Exception& e) {
bufferManager->unpin(*wal->fileHandle, walPageInfo.pageIdxInWAL);
Expand All @@ -506,7 +507,7 @@ void NullNodeColumn::writeInternal(
offset_t nodeOffset, ValueVector* vectorToWriteFrom, uint32_t posInVectorToWriteFrom) {
writeValue(nodeOffset, vectorToWriteFrom, posInVectorToWriteFrom);
if (NullMask::isNull(vectorToWriteFrom->getNullMaskData(), posInVectorToWriteFrom)) {
propertyStatistics.setHasNull();
propertyStatistics.setHasNull(DUMMY_WRITE_TRANSACTION);
}
}

Expand Down
18 changes: 6 additions & 12 deletions src/storage/store/property_statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,17 @@ std::unique_ptr<PropertyStatistics> PropertyStatistics::deserialize(
return std::make_unique<PropertyStatistics>(hasNull);
}

// In a read-only context, readStatistics should always be non-null
// Read/write statistics cannot be cached since functions like checkpointInMemoryIfNecessary may
// overwrite them and invalidate the reference
bool RWPropertyStats::mayHaveNull() {
auto readStatistics = tablesStatistics->getReadPropertyStatisticsForTable(tableID, propertyID);
if (readStatistics) {
return readStatistics->mayHaveNull();
}

auto writeStatistics =
tablesStatistics->getWritePropertyStatisticsForTable(tableID, propertyID);
return writeStatistics.mayHaveNull();
bool RWPropertyStats::mayHaveNull(const transaction::Transaction& transaction) {
auto statistics =
tablesStatistics->getPropertyStatisticsForTable(transaction, tableID, propertyID);
return statistics.mayHaveNull();
}

void RWPropertyStats::setHasNull() {
void RWPropertyStats::setHasNull(const transaction::Transaction& transaction) {
auto writeStatistics =
tablesStatistics->getWritePropertyStatisticsForTable(tableID, propertyID);
tablesStatistics->getPropertyStatisticsForTable(transaction, tableID, propertyID);
writeStatistics.setHasNull();
}

Expand Down
13 changes: 13 additions & 0 deletions test/common/null_mask_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,16 @@ TEST(NullMaskTests, CopyNullMaskOffsetInvert) {
// word 4 should be all set, as the inverted source
ASSERT_EQ(dest[4], ~0);
}

TEST(NullMaskTests, CopyNullMaskReturnValue) {
std::vector<uint64_t> emptySource(10, 0);
std::vector<uint64_t> source(10, ~0ull);
std::vector<uint64_t> dest(10);
ASSERT_EQ(NullMask::copyNullMask(source.data(), 0, dest.data(), 0, 64, false /*invert*/), true);
ASSERT_EQ(
NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, false /*invert*/), false);

ASSERT_EQ(NullMask::copyNullMask(source.data(), 0, dest.data(), 0, 64, true /*invert*/), false);
ASSERT_EQ(
NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, true /*invert*/), true);
}

0 comments on commit 4c9f231

Please sign in to comment.