2021-01-01 14:43:11 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-01-19 15:29:22 +00:00
|
|
|
#include "PostgreSQLConnection.h"
|
2021-01-27 15:29:28 +00:00
|
|
|
#include <Core/BackgroundSchedulePool.h>
|
2021-02-03 16:13:18 +00:00
|
|
|
#include "PostgreSQLReplicaMetadata.h"
|
2021-01-27 21:46:19 +00:00
|
|
|
#include <common/logger_useful.h>
|
2021-01-31 19:03:03 +00:00
|
|
|
#include <Storages/IStorage.h>
|
|
|
|
#include <Core/ExternalResultDescription.h>
|
2021-01-01 14:43:11 +00:00
|
|
|
#include "pqxx/pqxx"
|
2021-01-31 19:03:03 +00:00
|
|
|
#include <Storages/PostgreSQL/insertPostgreSQLValue.h>
|
2021-01-01 14:43:11 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2021-01-27 21:46:19 +00:00
|
|
|
struct LSNPosition
|
|
|
|
{
|
|
|
|
std::string lsn;
|
2021-01-31 19:03:03 +00:00
|
|
|
int64_t lsn_value;
|
2021-01-27 21:46:19 +00:00
|
|
|
|
2021-01-31 19:03:03 +00:00
|
|
|
int64_t getValue()
|
2021-01-27 21:46:19 +00:00
|
|
|
{
|
|
|
|
uint64_t upper_half, lower_half, result;
|
|
|
|
std::sscanf(lsn.data(), "%lX/%lX", &upper_half, &lower_half);
|
|
|
|
result = (upper_half << 32) + lower_half;
|
|
|
|
//LOG_DEBUG(&Poco::Logger::get("LSNParsing"),
|
|
|
|
// "Created replication slot. upper half: {}, lower_half: {}, start lsn: {}",
|
|
|
|
// upper_half, lower_half, result);
|
|
|
|
return result;
|
|
|
|
}
|
2021-01-31 19:03:03 +00:00
|
|
|
|
|
|
|
std::string getString()
|
|
|
|
{
|
|
|
|
char result[16];
|
|
|
|
std::snprintf(result, sizeof(result), "%lX/%lX", (lsn_value >> 32), lsn_value & 0xFFFFFFFF);
|
|
|
|
//assert(lsn_value == result.getValue());
|
|
|
|
std::string ans = result;
|
|
|
|
return ans;
|
|
|
|
}
|
2021-01-27 21:46:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-01-01 14:43:11 +00:00
|
|
|
class PostgreSQLReplicaConsumer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PostgreSQLReplicaConsumer(
|
2021-01-27 21:46:19 +00:00
|
|
|
std::shared_ptr<Context> context_,
|
2021-01-01 14:43:11 +00:00
|
|
|
const std::string & table_name_,
|
|
|
|
const std::string & conn_str_,
|
|
|
|
const std::string & replication_slot_name_,
|
|
|
|
const std::string & publication_name_,
|
2021-02-03 16:13:18 +00:00
|
|
|
const std::string & metadata_path,
|
2021-01-31 19:03:03 +00:00
|
|
|
const LSNPosition & start_lsn,
|
|
|
|
const size_t max_block_size_,
|
|
|
|
StoragePtr nested_storage_);
|
2021-01-01 14:43:11 +00:00
|
|
|
|
2021-01-27 21:46:19 +00:00
|
|
|
/// Start reading WAL from current_lsn position. Initial data sync from created snapshot already done.
|
|
|
|
void startSynchronization();
|
|
|
|
void stopSynchronization();
|
2021-01-01 14:43:11 +00:00
|
|
|
|
|
|
|
private:
|
2021-01-31 19:03:03 +00:00
|
|
|
/// Executed by wal_reader_task. A separate thread reads wal and advances lsn to last commited position
|
|
|
|
/// after rows were written via copyData.
|
|
|
|
void replicationStream();
|
|
|
|
void stopReplicationStream();
|
2021-01-27 21:46:19 +00:00
|
|
|
|
2021-02-03 16:13:18 +00:00
|
|
|
enum class PostgreSQLQuery
|
|
|
|
{
|
|
|
|
INSERT,
|
|
|
|
UPDATE,
|
|
|
|
DELETE
|
|
|
|
};
|
|
|
|
|
2021-01-27 21:46:19 +00:00
|
|
|
/// Start changes stream from WAL via copy command (up to max_block_size changes).
|
|
|
|
bool readFromReplicationSlot();
|
2021-02-03 16:13:18 +00:00
|
|
|
void processReplicationMessage(const char * replication_message, size_t size);
|
2021-01-27 21:46:19 +00:00
|
|
|
|
2021-01-31 19:03:03 +00:00
|
|
|
void insertValue(std::string & value, size_t column_idx);
|
2021-02-03 16:13:18 +00:00
|
|
|
//static void insertValueMaterialized(IColumn & column, uint64_t value);
|
|
|
|
void insertDefaultValue(size_t column_idx);
|
|
|
|
|
2021-01-31 19:03:03 +00:00
|
|
|
void syncIntoTable(Block & block);
|
|
|
|
void advanceLSN(std::shared_ptr<pqxx::nontransaction> ntx);
|
|
|
|
|
2021-01-27 21:46:19 +00:00
|
|
|
/// Methods to parse replication message data.
|
2021-02-03 16:13:18 +00:00
|
|
|
void readTupleData(const char * message, size_t & pos, PostgreSQLQuery type);
|
2021-01-19 15:29:22 +00:00
|
|
|
void readString(const char * message, size_t & pos, size_t size, String & result);
|
|
|
|
Int64 readInt64(const char * message, size_t & pos);
|
|
|
|
Int32 readInt32(const char * message, size_t & pos);
|
|
|
|
Int16 readInt16(const char * message, size_t & pos);
|
|
|
|
Int8 readInt8(const char * message, size_t & pos);
|
2021-01-27 15:29:28 +00:00
|
|
|
|
2021-01-01 14:43:11 +00:00
|
|
|
Poco::Logger * log;
|
2021-01-27 21:46:19 +00:00
|
|
|
std::shared_ptr<Context> context;
|
2021-01-01 14:43:11 +00:00
|
|
|
const std::string replication_slot_name;
|
|
|
|
const std::string publication_name;
|
2021-02-03 16:13:18 +00:00
|
|
|
PostgreSQLReplicaMetadata metadata;
|
2021-01-01 14:43:11 +00:00
|
|
|
|
|
|
|
const std::string table_name;
|
|
|
|
PostgreSQLConnectionPtr connection, replication_connection;
|
|
|
|
|
2021-01-31 19:03:03 +00:00
|
|
|
LSNPosition current_lsn, final_lsn;
|
2021-01-27 15:29:28 +00:00
|
|
|
BackgroundSchedulePool::TaskHolder wal_reader_task;
|
2021-01-31 19:03:03 +00:00
|
|
|
//BackgroundSchedulePool::TaskHolder table_sync_task;
|
2021-01-27 21:46:19 +00:00
|
|
|
std::atomic<bool> stop_synchronization = false;
|
2021-01-31 19:03:03 +00:00
|
|
|
|
|
|
|
const size_t max_block_size;
|
|
|
|
StoragePtr nested_storage;
|
|
|
|
Block sample_block;
|
|
|
|
ExternalResultDescription description;
|
|
|
|
MutableColumns columns;
|
|
|
|
/// Needed for insertPostgreSQLValue() method to parse array
|
|
|
|
std::unordered_map<size_t, PostgreSQLArrayInfo> array_info;
|
2021-02-03 16:13:18 +00:00
|
|
|
|
|
|
|
size_t data_version = 1;
|
2021-01-01 14:43:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|