2014-08-12 13:46:46 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Parsers/formatAST.h>
|
|
|
|
#include <DataStreams/IBlockOutputStream.h>
|
|
|
|
#include <Core/Block.h>
|
2017-08-03 17:42:31 +00:00
|
|
|
#include <common/ThreadPool.h>
|
2017-07-25 19:42:36 +00:00
|
|
|
#include <atomic>
|
|
|
|
#include <memory>
|
|
|
|
#include <chrono>
|
2017-08-03 17:42:31 +00:00
|
|
|
#include <experimental/optional>
|
2017-08-07 20:26:28 +00:00
|
|
|
#include <Interpreters/Cluster.h>
|
2017-07-25 19:42:36 +00:00
|
|
|
|
|
|
|
namespace Poco
|
|
|
|
{
|
|
|
|
class Logger;
|
|
|
|
}
|
2015-04-16 06:12:35 +00:00
|
|
|
|
2014-08-12 13:46:46 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-28 01:00:42 +00:00
|
|
|
class StorageDistributed;
|
|
|
|
|
2017-07-27 15:24:39 +00:00
|
|
|
/** If insert_sync_ is true, the write is synchronous. Uses insert_timeout_ if it is not zero.
|
|
|
|
* Otherwise, the write is asynchronous - the data is first written to the local filesystem, and then sent to the remote servers.
|
2017-04-16 15:00:33 +00:00
|
|
|
* If the Distributed table uses more than one shard, then in order to support the write,
|
|
|
|
* when creating the table, an additional parameter must be specified for ENGINE - the sharding key.
|
|
|
|
* Sharding key is an arbitrary expression from the columns. For example, rand() or UserID.
|
|
|
|
* When writing, the data block is splitted by the remainder of the division of the sharding key by the total weight of the shards,
|
|
|
|
* and the resulting blocks are written in a compressed Native format in separate directories for sending.
|
|
|
|
* For each destination address (each directory with data to send), a separate thread is created in StorageDistributed,
|
|
|
|
* which monitors the directory and sends data. */
|
2014-08-12 13:46:46 +00:00
|
|
|
class DistributedBlockOutputStream : public IBlockOutputStream
|
|
|
|
{
|
|
|
|
public:
|
2017-07-27 15:24:39 +00:00
|
|
|
DistributedBlockOutputStream(StorageDistributed & storage, const ASTPtr & query_ast, const ClusterPtr & cluster_, bool insert_sync_, UInt64 insert_timeout_);
|
2014-08-15 09:56:22 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void write(const Block & block) override;
|
2014-08-12 13:46:46 +00:00
|
|
|
|
2017-08-03 17:42:31 +00:00
|
|
|
void writePrefix() override;
|
2017-07-25 19:42:36 +00:00
|
|
|
|
2014-08-12 13:46:46 +00:00
|
|
|
private:
|
2017-08-03 17:42:31 +00:00
|
|
|
void writeAsync(const Block & block);
|
|
|
|
|
2017-08-07 20:26:28 +00:00
|
|
|
/// Performs synchronous insertion to remote nodes. If timeout_exceeded flag was set, throws.
|
2017-08-03 17:42:31 +00:00
|
|
|
void writeSync(const Block & block);
|
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
void calculateJobsCount();
|
2017-08-07 20:26:28 +00:00
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
struct WritingJobContext
|
|
|
|
{
|
|
|
|
/// Remote job per replica.
|
|
|
|
std::vector<bool> done_remote_jobs;
|
|
|
|
/// Local job per shard.
|
|
|
|
std::vector<bool> done_local_jobs;
|
|
|
|
std::atomic<unsigned> finished_jobs_count;
|
|
|
|
std::mutex mutex;
|
|
|
|
std::condition_variable cond_var;
|
|
|
|
};
|
2017-08-03 17:42:31 +00:00
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
ThreadPool::Job createWritingJob(WritingJobContext & context, const Block & block,
|
|
|
|
const Cluster::Address & address, size_t shard_id, size_t job_id);
|
2017-08-03 17:42:31 +00:00
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
void createWritingJobs(WritingJobContext & context, const Blocks & blocks);
|
|
|
|
|
|
|
|
void waitForUnfinishedJobs(WritingJobContext & context);
|
|
|
|
|
|
|
|
/// Returns the number of blocks was written for each cluster node. Uses during exception handling.
|
|
|
|
std::string getCurrentStateDescription(const WritingJobContext & context);
|
2017-08-03 17:42:31 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
IColumn::Selector createSelector(Block block);
|
2016-01-26 01:56:42 +00:00
|
|
|
|
2017-08-07 20:26:28 +00:00
|
|
|
/// Split block between shards.
|
2017-08-03 17:42:31 +00:00
|
|
|
Blocks splitBlock(const Block & block);
|
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
void writeSplitAsync(const Block & block);
|
2016-01-26 01:56:42 +00:00
|
|
|
|
2017-08-11 15:02:07 +00:00
|
|
|
void writeAsyncImpl(const Block & block, const size_t shard_id = 0);
|
2016-01-26 01:56:42 +00:00
|
|
|
|
2017-08-07 20:26:28 +00:00
|
|
|
/// Increments finished_writings_count after each repeat.
|
2017-08-11 15:02:07 +00:00
|
|
|
void writeToLocal(const Block & block, const size_t repeats);
|
2016-01-26 01:56:42 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void writeToShard(const Block & block, const std::vector<std::string> & dir_names);
|
2014-08-12 13:46:46 +00:00
|
|
|
|
2017-08-07 20:26:28 +00:00
|
|
|
/// Performs synchronous insertion to remote node.
|
2017-08-11 15:02:07 +00:00
|
|
|
void writeToShardSync(const Block & block, const std::string & connection_pool_name);
|
2017-07-25 19:42:36 +00:00
|
|
|
|
2016-01-28 01:00:42 +00:00
|
|
|
private:
|
2017-04-01 07:20:54 +00:00
|
|
|
StorageDistributed & storage;
|
|
|
|
ASTPtr query_ast;
|
|
|
|
ClusterPtr cluster;
|
2017-07-27 15:24:39 +00:00
|
|
|
bool insert_sync;
|
|
|
|
UInt64 insert_timeout;
|
2017-07-25 19:42:36 +00:00
|
|
|
size_t blocks_inserted = 0;
|
2017-07-27 15:24:39 +00:00
|
|
|
std::chrono::steady_clock::time_point deadline;
|
2017-08-03 17:42:31 +00:00
|
|
|
size_t remote_jobs_count;
|
2017-08-11 15:02:07 +00:00
|
|
|
size_t local_jobs_count;
|
2017-08-03 17:42:31 +00:00
|
|
|
std::experimental::optional<ThreadPool> pool;
|
2014-08-12 13:46:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|