Removed all trailing whitespaces [#CLICKHOUSE-2]. find . -name '*.h' -or -name '*.cpp' -or -name '*.cmake' -or -name 'CMakeLists.txt' -or -name '*.html' -or -name '*.xml' | grep -v contrib | xargs sed -i -r -e 's/\s+$//'

This commit is contained in:
Alexey Milovidov 2017-03-31 19:00:30 +03:00
parent f5a7498559
commit 4f44445ff0
42 changed files with 211 additions and 211 deletions

View File

@ -16,33 +16,33 @@
# #
# Usage: # Usage:
# set(ENV{Poco_DIR} path/to/poco/sdk) # set(ENV{Poco_DIR} path/to/poco/sdk)
# find_package(Poco REQUIRED OSP Data Crypto) # find_package(Poco REQUIRED OSP Data Crypto)
# #
# On completion, the script defines the following variables: # On completion, the script defines the following variables:
# #
# - Compound variables: # - Compound variables:
# Poco_FOUND # Poco_FOUND
# - true if all requested components were found. # - true if all requested components were found.
# Poco_LIBRARIES # Poco_LIBRARIES
# - contains release (and debug if available) libraries for all requested components. # - contains release (and debug if available) libraries for all requested components.
# It has the form "optimized LIB1 debug LIBd1 optimized LIB2 ...", ready for use with the target_link_libraries command. # It has the form "optimized LIB1 debug LIBd1 optimized LIB2 ...", ready for use with the target_link_libraries command.
# Poco_INCLUDE_DIRS # Poco_INCLUDE_DIRS
# - Contains include directories for all requested components. # - Contains include directories for all requested components.
# #
# - Component variables: # - Component variables:
# Poco_Xxx_FOUND # Poco_Xxx_FOUND
# - Where Xxx is the properly cased component name (eg. 'Util', 'OSP'). # - Where Xxx is the properly cased component name (eg. 'Util', 'OSP').
# True if a component's library or debug library was found successfully. # True if a component's library or debug library was found successfully.
# Poco_Xxx_LIBRARY # Poco_Xxx_LIBRARY
# - Library for component Xxx. # - Library for component Xxx.
# Poco_Xxx_LIBRARY_DEBUG # Poco_Xxx_LIBRARY_DEBUG
# - debug library for component Xxx # - debug library for component Xxx
# Poco_Xxx_INCLUDE_DIR # Poco_Xxx_INCLUDE_DIR
# - include directory for component Xxx # - include directory for component Xxx
# #
# - OSP BundleCreator variables: (i.e. bundle.exe on windows, bundle on unix-likes) # - OSP BundleCreator variables: (i.e. bundle.exe on windows, bundle on unix-likes)
# (is only discovered if OSP is a requested component) # (is only discovered if OSP is a requested component)
# Poco_OSP_Bundle_EXECUTABLE_FOUND # Poco_OSP_Bundle_EXECUTABLE_FOUND
# - true if the bundle-creator executable was found. # - true if the bundle-creator executable was found.
# Poco_OSP_Bundle_EXECUTABLE # Poco_OSP_Bundle_EXECUTABLE
# - the path to the bundle-creator executable. # - the path to the bundle-creator executable.
@ -52,24 +52,24 @@
set(Poco_HINTS set(Poco_HINTS
/usr/local /usr/local
C:/AppliedInformatics C:/AppliedInformatics
${Poco_DIR} ${Poco_DIR}
$ENV{Poco_DIR} $ENV{Poco_DIR}
) )
if(NOT Poco_ROOT_DIR) if(NOT Poco_ROOT_DIR)
# look for the root directory, first for the source-tree variant # look for the root directory, first for the source-tree variant
find_path(Poco_ROOT_DIR find_path(Poco_ROOT_DIR
NAMES Foundation/include/Poco/Poco.h NAMES Foundation/include/Poco/Poco.h
HINTS ${Poco_HINTS} HINTS ${Poco_HINTS}
) )
if(NOT Poco_ROOT_DIR) if(NOT Poco_ROOT_DIR)
# this means poco may have a different directory structure, maybe it was installed, let's check for that # this means poco may have a different directory structure, maybe it was installed, let's check for that
message(STATUS "Looking for Poco install directory structure.") message(STATUS "Looking for Poco install directory structure.")
find_path(Poco_ROOT_DIR find_path(Poco_ROOT_DIR
NAMES include/Poco/Poco.h NAMES include/Poco/Poco.h
HINTS ${Poco_HINTS} HINTS ${Poco_HINTS}
) )
if(NOT Poco_ROOT_DIR) if(NOT Poco_ROOT_DIR)
# poco was still not found -> Fail # poco was still not found -> Fail
if(Poco_FIND_REQUIRED) if(Poco_FIND_REQUIRED)
message(FATAL_ERROR "Poco: Could not find Poco install directory") message(FATAL_ERROR "Poco: Could not find Poco install directory")
@ -91,7 +91,7 @@ if(WIN32)
find_path(Poco_RUNTIME_LIBRARY_DIRS find_path(Poco_RUNTIME_LIBRARY_DIRS
NAMES PocoFoundation.dll NAMES PocoFoundation.dll
HINTS ${Poco_ROOT_DIR} HINTS ${Poco_ROOT_DIR}
PATH_SUFFIXES PATH_SUFFIXES
bin bin
lib lib
) )
@ -103,17 +103,17 @@ if(Poco_INSTALLED)
endif() endif()
# append the default minimum components to the list to find # append the default minimum components to the list to find
list(APPEND components list(APPEND components
${Poco_FIND_COMPONENTS} ${Poco_FIND_COMPONENTS}
# default components: # default components:
"Util" "Util"
"Foundation" "Foundation"
) )
list(REMOVE_DUPLICATES components) # remove duplicate defaults list(REMOVE_DUPLICATES components) # remove duplicate defaults
foreach( component ${components} ) foreach( component ${components} )
#if(NOT Poco_${component}_FOUND) #if(NOT Poco_${component}_FOUND)
# include directory for the component # include directory for the component
if(NOT Poco_${component}_INCLUDE_DIR) if(NOT Poco_${component}_INCLUDE_DIR)
if (${component} STREQUAL "DataODBC") if (${component} STREQUAL "DataODBC")
@ -127,7 +127,7 @@ foreach( component ${components} )
set (component_alt ${component}) set (component_alt ${component})
endif () endif ()
find_path(Poco_${component}_INCLUDE_DIR find_path(Poco_${component}_INCLUDE_DIR
NAMES NAMES
Poco/${component}.h # e.g. Foundation.h Poco/${component}.h # e.g. Foundation.h
Poco/${component}/${component}.h # e.g. OSP/OSP.h Util/Util.h Poco/${component}/${component}.h # e.g. OSP/OSP.h Util/Util.h
Poco/${component_alt}/${component}.h # e.g. Net/NetSSL.h Poco/${component_alt}/${component}.h # e.g. Net/NetSSL.h
@ -148,8 +148,8 @@ foreach( component ${components} )
# release library # release library
if(NOT Poco_${component}_LIBRARY) if(NOT Poco_${component}_LIBRARY)
find_library( find_library(
Poco_${component}_LIBRARY Poco_${component}_LIBRARY
NAMES Poco${component} NAMES Poco${component}
HINTS ${Poco_ROOT_DIR} HINTS ${Poco_ROOT_DIR}
PATH_SUFFIXES PATH_SUFFIXES
lib lib
@ -198,9 +198,9 @@ endif()
if(${Poco_OSP_FOUND}) if(${Poco_OSP_FOUND})
# find the osp bundle program # find the osp bundle program
find_program( find_program(
Poco_OSP_Bundle_EXECUTABLE Poco_OSP_Bundle_EXECUTABLE
NAMES bundle NAMES bundle
HINTS HINTS
${Poco_RUNTIME_LIBRARY_DIRS} ${Poco_RUNTIME_LIBRARY_DIRS}
${Poco_ROOT_DIR} ${Poco_ROOT_DIR}
PATH_SUFFIXES PATH_SUFFIXES

View File

@ -47,12 +47,12 @@ public:
{ {
setEmpty(); setEmpty();
} }
AutoArray(size_t size_) AutoArray(size_t size_)
{ {
init(size_, false); init(size_, false);
} }
/** Не будут вызваны конструкторы по-умолчанию для элементов. /** Не будут вызваны конструкторы по-умолчанию для элементов.
* В этом случае, вы должны вставить все элементы с помощью функции place и placement new, * В этом случае, вы должны вставить все элементы с помощью функции place и placement new,
* так как для них потом будут вызваны деструкторы. * так как для них потом будут вызваны деструкторы.
@ -61,13 +61,13 @@ public:
{ {
init(size_, true); init(size_, true);
} }
/** Инициализирует все элементы копирующим конструктором с параметром value. /** Инициализирует все элементы копирующим конструктором с параметром value.
*/ */
AutoArray(size_t size_, const T & value) AutoArray(size_t size_, const T & value)
{ {
init(size_, true); init(size_, true);
for (size_t i = 0; i < size_; ++i) for (size_t i = 0; i < size_; ++i)
{ {
new (place(i)) T(value); new (place(i)) T(value);
@ -134,7 +134,7 @@ public:
{ {
return elem(i); return elem(i);
} }
const T & operator[](size_t i) const const T & operator[](size_t i) const
{ {
return elem(i); return elem(i);
@ -234,7 +234,7 @@ private:
setEmpty(); setEmpty();
return; return;
} }
data = new char[size_ * sizeof(T) + sizeof(size_t)]; data = new char[size_ * sizeof(T) + sizeof(size_t)];
data += sizeof(size_t); data += sizeof(size_t);
m_size() = size_; m_size() = size_;

View File

@ -28,7 +28,7 @@ namespace DB
* - один или несколько пакетов Data. * - один или несколько пакетов Data.
* Конец данных определается по отправленному пустому блоку. * Конец данных определается по отправленному пустому блоку.
* Затем сервер отправляет клиенту пакет EndOfStream. * Затем сервер отправляет клиенту пакет EndOfStream.
* *
* Если запрос типа SELECT или другой, то сервер передаёт набор пакетов одного из следующих видов: * Если запрос типа SELECT или другой, то сервер передаёт набор пакетов одного из следующих видов:
* - Data - данные результата выполнения запроса (один блок); * - Data - данные результата выполнения запроса (один блок);
* - Progress - прогресс выполнения запроса; * - Progress - прогресс выполнения запроса;
@ -39,12 +39,12 @@ namespace DB
* Также, клиент может передать на сервер пакет Cancel - отмена выполнения запроса. * Также, клиент может передать на сервер пакет Cancel - отмена выполнения запроса.
* В этом случае, сервер может прервать выполнение запроса и вернуть неполные данные; * В этом случае, сервер может прервать выполнение запроса и вернуть неполные данные;
* но клиент всё равно должен читать все пакеты до EndOfStream. * но клиент всё равно должен читать все пакеты до EndOfStream.
* *
* Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая, * Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая,
* может быть отправлен пакет Totals и/или ProfileInfo. * может быть отправлен пакет Totals и/или ProfileInfo.
* Totals - блок с тотальными значениями. * Totals - блок с тотальными значениями.
* ProfileInfo - данные профайлинга - сериализованная структура BlockStreamProfileInfo. * ProfileInfo - данные профайлинга - сериализованная структура BlockStreamProfileInfo.
* *
* При запросах, которые возвращают данные, сервер, перед обработкой запроса, * При запросах, которые возвращают данные, сервер, перед обработкой запроса,
* отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк. * отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк.
* Используя этот заголовочный блок, клиент может заранее проинициализировать формат вывода * Используя этот заголовочный блок, клиент может заранее проинициализировать формат вывода

View File

@ -19,7 +19,7 @@ public:
ASTDropQuery() = default; ASTDropQuery() = default;
ASTDropQuery(const StringRange range_) : IAST(range_) {} ASTDropQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */ /** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return (detach ? "DetachQuery_" : "DropQuery_") + database + "_" + table; }; String getID() const override { return (detach ? "DetachQuery_" : "DropQuery_") + database + "_" + table; };

View File

@ -29,7 +29,7 @@ public:
ASTRenameQuery() = default; ASTRenameQuery() = default;
ASTRenameQuery(const StringRange range_) : IAST(range_) {} ASTRenameQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */ /** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Rename"; }; String getID() const override { return "Rename"; };

View File

@ -56,7 +56,7 @@ public:
if (sigemptyset(&sig_set) if (sigemptyset(&sig_set)
|| sigaddset(&sig_set, SIGINT)) || sigaddset(&sig_set, SIGINT))
throwFromErrno("Cannot manipulate with signal set.", ErrorCodes::CANNOT_MANIPULATE_SIGSET); throwFromErrno("Cannot manipulate with signal set.", ErrorCodes::CANNOT_MANIPULATE_SIGSET);
block(); block();
} }
@ -69,9 +69,9 @@ public:
{ {
if (!active) if (!active)
return false; return false;
timespec timeout = { 0, 0 }; timespec timeout = { 0, 0 };
if (-1 == sigtimedwait(&sig_set, nullptr, &timeout)) if (-1 == sigtimedwait(&sig_set, nullptr, &timeout))
{ {
if (errno == EAGAIN) if (errno == EAGAIN)

View File

@ -107,7 +107,7 @@ template < typename keytype, typename hashtype >
bool AvalancheTest ( pfHash hash, const int reps ) bool AvalancheTest ( pfHash hash, const int reps )
{ {
Rand r(48273); Rand r(48273);
const int keybytes = sizeof(keytype); const int keybytes = sizeof(keytype);
const int hashbytes = sizeof(hashtype); const int hashbytes = sizeof(hashtype);
@ -121,7 +121,7 @@ bool AvalancheTest ( pfHash hash, const int reps )
std::vector<int> bins(keybits*hashbits,0); std::vector<int> bins(keybits*hashbits,0);
calcBias<keytype,hashtype>(hash,bins,reps,r); calcBias<keytype,hashtype>(hash,bins,reps,r);
//---------- //----------
bool result = true; bool result = true;

View File

@ -51,7 +51,7 @@ struct Rand
{ {
uint32_t t = x ^ (x << 11); uint32_t t = x ^ (x << 11);
x = y; y = z; z = w; x = y; y = z; z = w;
w = w ^ (w >> 19) ^ t ^ (t >> 8); w = w ^ (w >> 19) ^ t ^ (t >> 8);
} }
uint32_t rand_u32 ( void ) uint32_t rand_u32 ( void )
@ -61,7 +61,7 @@ struct Rand
return x; return x;
} }
uint64_t rand_u64 ( void ) uint64_t rand_u64 ( void )
{ {
mix(); mix();

View File

@ -39,7 +39,7 @@ int main(int argc, char ** argv)
} }
std::cerr << std::endl; std::cerr << std::endl;
{ {
size_t n = 10; size_t n = 10;
using T = std::string; using T = std::string;
@ -58,7 +58,7 @@ int main(int argc, char ** argv)
Arr arr2 = std::move(arr); Arr arr2 = std::move(arr);
std::cerr << arr.size() << ", " << arr2.size() << std::endl; std::cerr << arr.size() << ", " << arr2.size() << std::endl;
for (size_t i = 0; i < arr2.size(); ++i) for (size_t i = 0; i < arr2.size(); ++i)
std::cerr << arr2[i] << std::endl; std::cerr << arr2[i] << std::endl;
} }
@ -78,7 +78,7 @@ int main(int argc, char ** argv)
Arr key(n); Arr key(n);
for (size_t j = 0; j < n; ++j) for (size_t j = 0; j < n; ++j)
key[j] = DB::toString(rand()); key[j] = DB::toString(rand());
map[std::move(key)] = "Hello, world! " + DB::toString(i); map[std::move(key)] = "Hello, world! " + DB::toString(i);
} }
@ -88,7 +88,7 @@ int main(int argc, char ** argv)
for (size_t j = 0; j < n; ++j) for (size_t j = 0; j < n; ++j)
std::cerr << (j == 0 ? "" : ", ") << it->first[j]; std::cerr << (j == 0 ? "" : ", ") << it->first[j];
std::cerr << "]"; std::cerr << "]";
std::cerr << ":\t" << it->second << std::endl; std::cerr << ":\t" << it->second << std::endl;
} }

View File

@ -61,7 +61,7 @@ int main(int argc, char ** argv)
<< " (" << rows / watch.elapsedSeconds() << " rows/sec., " << bytes / 1000000.0 / watch.elapsedSeconds() << " MB/sec.)" << " (" << rows / watch.elapsedSeconds() << " rows/sec., " << bytes / 1000000.0 / watch.elapsedSeconds() << " MB/sec.)"
<< std::endl; << std::endl;
} }
/* { /* {
Stopwatch watch; Stopwatch watch;

View File

@ -120,7 +120,7 @@ int test_vectors()
hash.update(in, part); hash.update(in, part);
hash.update(in + part, i - part); hash.update(in + part, i - part);
hash.get128(out); hash.get128(out);
uint64_t test_vector; uint64_t test_vector;

View File

@ -19,7 +19,7 @@ int main(int argc, char ** argv)
{ {
std::cerr << std::fixed << std::setprecision(3); std::cerr << std::fixed << std::setprecision(3);
std::ofstream devnull("/dev/null"); std::ofstream devnull("/dev/null");
DB::ReadBufferFromFileDescriptor in(STDIN_FILENO); DB::ReadBufferFromFileDescriptor in(STDIN_FILENO);
size_t n = atoi(argv[1]); size_t n = atoi(argv[1]);
size_t elems_show = 1; size_t elems_show = 1;
@ -116,7 +116,7 @@ int main(int argc, char ** argv)
DB::Arena pool; DB::Arena pool;
RefsSet set; RefsSet set;
Stopwatch watch; Stopwatch watch;
for (Vec::iterator it = vec.begin(); it != vec.end(); ++it) for (Vec::iterator it = vec.begin(); it != vec.end(); ++it)
set[StringRef(pool.insert(it->data(), it->size()), it->size())] = 0; set[StringRef(pool.insert(it->data(), it->size()), it->size())] = 0;

View File

@ -53,7 +53,7 @@ int main(int argc, char ** argv)
printType(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt32, DB::Int16>::Type()); std::cout << std::endl; printType(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt32, DB::Int16>::Type()); std::cout << std::endl;
printType(DB::NumberTraits::ResultOfIntegerDivision<DB::UInt8, DB::Int16>::Type()); std::cout << std::endl; printType(DB::NumberTraits::ResultOfIntegerDivision<DB::UInt8, DB::Int16>::Type()); std::cout << std::endl;
printType(DB::NumberTraits::ResultOfModulo<DB::UInt32, DB::Int8>::Type()); std::cout << std::endl; printType(DB::NumberTraits::ResultOfModulo<DB::UInt32, DB::Int8>::Type()); std::cout << std::endl;
ifLeftType<DB::UInt8>(); ifLeftType<DB::UInt8>();
ifLeftType<DB::UInt16>(); ifLeftType<DB::UInt16>();
ifLeftType<DB::UInt32>(); ifLeftType<DB::UInt32>();
@ -64,6 +64,6 @@ int main(int argc, char ** argv)
ifLeftType<DB::Int64>(); ifLeftType<DB::Int64>();
ifLeftType<DB::Float32>(); ifLeftType<DB::Float32>();
ifLeftType<DB::Float64>(); ifLeftType<DB::Float64>();
return 0; return 0;
} }

View File

@ -12,7 +12,7 @@
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
using namespace DB; using namespace DB;
try try
{ {
UncompressedCache cache(1024); UncompressedCache cache(1024);

View File

@ -23,7 +23,7 @@ namespace test
++buf.position(); ++buf.position();
negative = true; negative = true;
} }
if (*buf.position() == '0') if (*buf.position() == '0')
{ {
++buf.position(); ++buf.position();

View File

@ -22,13 +22,13 @@ int main(int argc, char ** argv)
DB::readIntText(a, in); DB::readIntText(a, in);
in.ignore(); in.ignore();
DB::readFloatText(b, in); DB::readFloatText(b, in);
in.ignore(); in.ignore();
DB::readEscapedString(c, in); DB::readEscapedString(c, in);
in.ignore(); in.ignore();
DB::readQuotedString(d, in); DB::readQuotedString(d, in);
std::cout << a << ' ' << b << ' ' << c << '\t' << '\'' << d << '\'' << std::endl; std::cout << a << ' ' << b << ' ' << c << '\t' << '\'' << d << '\'' << std::endl;

View File

@ -24,13 +24,13 @@ int main(int argc, char ** argv)
{ {
DB::readIntText(a, in); DB::readIntText(a, in);
in.ignore(); in.ignore();
DB::readFloatText(b, in); DB::readFloatText(b, in);
in.ignore(); in.ignore();
DB::readEscapedString(c, in); DB::readEscapedString(c, in);
in.ignore(); in.ignore();
DB::readQuotedString(d, in); DB::readQuotedString(d, in);
in.ignore(); in.ignore();

View File

@ -19,7 +19,7 @@ int main(int argc, char ** argv)
std::string s; std::string s;
std::cerr << static_cast<Int64>(x1) << std::endl; std::cerr << static_cast<Int64>(x1) << std::endl;
{ {
DB::WriteBufferFromString wb(s); DB::WriteBufferFromString wb(s);
DB::writeIntText(x1, wb); DB::writeIntText(x1, wb);

View File

@ -13,12 +13,12 @@ int main(int argc, char ** argv)
int repeats = 1; int repeats = 1;
if (argc >= 2) if (argc >= 2)
repeats = atoi(argv[1]); repeats = atoi(argv[1]);
std::string text((std::istreambuf_iterator<char>(std::cin)), std::string text((std::istreambuf_iterator<char>(std::cin)),
std::istreambuf_iterator<char>()); std::istreambuf_iterator<char>());
std::cout << "Text length: " << text.size() << std::endl; std::cout << "Text length: " << text.size() << std::endl;
Stopwatch timer; Stopwatch timer;
std::string str1; std::string str1;
{ {
@ -31,9 +31,9 @@ int main(int argc, char ** argv)
double t = timer.elapsedSeconds(); double t = timer.elapsedSeconds();
std::cout << "Wrote to string in " << t << "s at " << text.size() / 1e6 * repeats / t << "MB/s." << std::endl; std::cout << "Wrote to string in " << t << "s at " << text.size() / 1e6 * repeats / t << "MB/s." << std::endl;
std::cout << "String length: " << str1.size() << "(" << (str1.size() == text.size() * repeats ? "as " : "un") << "expected)" << std::endl; std::cout << "String length: " << str1.size() << "(" << (str1.size() == text.size() * repeats ? "as " : "un") << "expected)" << std::endl;
timer.restart(); timer.restart();
std::string str2; std::string str2;
{ {
DB::WriteBufferFromString simple_buf(str2); DB::WriteBufferFromString simple_buf(str2);

View File

@ -24,10 +24,10 @@ int main(int argc, char ** argv)
DB::writeIntText(a, out); DB::writeIntText(a, out);
DB::writeChar(' ', out); DB::writeChar(' ', out);
DB::writeFloatText(b, out); DB::writeFloatText(b, out);
DB::writeChar(' ', out); DB::writeChar(' ', out);
DB::writeEscapedString(c, out); DB::writeEscapedString(c, out);
DB::writeChar('\t', out); DB::writeChar('\t', out);

View File

@ -24,10 +24,10 @@ int main(int argc, char ** argv)
{ {
DB::writeIntText(a, out); DB::writeIntText(a, out);
DB::writeChar(' ', out); DB::writeChar(' ', out);
DB::writeFloatText(b, out); DB::writeFloatText(b, out);
DB::writeChar(' ', out); DB::writeChar(' ', out);
DB::writeEscapedString(c, out); DB::writeEscapedString(c, out);
DB::writeChar('\t', out); DB::writeChar('\t', out);

View File

@ -143,7 +143,7 @@ int main(int argc, char ** argv)
std::unordered_map<Key, Value, DefaultHash<Key> > map; std::unordered_map<Key, Value, DefaultHash<Key> > map;
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
++map[data[i]]; ++map[data[i]];
watch.stop(); watch.stop();
std::cerr << std::fixed << std::setprecision(2) std::cerr << std::fixed << std::setprecision(2)
<< "std::unordered_map. Size: " << map.size() << "std::unordered_map. Size: " << map.size()
@ -160,7 +160,7 @@ int main(int argc, char ** argv)
map.set_empty_key(-1ULL); map.set_empty_key(-1ULL);
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
++map[data[i]]; ++map[data[i]];
watch.stop(); watch.stop();
std::cerr << std::fixed << std::setprecision(2) std::cerr << std::fixed << std::setprecision(2)
<< "google::dense_hash_map. Size: " << map.size() << "google::dense_hash_map. Size: " << map.size()

View File

@ -437,7 +437,7 @@ int main(int argc, char ** argv)
std::unordered_map<Key, Value, DefaultHash<Key> > map; std::unordered_map<Key, Value, DefaultHash<Key> > map;
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
++map[data[i]]; ++map[data[i]];
watch.stop(); watch.stop();
std::cerr << std::fixed << std::setprecision(2) std::cerr << std::fixed << std::setprecision(2)
<< "std::unordered_map. Size: " << map.size() << "std::unordered_map. Size: " << map.size()
@ -454,7 +454,7 @@ int main(int argc, char ** argv)
map.set_empty_key(Key("\0", 1)); map.set_empty_key(Key("\0", 1));
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
++map[data[i]]; ++map[data[i]];
watch.stop(); watch.stop();
std::cerr << std::fixed << std::setprecision(2) std::cerr << std::fixed << std::setprecision(2)
<< "google::dense_hash_map. Size: " << map.size() << "google::dense_hash_map. Size: " << map.size()

View File

@ -595,7 +595,7 @@ int Server::main(const std::vector<std::string> & args)
} }
LOG_DEBUG( LOG_DEBUG(
log, "Closed connections." << (current_connections ? " But " + std::to_string(current_connections) + " remains." log, "Closed connections." << (current_connections ? " But " + std::to_string(current_connections) + " remains."
+ " Tip: To increase wait time add to config: <shutdown_wait_unfinished>60</shutdown_wait_unfinished> ." : "")); + " Tip: To increase wait time add to config: <shutdown_wait_unfinished>60</shutdown_wait_unfinished> ." : ""));
main_config_reloader.reset(); main_config_reloader.reset();

View File

@ -105,7 +105,7 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataWriter::writeTempPart(BlockWithDa
size_t part_size = (block.rows() + data.index_granularity - 1) / data.index_granularity; size_t part_size = (block.rows() + data.index_granularity - 1) / data.index_granularity;
String part_name = ActiveDataPartSet::getPartName( String part_name = ActiveDataPartSet::getPartName(
DayNum_t(min_date), DayNum_t(max_date), DayNum_t(min_date), DayNum_t(max_date),
temp_index, temp_index, 0); temp_index, temp_index, 0);

View File

@ -339,7 +339,7 @@ bool StorageMergeTree::merge(
/// Logging /// Logging
Stopwatch stopwatch; Stopwatch stopwatch;
auto new_part = merger.mergePartsToTemporaryPart( auto new_part = merger.mergePartsToTemporaryPart(
merging_tagger->parts, merged_name, *merge_entry_ptr, aio_threshold, time(0), merging_tagger->reserved_space.get()); merging_tagger->parts, merged_name, *merge_entry_ptr, aio_threshold, time(0), merging_tagger->reserved_space.get());

View File

@ -1157,7 +1157,7 @@ bool StorageReplicatedMergeTree::executeLogEntry(const LogEntry & entry)
/// Logging /// Logging
Stopwatch stopwatch; Stopwatch stopwatch;
auto part = merger.mergePartsToTemporaryPart( auto part = merger.mergePartsToTemporaryPart(
parts, entry.new_part_name, *merge_entry, aio_threshold, entry.create_time, reserved_space.get()); parts, entry.new_part_name, *merge_entry, aio_threshold, entry.create_time, reserved_space.get());
@ -2077,11 +2077,11 @@ bool StorageReplicatedMergeTree::fetchPart(const String & part_name, const Strin
ReplicatedMergeTreeAddress address(getZooKeeper()->get(replica_path + "/host")); ReplicatedMergeTreeAddress address(getZooKeeper()->get(replica_path + "/host"));
Stopwatch stopwatch; Stopwatch stopwatch;
MergeTreeData::MutableDataPartPtr part = fetcher.fetchPart( MergeTreeData::MutableDataPartPtr part = fetcher.fetchPart(
part_name, replica_path, address.host, address.replication_port, to_detached); part_name, replica_path, address.host, address.replication_port, to_detached);
if (!to_detached) if (!to_detached)
{ {
zkutil::Ops ops; zkutil::Ops ops;
@ -2386,7 +2386,7 @@ bool StorageReplicatedMergeTree::optimize(const String & partition, bool final,
/// Logging /// Logging
Stopwatch stopwatch; Stopwatch stopwatch;
auto new_part = unreplicated_merger->mergePartsToTemporaryPart( auto new_part = unreplicated_merger->mergePartsToTemporaryPart(
parts, merged_name, *merge_entry, settings.min_bytes_to_use_direct_io, time(0)); parts, merged_name, *merge_entry, settings.min_bytes_to_use_direct_io, time(0));

View File

@ -11,11 +11,11 @@
<header class="caption"> <header class="caption">
<h1>Параллельный и распределённый GROUP BY</h1> <h1>Параллельный и распределённый GROUP BY</h1>
</header> </header>
<section class="slide" id="cover"> <section class="slide" id="cover">
<h1 style="margin-top: 200px">Параллельный и распределённый GROUP BY</h1> <h1 style="margin-top: 200px">Параллельный и распределённый GROUP BY</h1>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Обо мне</h2> <h2>Обо мне</h2>
<p>Алексей, разработчик ClickHouse.</p> <p>Алексей, разработчик ClickHouse.</p>
@ -28,12 +28,12 @@
<p>Один запрос &mdash; много данных на входе, мало на выходе.</p> <p>Один запрос &mdash; много данных на входе, мало на выходе.</p>
<p>Данные нужно агрегировать налету.</p> <p>Данные нужно агрегировать налету.</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Метрика 2.0</h2> <h2>Метрика 2.0</h2>
<img src="pictures/metrika2.png" style="height:70%"/> <img src="pictures/metrika2.png" style="height:70%"/>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Пример запроса</h2> <h2>Пример запроса</h2>
<p style="font-family: Monospace">SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u<br /> <p style="font-family: Monospace">SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u<br />
@ -42,7 +42,7 @@
<b>GROUP BY</b> MobilePhoneModel<br /> <b>GROUP BY</b> MobilePhoneModel<br />
ORDER BY u DESC</p> ORDER BY u DESC</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>&nbsp;</h2> <h2>&nbsp;</h2>
<p>Чтобы быстро обрабатывать запросы, данные необходимо:</p> <p>Чтобы быстро обрабатывать запросы, данные необходимо:</p>
@ -54,7 +54,7 @@
<p>Конвейер выполнения запроса:</p> <p>Конвейер выполнения запроса:</p>
<p>&mdash; фильтрация, JOIN, <b>агрегация</b>, сортировка...</p> <p>&mdash; фильтрация, JOIN, <b>агрегация</b>, сортировка...</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2 style="font-size: 45px;">Как тестировать производительность?</h2> <h2 style="font-size: 45px;">Как тестировать производительность?</h2>
<p>Бенчмарки должны быть:</p> <p>Бенчмарки должны быть:</p>
@ -65,7 +65,7 @@
<li>автоматизированные.</li> <li>автоматизированные.</li>
</ul> </ul>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Пример бенчмарка (не лучшего)</h2> <h2>Пример бенчмарка (не лучшего)</h2>
<pre style="white-space: pre; font-family: Monospace; font-size: 14px; line-height: 1.25em;">/** Выполнять так: <pre style="white-space: pre; font-family: Monospace; font-size: 14px; line-height: 1.25em;">/** Выполнять так:
@ -82,7 +82,7 @@ for file in <b>MobilePhoneModel PageCharset Params URLDomain UTMSource Referer U
if [[ $TOTAL_ELEMS -gt 25000000 ]]; then break; fi if [[ $TOTAL_ELEMS -gt 25000000 ]]; then break; fi
./hash_map_string_3 $size $method < ${file}.bin 2>&1 | ./hash_map_string_3 $size $method < ${file}.bin 2>&1 |
grep HashMap | grep -oE '[0-9\.]+ elem'; grep HashMap | grep -oE '[0-9\.]+ elem';
done | awk -W interactive '{ if ($1 > x) { x = $1 }; printf(".") } END { print x }' | done | awk -W interactive '{ if ($1 > x) { x = $1 }; printf(".") } END { print x }' |
tee /tmp/hash_map_string_3_res; tee /tmp/hash_map_string_3_res;
CUR_RESULT=$(cat /tmp/hash_map_string_3_res | tr -d '.') CUR_RESULT=$(cat /tmp/hash_map_string_3_res | tr -d '.')
if [[ $CUR_RESULT -gt $BEST_RESULT ]]; then if [[ $CUR_RESULT -gt $BEST_RESULT ]]; then
@ -95,15 +95,15 @@ for file in <b>MobilePhoneModel PageCharset Params URLDomain UTMSource Referer U
done done
*/</pre> */</pre>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Агрегация</h2> <h2>Агрегация</h2>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Одна машина, одно ядро</h2> <h2>Одна машина, одно ядро</h2>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Плохой способ</h2> <h2>Плохой способ</h2>
<p>Читаем данные в массив; сортируем по ключу; <p>Читаем данные в массив; сортируем по ключу;
@ -117,7 +117,7 @@ done
Отвратительно работает при N > M &mdash; в типичном случае. Отвратительно работает при N > M &mdash; в типичном случае.
Тратится O(N) оперативки на промежуточные данные вместо O(M).</p> Тратится O(N) оперативки на промежуточные данные вместо O(M).</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Хороший способ</h2> <h2>Хороший способ</h2>
<p>Читаем данные, кладём в ассоциативный массив</p> <p>Читаем данные, кладём в ассоциативный массив</p>
@ -131,19 +131,19 @@ done
<p>Бинарное дерево. Skip-лист. B-дерево. </p> <p>Бинарное дерево. Skip-лист. B-дерево. </p>
<p>Трай. Трай+хэш-таблица...</p> <p>Трай. Трай+хэш-таблица...</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Бинарное дерево</h2> <h2>Бинарное дерево</h2>
<p>&minus; слишком большой оверхед на элемент;</p> <p>&minus; слишком большой оверхед на элемент;</p>
<p>&minus; отвратительная кэш-локальность;</p> <p>&minus; отвратительная кэш-локальность;</p>
<p>&minus; вообще тормозит.</p> <p>&minus; вообще тормозит.</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Skip-лист. Трай. B-дерево...</h2> <h2>Skip-лист. Трай. B-дерево...</h2>
<p>&minus; вообще для другой задачи;</p> <p>&minus; вообще для другой задачи;</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Lookup-таблица</h2> <h2>Lookup-таблица</h2>
<p>+ прекрасно для агрегации по числовым ключам не более ~16 бит;</p> <p>+ прекрасно для агрегации по числовым ключам не более ~16 бит;</p>
@ -155,12 +155,12 @@ done
<p>+ моя любимая структура данных;</p> <p>+ моя любимая структура данных;</p>
<p>&minus; много деталей.</p> <p>&minus; много деталей.</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Трай+хэш-таблица</h2> <h2>Трай+хэш-таблица</h2>
<p>+ иногда кое что в этом есть, см. далее;</p> <p>+ иногда кое что в этом есть, см. далее;</p>
</section> </section>
<section class="slide"> <section class="slide">
<h2>Одна машина, много ядер</h2> <h2>Одна машина, много ядер</h2>
</section> </section>
@ -168,18 +168,18 @@ done
<section class="slide"> <section class="slide">
<h2>1. Тривиальный способ</h2> <h2>1. Тривиальный способ</h2>
<p>Разные потоки читают разные данные по мере возможности. <p>Разные потоки читают разные данные по мере возможности.
Агрегируют независимо в свои локальные хэш-таблицы. Агрегируют независимо в свои локальные хэш-таблицы.
Когда все данные прочитаны, мержим все хэш-таблицы в одну. Когда все данные прочитаны, мержим все хэш-таблицы в одну.
Например, идём по всем локальным хэш-таблицам кроме первой Например, идём по всем локальным хэш-таблицам кроме первой
и перекладываем всё в первую. и перекладываем всё в первую.
Фаза чтения данных и предварительной агрегации распараллеливается. Фаза чтения данных и предварительной агрегации распараллеливается.
Фаза мержа выполняется последовательно. Фаза мержа выполняется последовательно.
Пусть N &mdash; общее число данных, а M &mdash; количество ключей. Пусть N &mdash; общее число данных, а M &mdash; количество ключей.
O(M) работы выполняется последовательно O(M) работы выполняется последовательно
и при большом M (кардинальность GROUP BY) и при большом M (кардинальность GROUP BY)
работа плохо распараллеливается. работа плохо распараллеливается.
Достоинства: тривиально. Достоинства: тривиально.
@ -193,42 +193,42 @@ O(M) работы выполняется последовательно
<p>Для каждого блока данных, выполняем агрегацию в две стадии: <p>Для каждого блока данных, выполняем агрегацию в две стадии:
Стадия 1. Стадия 1.
Разные потоки будут обрабатывать разные куски блока, какие успеют. Разные потоки будут обрабатывать разные куски блока, какие успеют.
В каждом потоке, с помощью отдельной хэш-функции, В каждом потоке, с помощью отдельной хэш-функции,
хэшируем ключ в номер потока и запоминаем его. хэшируем ключ в номер потока и запоминаем его.
hash: key -> bucket_num hash: key -> bucket_num
Стадия 2. Стадия 2.
Каждый поток идёт по всему блоку данных Каждый поток идёт по всему блоку данных
и берёт для агрегации только строки с нуждым номером корзины. и берёт для агрегации только строки с нуждым номером корзины.
Модификация: можно всё в одну стадию &mdash; тогда каждый поток Модификация: можно всё в одну стадию &mdash; тогда каждый поток
будет вычислять хэш-функцию от всех строк заново: будет вычислять хэш-функцию от всех строк заново:
подходит, если это дёшево. подходит, если это дёшево.
</section> </section>
<section class="slide"> <section class="slide">
<p> <p>
Достоинства: Достоинства:
+ хорошо масштабируется при большой кардинальности + хорошо масштабируется при большой кардинальности
и равномерном распределении ключей; и равномерном распределении ключей;
+ идейная простота. + идейная простота.
Недостатки: Недостатки:
&minus; если объём данных распределён неравномерно по ключам, &minus; если объём данных распределён неравномерно по ключам,
то стадия 2 плохо масштабируется. то стадия 2 плохо масштабируется.
Это типичный случай. Это типичный случай.
Почти всегда объём данных по ключам распределён по power law. Почти всегда объём данных по ключам распределён по power law.
Ещё недостатки: Ещё недостатки:
&minus; если размер блока маленький, то получается слишком &minus; если размер блока маленький, то получается слишком
мелко-гранулированная многопоточность: мелко-гранулированная многопоточность:
большой оверхед на синхронизацию; большой оверхед на синхронизацию;
&minus; если размер блока большой, то плохая кэш-локальность; &minus; если размер блока большой, то плохая кэш-локальность;
&minus; на второй стадии, часть memory bandwidth умножается на число потоков; &minus; на второй стадии, часть memory bandwidth умножается на число потоков;
&minus; нужно вычислять ещё одну хэш-функцию, &minus; нужно вычислять ещё одну хэш-функцию,
она должна быть независима от той, что в хэш-таблице;</p> она должна быть независима от той, что в хэш-таблице;</p>
</section> </section>
@ -238,7 +238,7 @@ O(M) работы выполняется последовательно
<p>Отресайзим полученные в разных потоках хэш-таблицы к одному размеру. <p>Отресайзим полученные в разных потоках хэш-таблицы к одному размеру.
Разобъём их неявно на разные подмножества ключей. Разобъём их неявно на разные подмножества ключей.
В разных потоках будем мержить соответствующие В разных потоках будем мержить соответствующие
подмножества ключей хэш-таблиц. подмножества ключей хэш-таблиц.
Рисунок на доске. Рисунок на доске.
@ -252,18 +252,18 @@ O(M) работы выполняется последовательно
<h2>4. Ordered мерж хэш-таблиц</h2> <h2>4. Ordered мерж хэш-таблиц</h2>
<p>Для open addressing linear probing хэш-таблиц, или для chaining хэш-таблиц, <p>Для open addressing linear probing хэш-таблиц, или для chaining хэш-таблиц,
данные в хэш-таблице расположены почти упорядоченно данные в хэш-таблице расположены почти упорядоченно
по остатку от деления хэш-функции на размер хэш-таблицы по остатку от деления хэш-функции на размер хэш-таблицы
&mdash; с точностью до цепочек разрешения коллизий. &mdash; с точностью до цепочек разрешения коллизий.
Отресайзим полученные в разных потоках хэш-таблицы к одному размеру. Отресайзим полученные в разных потоках хэш-таблицы к одному размеру.
Сделаем ordered iterator, который будет Сделаем ordered iterator, который будет
перебирать данные в хэш-таблице в фиксированном порядке. перебирать данные в хэш-таблице в фиксированном порядке.
Объём работы на итерирование: Объём работы на итерирование:
количество цепочек разрешения коллизий * средний квадрат длин цепочек. количество цепочек разрешения коллизий * средний квадрат длин цепочек.
Сделаем merging iterator, который с помощью heap (priority queue) Сделаем merging iterator, который с помощью heap (priority queue)
будет перебирать все хэш-таблицы разом. будет перебирать все хэш-таблицы разом.
</section> </section>
@ -279,9 +279,9 @@ O(M) работы выполняется последовательно
&minus; отвратительно сложный код; &minus; отвратительно сложный код;
&minus; для open addressing linear probing хэш-таблиц, &minus; для open addressing linear probing хэш-таблиц,
средний квадрат длин цепочек разрешения коллизий слишком большой; средний квадрат длин цепочек разрешения коллизий слишком большой;
&minus; priority queue тормозит; &minus; priority queue тормозит;
&minus; стадия мержа не распараллеливается* &minus; стадия мержа не распараллеливается*
@ -294,9 +294,9 @@ O(M) работы выполняется последовательно
<section class="slide"> <section class="slide">
<h2 style="font-size: 40px;">5. Robin Hood ordered мерж хэш-таблиц</h2> <h2 style="font-size: 40px;">5. Robin Hood ordered мерж хэш-таблиц</h2>
<p>Если использовать Robin Hood хэш-таблицу, то данные <p>Если использовать Robin Hood хэш-таблицу, то данные
(за исключением O(1) граничных цепочек разрешения коллизий) (за исключением O(1) граничных цепочек разрешения коллизий)
будут полностью упорядочены будут полностью упорядочены
по остатку от деления хэш-функции на размер хэш-таблицы. по остатку от деления хэш-функции на размер хэш-таблицы.
Достоинства: Достоинства:
@ -326,12 +326,12 @@ O(M) работы выполняется последовательно
Недостатки: Недостатки:
&minus; в типичном случае данные распределены сильно неравномерно, &minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей корзине. и потоки будут конкурировать на одной горячей корзине.
&minus; в случае маленькой хэш-таблицы, слишком тормозит. &minus; в случае маленькой хэш-таблицы, слишком тормозит.
Достоинства: если данные почему-то распределены равномерно, Достоинства: если данные почему-то распределены равномерно,
то кое-как масштабируется.</p> то кое-как масштабируется.</p>
</section> </section>
@ -341,11 +341,11 @@ O(M) работы выполняется последовательно
<p>Недостатки: <p>Недостатки:
&minus; spin-lock &mdash; это очень опасно; &minus; spin-lock &mdash; это очень опасно;
очень сложно тестировать производительность; очень сложно тестировать производительность;
вы обязательно сделаете отстой. вы обязательно сделаете отстой.
&minus; в типичном случае данные распределены сильно неравномерно, &minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей ячейке.</p> и потоки будут конкурировать на одной горячей ячейке.</p>
</section> </section>
@ -357,7 +357,7 @@ O(M) работы выполняется последовательно
&minus; lock free хэш-таблицы либо нельзя ресайзить, либо они очень сложные; &minus; lock free хэш-таблицы либо нельзя ресайзить, либо они очень сложные;
&minus; в типичном случае данные распределены сильно неравномерно, &minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей ячейке: и потоки будут конкурировать на одной горячей ячейке:
false sharing, тормоза. false sharing, тормоза.
@ -370,14 +370,14 @@ O(M) работы выполняется последовательно
<section class="slide"> <section class="slide">
<h2 style="font-size: 35px;">10. Shared хэш-таблица + thread local хэш-таблицы</h2> <h2 style="font-size: 35px;">10. Shared хэш-таблица + thread local хэш-таблицы</h2>
<p>Пытаемся положить в shared хэш-таблицу путём блокирования ячейки; <p>Пытаемся положить в shared хэш-таблицу путём блокирования ячейки;
если ячейка уже заблокирована &mdash; кладём к локальную хэш-таблицу. если ячейка уже заблокирована &mdash; кладём к локальную хэш-таблицу.
Тогда горячие ключи попадут в локальные хэш-таблицы. Тогда горячие ключи попадут в локальные хэш-таблицы.
Локальные хэш-таблицы будут маленькими. Локальные хэш-таблицы будут маленькими.
В конце мержим все локальные хэш-таблицы в глобальную. В конце мержим все локальные хэш-таблицы в глобальную.
Дополнения: можно сначала смотреть Дополнения: можно сначала смотреть
на наличие ключа в локальной хэш-таблице. на наличие ключа в локальной хэш-таблице.
Достоинства: Достоинства:
@ -387,7 +387,7 @@ O(M) работы выполняется последовательно
Недостатки: Недостатки:
&minus; много лукапов, много инструкций &mdash; в целом довольно медленно. &minus; много лукапов, много инструкций &mdash; в целом довольно медленно.
Даже не смотря на то, что thread local хэш-таблица Даже не смотря на то, что thread local хэш-таблица
зачастую ещё и cache local.</p> зачастую ещё и cache local.</p>
</section> </section>
@ -395,18 +395,18 @@ O(M) работы выполняется последовательно
<section class="slide"> <section class="slide">
<h2>11. Two-level хэш-таблица</h2> <h2>11. Two-level хэш-таблица</h2>
<p>На первой стадии, в каждом потоке независимо <p>На первой стадии, в каждом потоке независимо
кладём данные в свои num_buckets = 256 хэш-таблиц, кладём данные в свои num_buckets = 256 хэш-таблиц,
хранящих разные ключи. хранящих разные ключи.
В какую из них класть (номер корзины) В какую из них класть (номер корзины)
определяется другой хэш-функцией, определяется другой хэш-функцией,
либо отдельным байтом хэш-функции. либо отдельным байтом хэш-функции.
Имеем num_threads * num_buckets хэш-таблиц. Имеем num_threads * num_buckets хэш-таблиц.
На второй стадии мержим состояния На второй стадии мержим состояния
num_threads * num_buckets хэш-таблиц num_threads * num_buckets хэш-таблиц
в одни num_buckets хэш-таблиц, в одни num_buckets хэш-таблиц,
распараллеливая мерж по bucket-ам. распараллеливая мерж по bucket-ам.
</section> </section>
@ -427,13 +427,13 @@ num_threads * num_buckets хэш-таблиц
Недостатки: Недостатки:
&minus; при большой кардинальности, во время мержа &minus; при большой кардинальности, во время мержа
делается до такого же объёма работ как на первой стадии; делается до такого же объёма работ как на первой стадии;
&minus; при маленькой кардинальности, &minus; при маленькой кардинальности,
слишком много отдельных хэш-таблиц; слишком много отдельных хэш-таблиц;
&minus; при маленькой кардинальности, &minus; при маленькой кардинальности,
работает несколько медленнее тривиального способа;</p> работает несколько медленнее тривиального способа;</p>
</section> </section>
@ -453,7 +453,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide"> <section class="slide">
<h2>Много машин, много ядер</h2> <h2>Много машин, много ядер</h2>
<p>На разных машинах расположены части данных, <p>На разных машинах расположены части данных,
которые надо обработать. которые надо обработать.
Отличия от shared memory: Отличия от shared memory:
@ -466,7 +466,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide"> <section class="slide">
<h2>1. Тривиальный способ</h2> <h2>1. Тривиальный способ</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса. <p>Передаём промежуточные результаты на сервер-инициатор запроса.
Последовательно кладём всё в одну хэш-таблицу. Последовательно кладём всё в одну хэш-таблицу.
Достоинства: Достоинства:
@ -484,7 +484,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide"> <section class="slide">
<h2>2. Ordered merge</h2> <h2>2. Ordered merge</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса <p>Передаём промежуточные результаты на сервер-инициатор запроса
в заданном порядке. Мержим. в заданном порядке. Мержим.
Достоинства: Достоинства:
@ -501,15 +501,15 @@ num_threads * num_buckets хэш-таблиц
<section class="slide"> <section class="slide">
<h2>3. Partitioned merge</h2> <h2>3. Partitioned merge</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса, <p>Передаём промежуточные результаты на сервер-инициатор запроса,
разбитыми на отдельные согласованные корзины-партиции, разбитыми на отдельные согласованные корзины-партиции,
в заданном порядке корзин. в заданном порядке корзин.
Мержим по одной или по несколько корзин одновременно. Мержим по одной или по несколько корзин одновременно.
Достоинства: Достоинства:
+ тратится до в num_buckets раз меньше оперативки, чем размер результата; + тратится до в num_buckets раз меньше оперативки, чем размер результата;
+ можно легко распараллелить, мержа сразу несколько корзин + можно легко распараллелить, мержа сразу несколько корзин
&mdash; отлично масштабируется по ядрам. &mdash; отлично масштабируется по ядрам.
Недостатки: Недостатки:
@ -528,8 +528,8 @@ num_threads * num_buckets хэш-таблиц
<p>На удалённых серверах получаем промежуточные результаты, <p>На удалённых серверах получаем промежуточные результаты,
разбитые на согласованные партиции. разбитые на согласованные партиции.
Затем передаём партиции между серверами так, Затем передаём партиции между серверами так,
чтобы на разных серверах были разные партиции, чтобы на разных серверах были разные партиции,
а данные одной партиции оказались на одном сервере. а данные одной партиции оказались на одном сервере.
Мержим на всех серверах параллельно, да ещё и используя многие ядра. Мержим на всех серверах параллельно, да ещё и используя многие ядра.
@ -537,7 +537,7 @@ num_threads * num_buckets хэш-таблиц
Достоинства: Достоинства:
+ прекрасно масштабируется; + прекрасно масштабируется;
+ при INSERT SELECT, результат можно + при INSERT SELECT, результат можно
вовсе не передавать на сервер-инициатор, вовсе не передавать на сервер-инициатор,
а сразу сохранить в распределённую таблицу на кластере. а сразу сохранить в распределённую таблицу на кластере.
Недостатки: Недостатки:
@ -551,8 +551,8 @@ num_threads * num_buckets хэш-таблиц
<p style="font-size: 50px;">Можно задавать вопросы.</p> <p style="font-size: 50px;">Можно задавать вопросы.</p>
</section> </section>
<div class="progress"></div> <div class="progress"></div>
<script src="shower/shower.min.js"></script> <script src="shower/shower.min.js"></script>
</body> </body>

View File

@ -15,7 +15,7 @@
<section class="slide" id="cover"> <section class="slide" id="cover">
<h1 style="margin-top: 200px">ClickHouse meetup<br/>в Санкт-Петербурге</h1> <h1 style="margin-top: 200px">ClickHouse meetup<br/>в Санкт-Петербурге</h1>
</section> </section>
<section class="slide"> <section class="slide">
<h2>ClickHouse: настоящее и будущее</h2> <h2>ClickHouse: настоящее и будущее</h2>
</section> </section>
@ -33,7 +33,7 @@
</section> </section>
<section class="slide"> <section class="slide">
<h2>В предыдущих сериях</h2> <h2>В предыдущих сериях</h2>
<p>&mdash; HTTP и executable источники;</p> <p>&mdash; HTTP и executable источники;</p>
@ -136,7 +136,7 @@
<p>https://www.percona.com/blog/2017/02/13/clickhouse-new-opensource-columnar-database/</p> <p>https://www.percona.com/blog/2017/02/13/clickhouse-new-opensource-columnar-database/</p>
<img src="pictures/spark.png" style="height:60%"/> <img src="pictures/spark.png" style="height:60%"/>
</section> </section>
<section class="slide"> <section class="slide">
<h2>ClickHouse vs. Greenplum</h2> <h2>ClickHouse vs. Greenplum</h2>
<p><img src="pictures/greenplum.png" style="width:50%"/></p> <p><img src="pictures/greenplum.png" style="width:50%"/></p>

View File

@ -813,7 +813,7 @@ curl -sS 'http://localhost:8123/?max_result_bytes=4000000&amp;buffer_size=300000
- построение графиков, диаграмм и отображение геокоординат для результатов запросов; - построение графиков, диаграмм и отображение геокоординат для результатов запросов;
- интерактивный конструктор сводных таблиц (pivot) для результатов запросов; - интерактивный конструктор сводных таблиц (pivot) для результатов запросов;
- графические средства для анализа состояния ClickHouse; - графические средства для анализа состояния ClickHouse;
- два цветовых оформления: светлое и темное. - два цветовых оформления: светлое и темное.
<a href="https://tabix.io/doc/">Документация Tabix</a> <a href="https://tabix.io/doc/">Документация Tabix</a>

View File

@ -12,7 +12,7 @@
* Не парсит JSON до конца (парсит только часть, необходимую для выполнения вызванного метода). * Не парсит JSON до конца (парсит только часть, необходимую для выполнения вызванного метода).
* Парсинг необходимой части запускается каждый раз при вызове методов. * Парсинг необходимой части запускается каждый раз при вызове методов.
* Может работать с обрезанным JSON-ом. * Может работать с обрезанным JSON-ом.
* При этом, (в отличие от SAX-подобных парсеров), предоставляет удобные методы для работы. * При этом, (в отличие от SAX-подобных парсеров), предоставляет удобные методы для работы.
* *
* Эта структура данных более оптимальна, если нужно доставать несколько элементов из большого количества маленьких JSON-ов. * Эта структура данных более оптимальна, если нужно доставать несколько элементов из большого количества маленьких JSON-ов.
* То есть, подходит для обработки "параметров визитов" и "параметров интернет магазинов" в Яндекс.Метрике. * То есть, подходит для обработки "параметров визитов" и "параметров интернет магазинов" в Яндекс.Метрике.
@ -81,7 +81,7 @@ public:
}; };
ElementType getType() const; ElementType getType() const;
bool isObject() const { return getType() == TYPE_OBJECT; }; bool isObject() const { return getType() == TYPE_OBJECT; };
bool isArray() const { return getType() == TYPE_ARRAY; }; bool isArray() const { return getType() == TYPE_ARRAY; };
bool isNumber() const { return getType() == TYPE_NUMBER; }; bool isNumber() const { return getType() == TYPE_NUMBER; };
@ -138,7 +138,7 @@ public:
/// Класс JSON одновременно является итератором по самому себе. /// Класс JSON одновременно является итератором по самому себе.
using iterator = JSON; using iterator = JSON;
using const_iterator = JSON; using const_iterator = JSON;
iterator operator* () const { return *this; } iterator operator* () const { return *this; }
const JSON * operator-> () const { return this; } const JSON * operator-> () const { return this; }
bool operator== (const JSON & rhs) const { return ptr_begin == rhs.ptr_begin; } bool operator== (const JSON & rhs) const { return ptr_begin == rhs.ptr_begin; }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/** Пример: /** Пример:
* *
* class Derived : public Singleton<Derived> * class Derived : public Singleton<Derived>
* { * {
* friend class Singleton<Derived>; * friend class Singleton<Derived>;

View File

@ -183,7 +183,7 @@ JSON::ElementType JSON::getType() const
return TYPE_OBJECT; return TYPE_OBJECT;
case '[': case '[':
return TYPE_ARRAY; return TYPE_ARRAY;
case 't': case 't':
case 'f': case 'f':
return TYPE_BOOL; return TYPE_BOOL;
case 'n': case 'n':
@ -225,7 +225,7 @@ void JSON::checkPos(Pos pos) const
JSON::Pos JSON::skipString() const JSON::Pos JSON::skipString() const
{ {
//std::cerr << "skipString()\t" << data() << std::endl; //std::cerr << "skipString()\t" << data() << std::endl;
Pos pos = ptr_begin; Pos pos = ptr_begin;
checkPos(pos); checkPos(pos);
if (*pos != '"') if (*pos != '"')
@ -257,7 +257,7 @@ JSON::Pos JSON::skipString() const
if (*pos != '"') if (*pos != '"')
throw JSONException(std::string("JSON: expected \", got ") + *pos); throw JSONException(std::string("JSON: expected \", got ") + *pos);
++pos; ++pos;
return pos; return pos;
} }
@ -265,7 +265,7 @@ JSON::Pos JSON::skipString() const
JSON::Pos JSON::skipNumber() const JSON::Pos JSON::skipNumber() const
{ {
//std::cerr << "skipNumber()\t" << data() << std::endl; //std::cerr << "skipNumber()\t" << data() << std::endl;
Pos pos = ptr_begin; Pos pos = ptr_begin;
checkPos(pos); checkPos(pos);
@ -292,10 +292,10 @@ JSON::Pos JSON::skipNumber() const
JSON::Pos JSON::skipBool() const JSON::Pos JSON::skipBool() const
{ {
//std::cerr << "skipBool()\t" << data() << std::endl; //std::cerr << "skipBool()\t" << data() << std::endl;
Pos pos = ptr_begin; Pos pos = ptr_begin;
checkPos(pos); checkPos(pos);
if (*ptr_begin == 't') if (*ptr_begin == 't')
pos += 4; pos += 4;
else if (*ptr_begin == 'f') else if (*ptr_begin == 'f')
@ -310,7 +310,7 @@ JSON::Pos JSON::skipBool() const
JSON::Pos JSON::skipNull() const JSON::Pos JSON::skipNull() const
{ {
//std::cerr << "skipNull()\t" << data() << std::endl; //std::cerr << "skipNull()\t" << data() << std::endl;
return ptr_begin + 4; return ptr_begin + 4;
} }
@ -318,7 +318,7 @@ JSON::Pos JSON::skipNull() const
JSON::Pos JSON::skipNameValuePair() const JSON::Pos JSON::skipNameValuePair() const
{ {
//std::cerr << "skipNameValuePair()\t" << data() << std::endl; //std::cerr << "skipNameValuePair()\t" << data() << std::endl;
Pos pos = skipString(); Pos pos = skipString();
checkPos(pos); checkPos(pos);
@ -327,14 +327,14 @@ JSON::Pos JSON::skipNameValuePair() const
++pos; ++pos;
return JSON(pos, ptr_end, level + 1).skipElement(); return JSON(pos, ptr_end, level + 1).skipElement();
} }
JSON::Pos JSON::skipArray() const JSON::Pos JSON::skipArray() const
{ {
//std::cerr << "skipArray()\t" << data() << std::endl; //std::cerr << "skipArray()\t" << data() << std::endl;
if (!isArray()) if (!isArray())
throw JSONException("JSON: expected ["); throw JSONException("JSON: expected [");
Pos pos = ptr_begin; Pos pos = ptr_begin;
@ -366,7 +366,7 @@ JSON::Pos JSON::skipArray() const
JSON::Pos JSON::skipObject() const JSON::Pos JSON::skipObject() const
{ {
//std::cerr << "skipObject()\t" << data() << std::endl; //std::cerr << "skipObject()\t" << data() << std::endl;
if (!isObject()) if (!isObject())
throw JSONException("JSON: expected {"); throw JSONException("JSON: expected {");
Pos pos = ptr_begin; Pos pos = ptr_begin;
@ -374,7 +374,7 @@ JSON::Pos JSON::skipObject() const
checkPos(pos); checkPos(pos);
if (*pos == '}') if (*pos == '}')
return ++pos; return ++pos;
while (1) while (1)
{ {
pos = JSON(pos, ptr_end, level + 1).skipNameValuePair(); pos = JSON(pos, ptr_end, level + 1).skipNameValuePair();
@ -398,7 +398,7 @@ JSON::Pos JSON::skipObject() const
JSON::Pos JSON::skipElement() const JSON::Pos JSON::skipElement() const
{ {
//std::cerr << "skipElement()\t" << data() << std::endl; //std::cerr << "skipElement()\t" << data() << std::endl;
ElementType type = getType(); ElementType type = getType();
switch(type) switch(type)
@ -618,7 +618,7 @@ std::string JSON::getString() const
case 'u': case 'u':
{ {
Poco::UTF8Encoding utf8; Poco::UTF8Encoding utf8;
++s; ++s;
checkPos(s + 4); checkPos(s + 4);
std::string hex(s, 4); std::string hex(s, 4);

View File

@ -36,7 +36,7 @@ static time_t orderedIdentifierToDate(unsigned value)
void loop(time_t begin, time_t end, int step) void loop(time_t begin, time_t end, int step)
{ {
const auto & date_lut = DateLUT::instance(); const auto & date_lut = DateLUT::instance();
for (time_t t = begin; t < end; t += step) for (time_t t = begin; t < end; t += step)
{ {
time_t t2 = date_lut.makeDateTime(date_lut.toYear(t), date_lut.toMonth(t), date_lut.toDayOfMonth(t), time_t t2 = date_lut.makeDateTime(date_lut.toYear(t), date_lut.toMonth(t), date_lut.toDayOfMonth(t),
@ -44,9 +44,9 @@ void loop(time_t begin, time_t end, int step)
std::string s1 = toString(t); std::string s1 = toString(t);
std::string s2 = toString(t2); std::string s2 = toString(t2);
std::cerr << s1 << ", " << s2 << std::endl; std::cerr << s1 << ", " << s2 << std::endl;
if (s1 != s2) if (s1 != s2)
throw Poco::Exception("Test failed."); throw Poco::Exception("Test failed.");
} }

View File

@ -642,7 +642,7 @@ TEST(JSON_Suite, SimpleTest)
try try
{ {
JSON j(r.input.c_str(), r.input.c_str() + r.input.size()); JSON j(r.input.c_str(), r.input.c_str() + r.input.size());
ASSERT_EQ(j.getString(), r.result); ASSERT_EQ(j.getString(), r.result);
ASSERT_TRUE(r.result_type == ResultType::Return); ASSERT_TRUE(r.result_type == ResultType::Return);
} }

View File

@ -20,18 +20,18 @@ public:
template <typename T> using KeyValuePair = std::pair<std::string, T>; template <typename T> using KeyValuePair = std::pair<std::string, T>;
template <typename T> using KeyValueVector = std::vector<KeyValuePair<T>>; template <typename T> using KeyValueVector = std::vector<KeyValuePair<T>>;
template <typename T> void write(const std::string & key, const T & value, template <typename T> void write(const std::string & key, const T & value,
time_t timestamp = 0, const std::string & custom_root_path = "") time_t timestamp = 0, const std::string & custom_root_path = "")
{ {
writeImpl(KeyValuePair<T>{ key, value }, timestamp, custom_root_path); writeImpl(KeyValuePair<T>{ key, value }, timestamp, custom_root_path);
} }
template <typename T> void write(const KeyValueVector<T> & key_val_vec, template <typename T> void write(const KeyValueVector<T> & key_val_vec,
time_t timestamp = 0, const std::string & custom_root_path = "") time_t timestamp = 0, const std::string & custom_root_path = "")
{ {
writeImpl(key_val_vec, timestamp, custom_root_path); writeImpl(key_val_vec, timestamp, custom_root_path);
} }
/// возвращает путь root_path.server_name /// возвращает путь root_path.server_name
static std::string getPerServerPath(const std::string & server_name, const std::string & root_path = "one_min"); static std::string getPerServerPath(const std::string & server_name, const std::string & root_path = "one_min");
private: private:
@ -60,7 +60,7 @@ private:
template <typename T> template <typename T>
void out(std::ostream & os, const KeyValuePair<T> & key_val, time_t timestamp, const std::string & custom_root_path) void out(std::ostream & os, const KeyValuePair<T> & key_val, time_t timestamp, const std::string & custom_root_path)
{ {
os << (custom_root_path.empty() ? root_path : custom_root_path) << os << (custom_root_path.empty() ? root_path : custom_root_path) <<
'.' << key_val.first << ' ' << key_val.second << ' ' << timestamp << '\n'; '.' << key_val.first << ' ' << key_val.second << ' ' << timestamp << '\n';
} }

View File

@ -12,7 +12,7 @@ class Query;
/** Базовый класс для UseQueryResult и StoreQueryResult. /** Базовый класс для UseQueryResult и StoreQueryResult.
* Содержит общую часть реализации, * Содержит общую часть реализации,
* Ссылается на Connection. Если уничтожить Connection, то пользоваться ResultBase и любым результатом нельзя. * Ссылается на Connection. Если уничтожить Connection, то пользоваться ResultBase и любым результатом нельзя.
* Использовать объект можно только для результата одного запроса! * Использовать объект можно только для результата одного запроса!
* (При попытке присвоить объекту результат следующего запроса - UB.) * (При попытке присвоить объекту результат следующего запроса - UB.)

View File

@ -12,15 +12,15 @@ StoreQueryResult::StoreQueryResult(MYSQL_RES * res_, Connection * conn_, const Q
UInt32 fields = getNumFields(); UInt32 fields = getNumFields();
reserve(rows); reserve(rows);
lengths.resize(rows * fields); lengths.resize(rows * fields);
for (UInt64 i = 0; MYSQL_ROW row = mysql_fetch_row(res); ++i) for (UInt64 i = 0; MYSQL_ROW row = mysql_fetch_row(res); ++i)
{ {
MYSQL_LENGTHS lengths_for_row = mysql_fetch_lengths(res); MYSQL_LENGTHS lengths_for_row = mysql_fetch_lengths(res);
memcpy(&lengths[i * fields], lengths_for_row, sizeof(lengths[0]) * fields); memcpy(&lengths[i * fields], lengths_for_row, sizeof(lengths[0]) * fields);
push_back(Row(row, this, &lengths[i * fields])); push_back(Row(row, this, &lengths[i * fields]));
} }
checkError(conn->getDriver()); checkError(conn->getDriver());
} }
} }

View File

@ -16,7 +16,7 @@ class Foundation_API LevelFilterChannel: public Channel
public: public:
void log(const Message& msg); void log(const Message& msg);
/// Sends the given Message to all /// Sends the given Message to all
/// attaches channels. /// attaches channels.
void setProperty(const std::string& name, const std::string& value); void setProperty(const std::string& name, const std::string& value);
/// Sets or changes a configuration property. /// Sets or changes a configuration property.
@ -24,7 +24,7 @@ public:
/// Only the "level" property is supported, which allows setting desired level /// Only the "level" property is supported, which allows setting desired level
void setChannel(Channel* pChannel); void setChannel(Channel* pChannel);
/// Sets the destination channel to which the formatted /// Sets the destination channel to which the formatted
/// messages are passed on. /// messages are passed on.
Channel* getChannel() const; Channel* getChannel() const;
@ -33,10 +33,10 @@ public:
void open(); void open();
/// Opens the attached channel. /// Opens the attached channel.
void close(); void close();
/// Closes the attached channel. /// Closes the attached channel.
void setLevel(Message::Priority); void setLevel(Message::Priority);
/// Sets the Logger's log level. /// Sets the Logger's log level.
void setLevel(const std::string& value); void setLevel(const std::string& value);

View File

@ -1,29 +1,29 @@
// //
// LevelFilterChannel.cpp // LevelFilterChannel.cpp
// //
// $Id$ // $Id$
// //
// Library: Ext // Library: Ext
// Package: Logging // Package: Logging
// Module: LevelFilterChannel // Module: LevelFilterChannel
// //
// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
@ -70,7 +70,7 @@ void LevelFilterChannel::open()
_channel->open(); _channel->open();
} }
void LevelFilterChannel::close() void LevelFilterChannel::close()
{ {
if (_channel) if (_channel)

View File

@ -4,7 +4,7 @@
namespace zkutil namespace zkutil
{ {
class Increment class Increment
{ {
public: public:
@ -13,15 +13,15 @@ public:
{ {
zookeeper_holder->getZooKeeper()->createAncestors(path); zookeeper_holder->getZooKeeper()->createAncestors(path);
} }
size_t get() size_t get()
{ {
LOG_TRACE(log, "Get increment"); LOG_TRACE(log, "Get increment");
size_t result = 0; size_t result = 0;
std::string result_str; std::string result_str;
zkutil::Stat stat; zkutil::Stat stat;
bool success = false; bool success = false;
auto zookeeper = zookeeper_holder->getZooKeeper(); auto zookeeper = zookeeper_holder->getZooKeeper();
do do
@ -37,7 +37,7 @@ public:
} }
} }
while (!success); while (!success);
return result; return result;
} }
private: private:

View File

@ -8,7 +8,7 @@ int main()
{ {
auto zookeeper_holder = std::make_shared<zkutil::ZooKeeperHolder>(); auto zookeeper_holder = std::make_shared<zkutil::ZooKeeperHolder>();
zookeeper_holder->init("localhost:2181"); zookeeper_holder->init("localhost:2181");
zkutil::Lock l(zookeeper_holder, "/test", "test_lock"); zkutil::Lock l(zookeeper_holder, "/test", "test_lock");
std::cout << "check " << l.tryCheck() << std::endl; std::cout << "check " << l.tryCheck() << std::endl;
std::cout << "lock tryLock() " << l.tryLock() << std::endl; std::cout << "lock tryLock() " << l.tryLock() << std::endl;