MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / selectReadBuffer

Function selectReadBuffer

src/Storages/StorageFile.cpp:419–493  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

417}
418
419std::unique_ptr<ReadBuffer> selectReadBuffer(
420 const String & current_path,
421 bool use_table_fd,
422 int table_fd,
423 const struct stat & file_stat,
424 ContextPtr context)
425{
426 auto read_method = context->getSettingsRef()[Setting::storage_file_read_method];
427
428 /** Using mmap on server-side is unsafe for the following reasons:
429 * - concurrent modifications of a file will result in SIGBUS;
430 * - IO error from the device will result in SIGBUS;
431 * - recovery from this signal is not feasible even with the usage of siglongjmp,
432 * as it might require stack unwinding from arbitrary place;
433 * - arbitrary slowdown due to page fault in arbitrary place in the code is difficult to debug.
434 *
435 * But we keep this mode for clickhouse-local as it is not so bad for a command line tool.
436 */
437 if (context->getApplicationType() == Context::ApplicationType::SERVER && read_method == LocalFSReadMethod::mmap)
438 throw Exception(ErrorCodes::BAD_ARGUMENTS, "Using storage_file_read_method=mmap is not safe in server mode. Consider using pread.");
439
440 /// Avoid zero-length mmap: empty regular files still read as empty via `pread`, while
441 /// pseudo-files such as `/proc` and `/sys` may report `st_size == 0` despite readable content.
442 /// See #69070.
443 if (S_ISREG(file_stat.st_mode) && read_method == LocalFSReadMethod::mmap && file_stat.st_size > 0)
444 {
445 try
446 {
447 std::unique_ptr<ReadBufferFromFileBase> res;
448 if (use_table_fd)
449 res = std::make_unique<MMapReadBufferFromFileDescriptor>(table_fd, 0);
450 else
451 res = std::make_unique<MMapReadBufferFromFile>(current_path, 0);
452
453 ProfileEvents::increment(ProfileEvents::CreatedReadBufferMMap);
454 return res;
455 }
456 catch (const ErrnoException &)
457 {
458 /// Fallback if mmap is not supported.
459 ProfileEvents::increment(ProfileEvents::CreatedReadBufferMMapFailed);
460 }
461 }
462
463 std::unique_ptr<ReadBufferFromFileBase> res;
464 if (S_ISREG(file_stat.st_mode) && (read_method == LocalFSReadMethod::pread || read_method == LocalFSReadMethod::mmap))
465 {
466 if (use_table_fd)
467 res = std::make_unique<ReadBufferFromFileDescriptorPRead>(table_fd, context->getSettingsRef()[Setting::max_read_buffer_size]);
468 else
469 res = std::make_unique<ReadBufferFromFilePRead>(current_path, context->getSettingsRef()[Setting::max_read_buffer_size]);
470
471 ProfileEvents::increment(ProfileEvents::CreatedReadBufferOrdinary);
472 }
473 else if (read_method == LocalFSReadMethod::io_uring && !use_table_fd)
474 {
475#if USE_LIBURING
476 auto & reader = getIOUringReaderOrThrow(context);

Callers 1

createReadBufferFunction · 0.85

Calls 3

getApplicationTypeMethod · 0.80
ExceptionClass · 0.50
incrementFunction · 0.50

Tested by

no test coverage detected