Compare commits

...

872 Commits

Author SHA1 Message Date
Dani Tweig
5078a054d6 github: bug_report.yml: Improve bug report template structure
V1: Perform a yaml "face lift" on the old bug report md template, making bug reporting more efficient.

Add dedicated textarea fields for problem description and expected behavior
Include pre-filled placeholders to guide issue reporting
Add formatted log output section with shell syntax highlighting

V2: updated the contact details of scylla and performed some code cleanup.
2024-11-14 12:47:06 +02:00
Dani Tweig
8cc510a51b Update bug_report.yml
Perform a yaml "face lift" to the old bug report md template.
Asking to fill in addition to the former data details about reproduction steps and description of the problem.

Making bug reporting more efficient.
2024-11-11 16:03:53 +02:00
Yaron Kaikov
cc71077e33 .github/scripts/label_promoted_commits.py: only match the Close tag in the last line in the commit message
When a backport PR is promoted to the release branch, we automatically close the backport PR (since GitHub will only close the one based on the default branch) and update the labels in the original PRs

In a situation when we have multiple `closes` prefixes, the script will use the first one (which is not the correct one), see 3ddb61c90e

Fixing this by always using the last line with the `closes` prefix

Closes scylladb/scylladb#21498
2024-11-11 11:04:33 +02:00
Dani Tweig
381faa2649 Rename .github/ISSUE_TEMPLATE.md to .github/ISSUE_TEMPLATE/bug_report.yml
GitHub issue template process has changed.
The issue template file should be replaced and renamed.

Closes scylladb/scylladb#21518
2024-11-11 11:00:38 +02:00
Nikita Kurashkin
3032d8ccbf add check to refuse usage of DESC TABLE on a materialized view
Fixes #21026

Closes scylladb/scylladb#21500
2024-11-11 10:23:30 +02:00
Yaron Kaikov
2596d1577b ./github/workflows/add-label-when-promoted.yaml: Run auto-backport only on default branch
In https://github.com/scylladb/scylladb/pull/21496#event-15221789614
```
scylladbbot force-pushed the backport/21459/to-6.1 branch from 414691c to 59a4ccd Compare 2 days ago
```

Backport automation triggered by `push` but also should either start from `master` branch (or `enterprise` branch from Enterprise), we need to verify it by checking also the default branch.

Fixes: https://github.com/scylladb/scylladb/issues/21514

Closes scylladb/scylladb#21515
2024-11-11 09:16:35 +02:00
Pavel Emelyanov
57af69e15f Merge 'Add retries to the S3 client' from Ernest Zaslavsky
1. Add `retry_strategy` interface and default implementation for exponential back-off retry strategy.
2. Add new S3 related errors, also introduce additional errors to describe pure http errors that has no additional information in the body.
3. Add retries to the s3 client, all retries are coordinated by an instance of `retry_strategy`. In a case of error also parse response body in attempt to retrieve additional and more focused error information as suggested by AWS. See https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html. Introduce `aws_exception` to carry the original `aws_error`.
4. Discard whatever exception is thrown in `abort_upload` when aborting multipart upload since we don't care about cleanly aborting it since there are other means to clean up dangling parts, for example `rclone cleanup` or S3 bucket's Lifecycle Management Policy.
5. Add tests to cover retries, and retry exhaustion. Also add tests for jumbo upload.
6. Add the S3 proxy which is used to randomly inject retryable S3 errors to test the "retry" part of the S3 client. Switch the `s3_test` to use the S3 proxy. `s3_tests` set afloat `put_object` problem that was causing segmentation when retrying, fixed.
7. Extend the `s3_test` to use both `minio` and `proxy` configurations.
8. Add parameter to the proxy to seed the error injection randomization to make it replayable.

fixes: #20611
fixes: #20613

Closes scylladb/scylladb#21054

* github.com:scylladb/scylladb:
  aws_errors: Make error messages more verbose.
  test: Make the minio proxy randomization re-playable
  test/boost/s3_test: add error injection scenarios to existing test suite
  test: Switch `s3_test` to use proxy
  test: Add more tests
  client: Stop returning error on `DELETE` in multipart upload abortion
  client: Fix sigsegv when retrying
  client: Add retries
  client: Adjust `map_s3_client_exception` to return exception instance
  aws_errors: Change aws_error::parse to return std::optional<>
  aws_errors: Add http errors mapping into aws_error
  client: Add aws_exception mapping
  aws_error: Add `aws_exeption` to carry original `aws_error`
  aws_errors: Add new error codes
  client: Introduce retry strategy
2024-11-11 08:35:55 +03:00
Takuya ASADA
92af373fab unified: drop scylla-tools from unified package
On b8634fb, we dropped scylla-tools from rpm and deb, we should drop it
from unified package as well.

Closes #20739

Closes scylladb/scylladb#20740
2024-11-10 12:56:43 +02:00
Avi Kivity
b58dbe57aa Merge 'repair: introduce and use buffer size hint for mixed-shard multishard reader' from Botond Dénes
Add a buffer hint to the multishard reader. This is an internal hint, used by the multishard reader to provide a hint to the shard reader, on how much data exactly is needed by the multishard reader from the respective shard. This hint allows eliminating extraneous cross-shard round-trips and possible shard reader evict-recreate cycles. Building on this, repair sets its own row buffer size as the max buffer size on the multishard reader, ensuring that the row buffer is filled with the minimum amount of cross-shard round trips and minimal reader recreation.
To further eliminate unnecessary evictions, this PR also disables the multishard reader's read-ahead which is a mechanism that was designed to reduce latency for user-reads but it can be too aggressive for repair, causing unnecessary extra congestion on the already struggling streaming semaphores.

Refs: https://github.com/scylladb/scylladb/issues/18269
Fixes: https://github.com/scylladb/scylladb/issues/21113

The performance impact was measured with an SCT test, which creates a cluster of 3 nodes with 16 shards, then adds a 4th one with 12 shards.
Currently, it is the bootstrap time which is the worse in the case of mixed shard clusters, see below for the improvement measured during bootstrap:

|              | master        | buffer-hint   | metric                                              |
| ------------ | ------------- | ------------- | --------------------------------------------------- |
| evictions    |          0.9M |         93.0K | scylla_database_paused_reads_permit_based_evictions |
| read (bytes) |          9.0T |          3.9T | scylla_reactor_aio_bytes_read                       |
| read (ops)   |         88.0M |         33.5M | scylla_reactor_aio_reads                            |
| time         |         56min |         20min | N/A                                                 |

This is a performance improvement, no backport required.

Closes scylladb/scylladb#20815

* github.com:scylladb/scylladb:
  test/boost/mutation_reader_test: add test for multishard reader buffer hint
  repair/row_level: disable read-ahead
  db/config: introduce repair_multishard_reader_enable_read_ahead
  readers/multishard: implement the read_ahead flag
  replica/database: make_multishard_streaming_reader(): expose the read_ahead parameter
  readers/multishard: add read_ahead parameter
  repair/row_level: set max buffer size on multishard reader
  replica/database: make_multishard_streaming_reader(): expose buffer_hint parameter
  db/config: introduce enable_repair_multishard_reader_buffer_hint
  readers/multishard: multishard_reader: pass hint to shard_reader
  readers/multishard: shard_reader_v2::fill_reader_buffer(): respect the hint
  readers/multishard: propagate fill_buffer_hint to shard_reader:fill_reader_buffer()
  readers/multishard: shard_reader: extract buffer-fill into its own method
2024-11-10 12:55:19 +02:00
Kefu Chai
961a53f716 dist: systemd: use default KillMode
before this change, we specify the KillMode of the scylla-service
service unit explicitly to "process". according to
according to
https://www.freedesktop.org/software/systemd/man/latest/systemd.kill.html,

> If set to process, only the main process itself is killed (not recommended!).

and the document suggests use "control-group" over "process".
but scylla server is not a multi-process server, it is a multi-threaded
server. so it should not make any difference even if we switch to
the recommended "control-group".

in the light that we've been seeing "defunct" scylla process after
stopping the scylla service using systemd. we are wondering if we should
try to change the `KillMode` to "control-group", which is the default
value of this setting.

in this change, we just drop the setting so that the systemd stops the
service by stopping all processes in the control group of this unit
are stopped.

Refs scylladb/scylladb#21507

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21508
2024-11-09 20:07:11 +02:00
Kefu Chai
1f940d56b2 build: cmake: s/idle_compiler/idl_compiler/
before this change, the header files generated with `idl-compiler.py`
are not regenerated if `idl-compiler.py` is updated. but they should,
as the change to the script could in turn change the generated header
files. because we have a typo in the `DEPENDS` argument,
`${idle_compiler}` is expanded to an empty string.

in this change, the typo is corrected, and the dependency from the
generated headers to the script is correctly reflected in the building
rules.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21475
2024-11-09 20:06:23 +02:00
Piotr Dulikowski
7021efd6b0 Merge 'main,cql_test_env: start group0_service before view_builder' from Michał Jadwiszczak
In scylladb/scylladb#19745, view_builder was migrated to group0 and since then it is dependant on group0_service.
Because of this, group0_service should be initialized/destroyed before/after view_builder.

This patch also adds error injection to `raft_server_with_timeouts::read_barrier`, which does 1s sleep before doing the read barrier. There is a new test which reproduces the use after free bug using the error injection.

Fixes scylladb/scylladb#20772

scylladb/scylladb#19745 is present in 6.2, so this fix should be backported to it.

Closes scylladb/scylladb#21471

* github.com:scylladb/scylladb:
  test/boost/secondary_index_test: add test for use after free
  api/raft: use `get_server_with_timeouts().read_barrier()` in coroutines
  main,cql_test_env: start group0_service before view_builder
2024-11-08 20:27:09 +01:00
Kefu Chai
aebb532906 bytes, utils: include fmt/iostream.h and iostream when appropriate
in seastar e96932b05f394b27cd0101e24f0584736795b50f, we stopped
including unused `fmt/ostream.h`. this helped to reduce the header
dependency. but this also broke the build of scylladb, as we rely
on the `fmt/ostream.h` indirectly included by seastar's header project.

in this change, we include `fmt/iostream.h` and `iostream` explictly
when we are using the declarations in them. this enables us to

- bump up the seastar submodule
- potentially reduce the header dependency as we will be able to
  include seastar/core/format.hh instead of a more bloated
  seastar/core/print.hh after bumping up seastar submodule

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21494
2024-11-08 16:43:25 +03:00
Michał Jadwiszczak
f998f027a2 test/boost/secondary_index_test: add test for use after free
Reproduces scylladb/scylladb#20772.

Add error injection to `raft_server_with_timeouts::read_barrier`,
which does 1s sleep before doing the read barrier.
2024-11-08 14:16:19 +01:00
Michał Jadwiszczak
de7b58e8d4 api/raft: use get_server_with_timeouts().read_barrier() in coroutines
It is unsafe to do `get_server_with_timeouts().read_barrier()` in
continuations because `get_server_with_timeouts()` returns
raft server by value and it may be deallocated when `read_barrier()` yields,
causing use-after-return.

Simple workaround is to use the read barrier in coroutine and co_await
it. Then the raft server is kept on stack until the read barrier is
finished.

I've checked all codebase and it looks like the only place where
`group0_with_timeouts().read_barrier()` is in continuation, is
api/raft.cc.

Co-authored-by: Piotr Dulikowski <piodul@scylladb.com>
2024-11-08 14:15:13 +01:00
Botond Dénes
e3e8a94c9a Merge 'Allow explicitly enabling or disabling tablets when creating a new keyspace' from Benny Halevy
Separate the configuration for enabling the tablets feature from the enablement of tablets when creating new keyspaces.

This change always enables the TABLETS cluster feature and the tablets logic respectively.

The `enable_tablets` config option just controls whether tablets are enabled or disabled by default for new keyspaces.

If `enable_tablets` is set to `true`, tablets can be disabled using `CREATE KEYSPACE WITH tablets = { 'enabled': false }` as it is today.

If `enable_tablets` is set to `false`, tablets can be enabled using `CREATE KEYSPACE WITH tablets = { 'enabled': true }`.

The motivation for this change is to simplify the user experience of using tablets by setting the default for new keyspaces to false amd allowing the user to simply opt-in by using tablets = {enabled: true }.
This is not pissible today.
The user has to enable tablets by default for all new keyspaces (that use the NetworkTopologyStrategy) and then actively opt-out to use vnodes.

* Not required to be backported to OSS versions.  May be backported to specific enterprise versions

* This PR resubmits https://github.com/scylladb/scylladb/pull/20729 that was reverted in 73b1f66b70 due to https://github.com/scylladb/scylladb/issues/21159 which is now fixed

Closes scylladb/scylladb#21451

* github.com:scylladb/scylladb:
  data_dictionary: keyspace_metadata::describe: print tablets enabled also when defaulted
  tablets_test: test enable/disable tablets when creating a new keyspace
  treewide: always allow tablets keyspaces
  feature_service: prevent enabling both tablets and gossip topology changes
  alternator: create_keyspace_metadata: enable tablets using feature_service
2024-11-08 09:15:42 +02:00
Michał Chojnowski
35921eb67e mvcc_test: fix a benign failure of test_apply_to_incomplete_respects_continuity
For performance reasons, mutation_partition_v2::maybe_drop(), and by extension
also mutation_partition_v2::apply_monotonically(mutation_partition_v2&&)
can evict empty row entries, and hence change the continuity of the merged
entry.

For checking that apply_to_incomplete respects continuity,
test_apply_to_incomplete_respects_continuity obtains the continuity of
the partition entry before and after apply_to_incomplete by calling
e.squashed().get_continuity(). But squashed() uses apply_monotonically(),
so in some circumstances the result of squashed() can have smaller
continuity than the argument of squashed(), which messes with the thing
that the test is trying to check, and causes spurious failures.

This patch changes the method of calculating the continuity set,
so that it matches the entry exactly, fixing the test failures.

Fixes scylladb/scylladb#13757

Closes scylladb/scylladb#21459
2024-11-08 06:08:39 +01:00
Ernest Zaslavsky
029837a4a1 aws_errors: Make error messages more verbose.
Add more information to the error messages to make the failure reason clearer. Also add tests to check exceptions propagated from s3 client failure.
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
14f3832749 test: Make the minio proxy randomization re-playable
Provide a seed to the proxy randomization, the idea that the `test.py` will initialize the seed from `/dev/urandom` and print the seed when starting, in case some tests failed the dev is supposed to re-play it locally with the same seed (if it didnt repro otherwise) using the `start_s3_proxy.py` and providing it with the aforementioned seed using `--rnd-seed` command line argument
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
0c62635f05 test/boost/s3_test: add error injection scenarios to existing test suite
Add variants of existing S3 tests that route through a proxy instead of connecting directly to MinIO. The proxy allows injecting errors to validate error handling and recovery mechanisms under failure conditions.
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
8919e0abab test: Switch s3_test to use proxy
Switch `s3_test` to use the S3 proxy which is used to randomly inject retryable S3 errors to test the "retry" part of the S3 client.
Fix `put_object` to make it retryable
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
b1e36c868c test: Add more tests
Add tests to cover retries, and retry exhaustion. Also add tests for jumbo upload.
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
7fd1ff8d79 client: Stop returning error on DELETE in multipart upload abortion
Discard whatever exception is thrown in `abort_upload` when aborting multipart upload since we don't care about cleanly aborting it since there are other means to clean up dangling parts, for example `rclone cleanup` or S3 bucket's Lifecycle Management Policy
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
064a239180 client: Fix sigsegv when retrying
Stop moving the `file` into the `make_file_input_stream` since it will try to use it again on retry
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
dc6e4c0d97 client: Add retries
Add retries to the s3 client, all retries are coordinated by an instance of `retry_strategy`. In a case of error also parse response body in attempt to retrieve additional and more focused error information as suggested by AWS. See https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html.

Also move the expected http status check to the `make_s3_error_handler` since the http::client::make_request call is done with `nullopt` - we want to manage all the aws errors handling in s3 client to prevent the http client to validate it and fail before we have a chance to analyze the error properly
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
244635ebd8 client: Adjust map_s3_client_exception to return exception instance
"Unfuturize" the `map_s3_client_exception` since the retryable client is going to be implemented using coroutines and no `future` is needed here, just to save unnecessary `co_await` on it
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
bd3d4ed417 aws_errors: Change aws_error::parse to return std::optional<>
Change aws_error::parse to return std::optional<> to signify that no error was found in the response body
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
58decef509 aws_errors: Add http errors mapping into aws_error
Add http errors mapping into aws_error since the retry strategy is going to operate on aws_error and should not be aware of HTTP status codes
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
fa9e8b7ed0 client: Add aws_exception mapping
Map aws_exceptions in `map_s3_client_exception`, will be needed in retryable client calls to remap newly added  AWS errors to `storage_io_error`
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
54e250a6f1 aws_error: Add aws_exeption to carry original aws_error
Add `aws_exeption` to carry original `aws_error` for proper error handling in retryable s3 client
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
e6ff34046f aws_errors: Add new error codes
Add new S3 related errors, also introduce additional errors to describe pure http errors that has no additional information in the body
2024-11-07 21:01:25 +02:00
Ernest Zaslavsky
8dbe351888 client: Introduce retry strategy
Add `retry_strategy` interface and default implementation for exponential back-off retry strategy
2024-11-07 21:01:25 +02:00
Michał Jadwiszczak
7bad8378c7 main,cql_test_env: start group0_service before view_builder
In scylladb/scylladb#19745, view_builder was migrated to group0
and since then it is dependent on group0_service.
Because of this, group0_service should be initialized/destroyed
before/after view_builder.

Fixes scylladb/scylladb#20772

Co-authored-by: Dawid Mędrek <dawid.medrek@scylladb.com>
2024-11-07 14:08:11 +01:00
Kamil Braun
c268cf2e33 Merge 'test: rename "cql-pytest" to "cqlpy"' from Nadav Har'El
Python and Python developers don't like directory names to include a  minus sign, like "cql-pytest". In this patch we rename test/cql-pytest to test/cqlpy, and also change a few references in other code (e.g., code that used test/cql-pytest/run.py) and also references to this test suite in documentation and comments.

Arguably, the word "test" was always redundant in test/cql-pytest, and I want to leave the "py" in test/cqlpy to emphasize that it's Python-based tests, contrasting with test/cql which are CQL-request-only approval tests.

The second patch in the series fixes a small regression in the test/cqlpy/run script.

Fixes #20846

Test organization only, so backports not strictly necessary, but let's do them anyway because otherwise it will make any future backporting of tests in the cqlpy directory more messy than it needs to be.

Closes scylladb/scylladb#21446

* github.com:scylladb/scylladb:
  test/cqlpy: fix "run" script without any parameters
  test: rename "cql-pytest" to "cqlpy"
2024-11-07 13:26:07 +01:00
Benny Halevy
40928bd886 data_dictionary: keyspace_metadata::describe: print tablets enabled also when defaulted
Now that tablets may be explicitly enabled when
creating a new keyspace, describe tablets as enabled
even when the default initial_tablets==0 is used.

Refs https://github.com/scylladb/scylla-enterprise/issues/4860

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-07 13:59:59 +02:00
Benny Halevy
8620d9f672 tablets_test: test enable/disable tablets when creating a new keyspace
Test both configuration values for `enable_tablets`
and the possibility to explicitly enable or disable
tablets, respectively, when creating a keyspace using the
`tablets = {'enabled': true|false}` CREATE KEYSPACE option.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-07 13:57:40 +02:00
Benny Halevy
4b21cca443 treewide: always allow tablets keyspaces
With the tablets feature always enabled (Unless gossip toopology
changes are forced), the enable_tablets option now controls only
the default for newly created keyspaces.

Even when set to `false`, tablets are still enabled as a
feature and the user may explicitly enable tablets
using `CREATE KEYSPACE <name> WITH tablets = {'enabled': true}`

Note: best viewed with `git show -w`

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-07 13:57:39 +02:00
Benny Halevy
974b0f2080 feature_service: prevent enabling both tablets and gossip topology changes
Tablets require raft consistent topology changes.
Therefore, document that they are incompatible in
the config help and prevent their usage in
`feature_config_from_db_config`

Fixes scylladb/scylladb#21075

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-07 13:56:59 +02:00
Benny Halevy
4cf3b683bc alternator: create_keyspace_metadata: enable tablets using feature_service
Rather than using the local configuration option
on this node, check the cluster feature instead.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-07 13:56:59 +02:00
Botond Dénes
e21346179c test/boost/mutation_reader_test: add test for multishard reader buffer hint 2024-11-07 02:47:54 -05:00
Botond Dénes
5c5c77746e repair/row_level: disable read-ahead
The multishard reader's read-ahead was designed to reduce the latency of
range scans. But in the case of repair, read-ahead is suspected to
contribute significant extra load on the congested streaming semaphore
and thus contribute to the subsequent trashing (excessive reader
eviction).
First off, read-ahead was designed with pages of limited size in mind.
Repair can read much more, even for a single repair buffer. This can
lead to read-ahead concurrency to continue ramping up, creating and
using more and more readers.
Secondly, repair is not latency sensitive, so even when working well and
there is no congestion, the benefits are negligible.

The use of read-ahead is now controllable by the new
repair_multishard_reader_enable_read_ahead config item, defaulting to
false.
2024-11-07 02:47:54 -05:00
Botond Dénes
a248520201 db/config: introduce repair_multishard_reader_enable_read_ahead
Not used yet.
2024-11-07 02:47:54 -05:00
Botond Dénes
36a8756028 readers/multishard: implement the read_ahead flag
Don't do read-aheads when read-ahead was not enabled.
2024-11-07 02:47:54 -05:00
Botond Dénes
8938e06ebe replica/database: make_multishard_streaming_reader(): expose the read_ahead parameter
Continuing the previous patch, expose the just added read_ahead
parameter of make_multishard_combining>_reader_v2().
Set to read_ahead::yes by all callers, keeping the current default.
2024-11-07 02:47:54 -05:00
Botond Dénes
c6c62deaa5 readers/multishard: add read_ahead parameter
And propagate to the reader itself. Not used yet.
2024-11-07 02:47:54 -05:00
Botond Dénes
784f89f585 repair/row_level: set max buffer size on multishard reader
The multishard reader is used in the mixed-shard case, when a repair has
to read from all other shards. It is very important that cross-shard
roundtrips and possible evict-recreate cycles for the shard readers is
avoided. For this end, make use of the recently introduced internal
buffer hint feature in the multishard reader and set it's buffer size to
match that of the row level repair buffer size.

The use of the buffer-hint can be controlled with the recently
introduced repair_multishard_reader_buffer_hint_size config param.
2024-11-07 02:47:54 -05:00
Botond Dénes
e2344e28b6 replica/database: make_multishard_streaming_reader(): expose buffer_hint parameter
Expose the buffer hint functionality added by the previous commits, to
callers of make_multishard_streaming_reader(). All callers disable it
currently, it will be used in the next patch.
2024-11-07 02:47:46 -05:00
Yaron Kaikov
ef104b7b96 .github/scripts/auto-backport.py: update method to get closed prs
`commit.get_pulls()` in PyGithub returns pull requests that are directly associated with the given commit

Since in closed PR. the relevant commit is an event type, the backport
automation didn't get the PR info for backporting

Ref: https://github.com/scylladb/scylladb/issues/18973

Closes scylladb/scylladb#21468
2024-11-07 09:28:46 +02:00
Avi Kivity
9e67649fe5 utils: loading_cache: tighten clock sampling
Sample the clock once to avoid the filter returning different results.

Range algorithms may use multiple passes, so it's better to return
consistent results.

Closes scylladb/scylladb#21400
2024-11-07 10:28:01 +03:00
Kefu Chai
50fbab29ca compaction: remove unused "#include"
we don't use `std::list` in compaction/compaction_manager.hh, neither
is this header responsible for exposing the declarations in `<list>`.
so let's stop `#include` this header.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21436
2024-11-07 10:25:27 +03:00
Avi Kivity
f5489ba4a1 locator: tablet_metadata_guard: forward declare database
No need to bring in a heavy databas.hh dependency.

Closes scylladb/scylladb#21447
2024-11-07 10:24:35 +03:00
Kefu Chai
ba021f72a6 api: s/mulformatted/malformatted
mulformatted was a typo, let's fix it.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21442
2024-11-07 10:07:11 +03:00
Pavel Emelyanov
49949092ad Merge 'Make s3 client ops use abort source + use in backup task' from Calle Wilund
Fixes #20716

Adds optional abort_source to all s3 client operations. If provided, will propagate to actual HTTP client and allow for aborting actual net op.

Note: this uses an abort source per call, not a client-local one.
This is for two reasons:

1.) The usage pattern of the client object is to create it outside the eventual owning object (task) that hosts the relevant abort source
2.) It is quite possible to want to have different/no abort source for some operation usage.

Also adds forward usage of task abort_source in backup tasks upload s3 call, making it more readily abort-able.

Closes scylladb/scylladb#21431

* github.com:scylladb/scylladb:
  backup_task: Use task abort source in s3 client call
  s3::client: Make operations (individually) abortable
2024-11-07 10:03:25 +03:00
Yaron Kaikov
9d8562caf3 Add conflict_reminder action for backport PR
In order not to forget to resolve conflicts in backport PRs, we should add some reminders to the PR author so it will not be forgotten

the new action will run twice a week and will send a reminder only for
PR opened with conflicts for 3 days or more

Fixes: https://github.com/scylladb/scylladb/issues/21448

Closes scylladb/scylladb#21449
2024-11-07 06:55:37 +02:00
Calle Wilund
0db4b9fd94 backup_task: Use task abort source in s3 client call
Fixes #20716

Propagates abort source in task object to actual network call,
thus making the upload workload more quickly abortable.

v2: Fix test to handle two versions after each other
2024-11-06 15:20:23 +00:00
Nadav Har'El
1fd7b797c7 test/cqlpy: fix "run" script without any parameters
A recent improvement to test/cqlpy/run to add the "--release" option
broke the ability to run this script it without *any* options (no test
name, etc.). This patch fixes this case.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-11-06 16:48:36 +02:00
Nadav Har'El
8c215141a1 test: rename "cql-pytest" to "cqlpy"
Python and Python developers don't like directory names to include a
minus sign, like "cql-pytest". In this patch we rename test/cql-pytest
to test/cqlpy, and also change a few references in other code (e.g., code
that used test/cql-pytest/run.py) and also references to this test suite
in documentation and comments.

Arguably, the word "test" was always redundant in test/cql-pytest, and
I want to leave the "py" in test/cqlpy to emphasize that it's Python-based
tests, contrasting with test/cql which are CQL-request-only approval
tests.

Fixes #20846

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-11-06 16:48:36 +02:00
Kefu Chai
6efde20939 utils/to_string: do not include fmt/ostream.h
to_string.hh does not use this header, neither is it obliged to
expose the content of this header. so, let's remove this include.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21440
2024-11-06 17:21:29 +03:00
Botond Dénes
3c25e6fcb4 db/config: introduce enable_repair_multishard_reader_buffer_hint
Allows enabling/disabling the multishard reader buffer hint
optimization. Not wired yet.
2024-11-06 08:51:00 -05:00
Botond Dénes
b052c5df62 readers/multishard: multishard_reader: pass hint to shard_reader
Calculate a buffer fill hint and pass it to
shard_reader_v2::fill_buffer(), so the underlying buffer-fill can be
optimized to avoid multiple cross shard round-trips, as well as possible
evict-recreate cycles.
The buffer hint mechanism is opt-in, enabled via the new
multishard_reader_buffer_hint parameter.
2024-11-06 08:51:00 -05:00
Botond Dénes
912b4dfba3 readers/multishard: shard_reader_v2::fill_reader_buffer(): respect the hint
When the hint is provided, respect it: make sure the returned buffer is
of the requested size, stopping early if the stop_token is seen.
To reduce the amount of possible eviction-recreate cycles while the
buffer is filled, disable auto-pause for the duration of the
fill_reader_buffer() call. For this purpose, auto_pause_disable_guard is
added to evictable_reader_v2.
2024-11-06 08:51:00 -05:00
Botond Dénes
8d5283f036 readers/multishard: propagate fill_buffer_hint to shard_reader:fill_reader_buffer()
The hint will tell the shard reader exactly how much data to produce, to
avoid multiple cross-shard round-trips and possible evict-recreate
cycles.

The hint is neither used yet or calculated yet, this is coming in the
next patches.
2024-11-06 08:51:00 -05:00
Botond Dénes
ee7ecb9155 readers/multishard: shard_reader: extract buffer-fill into its own method
It is about to get a bit more complicated, so worth to extract into a
method so it can be shared by the two call-sites.
2024-11-06 08:51:00 -05:00
Tomasz Grabiec
f7d35d535e Merge 'bytes_ostream: replace boost ranges with std ranges' from Avi Kivity
To reduce the dependency load, replace boost ranges with std::ranges.

Cleanup; no backport.

Closes scylladb/scylladb#21450

* github.com:scylladb/scylladb:
  bytes_ostream: replace boost ranges with std ranges
  bytes_ostream: extract fragment_iterator into namespace scope
2024-11-06 14:01:27 +01:00
Yaron Kaikov
77604b4ac7 .github/script/auto-backport.py: push backport PR to scylladbbot fork
Since Scylla is a public repo, when we create a fork, it doesn't fork the team and permissions (unlike private repos where it does).

When we have a backport PR with conflicts, the developers need to be able to update the branch to fix the conflicts. To do so, we modified the logic of the backport automation as follows:

- Every backport PR (with and without conflicts) will be open directly on the `scylladbbot` fork repo
- When there are conflicts, an email will be sent to the original PR author with an invitation to become a contributor in the `scylladbbot` fork with `push` permissions. This will happen only once if Auther is not a contributor.
- Together with sending the invite, all backport labels will be removed and a comment will be added to the original PR with instructions
- The PR author must add the backport labels after the invitation is accepted

Fixes: https://github.com/scylladb/scylladb/issues/18973

Closes scylladb/scylladb#21401
2024-11-06 14:29:37 +02:00
David Garcia
a072478f4f docs: enable tooltips
Updates the theme to the latest version to enable tooltips and modifies the db_options.tmpl to show the new role in action.

Closes scylladb/scylladb#21324
2024-11-06 14:09:28 +02:00
Andrei Chekun
afd1fc8e9f test.py: Add pytest-xdist to the toolchain
Add new dependency pytest-xdist to the toolchain. This will allow executing
boost and unit tests from pytest in parallel, reducing the time
needed for the run.

Closes scylladb/scylladb#21222
2024-11-06 14:09:01 +02:00
Botond Dénes
0ad32c153d Merge 'test_tablets: add rack decommission test cases' from Benny Halevy
test_tablets: add rack decommission test cases

Test scenarios where decommissioing a compelte rack
should succeed, and reproduce scylladb/scylladb#19475
where decommissioning a rack would fail since the
number of remaining racks is insufficient to satisfy
the replication factor, even though the number of nodes
is sufficient, enshrining this behavior.

Refs scylladb/scylladb#19475

* This PR adds unit tests and improves an error message.  No backport required.

Closes scylladb/scylladb#20747

* github.com:scylladb/scylladb:
  tablet_allocator: improve error message when unable to find replicas when draining
  test_tablets: add rack decommission test cases
  topology_experimental_raft/test_tablets: get_tablet_count_per_shard_for_host: move shards_count param to be last
  test/pylib: ServerInfo: add datacenter and rack attributes
  test: everywhere: drop unused imports of ServerInfo
2024-11-06 14:07:47 +02:00
Calle Wilund
3321820c67 s3::client: Make operations (individually) abortable
Refs #20716

Adds optional abort_source to all s3 client operations. If provided, will
propagate to actual HTTP client and allow for aborting actual net op.

Note: this uses an abort source per call, not a client-local one.
This is for two reasons:

1.) The usage pattern of the client object is to create it outside the
    eventual owning object (task) that hosts the relevant abort source
2.) It is quite possible to want to have different/no abort source for
    some operation usage.
2024-11-05 14:23:24 +00:00
Avi Kivity
8fb6d98ba3 Merge "various gossiper code cleanups" from Gleb
* 'gleb/gossip-cleanup-v3' of github.com:scylladb/scylla-dev:
  gossiper: start failure_detector_loop on shard 0 only
  gossiper: use 1 seconds instead of 1000 milliseconds
  gossiper: remove unused code
  gossiper: co-routinize do_send_ack2_msg
  gossiper: do not needlessly call get_endpoint_state_ptr in handle_major_state_change
  gossiper: fix weird logic in get_live_members
  gossiper: drop unneeded this->
  gossiper: fold get_or_create_endpoint_state into my_endpoint_state
  gossiper: co-routinize do_send_ack_msg
2024-11-05 15:31:58 +02:00
Avi Kivity
baaa92c6f5 bytes_ostream: replace boost ranges with std ranges
Have fragment_iterator support iterator_concept for compatibility with
std ranges, and switch from boost iterator_range to std::ranges::subrange.
2024-11-05 14:50:38 +02:00
Avi Kivity
cb026c347e bytes_ostream: extract fragment_iterator into namespace scope
C++ concept evaluation rules clash with nested class definition rules
with the result that evaluating concepts about the nested class within
the enclosing class doesn't work. Extract bytes_ostream::fragment_iterator
to avoid that.
2024-11-05 14:43:49 +02:00
Avi Kivity
4dab2473a2 Merge 'treewide: trade boost's any_of and all_of for std's any_of and all_of' from Kefu Chai
now that we are allowed to use C++23. we now have the luxury of using
`std::ranges::all_of` and `std::ranges::any_of`

in this change, we replace `boost::algorithm::all_of` and `boost::algorithm::any_of` with
`std::ranges::all_of` and `std::ranges::any_of` respectively.

to reduce the dependency to boost for better maintainability, and leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase and reduce external dependencies where possible.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#21411

* github.com:scylladb/scylladb:
  treewide: s/boost::algorithm::any_of/std::ranges::any_of/
  treewide: s/boost::algorithm::all_of/std::ranges::all_of/
2024-11-05 12:48:24 +02:00
Piotr Dulikowski
7f17894c88 Merge 'cql3: Allow for describing CDC log tables' from Dawid Mędrek
In the past, DESC SCHEMA would produce create statements for both the base
and the log table. That was incorrect as the log table is automatically
created alongside the base one. That was solved in scylladb/scylladb@9ab57b1
(scylladb/scylladb#18467).

The mentioned changes implemented the following solution:

* DESC SCHEMA/KEYSPACE/TABLE would still print a create statement for the
  CDC base table,
* DESC SCHEMA/KEYSPACE would start printing an alter statement for the
  CDC log table. That statement would ensure that the restored log table
  has the same parameters as the original one,
* DESC TABLE <base table> would behave as DESC SCHEMA/KEYSPACE, i.e.
  it would print a create statement for the base table and an alter
  statement for the log table,
* DESC TABLE <log table> would result in an error.

While that solution was good and behaved correctly in the context of
restoring the schema, it had one flaw: describe statement aren't only
used as a means for producing a backup; they also serve an informative
purpose to learn about the schema, e.g. to learn what parameters a specific
table uses. Because we didn't allow for describing CDC log tables, the user
couldn't look them up directly via a describe statement -- they had to
describe the base table for that.

Attempting to describe a log table ended with an error, e.g.:

```
$ DESC TABLE ks.t_scylla_cdc_log;

ks.t_scylla_cdc_log is a cdc log table and it cannot be described directly. Try `DESC TABLE ks.t` to describe cdc base table and it's log table.
```

In these changes, we allow for describing CDC log tables again. The
semantics of the first three bullets above remains unchanged, but
we impose new behavior for DESC TABLE <log table>:

* When the user executes DESC TABLE <log table>, a create statement
  will be returned, treating the table as if it were a regular one,
* The create statement will be wrapped in CQL comment markers.

The rationale for the second bullet is that although we want to give the
user a means to look into the structure and options of a CDC log table,
the returned statement is not supposed to be ever executed by them. We
want to minimize the risk of that.

An example of the behavior after the change:

```
$ DESC TABLE ks.t_scylla_cdc_log;

/* Do NOT execute this statement! It's only for informational purposes.
   A CDC log table is created automatically when the base is created.

CREATE TABLE ks.t_scylla_cdc_log (
    "cdc$stream_id" blob,
    "cdc$time" timeuuid,
    "cdc$batch_seq_no" int,
    "cdc$end_of_batch" boolean,
    "cdc$operation" tinyint,
    "cdc$ttl" bigint,
    p int,
    PRIMARY KEY ("cdc$stream_id", "cdc$time", "cdc$batch_seq_no")
) WITH CLUSTERING ORDER BY ("cdc$time" ASC, "cdc$batch_seq_no" ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'enabled': 'false', 'keys': 'NONE', 'rows_per_partition': 'NONE'}
    AND comment = 'CDC log for ks.t'
    AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_size': '60', 'compaction_window_unit': 'MINUTES', 'expired_sstable_check_frequency_seconds': '1800'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 0
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND speculative_retry = '99.0PERCENTILE';

*/
```

We also extend the developer documentation regarding DESCRIBE
statements on CDC tables.

Fixes scylladb/scylladb#21235

Backport: these changes are an enhancement, so not needed.

Closes scylladb/scylladb#21228

* github.com:scylladb/scylladb:
  docs/dev: Document semantics of describing CDC tables
  cql3: Allow for describing CDC log tables
2024-11-05 10:06:13 +01:00
Pavel Emelyanov
440c1e3e3f error_injection: Remove unused inject(sleep, then invoke) overload
The overload was introduced by a8b14b0227 (utils: add timeout error
injection with lambda), but is only used by the test nowadays.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21377
2024-11-05 09:56:08 +02:00
Yaniv Michael Kaul
4c5e102aee node_exporter: use fewer collectors
Remove unused / less useful collectors by default. While it doesn't seem to reduce memory usage, it may reduce potential performance or security issues in the future.
This is what we are left with (snippet of log when loading node exporter manually with the changed command line):

ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:111 level=info msg="Enabled collectors"
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=arp
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=bonding
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=conntrack
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=cpu
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=cpufreq
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=diskstats
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=dmi
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=edac
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=entropy
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=filefd
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=filesystem
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=interrupts
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=loadavg
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=mdadm
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=meminfo
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=netclass
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=netdev
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=netstat
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=nvme
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=os
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=pressure
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=schedstat
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=selinux
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=sockstat
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=softnet
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=stat
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=textfile
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=time
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=timex
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=uname
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=vmstat
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=watchdog
ts=2024-11-03T15:41:06.855Z caller=node_exporter.go:118 level=info collector=xfs

Signed-off-by: Yaniv Kaul <yaniv.kaul@scylladb.com>

Improvement, no need to backport.

Closes scylladb/scylladb#21419
2024-11-05 10:41:09 +03:00
Avi Kivity
b292aeecac replica: query.hh: drop dependency on database.hh
database.hh has large fan-in and therefore can trigger a lot
of recompilations if included. Replace with smaller dependencies.

Closes scylladb/scylladb#21424
2024-11-05 10:40:33 +03:00
Pavel Emelyanov
a98b57212e Merge 'lang, .github: remove unused includes, add more directories to CLEANER_DIR' from Kefu Chai
in this series:

- remove unused `#include` in "lang" subdirectory
- add index and lang to CLEANER_DIR

---

cleanup and improvements in the CI, hence no need to backport.

Closes scylladb/scylladb#21437

* github.com:scylladb/scylladb:
  .github: add index and lang to CLEANER_DIR
  lang: remove unused "#includes"
2024-11-05 10:37:04 +03:00
Kefu Chai
f1d4812ad6 test: lib: rest_client: use isinstance() over type()
in addition to the inheritance support, `isinstance()` is also
the recommended way to check for types by PEP8.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21438
2024-11-05 10:36:31 +03:00
Kefu Chai
59eb2ab119 treewide: s/boost::algorithm::any_of/std::ranges::any_of/
now that we are allowed to use C++23. we now have the luxury of using
`std::ranges::any_of`.

in this change, we replace `boost::algorithm::any_of` with
`std::ranges::any_of`

to reduce the dependency to boost for better maintainability, and
leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase
and reduce external dependencies where possible.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-11-05 14:06:09 +08:00
Kefu Chai
f8bb1c64f1 treewide: s/boost::algorithm::all_of/std::ranges::all_of/
now that we are allowed to use C++23. we now have the luxury of using
`std::ranges::all_of`.

in this change, we replace `boost::algorithm::all_of` with
`std::ranges::all_of`

to reduce the dependency to boost for better maintainability, and
leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase
and reduce external dependencies where possible.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-11-05 14:05:24 +08:00
Kefu Chai
e651b6dc69 .github: add index and lang to CLEANER_DIR
also explain why we don't run the cleaner against the "idl" subdirectory.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-11-05 10:01:04 +08:00
Kefu Chai
ee2a9419b3 lang: remove unused "#includes"
these unused includes are identified by clang-include-cleaner. after
auditing the source files, all of the reports have been confirmed.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-11-05 10:01:04 +08:00
Avi Kivity
ee92784098 serialization: replace boost::type with std::type_identity
Recently, seastar rpc started accepting std::type_identity in addition
to boost::type as a type marker (while labeling the latter with an
ominous deprecation warning). Reduce our depedendency on boost
by switching to std::type_identity.
2024-11-05 00:43:27 +01:00
Avi Kivity
075b13597d serializer: drop dependency on boost ranges
The call to boost::range::for_each is easily replaced with ranged for.

Closes scylladb/scylladb#21422
2024-11-04 17:48:17 +02:00
Gleb Natapov
2dbae78542 gossiper: start failure_detector_loop on shard 0 only
failure_detector_loop does nothing on all other shards.
2024-11-04 17:15:06 +02:00
Gleb Natapov
323b04137d gossiper: use 1 seconds instead of 1000 milliseconds 2024-11-04 17:15:06 +02:00
Gleb Natapov
0cb4c71846 gossiper: remove unused code 2024-11-04 17:15:06 +02:00
Gleb Natapov
0e4f149dee gossiper: co-routinize do_send_ack2_msg 2024-11-04 17:15:06 +02:00
Gleb Natapov
1fbac54fb8 gossiper: do not needlessly call get_endpoint_state_ptr in handle_major_state_change
The code calls for get_endpoint_state_ptr several times instead of using
the result of the first call. Change it.
2024-11-04 17:15:06 +02:00
Gleb Natapov
e2cf93abb9 gossiper: fix weird logic in get_live_members
The code adds a node to a set and then removes it if a condition is met.
Add to the set if the condition is not met instead.  Note that the
original set never has local endpoint (it is only added locally), so the
code is equivalent.
2024-11-04 17:14:55 +02:00
Benny Halevy
caedcf20c6 tablet_allocator: improve error message when unable to find replicas when draining
Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-04 14:54:54 +02:00
Benny Halevy
d8be1cafb5 test_tablets: add rack decommission test cases
Test scenarios where decommissioing a compelte rack
should succeed, and reproduce scylladb/scylladb#19475
where decommissioning a rack would fail since the
number of remaining racks is insufficient to satisfy
the replication factor, even though the number of nodes
is sufficient, enshrining this behavior.

Refs scylladb/scylladb#19475

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-04 14:54:13 +02:00
Avi Kivity
b706e3e9e4 Merge 'sstables/index_reader: avoid unnecessary index page reads in single-partition reads' from Michał Chojnowski
Terminology note: in the context of this series, "index page" means an contiguous segment of the index file starting (inclusive) at a key corresponding to a summary entry and ending (exclusive) before the key corresponding to the next summary entry. "Index pages" are not related to filesystem pages.

---

In a single-partition read, if the searched partition key is the first key in its index page, we start scanning the index for that key starting at the previous index page (inclusive), even though we could start directly from the key's page. Similarly, if the searched partition key is absent from the sstable and lies after all other keys in its appropriate page, we additionally scan the next page, even though it's known from the summary that it can't possibly contain the key.

Those cases are wasteful. It's worse than it might seem at first glance. When partitions are small, only a small fraction of search keys fulfills those conditions (i.e. "first key in its page" or "an absent key greater than the last key in its page"), so the waste doesn't matter much. But when partitions are big enough, every index page contains only one partition key (and a promoted index for that partition), which directly means that *all* search keys fulfill the conditions, which means that total index reading work is two times bigger than what it should be.

In addition, there is a secondary performance bug which, when the aforementioned conditions are fulfilled, causes *additional* I/O to happen *past* the index reads which are actually parsed and used. In effect, the index I/O in single-partition reads might be not just doubled, but even tripled (that's for IOPS — throughput might be multiplied even more), all because of a slight inaccuracy in the edge cases.

This series fixes those inefficiencies by tightening the edge cases and ensuring that single-partition reads always read only a single index page.

Here's an example where we query the first row (i.e. `LIMIT 1`) of a certain partition key, in a table with large (1 MB) promoted indexes. Before the patch, the lookup of the lower bound involves 3 serialized disk reads (as described above) to subsequent index pages, and even the lookup of the upper bound involves 2 disk reads:

```
                                                                                                                                                                                     Execute CQL3 query
                                                                                                                                                                          Parsing a statement [shard 0]
                                                                                                                                     Processing a statement for authenticated user: anonymous [shard 0]
                                                                                                                                                        Executing read query (reversed false) [shard 0]
                                                                   Creating read executor for token -1297921881139976049 with all: [127.11.11.1] targets: [127.11.11.1] repair decision: NONE [shard 0]
                                                                    Creating never_speculating_read_executor - speculative retry is disabled or there are no extra replicas to speculate with [shard 0]
                                                                                                                                                                  read_data: querying locally [shard 0]
                                                                                                                         Start querying singular range {{-1297921881139976049, pk{00023130}}} [shard 0]
                                                                                                                                     [reader concurrency semaphore user] admitted immediately [shard 0]
                                                                                                                                           [reader concurrency semaphore user] executing read [shard 0]
                            Reading key {-1297921881139976049, pk{00023130}} from sstable ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 38359040 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 38391808 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 38359040, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 38391808, successfully read 32768 bytes [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 39370752 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 39403520 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 39370752, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 39403520, successfully read 32768 bytes [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40378368 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40411136 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40378368, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40411136, successfully read 32768 bytes [shard 0]
                                                                                                                      upper_bound_cache_only({position: clustered, ckp{}, 1}): no upper bound [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40378368 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40411136 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40378368, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40411136, successfully read 32768 bytes [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 41390080 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 41422848 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 41390080, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 41422848, successfully read 32768 bytes [shard 0]
                                 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db: scheduling bulk DMA read of size 21926 at offset 819200 [shard 0]
    ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db: finished bulk DMA read of size 21926 at offset 819200, successfully read 24576 bytes [shard 0]
                                      Page stats: 1 partition(s), 0 static row(s) (0 live, 0 dead), 1 clustering row(s) (1 live, 0 dead), 0 range tombstone(s) and 0 cell(s) (0 live, 0 dead) [shard 0]
                                                                                                                                                                             Querying is done [shard 0]
                                                                                                                                                         Done processing - preparing a result [shard 0]
                                                                                                                                                                                       Request complete
```

After the patch, the lookup of each bound involves 1 read:
```

                                                                                                                                                                                     Execute CQL3 query
                                                                                                                                                                          Parsing a statement [shard 0]
                                                                                                                                     Processing a statement for authenticated user: anonymous [shard 0]
                                                                                                                                                        Executing read query (reversed false) [shard 0]
                                                                   Creating read executor for token -1297921881139976049 with all: [127.11.11.1] targets: [127.11.11.1] repair decision: NONE [shard 0]
                                                                    Creating never_speculating_read_executor - speculative retry is disabled or there are no extra replicas to speculate with [shard 0]
                                                                                                                                                                  read_data: querying locally [shard 0]
                                                                                                                         Start querying singular range {{-1297921881139976049, pk{00023130}}} [shard 0]
                                                                                                                                     [reader concurrency semaphore user] admitted immediately [shard 0]
                                                                                                                                           [reader concurrency semaphore user] executing read [shard 0]
                            Reading key {-1297921881139976049, pk{00023130}} from sstable ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 39370752 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 39403520 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 39370752, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 39403520, successfully read 32768 bytes [shard 0]
                                                                                                                      upper_bound_cache_only({position: clustered, ckp{}, 1}): no upper bound [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40378368 [shard 0]
                              ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: scheduling bulk DMA read of size 32768 at offset 40411136 [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40378368, successfully read 32768 bytes [shard 0]
 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Index.db: finished bulk DMA read of size 32768 at offset 40411136, successfully read 32768 bytes [shard 0]
                                 ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db: scheduling bulk DMA read of size 21926 at offset 819200 [shard 0]
    ./workdir_01/data/ks/t-536c31f09a9c11efbd5082a6aa3e8d0c/me-3gky_0v18_3rgjk2dsjae431s4uz-big-Data.db: finished bulk DMA read of size 21926 at offset 819200, successfully read 24576 bytes [shard 0]
                                      Page stats: 1 partition(s), 0 static row(s) (0 live, 0 dead), 1 clustering row(s) (1 live, 0 dead), 0 range tombstone(s) and 0 cell(s) (0 live, 0 dead) [shard 0]
                                                                                                                                                                             Querying is done [shard 0]
                                                                                                                                                         Done processing - preparing a result [shard 0]
                                                                                                                                                                                       Request complete
```

Doesn't have to be backported, since the problem only affects performance, not correctness, and it has been present since forever.

Closes scylladb/scylladb#20897

* github.com:scylladb/scylladb:
  index_reader: remove a piece of misguided code involved in single-partition reads
  index_reader: in single-partition reads, don't read more than one page
  index_reader: fix unnecessary reads of preceding index pages
2024-11-04 14:28:27 +02:00
Avi Kivity
2531dc2d80 schema_registry: stop including replica/database.hh
database.hh is a hotspot that changes often (or its dependencies
do). Avoid including it to reduce recompilations.

Closes scylladb/scylladb#21407
2024-11-04 13:16:27 +01:00
Benny Halevy
9ff614da9f topology_experimental_raft/test_tablets: get_tablet_count_per_shard_for_host: move shards_count param to be last
Prepare for the next comit that will add a version
accepting a list of servers: `get_tablet_count_per_shard_for_hosts`
for which we want `shards_per_node` to be last and have a default value.

Also, fix the type hint for `full_tables`, as it had a syntax error,
using `:` instead of `,`.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-04 14:11:30 +02:00
Benny Halevy
0c1e85b6e3 test/pylib: ServerInfo: add datacenter and rack attributes
Set to "DEFAULT_DC" and "DEFAULT_RACK" by default.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-04 14:11:30 +02:00
Benny Halevy
efa64cb92a test: everywhere: drop unused imports of ServerInfo
Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-04 14:11:30 +02:00
Avi Kivity
7cb1ad8c87 Merge 'compaction_manager: stop_tasks, stop_ongoing_compactions: ignore errors' from Benny Halevy
stop() methods, like destructors must always succeed,
and returning errors from them is futile as there is
nothing else we can do with them by continue with shutdown.

stop_ongoing_compactions, in particular, currently returns the status
of stopped compaction tasks from `stop_tasks`, but still all tasks
must be stopped after it, even if they failed, so assert that
and ignore the errors.

Fixes scylladb/scylladb#21159

* Needs backport to 6.2 and 6.1, as commit 8cc99973eb causes handles storage that might cause compaction tasks to fail and eventually terminate on shudown when the exceptions are thrown in noexcept context in the deferred stop destructor body

Closes scylladb/scylladb#21299

* github.com:scylladb/scylladb:
  compaction_manager: stop: await _stop_future if engaged
  compaction_manager: really_do_stop:  assert that no tasks are left behind
  compaction_manager: stop_tasks, stop_ongoing_compactions: ignore errors
  compaction/compaction_manager: stop_tasks(): unlink stopped tasks
  compaction/compaction_manager: make _tasks an intrusive list
2024-11-04 13:54:16 +02:00
Gleb Natapov
3b7d9fddbc gossiper: drop unneeded this-> 2024-11-04 12:02:51 +02:00
Gleb Natapov
501b8f6984 gossiper: fold get_or_create_endpoint_state into my_endpoint_state
my_endpoint_state() is the only called of
get_or_create_endpoint_state() and calling it is the only thing the
function does anyway.
2024-11-04 12:02:51 +02:00
Gleb Natapov
300cbcebf6 gossiper: co-routinize do_send_ack_msg 2024-11-04 12:02:51 +02:00
Pavel Emelyanov
f3f956841f sstables: Remove unused mp_row_consumer_m::range_tombstone_start
It's only used by its operator<< so remove it as well

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21380
2024-11-03 16:40:02 +02:00
Avi Kivity
704ea9d3b4 Merge 'api: Remove foreach_column_family() helper' from Pavel Emelyanov
There's a whole lot of helpers and wrappers in api/ that help handlers manipulate keyspaces and tables. One of those is foreach_column_family which calls the provided callable on a table on each shard. There's exactly the same (but a bit more flexible) helper nearby. While at it, this helper gets a better name.

Closes scylladb/scylladb#21398

* github.com:scylladb/scylladb:
  api: Rename set_tables -> for_tables_on_all_shards
  api: Remove foreach_column_family() helper
2024-11-03 15:46:27 +02:00
Avi Kivity
856489ded1 cql3: remove unused request_validations methods
These methods are not used and therefore removed.

Closes scylladb/scylladb#21392
2024-11-03 13:17:32 +02:00
Benny Halevy
6cce67bec8 compaction_manager: stop: await _stop_future if engaged
The current condition that consults the compaction manager
state for awaiting `_stop_future` works since _stop_future
is assigned after the state is set to `stopped`, but it is
incidental.  What matters is that `_stop_future` is engaged.

While at it, exchange _stop_future with a ready future
so that stop() can be safely called multiple times.
And dropped the superfluous co_return.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-03 10:53:35 +02:00
Benny Halevy
a7a55298ea compaction_manager: really_do_stop: assert that no tasks are left behind
stop_ongoing_compactions now ignores any errors returned
by tasks, and it should leave no task left behind.
Assert that here, before the compaction_manager is destroyed.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-03 10:53:34 +02:00
Benny Halevy
c08ba8af68 compaction_manager: stop_tasks, stop_ongoing_compactions: ignore errors
stop() methods, like destructors must always succeed,
and returning errors from them is futile as there is
nothing else we can do with them but continue with shutdown.

Leaked errors on the stop path may cause termination
on shutdown, when called in a deferred action destructor.

Fixes scylladb/scylladb#21298

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-11-03 10:52:58 +02:00
Botond Dénes
d8500472b3 compaction/compaction_manager: stop_tasks(): unlink stopped tasks
Stopped tasks currently linger in _tasks until the fiber that created
the task is scheduled again and unlinks the task. This window between
stop and remove prevents reliable checks for empty _tasks list after all
tasks are stopped.
Unlink the task early so really_do_stop() can safely check for an empty
_tasks list (next patch).
2024-11-03 10:17:11 +02:00
Botond Dénes
e942c074f2 compaction/compaction_manager: make _tasks an intrusive list
_tasks is currently std::list<shared_ptr<compaction_task_executor>>, but
it has no role in keeping the instances alive, this is done by the
fibers which create the task (and pin a shared ptr instance).
This lends itself to an intrusive list, avoiding that extra
allocation upon push_back().
Using an intrusive list also makes it simpler and much cheaper (O(1) vs.
O(N)) to remove tasks from the _tasks list. This will be made use of in
the next patch.

Code using _task has to be updated because the value_type changes from
shared_ptr<compaction_task_executor> to compaction_task_executor&.
2024-11-03 10:17:11 +02:00
Avi Kivity
39b55bd3a0 Update seastar submodule
* seastar f821bda19...fba36a3d1 (13):
  > build: do not include -DBoost_TEST_DYN_LINK in seastar_testing_cflags
  > doc: compatibility: update the notes on supported GCC versions
  > docker: bump up to clang {18,19} and gcc {13,14}
  > rpc: optimize small tuple deserialization
  > rpc: switch rpc::type from boost to std
  > thread: do not use fortify source
  > build: suppress CMake warning about CMP0057
  > core/units: remove space before literal identifier
  > signal.md: describe auto signal handling
  > build: persist Seastar options in SeastarConfig.cmake
  > sharded.hh: seperate invoke_on decls from defs
  > test: Add perf test for http client
  > gate: check: mark as const

Closes scylladb/scylladb#21390
2024-11-02 13:58:45 +02:00
Botond Dénes
19a43b5859 Merge 'repair: Reduce hints and batchlog flush' from Asias He
The hints and batchlog flush requests are issued to all nodes for each repair request when tombstone_gc repair mode is used.

The amount of such flush requests is high when all nodes in the cluster run repair. It is observed it takes a long time, up to 15s, for a repair request to finish such a flush request.

To reduce overhead of the flush, each node caches the flush and only executes the real flush when some time has passed. It is safe to do so before the real flush_time is returned. Repair uses the smallest flush_time from peers as the repair time.

The nice thing about the cache on the receiver side is that all senders can hit the cache. It is better than cache on the sender side.

A slightly smaller flush_time compared to the real flush time will be used with the benefits of significantly dropped hints and batchlog flush. The tradeoff is reasonable.

Fixes #20259

Performance improvement. No backports.

Closes scylladb/scylladb#20260

* github.com:scylladb/scylladb:
  test/test_repair.py: Add test_batchlog_flush_in_repair
  repair: Reduce hints and batchlog flush
  db/batchlog_manager: Add add_delay_to_batch_replay
  db/batchlog_manager: Add get_last_replay
  db/batchlog_manager: wire in batchlog_replay_cleanup_after_replays
  db/config: introduce batchlog_replay_cleanup_after_replays
  db/batchlog_manager: do_batch_log_replay(): add cleanup flag
2024-11-01 14:23:27 +02:00
Pavel Emelyanov
292fd52a60 Merge 'utils: chunked_vector: various constructor improvements' from Avi Kivity
Optimize the various constructors a little, and add an std::from_range_t
constructor.

Minor improvement, so no backports.

Closes scylladb/scylladb#21399

* github.com:scylladb/scylladb:
  utils: chunked_vector: add from_range_t constructor
  utils: chunked_vector: optimize initializer_list constructor
  utils: chunked_vector: iterator constructor: copy spanwise
  utils: chunked_vector: reserve for forward iterators, not just random access iterators, on construction
2024-11-01 15:02:56 +03:00
Botond Dénes
4bafaee523 Merge 'tasks: improve task_manager::lookup_virtual_task' from Aleksandra Martyniuk
Currently, to find the operation with given id, all operations tracked by a virtual task are listed. This isn't necessary, since we only need info regarding one particular operation.

Add a method to check whether a virtual task tracks the operation with the given id.

No backport needed

Closes scylladb/scylladb#20769

* github.com:scylladb/scylladb:
  tasks: delete virtual_task::get_ids method as it is unused
  tasks: improve task_manager::lookup_virtual_task
2024-11-01 13:44:04 +02:00
Kefu Chai
1b8446f92d compaction: fix the indent
in 38ce2c605d, we left a TODO for
reindent the code.

in this change, we reindent the code to address this TODO.

Refs 38ce2c605d
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21383
2024-11-01 12:55:47 +03:00
Avi Kivity
b5e46077df sstables: generation_type: replace boost ranges with std ranges
Reduce dependency load.

Closes scylladb/scylladb#21402
2024-11-01 12:45:24 +03:00
Pavel Emelyanov
d6169630a4 api: Rename set_tables -> for_tables_on_all_shards
The former name is not extremely descriptive, hopefully the latter one
is better in this sense.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-11-01 12:15:01 +03:00
Pavel Emelyanov
822758dffd api: Remove foreach_column_family() helper
There's a whole lot of helpers and wrappers in api/ that help handlers
manipulate keyspaces and tables. One of those is foreach_column_family
which calls the provided callable on a table on each shard. There's
exactly the same (but a bit more flexible) set_table() helper nearby.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-11-01 12:13:35 +03:00
Botond Dénes
0ee0dd3ef4 Merge 'Collect and report backup progress' from Pavel Emelyanov
Task manager GET /status method returns two counters that reflect task progress -- total and completed. To make caller reason about their meaning, additionally there's progress_units field next to those counters.

This patch implements this progress report for backup task. The units are bytes, the total counter is total size of files that are being uploaded, and the completed counter is total amount of bytes successfully sent with PUT requests. To get the counters, the client::upload_file() is extended to calculate those.

fixes #20653

Closes scylladb/scylladb#21144

* github.com:scylladb/scylladb:
  backup_task: Report uploading progress
  s3/client: Account upload progress for real
  s3/client: Introduce upload_progress
  s3: Extract client_fwd.hh
2024-11-01 10:57:12 +02:00
Kefu Chai
64122b3df3 treewide: s/boost::transform/std::ranges::transform/
now that we are allowed to use C++23. we now have the luxury of using
`std::ranges::transform`.

in this change, we:

- replace `boost::transform` with `std::ranges::transform`
- update affected code to work with `std::ranges::transform`

to reduce the dependency to boost for better maintainability, and
leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase
and reduce external dependencies where possible.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21318
2024-11-01 08:15:14 +02:00
Avi Kivity
8c67f9b42e cql3: util: remove unneeded boost/range includes from header files
The includes are redistributed to the source files that need them.

Closes scylladb/scylladb#21391
2024-10-31 23:49:44 +01:00
Nadav Har'El
ee2d75b088 Merge 'Generalize "breakpoint" type of error injection' from Pavel Emelyanov
This pattern is -- if requested (by test) suspend code execution until requestor (the test) explicitly wakes it up. For that the injected place should inject a lambda that is called with so called "handler" at hand and try to read message from the handler. In many cases the inner lambda additionally prints a message into logs that tests waits upon to make sure injection was stepped on. In the end of the day this "breakpoint" is injected like

```
    co_await inject("foo", [] (auto& handler) {
        log.info("foo waiting");
        co_await handler.wait_for_message(timeout);
    });
```

This PR makes breakpoints shorter and more unified, like this

```
    co_await inject("foo", wait_for_message(timeout));
```

where `wait_for_message` is a wrapper structure used to pick new `inject()` overload.

Closes scylladb/scylladb#21342

* github.com:scylladb/scylladb:
  sstables: Use inject(wait_for_message_overload)
  treewide,error_injection: Use inject(wait_for_message) and fix tests
  treewide,error_injection: Use inject(wait_for_message) overload
  error_injection: Add inject() overload with wait_for_message wrapper
2024-10-31 21:56:27 +02:00
Avi Kivity
6a9852d47b utils: chunked_vector: add from_range_t constructor
std::ranges::to<> has a little protocol with containers. Implement it
to get optimized construction.

Similar to the iterator pair constructor, if the range's size can be
obtained (even with an O(N) algorithm), favor that to avoid reallocations.
Copy elements spanwise to promote optimization to memcpy when possible.
2024-10-31 19:32:16 +02:00
Avi Kivity
b2769403d2 utils: chunked_vector: optimize initializer_list constructor
Delegate to the previously optimized iterator-pair constructor.
2024-10-31 18:10:14 +02:00
Avi Kivity
0a81be4321 utils: chunked_vector: iterator constructor: copy spanwise
Instead of copying element-by-element, copy contiguous spans. This
is much faster if the input is a span and the constructor is trivial,
since the whole thing translates to a memcpy.

Make the two branches constexpr to reduce work for the compiler in
optimizing the other branch away.
2024-10-31 18:10:08 +02:00
Avi Kivity
4653430c8e utils: chunked_vector: reserve for forward iterators, not just random access iterators, on construction
For a forward iterator, prefer a two pass algorithm to first count
the number of elements, reserver, then copy the elements, to a single
pass algorithm that involves reallocation and copying.
2024-10-31 17:55:42 +02:00
Kefu Chai
673b107ffa github: use GithubException when appropriate
`Exception` could be too general, what we really care about is
`GithubException`. so let's catch the latter instead for better
readability.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21364
2024-10-31 18:21:29 +03:00
Kefu Chai
f8221b960f test: route S3 mock server messages through logger
The S3 mock server (introduced in 5a96549c) currently prints its status
messages directly to stdout, which can be distracting when reviewing test
results. For example:

```console
$ ./test.py --verbose --mode debug object_store/test_backup::test_simple_backup
Found 1 tests.
Starting S3 mock server on ('127.226.51.1', 2012)
================================================================================
[N/TOTAL]   SUITE    MODE   RESULT   TEST
------------------------------------------------------------------------------
[1/1]      object_store  debug  [ PASS ] object_store.test_backup.1 5.99s
Stopping S3 mock server
-------------------------
CPU utilization: 6.5%
```

Move these messages to use proper logging to give developers more control
over their visibility:

- Make logger parameter mandatory in MockS3Server constructor
- Route "Stopping S3 mock server" message through the provided logger
- Add --log-level option to the standalone mock server launcher

The message is now hidden:

```console
$ ./test.py --verbose --mode debug --save-log-on-success object_store/test_backup::test_simple_backup
Found 1 tests.
================================================================================
[N/TOTAL]   SUITE    MODE   RESULT   TEST
------------------------------------------------------------------------------

[1/1]      object_store  debug  [ PASS ] object_store.test_backup.1 6.25s
------------------------------------------------------------------------------
CPU utilization: 5.5%
```

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21384
2024-10-31 18:21:29 +03:00
Benny Halevy
78ceaeabca compaction_manager: compaction_disabled: return true if not in compaction_state
When a compaction_group is removed via `compaction_manager::remove`,
it is erase from `_compaction_state`, and therefore compaction
is definitely not enabled on it.

This triggers an internal error if tablets are cleaned up
during drop/truncate, which checks that compaction is disabled
in all compaction groups.

Note that the callers of `compaction_disabled` aren't really
interested in compaction being actively disabled on the
compaction_group, but rather if it's enabled or not.
A follow-up patch can be consider to reverse the logic
and expose `compaction_enabled` rather than `compaction_disabled`.

Fixes scylladb/scylladb#20060

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#21378
2024-10-31 18:21:29 +03:00
Dawid Mędrek
495c1188e9 docs/dev: Document semantics of describing CDC tables 2024-10-31 11:25:19 +01:00
Dawid Mędrek
39e0513e1b cql3: Allow for describing CDC log tables
In the past, DESC SCHEMA would produce create statements for both the base
and the log table. That was incorrect as the log table is automatically
created alongside the base one. That was solved in scylladb/scylladb@9ab57b1
(scylladb/scylladb#18467).

The mentioned changes implemented the following solution:

* DESC SCHEMA/KEYSPACE/TABLE would still print a create statement for the
  CDC base table,
* DESC SCHEMA/KEYSPACE would start printing an alter statement for the
  CDC log table. That statement would ensure that the restored log table
  has the same parameters as the original one,
* DESC TABLE <base table> would behave as DESC SCHEMA/KEYSPACE, i.e.
  it would print a create statement for the base table and an alter
  statement for the log table,
* DESC TABLE <log table> would result in an error.

While that solution was good and behaved correctly in the context of
restoring the schema, it had one flaw: describe statement aren't only
used as a means for producing a backup; they also serve an informative
purpose to learn about the schema, e.g. to learn what parameters a specific
table uses. Because we didn't allow for describing CDC log tables, the user
couldn't look them up directly via a describe statement -- they had to
describe the base table for that.

Attempting to describe a log table ended with an error, e.g.:

```
$ DESC TABLE ks.t_scylla_cdc_log;

ks.t_scylla_cdc_log is a cdc log table and it cannot be described directly. Try `DESC TABLE ks.t` to describe cdc base table and it's log table.
```

In these changes, we allow for describing CDC log tables again. The
semantics of the first three bullets above remains unchanged, but
we impose new behavior for DESC TABLE <log table>:

* When the user executes DESC TABLE <log table>, a create statement
  will be returned, treating the table as if it were a regular one,
* The create statement will be wrapped in CQL comment markers.

The rationale for the second bullet is that although we want to give the
user a means to look into the structure and options of a CDC log table,
the returned statement is not supposed to be ever executed by them. We
want to minimize the risk of that.

An example of the behavior after the change:

```
$ DESC TABLE ks.t_scylla_cdc_log;

/* Do NOT execute this statement! It's only for informational purposes.
   A CDC log table is created automatically when the base is created.

CREATE TABLE ks.t_scylla_cdc_log (
    "cdc$stream_id" blob,
    "cdc$time" timeuuid,
    "cdc$batch_seq_no" int,
    "cdc$end_of_batch" boolean,
    "cdc$operation" tinyint,
    "cdc$ttl" bigint,
    p int,
    PRIMARY KEY ("cdc$stream_id", "cdc$time", "cdc$batch_seq_no")
) WITH CLUSTERING ORDER BY ("cdc$time" ASC, "cdc$batch_seq_no" ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'enabled': 'false', 'keys': 'NONE', 'rows_per_partition': 'NONE'}
    AND comment = 'CDC log for ks.t'
    AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_size': '60', 'compaction_window_unit': 'MINUTES', 'expired_sstable_check_frequency_seconds': '1800'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 0
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND speculative_retry = '99.0PERCENTILE';

*/
```

Fixes scylladb/scylladb#21235
2024-10-31 11:25:19 +01:00
Wojciech Mitros
88ab8db944 mv: run view building in streaming scheduling group
View building is an expensive process that takes a long time to complete.
During the build, it's impact on other work should be minimized, even at
the expense of slightly slowing it down.

Instead, view building is currently performed in the the same scheduling
group (gossip) as other high-priority tasks, in particular raft processing,
which slows it down, making races more likely and increasing the number
of retries that need to be done.

While view building is still initiated in the gossip group (as it's the
result of adding a view, which is a schema change), in this patch the bulk
of the view building work is moved to a low-priority, maintenance scheduling
group (named "streaming" after its main use case).

Additionally, a test is added, where we make sure that the scheduling
group is the one most used when building a view.

Fixes https://github.com/scylladb/scylladb/issues/21232

Closes scylladb/scylladb#21326
2024-10-31 10:13:20 +01:00
Nadav Har'El
7572c483b1 test/topology_experimental_raft: fix flaky test
Today, each test function in test/topology_experimental_raft creates a
cluster in the beginning of the test and drops it at the end of the
function. This is very inefficient if you hope (like I do) to write many
small and pinpointed test functions instead of large test functions that
test 20 unrelated things.

Trying to propose a way to change this sad state of affairs, in
test_alternator.py I created a fixture "alternator3" which I hoped could
be used in multiple tests that need a 3-node Alternator cluster.
Currently only one test uses this fixture.

Unfortunately, it turns out the alternator3 fixture is broken, and
led to flaky test runs (sometimes the test using alternator3 picked
up an existing cluster instead of starting with an empty cluster,
and failed). These problems cannot be *completely* fixed at the current
state of the framework. The framework does not currently allow keeping
a 3-node cluster between test functions, while also allowing other test
functions to create different clusters. The specific flakiness we saw
could be fixed by adding a missing before_test() call, but in the
future we would need to ensure that all the test functions that
use it are contiguous in the test file, and I don't see how we can (or
want to) ensure this. So at this point I am giving up and withdrawing
this proposal until the developers of the topology test framework
make this one of their design goals.

Since there was only one test using this fixture, removing it should
make no performance or correctness difference - it should just fix
the flakiness.

Fixes scylladb/scylladb#21322.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#21370
2024-10-31 10:12:26 +01:00
Calle Wilund
c4361037f7 cql_test_env/gossip: Prevent double shutdown call crash
Fixes scylladb/scylladb#21159

When an exception is thrown in sstable write etc such that
storage_manager::isolate is initiated, we start a shutdown chain
for message service, gossip etc. These are synced (properly) in
storage_manager::stop, but if we somehow call gossiper::shutdown
outside the normal service::stop cycle, we can end up running the
method simultaneously, intertwined (missing the guard because of
the state change between check and set). We then end up co_awaiting
an invalid future (_failure_detector_loop_done) - a second wait.

Fixed by
a.) Remove superfluous gossiper::shutdown in cql_test_env. This was added
    in 20496ed, ages ago. However, it should not be needed nowadays.
b.) Ensure _failure_detector_loop_done is always waitable. Just to be sure.

Closes scylladb/scylladb#21379
2024-10-31 10:11:20 +01:00
Nadav Har'El
d3f09638f0 Merge 'compound_compat: replace use of boost ranges with std ranges' from Avi Kivity
Replace use of boost::ranges::join() with another construct, as it
has no std replacement, and replace other uses with their std
equivalent, in order to reduce dependency load.

Code cleanup - no backport.

Closes scylladb/scylladb#21382

* github.com:scylladb/scylladb:
  compound_compat: replace use of boost ranges with std ranges
  compound_compat: simplify seriakization of ka/la sstables static cell names
2024-10-31 10:16:41 +02:00
Nadav Har'El
65e29f28bd Merge 'gms: remove unused #includes ' from Kefu Chai
these unused includes are identified by clang-include-cleaner. after auditing the source files, all of the reports have been
confirmed.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#21374

* github.com:scylladb/scylladb:
  .github: add gms to iwyu's CLEANER_DIR
  gms: remove unused `#include`s
2024-10-31 09:06:37 +02:00
Kefu Chai
2498e37a2f mutation_writer,streaming: use reader_consumer_v2 type when appropriate
The `reader_consumer_v2` type
(`std::function<future<> (mutation_reader)>`) is defined alongside
`mutation_reader` in `mutation_reader.hh`.

before this change, we sometimes use
`std::function<future<> (mutation_reader)>` directly when defining a
consumer parameter or a consumer variable.

in this change, we improve maintainability by:

- Reducing duplicate function type declarations
- Centralizing the consumer type definition
- Making future signature updates easier to implement

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21369
2024-10-31 07:17:47 +02:00
Avi Kivity
907da210b6 compound_compat: replace use of boost ranges with std ranges
To reduce the dependency load, replace use of boost ranges
with the std equivalent.

Files that lost the indirect boost dependency have it added as a
direct dependency.
2024-10-30 19:58:07 +02:00
Avi Kivity
982cebc1f6 compound_compat: simplify seriakization of ka/la sstables static cell names
compound_compat is used for serializing ka/la sstables static cell names.
Since we can no longer write such sstabkes, the function is used only
in some tests.

Reduce the use of boost::range::join(): it has no direct equivalent
in std (std::views::concat is in C++26), and it is slow due to the
need to type-erase. Instead of using boost::range::join, extend the
vector used to hold the empty clustering key a bit more, and copy
the view representing the static cell name into into it.
2024-10-30 19:19:57 +02:00
Kefu Chai
d3a6931b14 .github: add gms to iwyu's CLEANER_DIR
to avoid future violations of include-what-you-use.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-30 23:01:34 +08:00
Kefu Chai
52ec315ffd gms: remove unused #includes
these unused includes are identified by clang-include-cleaner.
after auditing the source files, all of the reports have been
confirmed.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-30 23:01:34 +08:00
Pavel Emelyanov
c16369323b sstables: Use inject(wait_for_message_overload)
This place could be in the pre-previous patch, it just can use the
overload, but it seemengly has a bug. It prints _two_ messages -- that
the injection handler was suspended and that it was woken up. The bug is
in the 2nd message -- it's printed without waiting for the message, so
it likely gets printed before wakeup itself. It seems that no tests care
about it though.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-30 16:53:33 +03:00
Pavel Emelyanov
39cb93be3c treewide,error_injection: Use inject(wait_for_message) and fix tests
This is continuation of previous patch, this time also update tests that
wait for specific message in logs (to make sure injection handler was
called and paused the code execution).

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-30 16:53:33 +03:00
Pavel Emelyanov
7d8cc3ccc2 treewide,error_injection: Use inject(wait_for_message) overload
Many places want to inject a handler that waits for external kick. Now
there's convenience inject() method overload for this. It will result in
extra messages in logs, but so far no code/test cares about it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-30 16:53:33 +03:00
Pavel Emelyanov
c1432f3657 error_injection: Add inject() overload with wait_for_message wrapper
The wrapper object denotes that injection should run a handler and
wait_for_message() on it. Wrapper carries the timeout used to call the
mentioned method. It's currently unused, next patches will start enjoing
it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-30 16:53:33 +03:00
Dawid Mędrek
b984488552 cql3: Rename SALTED HASH to HASHED PASSWORD
Cassandra 4.1 announced a new option to create a role with:
`HASHED PASSWORD`. Example:

```
CREATE ROLE bob WITH HASHED PASSWORD = 'hashed_password';
```

We've already introduced another option following the same
semantics: `SALTED HASH`; example:

```
CREATE ROLE bob WITH SALTED HASH = 'salted_hash';
```

The change hasn't made it to any release yet, so in this commit
we rename it to `HASHED PASSWORD` to be compatible with Cassandra.

Additionally, we adjust existing tests to work against Cassandra too.

Fixes scylladb/scylladb#21350

Closes scylladb/scylladb#21352
2024-10-30 14:07:58 +02:00
Aleksandra Martyniuk
bc5b1f9a5d tasks: delete virtual_task::get_ids method as it is unused 2024-10-30 12:25:47 +01:00
Aleksandra Martyniuk
9b5d69ae96 tasks: improve task_manager::lookup_virtual_task
Currently, lookup_virtual_task gets the list of ids of all operations
tracked by a virtual task and checks whether it contains given id.
The list of all ids isn't required and the check whether one particular
operation id is tracked by the virtual task may be quicker than listing
all operations.

Add virtual_task::contains method and use it in lookup_virtual_task.
2024-10-30 12:24:38 +01:00
Kefu Chai
d81ed5adb4 compaction: explain make_interpose_consumer() in compaction strategy
Add documentation to clarify the purpose and behavior of
make_interpose_consumer() in the compaction_strategy_impl class. This
method is crucial for building layered processing pipelines but its
semantics were previously undocumented.

The added documentation explains how:
- It decorates end consumers with additional processing steps
- It enables construction of processing pipelines
- The original consumer's semantics are preserved

This improves code maintainability by making the pipeline construction
pattern more apparent to developers.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21336
2024-10-30 13:22:00 +03:00
Tomasz Grabiec
f3869dadc6 Merge 'compound: replace boost ranges with std ranges' from Avi Kivity
Continue standardization on std::ranges. Since compound contains a custom
iterator, we first have to upgrade it to C++20 iterator concepts.

Cleanup / minor refactoring, so no backport.

Closes scylladb/scylladb#21320

* github.com:scylladb/scylladb:
  compound: replace boost ranges with std ranges
  compound: upgrade iterator to be an std::forward_iterator
2024-10-30 11:02:51 +01:00
Asias He
73806f66a5 test/test_repair.py: Add test_batchlog_flush_in_repair
It checks batchlog flush request cache in repair.
2024-10-30 11:10:39 +08:00
Asias He
b3b3e880d3 repair: Reduce hints and batchlog flush
The hints and batchlog flush requests are issued to all nodes for each
repair request when tombstone_gc repair mode is used.

The amount of such flush requests is high when all nodes in the cluster
run repair. It is observed it takes a long time, up to 15s, for a repair
request to finish such a flush request.

To reduce overhead of the flush, each node caches the flush and only
executes the real flush when the cahce time has passed. It is safe to do
so because the real flush_time is returned. Repair uses the smallest
flush_time returned from peers as the repair time.

The nice thing about the cache on the receiver side is that all senders
can hit the cache. It is better than cache on the sender side.

A slightly smaller flush_time compared to the real flush time will be
used with the benefits of significantly dropped hints and batchlog
flush. The trade-off looks reasonable.

Tests: 2 nodes, with 1s batchlog delay:

Before:
   Repair nr_repairs=20 cache_time_in_ms=0 total_repair_duration=40.04245328903198

After:
   Repair nr_repairs=20 cache_time_in_ms=5000 total_repair_duration=1.252073049545288

Fixes #20259
2024-10-30 11:07:57 +08:00
Asias He
f8ad78ba1e db/batchlog_manager: Add add_delay_to_batch_replay
It is used to simulate slow replay.
2024-10-30 11:07:57 +08:00
Asias He
fed9b54664 db/batchlog_manager: Add get_last_replay
It is used to get the time when the last replay is executed.
2024-10-30 11:07:57 +08:00
Botond Dénes
3361542e84 db/batchlog_manager: wire in batchlog_replay_cleanup_after_replays
After the specified amount of replays, trigger a cleanup: flush batchlog
table memtables. This allows the cleanup to happen on a configurable
interval, instead of on every batchlog replay attempt, which might be
too much.
2024-10-30 11:07:57 +08:00
Botond Dénes
1635525526 db/config: introduce batchlog_replay_cleanup_after_replays
Not used yet.
2024-10-30 11:07:57 +08:00
Botond Dénes
169c74346d db/batchlog_manager: do_batch_log_replay(): add cleanup flag
Add a flag controlling whether cleanup (memtable flush) will be done
after the replay. This is to allow repair to opt out from cleanup --
when many concurrenty repairs are running, there can be storms of calles
to do_batch_log_replay(), which will be mostly no-op, but they will all
attempt to flush the memtable to clean-up after themselves. This is
unnecessary and introduces latency to repairs, best to leave the cleanup
to the periodic batch-log replay.
2024-10-30 11:07:57 +08:00
Avi Kivity
73b1f66b70 Revert "Merge 'Allow explicitly enabling or disabling tablets when creating a new keyspace' from Benny Halevy"
This reverts commit c286434e4c, reversing
changes made to 6712fcc316.

The commit causes memtable_test to be very flaky in debug mode.
Specifically, subtests test_exceptions_in_flush_on_sstable_open
and test_exceptions_in_flush_on_sstable_write).
2024-10-30 00:55:29 +02:00
Avi Kivity
b9df3aec12 gdb: avoid @classmethod/@property combinations
The @classmethod/@property combination was deprecated in Python 3.11
and removed[1] in Python 3.13. It's used in scylla-gdb.py, breaking it
with Python 3.13.

To fix, just make all users (size_t and _vptr_type) top-level
functions. The definitions are all identical and don't need to be
in class scope.

[1] https://docs.python.org/3.13/library/functions.html#classmethod

Closes scylladb/scylladb#21349
2024-10-29 19:37:07 +02:00
Gleb Natapov
cc7f25062a topology coordinator: take a copy of a replication state in raft_topology_cmd_handler
Current code takes a reference and holds it past preemption points. And
while the state itself is not suppose to change the reference may
become stale because the state is re-created on each raft topology
command.

Fix it by taking a copy instead. This is a slow path anyway.

Fixes: scylladb/scylladb#21220

Closes scylladb/scylladb#21316
2024-10-29 15:47:43 +01:00
Avi Kivity
020ccbd76a Merge 'utils: cached_file: Mark permit as awaiting on page miss' from Tomasz Grabiec
Otherwise, the read will be considered as on-cpu during promoted index
search, which will severely underutlize the disk because by default
on-cpu concurrency is 1.

I verified this patch on the worst case scenario, where the workload
reads missing rows from a large partition. So partition index is
cached (no IO) and there is no data file IO (relies on https://github.com/scylladb/scylladb/pull/20522).
But there is IO during promoted index search (via cached_file).

Before the patch this workload was doing 4k req/s, after the patch it does 30k req/s.

The problem is much less pronounced if there is data file or partition index IO involved
because that IO will signal read concurrency semaphore to invite more concurrency.

Fixes #21325

Closes scylladb/scylladb#21323

* github.com:scylladb/scylladb:
  utils: cached_file: Mark permit as awaiting on page miss
  utils: cached_file: Push resource_unit management down to cached_file
2024-10-29 16:15:21 +02:00
Kamil Braun
36cc3bcc90 test: test_crash_coordinator_before_streaming: enable TRACE for raft_topology logger
Issue scylladb/scylladb#21114 reported that sometimes during the test we
timeout when waiting for node to restart after it was killed.
Preliminary investigation showed that the node appears to be hanging
inside `topology_state_load`, while holding `token_metadata` lock, which
prevents `join_topology` from progressing.

Enable TRACE level logging for `raft_topology` so we get more accurate
info where inside `topology_state_load` the hang happens, once the
problem reproduces again in CI.

Closes scylladb/scylladb#21247
2024-10-29 12:46:47 +02:00
Kefu Chai
54d438168a build: cmake: explicitly mark convenience libraries as STATIC
before this change, these
[convenience libraries](https://www.gnu.org/software/automake/manual/html_node/Libtool-Convenience-Libraries.html)
were implicitly built as static libraries by default,
but weren't explicitly marked as STATIC in CMake. While this worked
with default settings, it could cause issues if `BUILD_SHARED_LIBS` is
enabled.

So before we are ready for building these components as shared
libraries, let's mark all convenience libraries as STATIC for
consistency and to prevent potential issues before we properly support
shared library builds.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21274
2024-10-29 10:22:19 +01:00
Yaron Kaikov
94a9efbf1c github: add script for backports automation instead of Mergify
Adding an auto-backport.py script to handle backport automation instead of Mergify.

The rules of backport are as follows:

* Merged or Closed PRs with any backport/x.y label (one or more) and promoted-to-master label
* Backport PR will be automatically assigned to the original PR author
* In case of conflicts the backport PR will be open in the original autoor fork in draft mode. This will give the PR owner the option to resolve conflicts and push those changes to the PR branch (Today in Scylla when we have conflicts, the developers are forced to open another PR and manually close the backport PR opened by Mergify)
* Fixing cherry-pick the wrong commit SHA. With the new script, we always take the SHA from the stable branch
* Support backport for enterprise releases (from Enterprise branch)

Fixes: https://github.com/scylladb/scylladb/issues/18973

Closes scylladb/scylladb#21302
2024-10-29 10:04:30 +02:00
Pavel Emelyanov
25ae3d0aed backup_task: Report uploading progress
Do it by passing reference to s3::upload_progress_monitor object that
sits on task impl itself. Different files' uploads would then update the
monitor with their sizes and uploaded counters. The structure is
reported by get_progress() method. Unit size is set to be bytes. Test is
updated.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-29 08:40:35 +03:00
Pavel Emelyanov
2efcfc13e8 s3/client: Account upload progress for real
Before upload starts file size is checked, so this is the place that
updates progress.total counter.

Uploading a file happens by reading unit_size bytes from file input
stream and writing the buffer into http body writer stream. This is the
place to update progress.uploaded counter.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-29 08:38:39 +03:00
Pavel Emelyanov
51e03b1025 s3/client: Introduce upload_progress
This is a structure with "total" and "uploaded" counters that's passed
by user to client::upload_file() method so that client would update it
with the progress.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-29 08:38:39 +03:00
Pavel Emelyanov
f9a5e02b53 s3: Extract client_fwd.hh
This is to export some simple structures to users without the need to
include client.hh itself (rather large already)

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-29 08:38:39 +03:00
Avi Kivity
49d3e281d6 Merge 'Sanitize /system/highest_supported_sstable_version API endpoint' from Pavel Emelyanov
Its handler dereferences long chain of objects to get to the value it needs. There's shorter way.
Also, the endpoint in question is not unregistered on stop.

Closes scylladb/scylladb#21279

* github.com:scylladb/scylladb:
  api: Make get_highest_supported_sstable_version use proper service
  api: Move system::get_highest_supported_sstable_version set/unset
  api: Scaffold for sstables-format-selector
2024-10-28 21:42:41 +02:00
Pavel Emelyanov
b09bb6bc19 error_injection: Re-use enter() code in inject() overloads
Most of inject() overloads check if the injection is enabled, then
optionally clear the one-shot one, then do the injection. Everything
but doing the injection is implemented in the enter() method, it's
perfectly worth re-using one.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21285
2024-10-28 21:37:20 +02:00
Kefu Chai
7610b907c6 build: include subdirectory rules in compilation database merge
Previously in e65185ba, when merging Seastar's and ScyllaDB's compilation
databases, the "prefix" parameter in merge-compdb.py was too restrictive.
It only included build rules for files with "CMakeFiles" prefix, excluding
source files in subdirectories like `apps/iotune/CMakeFiles/app_iotune.dir/iotune.cc.o`.

In this change, we change the prefix parameter to an empty string to
include all source files whose object files are located under build directories, regardless of their path structure.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21312
2024-10-28 21:34:21 +02:00
Avi Kivity
c286434e4c Merge 'Allow explicitly enabling or disabling tablets when creating a new keyspace' from Benny Halevy
Separate the configuration for enabling the tablets feature from the enablement of tablets when creating new keyspaces.

This change always enables the TABLETS cluster feature and the tablets logic respectively.

The `enable_tablets` config option just controls whether tablets are enabled or disabled by default for new keyspaces.

If `enable_tablets` is set to `true`, tablets can be disabled using `CREATE KEYSPACE WITH tablets = { 'enabled': false }` as it is today.

If `enable_tablets` is set to `false`, tablets can be enabled using `CREATE KEYSPACE WITH tablets = { 'enabled': true }`.

The motivation for this change is to simplify the user experience of using tablets by setting the default for new keyspaces to false amd allowing the user to simply opt-in by using tablets = {enabled: true }.
This is not pissible today.
The user has to enable tablets by default for all new keyspaces (that use the NetworkTopologyStrategy) and then actively opt-out to use vnodes.

* Not required to be backported to OSS versions.  May be backported to specific enterprise versions

Closes scylladb/scylladb#20729

* github.com:scylladb/scylladb:
  data_dictionary: keyspace_metadata::describe: print tablets enabled also when defaulted
  tablets_test: test enable/disable tablets when creating a new keyspace
  treewide: always allow tablets keyspaces
  feature_service: prevent enabling both tablets and gossip topology changes
  alternator: create_keyspace_metadata: enable tablets using feature_service
2024-10-28 21:33:17 +02:00
Nadav Har'El
6712fcc316 test/cql-pytest: add option to run cql-pytes tests against specific release
This patch adds the option "--release <version>" to test/cql-pytest/run,
which downloads the pre-compiled Scylla release with the given version
number and runs the tests against that version. For example, it can be used
to demonstrate that #15559 was indeed a regression between 2022.1 and 2022.2,
by running a recently-added test against these two old versions:

test/cql-pytest/run --release 2022.1 --runxfail \
        test_prepare.py::test_duplicate_named_bind_marker_prepared

test/cql-pytest/run --release 2022.2 --runxfail \
        test_prepare.py::test_duplicate_named_bind_marker_prepared

The first run passes, the second fails - showing the regression.

The Scylla releases are downloaded from ScyllaDB's S3 bucket
(downloads.scylladb.com). They are saved in the build/ directory
(e.g., build/2022.2.9), and if that directory is not removed, when
"run --release" requests the same version again, the previous download
is reused.

Release numbers can look like:

    * 5.4.7
    * 5.4 (will get the latest in the 5.4 branch, e.g., 5.4.7)
    * 5.4.0~rc2 (a prerelease)
    * 2021.1.9 (Enterprise release)
    * 2023.1 (latest in this branch, Enterprise release)

Fixes #13189

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#19228
2024-10-28 21:29:44 +02:00
Kefu Chai
f3dee5b636 build: enable CMAKE_CXX_EXTENSIONS explicitly
before this change, Seastar enables CXX_EXTENSIONS in its own
build rules. but it does not expose it to the parent project. but
scylladb's CMake building system respect seastar's .pc file and
includes the cflags exposed by it. without this change, scylladb
included "-std=c++23" from seastar, and "-std=gnu++23" from itself.
this is both confusing and inconsistent with the build rules generated
by `configure.py`.

in this change, we explicitly set `CMAKE_CXX_EXTENSIONS` when creating
Seastar's building rules, so that it can populate this setting to its
.pc file. in this way, we don't have two different options for
specifying the C++ standard when building scylladb with CMake.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21311
2024-10-28 21:23:04 +02:00
Kefu Chai
8b80ef3290 build: Remove GCC ARM warning workaround (originally added in 193d1942)
The workaround was initially added to silence warnings on GCC < 6.4 for ARM
platforms due to a compiler bug (gcc.gnu.org/bugzilla/show_bug.cgi?id=77728).
Since our codebase now requires modern GCC versions for coroutine support,
and the bug was fixed in GCC 6.4+, this workaround is no longer needed.

Refs 193d1942f2

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21308
2024-10-28 21:19:56 +02:00
Avi Kivity
94c21e5c05 Merge 'sstables: Reduce amount of I/O for clustering-key-bounded reads from large partitions' from Tomasz Grabiec
Single-row reads from large partition issue 64 KiB reads to the data file,
which is equal to the default span of the promoted index block in the data file.
If users would want to increase selectivity of the index to speed up single-row reads,
this won't be effective. The reason is that the reader uses promoted index
to look up the start position in the data file of the read, but end position
will in practice extend to the next partition, and amount of I/O will be
determined by the underlying file input stream implementation and its
read-ahead heuristics. By default, that results in at least 2 IOs 32KB each.

There is already infrastructure to lookup end position based on upper
bound of the read, in anticipation for sharing the promoted index cache,
but it's not effective becasue it's a non-populating lookup and the upper
bound cursor has its own private cached_promoted_index, which is cold
when positions are computed. It's non-populating on purpose, to avoid
extra index file IO to read upper bound. In case upper bound is far-enough
from the lower bound, this will only increase the cost of the read.

The solution employed here is to warm up the lower bound cursor's
cache before positions are computed, and use that cursor for
non-populating lookup of the upper bound.

We use the lower bound cursor and the slice's lower bound so that we
read the same blocks as later lower-bound slicing would, so that we
don't incur extra IO for cases where looking up upper bound is not
worth it, that is when upper bound is far from the lower bound. If
upper bound is near lower bound, then warming up using lower bound
will populate cached_promoted_index with blocks which will allow us to
locate the upper bound block accurately.  This is especially important
for single-row reads, where the bounds are around the same key.  In
this case we want to read the data file range which belongs to a
single promoted index block.  It doesn't matter that the upper bound
is not exactly the same. They both will likely lie in the same block,
and if not, binary search will bring adjacent blocks into cache.  Even
if upper bound is not near, the binary search will populate the cache
with blocks which can be used to narrow down the data file range
somewhat.

Fixes #10030.

The change was tested with perf-fast-forward.

I populated the data set with `column_index_size_in_kb` set to 1

  scylla perf-fast-forward --populate --run-tests=large-partition-slicing --column-index-size-in-kb=1

Test run:

  build/release/scylla perf-fast-forward --run-tests=large-partition-select-few-rows -c1 --keep-cache-across-test-cases --test-case-duration=0

This test issues two reads of subsequent keys from the middle of a large partition (1M rows in total). The first read will miss in the index file page cache, the second read will hit.

Notice that before the change, the second read issued 2 aio requests worth of 64KiB in total.
After the change, the second read issued 1 aio worth of 2 KiB. That's because promoted index block is larger than 1 KiB.
I verified using logging that the data file range matches a single promoted index block.

Also, the first read which misses in cache is still faster after the change.

Before:

```
running: large-partition-select-few-rows on dataset large-part-ds1
Testing selecting few rows from a large partition:
stride  rows      time (s)   iterations     frags     frag/s    mad f/s    max f/s    min f/s    avg aio    aio      (KiB) blocked dropped  idx hit idx miss  idx blk    c hit   c miss    c blk    allocs   tasks insns/f    cpu
500000  1         0.009802            1         1        102          0        102        102       21.0     21        196       2       1        0        1        1        0        0        0       568     269 4716050  53.4%
500001  1         0.000321            1         1       3113          0       3113       3113        2.0      2         64       1       0        1        0        0        0        0        0       116      26  555110  45.0%
```

After:

```
running: large-partition-select-few-rows on dataset large-part-ds1
Testing selecting few rows from a large partition:
stride  rows      time (s)   iterations     frags     frag/s    mad f/s    max f/s    min f/s    avg aio    aio      (KiB) blocked dropped  idx hit idx miss  idx blk    c hit   c miss    c blk    allocs   tasks insns/f    cpu
500000  1         0.009609            1         1        104          0        104        104       20.0     20        137       2       1        0        1        1        0        0        0       561     268 4633407  43.1%
500001  1         0.000217            1         1       4602          0       4602       4602        1.0      1          2       1       0        1        0        0        0        0        0       110      26  313882  64.1%
```

Backports: none, not a regression

Closes scylladb/scylladb#20522

* github.com:scylladb/scylladb:
  perf: perf_fast_forward: Add test case for querying missing rows
  perf-fast-forward: Allow overriding promoted index block size
  perf-fast-forward: Test subsequent key reads from the middle in test_large_partition_select_few_rows
  perf-fast-forward: Allow adding key offset in test_large_partition_select_few_rows
  perf-fast-forward: Use single-partition reads in test_large_partition_select_few_rows
  sstables: bsearch_clustered_cursor: Add more tracing points
  sstables: reader: Log data file range
  sstables: bsearch_clustered_cursor: Unify skip_info logging
  sstables: bsearch_clustered_cursor: Narrow down range using "end" position of the block
  sstables: bsearch_clustered_cursor: Skip even to the first block
  test: sstables: sstable_3_x_test: Improve failure message
  sstables: mx: writer: Never include partition_end marker in promoted index block width
  sstables: Reduce amount of I/O for clustering-key-bounded reads from large partitions
  sstables: clustered_cursor: Track current block
2024-10-28 21:13:23 +02:00
Tomasz Grabiec
0f2101b055 utils: cached_file: Mark permit as awaiting on page miss
Otherwise, the read will be considered as on-cpu during promoted index
search, which will severely underutlize the disk because by default
on-cpu concurrency is 1.

I verified this patch on the worst case scenario, where the workload
reads missing rows from a large partition. So partition index is
cached (no IO) and there is no data file IO. But there is IO during
promoted index search (via cached_file). Before the patch this
workload was doing 4k req/s, after the patch it does 30k req/s.

The problem is much less pronounced if there is data file or index
file IO involved because that IO will signal read concurrency
semaphore to invite more concurrency.
2024-10-28 19:54:58 +01:00
Tomasz Grabiec
868f5b59c4 utils: cached_file: Push resource_unit management down to cached_file
It saves us permit operations on the hot path when we hit in cache.

Also, it will lay the ground for marking the permit as awaiting later.
2024-10-28 19:49:58 +01:00
Avi Kivity
d3dae09316 compound: replace boost ranges with std ranges
Standardize on the standard range library.

The serialize_value(initializer_list) overload is disambiguated
not to call itself. Apparently it wasn't called before.

Since std::ranges::subrange does not provide operator==, replace
it with std::ranges::equals().
2024-10-28 18:35:41 +02:00
Avi Kivity
61d7f1f6a5 compound: upgrade iterator to be an std::forward_iterator
compound::iterator isn't far from a forward_iterator, and if we want
to use it with std::ranges, we have to upgrade it. This is because
std::ranges::subrange() only provides front() for forward ranges, and
we do use this front(). Boost apparently isn't as strict.

To make it a forward_range, we have to drop operator-> and make
operator* return a value (similar to std::views::tranform), since
forward iterators require that pointers and references be stable,
and this iterator returns a pointer to one of its members.

We also add an iterator_concept member to declare the compatibility
to std::ranges.
2024-10-28 17:16:36 +02:00
Kamil Braun
101c1d50f0 Merge 'fix nodetool status to show zero-token nodes' from Abhinav Kumar Jha
In the current scenario, the nodetool status doesn’t display information regarding zero token nodes. For example, if 5 nodes are spun by the administrator, out of which, 2 nodes are zero token nodes, then nodetool status only shows information regarding the 3 non-zero token nodes.

This commit intends to fix this issue by leveraging the “/storage_service/host_id ” API  and adding appropriate logic in scylla-nodetool.cc to support zero token nodes.

A test is also added in nodetool/test_status.py to verify this logic. This test fails without this commit’s zero token node support logic, hence verifying the behavior.

This PR fixes a bug. Hence we need to backport it. Backporting needs to be done only
to 6.2 version, since earlier versions don't support zero token nodes.

Fixes: scylladb/scylladb#19849
Fixes: scylladb/scylladb#17857

Closes scylladb/scylladb#20909

* github.com:scylladb/scylladb:
  fix nodetool status to show zero-token nodes
  test: move `wait_for_first_completed` to pylib/util.py
  token_metadata: rename endpoint_to_host_id_map getter and add support for joining nodes
2024-10-28 12:19:36 +01:00
Kefu Chai
9f8adcd207 backup_task: track the first failure uploading sstables
before this change, we only record the exception returned
by `upload_file()`, and rethrow the exception. but the exception
thrown by `update_file()` not populated to its caller. instead, the
exceptional future is ignored on pupose -- we need to perform
the uploads in parallel.  this is why the task is not marked fail
even if some of the uploads performed by it fail.

in this change, we

- coroutinize `backup_task_impl::do_backup()`. strictly speaking,
  this is not necessary to populate the exception. but, in order
  to ensure that the possible exception is captured before the
  gate is closed, and to reduce the intentation, the teardown
  steps are performed explicitly.
- in addition to note down the exception in the logging message,
  we also store it in a local variable, which it rethrown
  before this function returns.

Fixes scylladb/scylladb#21248
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21254
2024-10-28 12:54:27 +03:00
Tzach Livyatan
1878af9399 Update os-support-info.rst - add CentOS
ScyllaDB support RHEL 9 and derivatives, including CentOS 9.

Fix https://github.com/scylladb/scylladb/issues/21309

Closes scylladb/scylladb#21310
2024-10-28 10:02:31 +02:00
Kefu Chai
8ac471b74b dht: do not include unused headers
in 8d1b3223, we removed some unused "#include"s, but we failed to
address all of them in "dht" subdirectory. and the unaddressed
"#include"s are identified by the iwyu workflow.

in this change, we address the leftovers.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21291
2024-10-28 09:58:42 +02:00
Anna Stuchlik
44a807f5bc doc: improve the README file in the docs folder
This commit improves the README file so that it's more helpful
to documentation contributors. Especially, it:
- Adds the link to the prerequisites.
- Add information on troubleshooting (checking the links, headings, etc.)
- Removes the section on creating a knowledge base article, as we no longer
  promote adding KBs in favor of creating a coherent documentation set.

Fixes https://github.com/scylladb/scylladb/issues/21257

Closes scylladb/scylladb#21262
2024-10-28 09:55:40 +02:00
Anna Stuchlik
212eb204a7 doc: set 6.2 as the latest stable version
This commit updates the configuration for ScyllaDB documentation so that:
- 6.2 is the latest version.
- 6.2 is removed from the list of unstable versions.

It must be merged when ScyllaDB 6.2 is released.

In addition, this commit uncomments the redirections that should be applied
when version 6.2 is the latest stable version (which will happen when this commit
is merged).

No backport is required.

Closes scylladb/scylladb#21133
2024-10-28 09:45:37 +02:00
Pavel Emelyanov
420baf5035 api: Make get_highest_supported_sstable_version use proper service
This endpoint now grabs one via database -> table -> sstables manager
chain, but there's shorter route, namely via sstables format selector.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-28 10:18:57 +03:00
Pavel Emelyanov
61c8b571e5 api: Move system::get_highest_supported_sstable_version set/unset
It's currently registered with all other system endpoints and is not
unregistered. Its correct place is in the sstables-format-selector
set/unset functions.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-28 10:18:23 +03:00
Pavel Emelyanov
f090bdabbb api: Scaffold for sstables-format-selector
This "service" will have its own endpoint soon

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-28 10:17:38 +03:00
Botond Dénes
31342ecb5d Merge 'tasks: fix virtual tasks children' from Aleksandra Martyniuk
Fix how regular tasks that have a virtual parent are created
in task_manager::module::make_task: set sequence number
of a task and subscribe to module's abort source.

Fixes: #21278.

Needs backport to 6.2

Closes scylladb/scylladb#21280

* github.com:scylladb/scylladb:
  tasks: fix sequence number assignment
  tasks: fix abort source subscription of virtual task's child
2024-10-28 08:59:40 +02:00
Aleksandra Martyniuk
85d9565158 test: repair: drop log checks from test_repair_succeeds_with_unitialized_bm
Currently, test_repair_succeeds_with_unitialized_bm checks whether
repair finishes successfully and the error is properly handled
if batchlog_manager isn't initialized. Error handling depends on
logs, making the test fragile to external conditions and flaky.

Drop the error handling check, successful repair is a sufficient
passing condition.

Fixes: #21167.

Closes scylladb/scylladb#21208
2024-10-28 08:39:16 +02:00
Botond Dénes
416159e5d9 Merge 'docs/alternator: explain service discovery HTTP requests' from Nadav Har'El
Add a description of the service discovery HTTP requests - `/` and  `/localnodes` that was previously not documented except in a design document that is unfortunately no longer available publically (https://docs.google.com/document/d/1twgrs6IM1B10BswMBUNqm7bwu5HCm47LOYE-Hdhuu_8/edit).

Fixes https://github.com/scylladb/scylladb/issues/20989

Developer-oriented documentation so no need to backport.

Closes scylladb/scylladb#21000

* github.com:scylladb/scylladb:
  docs/alternator: explain service discovery HTTP requests
  docs/alternator: split Alternator-specific APIs from alternator.md
2024-10-28 08:21:28 +02:00
Benny Halevy
2268912589 docs: add documentation for scylla_identifier
Commit 3a12ad96c7
added an sstable_identifier uuid to the SSTable
scylla_metadata component, however it was
under-documented and this patch adds the missing
documentation for the sstable component format,
and to the scylla sstable tool documentation.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#21221
2024-10-28 08:18:08 +02:00
Kefu Chai
0f9d2ab577 build: cmake: disable Seastar exception hack
in cc3953e5, we disabled Seastar exception hack in configure.py.
this change disabled the Seastar exception hack in the following
two builds:

- build generated directly by configure.py
- build configured with multi-config generator using CMake

but we also have non-multi-config build using CMake. to be more
consistent, let's apply the equivalent change to non-multi-config
build of CMake.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21233
2024-10-28 08:11:43 +02:00
Botond Dénes
be70755f47 Merge 'repair: Fix finished ranges metrics for removenode' from Asias He
The skipped ranges should be multiplied by the number of tables

Otherwise the finished ranges ratio will not reach 100%.

Fixes #21174

Closes scylladb/scylladb#21252

* github.com:scylladb/scylladb:
  test: Add test_node_ops_metrics.py
  repair: Make the ranges more consistent in the log
  repair: Fix finished ranges metrics for removenode
2024-10-28 08:09:32 +02:00
Asias He
9868ccbac0 test: Add test_node_ops_metrics.py
It tests the node_ops_metrics_done metric reaches 100% when a node ops
is done.

Refs: #21174
2024-10-28 08:45:37 +08:00
Pavel Emelyanov
2f9f76fddf sstables_loader: Mark to_replica_set() private
It's not called from outside

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21210
2024-10-27 22:28:54 +02:00
Anna Stuchlik
ef4bcf8b3f doc: remove the Cassandra references from notedool
This PR removes the reference to Cassandra from the nodetool index,
as the native nodetool is no longer a fork.

In addition, it removes the Apache copyright.

Fixes https://github.com/scylladb/scylladb/issues/21238

Closes scylladb/scylladb#21240
2024-10-27 22:26:33 +02:00
Kefu Chai
e65185ba6f build: merge scylla's and seastar's compilation database
Since commit 415c83fa, Seastar is built as an external project. As a result,
the compile_commands.json file generated by ScyllaDB's CMake build system no
longer contains compilation rules for Seastar's object files. This limitation
prevents tools from performing static analysis using the complete dependency
tree of translation units.

This change merges Seastar's compilation database with ScyllaDB's and places
the combined database in the source root directory, maintaining backward
compatibility.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21234
2024-10-27 22:01:29 +02:00
Tomasz Grabiec
850d9cfb59 node-exporter: Disable hwmon collector
This collector reads nvme temperature sensor, which was observed to
cause bad performance on Azure cloud following the reading of the
sensor for ~6 seconds. During the event, we can see elevated system
time (up to 30%) and softirq time. CPU utilization is high, with
nvm_queue_rq taking several orders of magnitude more time than
normally. There are signs of contention, we can see
__pv_queued_spin_lock_slowpath in the perf profile, called. This
manifests as latency spikes and potentially also throughput drop due
to reduced CPU capacity.

By default, the monitoring stack queries it once every 60s.

Closes scylladb/scylladb#21165
2024-10-27 21:59:15 +02:00
Kefu Chai
f5b29331a2 build: populate --enable-dist --disable-dist to CMake
before this change, the "dist" targets are always enabled in the
CMake-based building system. but the build rules generated by
`configure.py` does respect `--enable-dist` and `--disable-dist`
command line options, and enable/distable the dist targets
respectively.

in this change, we

- add an CMake option named "Scylla_DIST". the "dist"
  subdirectory in CMake only if this option is ON.
- pouplate the `--enable-dist` and `--disable-dist` option
  down to cmake by setting the `Scylla_DIST` option,
  when creating the build system using CMake.

this enables the CMake-based build system to be functionality
wise more closer to the legacy building system.

Refs scylladb/scylladb#2717

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21253
2024-10-27 21:57:46 +02:00
Kefu Chai
24d14b601b treewide: s/boost::adaptors::map_values/std::views::values/
now that we are allowed to use C++23. we now have the luxury of using
`std::views::values`.

in this change, we:

- replace `boost::adaptors::map_values` with `std::views::values`
- update affected code to work with `std::views::values`
- the places where we use `boost::join()` are not changed, because
  we cannot use `std::views::concat` yet. this helper is only
  available in C++26.

to reduce the dependency to boost for better maintainability, and
leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase
and reduce external dependencies where possible.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21265
2024-10-27 21:32:45 +02:00
Avi Kivity
3124711fc4 Merge 'Report rows_merged in compaction_history rest api and nodetool' from Łukasz Paszkowski
Currently, running the `nodetool compactionhistory` command or using the rest api `curl -X GET --header "Accept: application/json" "http://localhost:10000/compaction_manager/compaction_history"` return compaction history without the `row_merged` field.

The series computes rows merged during compaction and provides this information to users via both the nodetool command and the rest api. The `rows_merged` field contains information on merged clustering keys across multiple sstable files. For instance, compacting two sstables of a table consisting of 7 rows where two rows are part of the both sstables, the output would have the following format: {1: 5, 2: 2}.

No backport is required. It extends the existing compaction history output.

Fixes https://github.com/scylladb/scylladb/issues/666

Closes scylladb/scylladb#20481

* github.com:scylladb/scylladb:
  test/rest_api: Add tests for compactionhistory
  nodetool: Add rows merged stats into compactionhistory output
  compaction: Update compaction history with collected histogram
  compaction: Remove const qualifier from methods creating sstable readers
  sstable_set: Add optional statistics to make_local_shard_sstable_reader
  make_combined_reader: Add optional parameter, combined_reader_statistics
  reader_selector: Extend with maximum reader count
  mutation_fragment_merger: Create histogram while consuming mutation fragment batches
2024-10-27 21:26:11 +02:00
Kefu Chai
158008dd2c mutation_writer: simplify classification using with_deserialized() return value
Since `with_deserialized()` returns the lambda function's result, we can
directly return the bucket from within the lambda instead of relying on
side effects. This makes the code more explicit and functional.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21273
2024-10-27 21:20:55 +02:00
Nadav Har'El
6fdd0ebd3b RBAC: confirm that unprivileged users can't read the roles table
A worry was raised that an unprivileged user might be able to read the
system.roles table - which contains the Alternator secret keys (and also
CQL's hashed passwords). This patch adds tests that show that this worry
is unjustified - and acts as a regression test to ensure it never
becomes justified. The tests show that an unprivileged user cannot read
the system.roles table using either CQL or Alternator APIs.

More specifically, the two tests in this patch demonstrate that:

* The Alternator API does not allow an unprivileged user to read ANY system
  table, unless explicitly granted permissions for that table.

* The CQL API whitelists (see service::client_state::has_access) specific
  system tables - e.g., system_schema.tables - that are made readable to any
  unprivileged user. But the system.auth table is NOT whitelisted in this
  way - and is unreadable to unprivileged users unless explicitly granted
  permissions on that table.

The new tests passes on both Scylla and Casssandra.

Refs #5206 (that issue is about removing the Alternator secret keys from
the roles table - but stealing CQL salted hashes is still pretty bad, so
it's good to know that unprivileged users can't read them).

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#21215
2024-10-27 21:09:38 +02:00
Nadav Har'El
1634a64ffd cql-pytest: test a few small materialized views CQL issues
While documenting materialized view in a new document (Refs #16569)
I encountered a few questions on how various CQL operations work on
a table that has views, and this patch contains tests that clarify their
answer - and can later guarantee that the answer doesn't unintentionally
change in the future. The questions that these tests answer are:

1. That TRUNCATE on a base table also TRUNCATEs its views. This is just
   a basic test, with no attempt to reproduce issue #17635 (which is
   about the truncation of the base and views not being atomic).

2. That DROP TABLE is *not allowed* on a base table that has views.

3. That DROP KEYSPACE is allowed, even if there are tables with views.

4. Test that ALTER TABLE tbl DROP is never allowed in Cassandra, but
   allowed in some cases by Scylla

5. Test that ALTER TABLE tbl ADD is allowed, and "SELECT *" expands to
   select the new column into the materialized view as well.

All the new tests pass on both Scylla and Cassandra.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#21142
2024-10-27 21:08:28 +02:00
Botond Dénes
7c75fc599f streaming: stream-session: switch to tracking permit
The stream-session is the receiving end of streaming, it reads the
mutation fragment stream from an RPC stream and writes it onto the disk.
As such, this part does no disk IO and therefore, using a permit with
count resources is superfluous. Furthermore, after
d98708013c, the count resources on this
permit can cause a deadlock on the receiver end, via the
`db::view::check_view_update_path()`, which wants to read the content of
a system table and therefore has to obtain a permit of its own.

Switch to a tracking-only permit, primarily to resolve the deadlock, but
also because admission is not necessary for a read which does no IO.

Refs: scylladb/scylladb#20885 (partial fix, solves only one of the deadlocks)
Fixes: scylladb/scylladb#21264

Closes scylladb/scylladb#21059
2024-10-27 20:01:25 +02:00
Avi Kivity
7ffbfe8bb3 Merge 'Squash some sstables::test helpers' from Pavel Emelyanov
There's a `missing_summary_first_last_sane` test case that uses some very specific way of modifying an sstable -- it loads one from resources, then tries to "write" the loaded stuff elsewhere. For that it uses a special purpose test::store() helper and a bunch of auxiliary ones from the same class. Those aux helpers are not used anywhere else and are also very special for this test case, so it make sense to keep this whole functionality in a single helper.

Closes scylladb/scylladb#21255

* github.com:scylladb/scylladb:
  test: Squash test::change_generation_number() into test::store()
  test: Squash test::change_dir() into test::store()
  test: Coroutinize sstables::test::store()
2024-10-27 19:59:59 +02:00
Anna Stuchlik
aa0dadea48 doc: extend the ToC for CDC
This commit adds the missing links to the CDC index page.

Fixes https://github.com/scylladb/scylladb/issues/21137

Closes scylladb/scylladb#21286
2024-10-27 19:57:59 +02:00
Anna Stuchlik
b2b9622e32 doc: fix redundant references to version 6.2
This commit removes mentions of version 6.2 that were introduced
with https://github.com/scylladb/scylladb/pull/17969.

Now that the documentation is versioned, there should be no reference to specific versions.

Fixes https://github.com/scylladb/scylladb/issues/21276

Closes scylladb/scylladb#21277
2024-10-27 14:47:40 +02:00
Paweł Zakrzewski
b077685fec test/cql-pytest: GROUP BY with static columns
This commit adds a new test case 'test_group_by_static_column_and_tombstones'
to verify the behavior of GROUP BY queries with static columns. The test is
adapted from Cassandra's test suite and aims to reproduce issue #21267.

Original, larger test:
cassandra_tests/validation/operations/select_group_by_test.py::testGroupByWithPaging()

Closes scylladb/scylladb#21270
2024-10-27 14:45:53 +02:00
Aleksandra Martyniuk
910a6fc032 tasks: fix sequence number assignment
Currently, children of virtual tasks do not have sequence number
assigned. Fix it.
2024-10-25 15:30:13 +02:00
Aleksandra Martyniuk
1eb47b0bbf tasks: fix abort source subscription of virtual task's child
Currently, if a regular task does not have a parent or its parent
is a virtual tasks then it subscribes to module's abort source
in task_manager::task::impl constructor. However, at this point
the kind of the task's parent isn't set. Due to that, children
of virtual tasks aren't aborted on shutdown.

Subscribe to module's abort source in task::impl::set_virtual_parent.
2024-10-25 14:18:00 +02:00
Kefu Chai
e7d6ab576b backup_task: remove unused member variable
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21258
2024-10-25 11:49:06 +03:00
Abhinav
c00d40b239 fix nodetool status to show zero-token nodes
In the current scenario, the nodetool status doesn’t display information
regarding zero token nodes. For example, if 5 nodes are spun by the
administrator, out of which, 2 nodes are zero token nodes, then nodetool
status only shows information regarding the 3 non-zero token nodes.

This commit intends to fix this issue by leveraging the “/storage_service/host_id
” API  and adding appropriate logic in scylla-nodetool.cc to support zero token nodes.

Robust topology tests are added, which spins up scylla nodes and confirm nodetool
status output for various cases, providing good coverage.
A test is also added in nodetool/test_status.py to verify this logic. These tests fail
without this commit’s zero token node support logic, hence verifying the behavior.

The test `test_status_keyspace_joining_node` has been removed. This test is
based on case where host_id=None, which is impossible. Since we now use
host_id_map for node discovery in nodetool, the nodes with "host_id=None"
go undetected. Since this case is anyway impossible, we can get rid of this.

This PR fixes a bug. Hence we need to backport it. Backporting needs to be done only
to 6.2 version, since earlier versions dont support zero token nodes.

Fixes: scylladb/scylladb#19849
2024-10-25 13:28:09 +05:30
Abhinav
39dfd2d7ac test: move wait_for_first_completed to pylib/util.py
This function is needed in a new test added in the next commit and this
refactoring avoids code duplication.
2024-10-25 13:26:42 +05:30
Abhinav
72f3c95a63 token_metadata: rename endpoint_to_host_id_map getter and add support for joining nodes
Rename host_id map getter, 'get_endpoint_to_host_id_map_for_reading' to 'get_endpoint_to_host_id_map_'
Also modify the getter to return information regarding joining nodes as well.

This getter will later be used for retrieving the nodes in nodetool status, hence it needs to show all nodes,
including joining ones.

The function name suffix `_for_reading` suggests that the function was used
in some other places in the past, and indeed if we need endpoints
"for reading" then we cannot show joining endpoints. But it was confirmed
that this function is currently only used by "/storage_service/host_id" endpoint,
hence it can be modified as required.

Fixes: scylladb/scylladb#17857
2024-10-25 13:20:27 +05:30
Pavel Emelyanov
5e713b2b14 Merge 'dht: remove unused #includes ' from Kefu Chai
these unused includes are identified by clang-include-cleaner. after auditing the source files, all of the reports have been
confirmed.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#21237

* github.com:scylladb/scylladb:
  .github: add dht to iwyu's CLEANER_DIR
  dht: remove unused `#include`s
2024-10-24 18:40:49 +03:00
Pavel Emelyanov
7595ef7303 test: Squash test::change_generation_number() into test::store()
No other usages of the former helper other than immediatelly followed by
the latter, no point in keepint it around.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-24 11:29:17 +03:00
Pavel Emelyanov
e885b0e6cd test: Squash test::change_dir() into test::store()
No other usages of the former helper other than immediatelly followed by
the latter, no point in keepint it around.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-24 11:28:39 +03:00
Pavel Emelyanov
874cf2ea6f test: Coroutinize sstables::test::store()
Ahead of future changes

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-24 11:28:07 +03:00
Benny Halevy
5498018cbe data_dictionary: keyspace_metadata::describe: print tablets enabled also when defaulted
Now that tablets may be explicitly enabled when
creating a new keyspace, describe tablets as enabled
even when the default initial_tablets==0 is used.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-24 10:18:42 +03:00
Benny Halevy
63cbb6e071 tablets_test: test enable/disable tablets when creating a new keyspace
Test both configuration values for `enable_tablets`
and the possibility to explicitly enable or disable
tablets, respectively, when creating a keyspace using the
`tablets = {'enabled': true|false}` CREATE KEYSPACE option.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-24 10:18:42 +03:00
Benny Halevy
b0e12cb40d treewide: always allow tablets keyspaces
With the tablets feature always enabled (Unless gossip toopology
changes are forced), the enable_tablets option now controls only
the default for newly created keyspaces.

Even when set to `false`, tablets are still enabled as a
feature and the user may explicitly enable tablets
using `CREATE KEYSPACE <name> WITH tablets = {'enabled': true}`

Note: best viewed with `git show -w`

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-24 10:18:42 +03:00
Benny Halevy
bc62407421 feature_service: prevent enabling both tablets and gossip topology changes
Tablets require raft consistent topology changes.
Therefore, document that they are incompatible in
the config help and prevent their usage in
`feature_config_from_db_config`

Fixes scylladb/scylladb#21075

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-24 10:18:42 +03:00
Benny Halevy
9ef2dc2428 alternator: create_keyspace_metadata: enable tablets using feature_service
Rather than using the local configuration option
on this node, check the cluster feature instead.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-24 10:18:42 +03:00
Asias He
1392a6068d repair: Make the ranges more consistent in the log
Consider the number of tables for the number of ranges logging. Make it
more consistent with the log when the ops starts.
2024-10-24 10:31:15 +08:00
Asias He
cffe3dc49f repair: Fix finished ranges metrics for removenode
The skipped ranges should be multiplied by the number of tables.

Otherwise the finished ranges ratio will not reach 100%.

Fixes #21174
2024-10-24 10:31:15 +08:00
Kefu Chai
a9e18f70b0 Revert submodule change in 6ead5a4696
in 6ead5a46, we included submodule changes in cqlsh and java by accident.
this was not intended. and this broke the artifacts-rocky8-test.

in this change, both changes in the submodule are reverted.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21236
2024-10-23 19:49:20 +03:00
Pavel Emelyanov
9014da26e1 Merge 'docs: reference object storage config doc from nodetool commands ' from Kefu Chai
this series:

- promote object storage configuration to user-facing documentation
- reference object storage config doc from nodetool commands

---

the nodetool backup/restore commands are not included by any LTS branches yet, hence no need to backport.

Closes scylladb/scylladb#21071

* github.com:scylladb/scylladb:
  docs: move keyspace-storage-option from cql-extensions to admin
  docs: reference admin.rst for object storage config
  docs: reference object storage config doc from nodetool commands
  docs: promote object storage configuration to user-facing documentation
2024-10-23 19:41:46 +03:00
Michał Jadwiszczak
68d0c9a18a test/auth_cluster/test_raft_service_levels: match enterprise SL limit
Despite OSS doesn't limit number of created service levels, match the
enterprise limit to decrease divergence in the test between OSS and
enterprise.

Fixes scylladb/scylladb#21044

Closes scylladb/scylladb#21045
2024-10-23 17:44:19 +02:00
Kefu Chai
bea18f0571 .github: add dht to iwyu's CLEANER_DIR
to avoid future violations of include-what-you-use.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-23 17:45:14 +08:00
Kefu Chai
8d1b3223ab dht: remove unused #includes
these unused includes are identified by clang-include-cleaner.
after auditing the source files, all of the reports have been
confirmed.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-23 17:45:14 +08:00
Dawid Mędrek
298cafff35 cql-pytest/test_describe: Introduce auxiliary type for service levels
We introduce an auxiliary type representing a service level for making
it easier to adjust the tests in Enterprise. We move the responsibility
of producing create statements for service levels to the class, so we
only need to modify the code in one place when necessary.

All existing relevant tests have been adjusted to this change.

Closes scylladb/scylladb#21230
2024-10-23 10:15:25 +02:00
Kamil Braun
f5c60e538d Merge 'cql/tablets: fix retrying ALTER tablets KEYSPACE' from Piotr Smaron
ALTER tablets-enabled KEYSPACES (KS) may fail due to
`group0_concurrent_modification`, in which case it's repeated by a `for`
loop surrounding the code. But because raft's `add_entry` consumes the
raft's guard (by `std::move`'ing the guard object), retries of ALTER KS
will use a moved-from guard object, which is UB, potentially a crash.
The fix is to remove the before mentioned `for` loop altogether and rethrow the exception, as the `rf_change` event
will be repeated by the topology state machine if it receives the
concurrent modification exception, because the event will remain present
in the global requests queue, hence it's going to be executed as the
very next event.
Note: refactor is implemented in the follow-up commit.

Fixes: scylladb/scylladb#21102

Should be backported to every 6.x branch, as it may lead to a crash.

Closes scylladb/scylladb#21121

* github.com:scylladb/scylladb:
  test: add UT to test retrying ALTER tablets KEYSPACE
  cql/tablets: fix indentation in `rf_change` event handler
  cql/tablets: fix retrying ALTER tablets KEYSPACE
2024-10-23 10:01:21 +02:00
Botond Dénes
519e167611 Merge 'replica/table: check memtable before discarding tombstone during read' from Lakshmi Narayanan Sreethar
On the read path, the compacting reader is applied only to the sstable
reader. This can cause an expired tombstone from an sstable to be purged
from the request before it has a chance to merge with deleted data in
the memtable leading to data resurrection.

Fix this by checking the memtables before deciding to purge tombstones
from the request on the read path. A tombstone will not be purged if a
key exists in any of the table's memtables with a minimum live timestamp
that is lower than the maximum purgeable timestamp.

Fixes #20916

`perf-simple-query` stats before and after this fix :

`build/Dev/scylla perf-simple-query --smp=1 --flush` :
```
// Before this Fix
// ---------------
94941.79 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59393 insns/op,   24029 cycles/op,        0 errors)
97551.14 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59376 insns/op,   23966 cycles/op,        0 errors)
96599.92 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59367 insns/op,   23998 cycles/op,        0 errors)
97774.91 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59370 insns/op,   23968 cycles/op,        0 errors)
97796.13 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59368 insns/op,   23947 cycles/op,        0 errors)

         throughput: mean=96932.78 standard-deviation=1215.71 median=97551.14 median-absolute-deviation=842.13 maximum=97796.13 minimum=94941.79
instructions_per_op: mean=59374.78 standard-deviation=10.78 median=59369.59 median-absolute-deviation=6.36 maximum=59393.12 minimum=59367.02
  cpu_cycles_per_op: mean=23981.67 standard-deviation=32.29 median=23967.76 median-absolute-deviation=16.33 maximum=24029.38 minimum=23947.19

// After this Fix
// --------------
95313.53 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59392 insns/op,   24058 cycles/op,        0 errors)
97311.48 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59375 insns/op,   24005 cycles/op,        0 errors)
98043.10 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59381 insns/op,   23941 cycles/op,        0 errors)
96750.31 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59396 insns/op,   24025 cycles/op,        0 errors)
93381.21 tps ( 71.1 allocs/op,   0.0 logallocs/op,  14.1 tasks/op,   59390 insns/op,   24097 cycles/op,        0 errors)

         throughput: mean=96159.93 standard-deviation=1847.88 median=96750.31 median-absolute-deviation=1151.55 maximum=98043.10 minimum=93381.21
instructions_per_op: mean=59386.60 standard-deviation=8.78 median=59389.55 median-absolute-deviation=6.02 maximum=59396.40 minimum=59374.73
  cpu_cycles_per_op: mean=24025.13 standard-deviation=58.39 median=24025.17 median-absolute-deviation=32.67 maximum=24096.66 minimum=23941.22
```

This PR fixes a regression introduced in ce96b472d3 and should be backported to older versions.

Closes scylladb/scylladb#20985

* github.com:scylladb/scylladb:
  topology-custom: add test to verify tombstone gc in read path
  replica/table: check memtable before discarding tombstone during read
  compaction_group: track maximum timestamp across all sstables
2024-10-23 10:28:00 +03:00
Botond Dénes
d6a79fefda Merge 'Do not leak S3 file-uploading parts on exceptions' from Pavel Emelyanov
File uploading code spawns all parts uploading into background. If this "spawning" fails (not the uploading code itself), any fiber that was spawned before is orphaned. It will eventually stop on its own, by while it's alive it may use(-after-free) the do_upload_file object.

Another issue with not handling spawn exception, is that multipart upload object is not aborted in this case. So it's leaked until garbage collector picks it up, which is not critical, but unpleasant.

Closes scylladb/scylladb#21139

* github.com:scylladb/scylladb:
  s3/client: Restore indentation after previous patch
  s3/client: Catch do_upload_file::upload_part() exceptions
2024-10-23 10:12:29 +03:00
Ernest Zaslavsky
59e2ed884d Update seastar submodule
* seastar abd20efd...f821bda1 (17):
  > http: http status classification
  > loopback: add pending capacity param and fix deadlock in httpd_test
  > allow setting buffer sizes on server_socket
  > core: add missing assert header to chunked_fifo
  > cmake: Don't emit message when searching for libarchive
  > stall-analyser: pass args.tmin instead of tmin
  > build: do not check for CMAKE_CXX_STANDARD < 20
  > README.md: specify CMAKE_CXX_STANDARD in the sample
  > cmake: Fix DPDK libarchive dep
  > c-ares: update cooking version to 1.32.3
  > build: support c-ares >= 1.34.1
  > iotune: clarify fsqual error message
  > Make total_steal_time() monotonic.
  > Remove account_idle
  > reactor: add better sleep time accounting
  > reactor: add cpu and awake time reactor metrics
  > Zero-init total sleep time

Closes scylladb/scylladb#21225
2024-10-23 09:30:56 +03:00
Botond Dénes
b9b778054a Merge 'test.py: Add option to fail after number of failures' from Petr Hála
* Add `--max-failures` flag to test.py, which will stop the execution after number of failures
   * Helps with "fails-fast" approach and can be used to improve CI speed, especially the 100times run
   * Adds the number of cancelled tests to both summary and junit xml. I did not include them in boost, since it does not contain any statistics.
* Removes unnecessary list creation in test.py
   * Completely unrelated change, but it is small enough that I feel it can be included as part of this one. If this is an issue I can create separate PR for it

*  Add `Test.started` property
   * Helps with determining the current status of the Test and differentiating cancelled/not started tests.
* Add `Test.failed` and `Test.did_not_run` read-only computed properties
   * Helper methods to determine status, instead of using `Test.success`, which does not tell the entire story
* Fix `ScyllaClusterManager.stop()` method, so it doesn't fail when ran multiple times
   * This happens when tasks are cancelled, not sure yet why, it almost certainly non-wanted behaviour but this behaviour was already there and with this fix it no longer causes errors

I will use backport/None for now as it is a new feature.

Fixes https://github.com/scylladb/qa-tasks/issues/1714

Closes scylladb/scylladb#21098

* github.com:scylladb/scylladb:
  test.py: Add option to fail after number of failures
  test.py: Add started, failed and did_not_run properties to Test
  test.py: Remove unnecessary list creation
  test: lib: Fix ScyllaClusterManager.stop()
2024-10-23 09:11:52 +03:00
Kefu Chai
6a7eaea9f4 mutation_writer/feed_writer: remove redundant check
`mutation_reader::is_end_of_stream()` returns
`_impl->is_end_of_stream() && is_buffer_empty()`, so
`!is_end_of_stream()` equals to `
`!_impl->is_end_of_stream() || !is_buffer_empty()`, which in turn
always equals to
`!_impl->is_end_of_stream() || !is_buffer_empty() || !is_buffer_empty()`.
hence there is no need to check `rd.is_buffer_empty()` again.

in this change, the redundant condition is dropped. simpler this way.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21224
2024-10-23 08:48:08 +03:00
Avi Kivity
cc3953e504 build: disable Seastar exception hack
In [1], Seastar started to bypass a lock in libgcc's exception throwing
mechanism to allow scalability on large machines. The problem is documented
in [2] and reported as fixed.

In [3], testing results on a 2s96c192t machine are reported. The problem
appears indeed fixed with gcc 14's runtime (which we use, even though we
build with clang).

Given the new results, we can safely drop the exception scalability hack.
As [1] states that the hack causes the loss of a translation cache, we
may gain some performance this way.

With that, we disable the cache by defining some random macro.

[1] https://github.com/scylladb/seastar/464f5e3ae43b366b05573018fc46321863bf2fae
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71744
[3] https://github.com/scylladb/seastar/issues/2479#issuecomment-2427098413

Closes scylladb/scylladb#21217
2024-10-22 22:20:07 +03:00
Nadav Har'El
5fd3177057 Merge 'mv: add a dedicated read concurrency semaphore for view update read before writes' from Wojciech Mitros
When writing to some tables with materialized views, we need to read from the base table first to perform a delete of the old view row. When doing so, the memory used for the read is tracked by the user read concurrency semaphore. When we have a large number of such reads, we may use up all of the semaphore units, causing the following reads to be queued. When we have some user reads coming at the same time, these reads can have very high latency due to the write workload on the base table. We want to avoid this, so that the write workload doesn't have a high impact on the latency of the read workload.

This is fixed in this patch by adding a separate read concurrency semaphore just for view update read-before-writes. With the new semaphore, even if there are many view update read-before-writes, they will be queued on a different semaphore than the user reads, and they won't impact their latency.

The second issue fixed by this patch is the concurrency of the view updates that is currently unlimited. Because of that view updates may take up so much memory that they we may run out of memory.

This is fixed by using the read admission on the view update concurrency semaphore.
This limits the number of concurrent view update reads to
max_count_concurrent_view_update_reads, all other incoming view update reads are
queued using just a small chunk of memory. Without this, the reads would also get
queued after exceeding view_update_reader_concurrency_semaphore_serialize_limit_multiplier, but they would take much more memory while staying in the queue.

The new semaphore has half the capacity of the regular user read concurrency semahpore and is currently used only for user writes - is't used independently of the scheduling group on which we base the read semaphore selection, but we use a different code path for streaming (not database::do_apply) and we shouldn't have view updates in system writes or during compaction.

This patch also adds a test to confirm that the view update workload doesn't impact the read latency, as well as a test which confirms that we do not run out of memory even under heavy view udpate workload.

The issue of view updates causing increased latencies most often occurs in the following scenario:
* we have a medium to high write workload to a table with a materialized view which requires reading from the base table before sending the update to delete the old rows
* we have any read workload
* one replica is slower or is handling more writes due to an imbalance of data distribution
* we write with a cl<ALL, the mentioned replica is replying to write requests slower while new ones keep being sent to it.
* each write performs a read first taking resources from the user read concurrency semaphore, so when enough writes accumulate the reads using the semaphore start getting queued
* the queue is shared by regular reads and view update reads. When there's enough view update reads in the queue, regular reads start getting increased latencies

An sct test (perf-regression-latency-mv-read-concurrency) was prepared to somewhat resemble this scenario:
* the tables were prepared satisfying the conditions above
* we use a medium write workload and a very low read workload
* the imbalance is achieved by writing to just a few (10) partitions - some replicas (and shards) can have twice or more used partitions than others. We also keep writing to a limited (though high) number of rows, to cause overwrites which require reading before sending the view update
* to minimize the test case, we use a cluster of 3 nodes and rf=2, we write with cl=ONE to have background replica writes and read with cl=ALL to wait for the slower replica to respond.

In the test above:
* without the fix, the latency of reads increases over 50s
* with the fix, the latency of reads stays below 20ms

Fixes https://github.com/scylladb/scylladb/issues/8873
Fixes https://github.com/scylladb/scylladb/issues/15805

The patch is not that small and it isn't fixing a regression, so no backports

Closes scylladb/scylladb#20887

* github.com:scylladb/scylladb:
  test: add test for high view update concurrency causing bad_allocs
  test: add test for high view update concurrency degrading read latency
  mv: add a dedicated read concurrency semaphore for view update read before writes
2024-10-22 22:17:23 +03:00
Aleksandra Martyniuk
878a12c922 test: change quotation marks
Before python 3.12 formatted strings couldn't have reused quotes.
Change the type of quotation mark in get_cgroup so it could be
used with earlier python versions.

Closes scylladb/scylladb#21209
2024-10-22 20:42:05 +03:00
Piotr Smaron
522bede8ec test: add UT to test retrying ALTER tablets KEYSPACE
The newly added testcase is based on the already existing
`test_alter_dropped_tablets_keyspace`.
A new error injection is created, which stops the ALTER execution just
before the changes are submitted to RAFT. In the meantime, a new schema
change is performed using the 2nd node in the cluster, thus causing the
1st node to retry the ALTER statement.
2024-10-22 18:22:01 +02:00
Piotr Smaron
3f4c8a30e3 cql/tablets: fix indentation in rf_change event handler
Just moved the code that previously was under a `for` loop by 1 tab, i.e. 4 spaces, to the left.
2024-10-22 18:22:01 +02:00
Piotr Smaron
de511f56ac cql/tablets: fix retrying ALTER tablets KEYSPACE
ALTER tablets-enabled KEYSPACES (KS) may fail due to
`group0_concurrent_modification`, in which case it's repeated by a `for`
loop surrounding the code. But because raft's `add_entry` consumes the
raft's guard (by `std::move`'ing the guard object), retries of ALTER KS
will use a moved-from guard object, which is UB, potentially a crash.
The fix is to remove the before mentioned `for` loop altogether and rethrow the exception, as the `rf_change` event
will be repeated by the topology state machine if it receives the
concurrent modification exception, because the event will remain present
in the global requests queue, hence it's going to be executed as the
very next event.
`topology_coordinator::handle_topology_coordinator_error` handling the
case of `group0_concurrent_modification` has been extended with logging
in order not to write catch-log-throw boilerplate.
Note: refactor is implemented in the follow-up commit.

Fixes: scylladb/scylladb#21102
2024-10-22 18:22:00 +02:00
Avi Kivity
ec543e3902 Merge 'Remove all_datadirs vector of strings from table::config' from Pavel Emelyanov
The all_datadirs keeps paths to directories where local sstables can be. In fact, Scylla doesn't put sstables there, but can try to find them on boot and when checking snapshots. The 0th element of this vector, called datadir, had recently been removed by #20675, now it's time to drop all_datadirs as well. The needed paths can be obtained from table's storage options (see #20542) and db::config::data_file_directories option.

Closes scylladb/scylladb#21212

* github.com:scylladb/scylladb:
  sstables: Open-code format_table_directory_name() moved recently
  replica,sstables: Move format_table_directory_name()
  table: Remove all_datadirs
  sstables: Generate table::all_datadirs from db::config and storage_options
  replica: Prepare vector of fs::path-s with table dirs
  table: Check storage options in get_snapshot_details()
2024-10-22 17:21:31 +03:00
Laszlo Ersek
63417f6a57 utils/small_vector: refactor expansion condition in reserve*()
Rewrite

  _begin + n > _capacity_end

as

  n > _capacity_end - _begin

and then as

  n > capacity()

for two reasons:

- The last form is easier to read than the first form.

- Per N4950 (the final C++23 working draft), [expr.add] paragraph 4, the
  expression

    _begin + n                            (i.e., P + J)

  is defined only if

    0 ≤ 0 + n ≤ _capacity_end - _begin    (i.e., 0 ≤ i + j ≤ n)

  equivalently, only if

    _begin ≤ _begin + n ≤ _capacity_end

  Therefore, the expression

    _begin + n

  invokes undefined behavior exactly when we'd expect our check

    _begin + n > _capacity_end

  to evaluate to true.

gcc and clang have been aggressively equating undefined behavior to "never
happens"; let's prevent that here.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>

Closes scylladb/scylladb#21213
2024-10-22 17:12:11 +03:00
Avi Kivity
847c850034 schema: add accessors for primary key columns and non-primary-key columns
It's somewhat common to ask for the partition key and clustering key
columns, or for the static and regular columsn. Provide accessors for them
rather than requiring the user to glue them.

Some callers are converted.

Closes scylladb/scylladb#21191
2024-10-22 15:01:14 +02:00
pehala
870f3b00fc test.py: Add option to fail after number of failures
Add --max-failures configuration option to specify the amount,
if not set, or not positive, it will never trigger.
Update also the junit reporting to include skipped tests
2024-10-22 13:29:34 +02:00
pehala
c1dd97a049 test.py: Add started, failed and did_not_run properties to Test
This ensures we can determine where in the execution pipeline
the test currently is.
failed and did_not_run are helper properties
2024-10-22 13:29:19 +02:00
pehala
e34dec71e7 test.py: Remove unnecessary list creation
Using generators & set constructor,
we can get rid of unnecessary list creation
2024-10-22 13:29:18 +02:00
pehala
16cd3fccdd test: lib: Fix ScyllaClusterManager.stop()
When cancelling running tasks, stop() could run multiple times and fail.
Removed usage of del and added checks to ensure it won't crash.
2024-10-22 13:29:18 +02:00
Kefu Chai
7a1e067b4e docs: move keyspace-storage-option from cql-extensions to admin
as the admin needs to known the name of the experimental feature option
they need to enable.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-22 18:30:29 +08:00
Kefu Chai
6f97c86a2b docs: reference admin.rst for object storage config
instead of repeating it in cql-extensions.md, let's reference
the object storage related settings in admin.rst

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-22 18:26:19 +08:00
Kefu Chai
fe13b4e10e docs: reference object storage config doc from nodetool commands
Enhance the documentation for nodetool commands that use the `--endpoint`
option by linking to the object storage configuration guide. This change
provides users with essential context and detailed setup instructions
for S3-compatible storage endpoints.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-22 18:26:19 +08:00
Kefu Chai
9bd9ee9f36 docs: promote object storage configuration to user-facing documentation
this commit moves the object storage configuration guide from the developer
documentation to the user-facing admin documentation. the change reflects
the increasing importance of object storage integration in user-facing
features.

in this change:

- move relevant content from `docs/dev/object_storage.md` to
  `docs/operating-scylla/admin.rst`
- reformat the content from Markdown to reStructuredText (RST)
- reword and restructure the content to be more user-friendly
- add explanations and context suitable for a broader audience

this change makes the object storage configuration information more
accessible to Scylla administrators and end-users, supporting the adoption
of new features built on top of object storage integration.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-22 18:26:19 +08:00
Benny Halevy
04d741bcbb storage_service: on_change: update_peer_info only if peer info changed
Return an optional peer_info from get_peer_info_for_update
when the `app_state_map` arg does not change peer_info,
so that we can skip calling update_peer_info, if it didn't
change.

Fixes scylladb/scylladb#20991
Refs scylladb/scylladb#16376

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#21152
2024-10-22 10:26:08 +02:00
Dawid Medrek
4ec0a014e3 docs/hinted-handoff: Add link to API reference
We add a link to the API reference for the convenience
of the user.

Closes scylladb/scylladb#20065
2024-10-22 09:24:14 +03:00
pehala
28aa57f836 test.py: Refactor retry()
Instead of metamethod that looks at all subclasses, use OOP with super() calls

Closes scylladb/scylladb#21155
2024-10-22 09:23:30 +03:00
David Garcia
6b7b4addf9 docs: add dark theme to api
Closes scylladb/scylladb#21161
2024-10-22 09:22:32 +03:00
pehala
59eb4eb528 test.py: Enhance progress report
* Do not leave passed tests in between failed ones.
* Use ANSI Escape sequences for manipulating console
  * Simplifies code and removes need for two object parameters

Closes scylladb/scylladb#21176
2024-10-22 09:22:08 +03:00
Łukasz Paszkowski
34c05cb94f test/rest_api: Add tests for compactionhistory
For a table with NullCompactionStrategy and
TimeWindowCompactionStrategy, the test
- inserts a bunch of data and flushes the table
- deletes/update some data, delete a range of data and flushes
  the table
- Triggers a major compaction and calls for compactionhistory
  to retrieve and validate the histogram
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
8188a71787 nodetool: Add rows merged stats into compactionhistory output
Incorporate rows merged statistics into the output of the compactionhistory
command. Depending on the requested format type, the output has
different form.

For instance, compacting two sstables of a table consisting of 7
rows where two rows are part of the both sstables, the output
would have the following format:
text: {1: 5, 2: 2}
json: [{"key":1,"value":5},{"key":2,"value":1}]}
yaml: - key: 1
        value: 5
      - key: 2
        value: 1
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
c01a38f3cf compaction: Update compaction history with collected histogram
A new field has been added to the compaction_stats structure to hold
collected combined reader statistics. The struct is than used to update
the compaction_history table.
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
7eac89da73 compaction: Remove const qualifier from methods creating sstable readers
Compaction classes start mutate their internal members to be used
in methods setup_sstable_reader and make_sstable_reader creating
sstable reades that are marked as const.

Remove the const qualifier from these methods. Even though it made
sense initially to mark them as const, it is no longer applicable.
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
484655bf0d sstable_set: Add optional statistics to make_local_shard_sstable_reader
The pointer to combined_reader_statistics is propagated down to
make_combined_reader in order to collect statistics. By default,
a null pointer is propagated.

Note that in case the pointer is valid and the sstable_set consists
of exactly one sstable, statistics are skipped as all rows originate
from exactly a single sstable file.

The existing optimization is crucial f75154afca
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
a9f776494c make_combined_reader: Add optional parameter, combined_reader_statistics
All the overloaded make_combined_reader functions accept an optional
pointer to combined_reader_statistics, to be propagated down through
merging_reader to mutation_fragment_merger. By default, a null pointer
is propagated.
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
84912c3155 reader_selector: Extend with maximum reader count
The maximum reader count allows to predict the number of readers
that can be created with create_new_readers(). This helps to
correctly allocate a vector size in the rows_merged statistics
when a combiner reader is created via make_combined_reader.
2024-10-22 08:15:02 +02:00
Łukasz Paszkowski
92f5c56afc mutation_fragment_merger: Create histogram while consuming mutation fragment batches
The mutation_fragment_merger takes one additional parameter in its
constructor, that is a pointer to a combined_reader_statistics
used to collect various statistics.

The histogram is populated with data while the merger consumes
batches from the producer and merges them into seperate mutation
fragments. The size of the batch, that represents the number of streams
the mutation fragment originates from, is used as a key in the
historgam and its corresponding value is increased by one.
2024-10-22 08:15:02 +02:00
Botond Dénes
41de340d93 Merge 'Update get_description.py script' from Amnon Heiman
get_description.py script is a document related script that looks for metrics description in the code.
Its configuration needs to address changes in the code.

This series contains a configuration change and a code fix that allows it to run as a standalone script, and not as a library.

No need to backport, this a documentation related script.

Closes scylladb/scylladb#19950

* github.com:scylladb/scylladb:
  scripts/get_description.py: param_mapping was missing
  scripts/metrics-config.yml: no need to get metrics from the tests
2024-10-22 08:42:15 +03:00
Kefu Chai
27fb893d9b docs: nodetools-commands/restore: update to reflect the latest implementation
in 787ea4b1d4, we added "sstables" argument to the "nodetool restore"
command. but we failed to update the document to reflect the change.

in this change, we update the document for "restore" command to reflect
the latest implementation changes introduced in commit 787ea4b1d4:

* Add information about the new "sstables" argument
* Update command line usage of "--table" argument -- it is now madatory
* Update the example accordingly.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21135
2024-10-22 08:30:06 +03:00
Kefu Chai
ce0a86c585 build: cmake: correct some tests' KIND
before this change, we build some tests as if they are Seastar tests.
but after 415c83fa, these tests failed to link. because the
Seastar::seastar_testing does not expose `-DSEASTAR_TESTING_MAIN` in
its cflags. the behavior of the Seastar::seastar_testing  is expected.
because a test linking against this library is not necessarily driven
by the `main()` provided by `testing/seastar_test.hh`.

so, in this change, we correct the `KIND` parameter of these tests,
so that they use `KIND BOOST`, as these tests can be driven by the
`main()` provided by Boost.Test's driver. also there are some tests
driven by Boost.Test's `main()`, but in the meanwhile, they utilize
seastar_testing, so let's add `Seastar::seastar_testing` to their
`LIBRARIES`.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21183
2024-10-22 07:10:47 +03:00
Kefu Chai
6ead5a4696 treewide: move log.hh into utils/log.hh
the log.hh under the root of the tree was created keep the backward
compatibility when seastar was extracted into a separate library.
so log.hh should belong to `utils` directory, as it is based solely
on seastar, and can be used all subsystems.

in this change, we move log.hh into utils/log.hh to that it is more
modularized. and this also improves the readability, when one see
`#include "utils/log.hh"`, it is obvious that this source file
needs the logging system, instead of its own log facility -- please
note, we do have two other `log.hh` in the tree.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-22 06:54:46 +03:00
Kefu Chai
6645cdf3b6 build: cmake: improve source generated for check_header
in check_headers.cmake, we verify the self containness of a header file
by replicating it and remove `#pragma once` directive in this header.
but this approach failed to compile headers which include a header file
with the same name in the root source directory, as we add
`-I<directory-of-original-header>` in the cflags when building the
generated source file, so that it can include the headers in the same
directory. but this confuses the compiler, as, assuming we have "log.hh"
in current directory, and under the root source directory, the compiler
would always include the "log.hh" in the current directory even it
should have included "log.hh" under the root source directory.

in this change, instead of adding `-I<directory-of-original-header>` to
cflags, we just include the header under test in a new .cc file
solely generated for testing. this should address this problem.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21216
2024-10-22 06:28:16 +03:00
Kefu Chai
2d6af2791e compaction: simplify time_window_compaction_strategy::get_window_lower_bound()
since chrono allows dividion between durations with different units. let
use it instead for rounding down to the nearest multiple of the window
size, for better readability.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20476
2024-10-21 16:01:15 +03:00
Pavel Emelyanov
516a5f06a8 sstables: Open-code format_table_directory_name() moved recently
This helper is small enough and it's easier to understand how table
directory name is formatted without it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:18:19 +03:00
Pavel Emelyanov
eeb0d637bb replica,sstables: Move format_table_directory_name()
Now this helper is not needed in replica code, as all manipulations of
tables' sstables now sit in the sstables/storage.cc.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:17:30 +03:00
Pavel Emelyanov
74728d3889 table: Remove all_datadirs
It's write-only now, all the places than wanted to know where table's
storage is (well -- "are", there can be several directories) already use
storage_options.

This finishes the work started by 9fe64b5d70.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:15:54 +03:00
Pavel Emelyanov
dedb9d349c sstables: Generate table::all_datadirs from db::config and storage_options
As mentioned in the previous patch, there are several places that need
to scan all datafile directories for a given table. This list is
currently stored on table.config.all_datadirs, this patch stops using
one and instead generates it from db::config::data_file_directories and
table's storage options.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:13:27 +03:00
Pavel Emelyanov
0358515118 replica: Prepare vector of fs::path-s with table dirs
Most of the time table with local storage keeps its sstables in a single
directory referenced by its storage_options::local.dir path. However,
there are two cases when code needs to check all datafile directories
that could be configured -- on boot when distributed loader loads
sstables, and when checking table snapshots.

Both those places check table.cfg.all_datadirs vector of strings and
convert strings to fs::path-s along the way. This patch prepares the
vector of fs::path-s in advance and updates the loop code to work with
path-s.

This is preparation to next patching that will generate vector of paths
for a table.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:10:53 +03:00
Pavel Emelyanov
4e329ba08f table: Check storage options in get_snapshot_details()
This is continuation of 24589cf00c and a734fd5c9c -- if table is not
based on local storage, getting snapshot details makes no sense.

Another goal this change pursuits is to have storage_options::local
object at hand to be used later.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-21 15:08:54 +03:00
Wojciech Mitros
4d719bacca test: add test for high view update concurrency causing bad_allocs
This commit add a test for checking whether a large view update workload
can cause Scylla to run out of memory.
In the test, we keep writing to a table table with a materialized view
with a limited number of rows, causing overwrites which require reading
from the table to perform view updates.
Currently, due to the unlimited concurrency of view update reads, we may
use too much memory which can lead to bad_allocs, causing Scylla to fail.
To reach the failing state more consistently, we use add a sleep after
reading the old value of the base row, to keep the reader concurrency
semaphore units longer. At the same time, we use high concurrency and
large row size to use up all Scylla's memory quickly.
The test fails if Scylla runs out of memory and aborts, and succeeds
otherwise.
2024-10-21 12:35:20 +02:00
Wojciech Mitros
f2c740710c test: add test for high view update concurrency degrading read latency
This commit add a test for checking whether a large view update workload
impacts the latency of other user reads.
In the test, we first create a table for reads and another table with
a materialized view. We then start writing to the table with the view
with a limited number of rows - when overwriting, we need to read the
previous value of the row to prepare a delete of the old row in the view.
This should not impact the latency of the read workload from the other
table that we start at the same time. The test fails if any of the reads
times out.
To reach the failing state more consistantly, we use add a sleep after
reading the old value of the base row, to keep the reader concurrency
semaphore units longer. At the same time, we use a lower threshold for
queueing reads on the semaphore, to see the impact of view update reads
earlier.
Because of the high load, the writes may timeout, but that's expected
- we fail the test only if the user reads time out.
2024-10-21 12:34:55 +02:00
Kefu Chai
5cd619a60c treewide: s/boost::adaptors::map_keys/std::views::keys/
now that we are allowed to use C++23. we now have the luxury of using
`std::views::keys`.

in this change, we:

- replace `boost::adaptors::map_keys` with `std::views::keys`
- update affected code to work with `std::views::keys`

to reduce the dependency to boost for better maintainability, and
leverage standard library features for better long-term support.

this change is part of our ongoing effort to modernize our codebase
and reduce external dependencies where possible.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21198
2024-10-21 12:47:52 +03:00
Wojciech Mitros
242079d70b mv: add a dedicated read concurrency semaphore for view update read before writes
When writing to some tables with materialized views, we need to read from the base
table first to perform a delete of the old view row. When doing so, the memory used
for the read is tracked by the user read concurrency semaphore. When we have a large
number of such reads, we may use up all of the semaphore units, causing the following
reads to be queued. When we have some user reads coming at the same time, these reads
can have very high latency due to the write workload on the base table. We want to avoid
this, so that the write workload doesn't have a high impact on the latency of the
read workload.

This is fixed in this patch by adding a separate read concurrency semaphore just for
view update read-before-writes. With the new semaphore, even if there are many view
update read-before-writes, they will be queued on a different semaphore than the user
reads, and they won't impact their latency.

The second issue fixed by this patch is the concurrency of the view updates that is
currently unlimited. Because of that view updates may take up so much memory that
they we may run out of memory.

This is fixed by using the read admission on the view update concurrency semaphore.
This limits the number of concurrent view update reads to
max_count_concurrent_view_update_reads, all other incoming view update reads are
queued using just a small chunk of memory. Without this, the reads would also get
queued after exceeding view_update_reader_concurrency_semaphore_serialize_limit_multiplier,
but they would take much more memory while staying in the queue.

The new semaphore has half the capacity of the regular user read concurrency semahpore
and is currently used only for user writes - is't used independently of the scheduling
group on which we base the read semaphore selection, but we use a different code path
for streaming (not database::do_apply) and we shouldn't have view updates in system
writes or during compaction.

Fixes https://github.com/scylladb/scylladb/issues/8873
Fixes https://github.com/scylladb/scylladb/issues/15805
2024-10-21 11:02:06 +02:00
Kefu Chai
5255f18c35 date: do not put space before literal operator
when compiling date.h, clang 20 complains:
```
/home/kefu/.local/bin/clang++ -DDEBUG -DDEBUG_LSA_SANITIZER -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -isystem /home/kefu/dev/scylladb/build/rust -isystem /home/kefu/dev/scylladb/seastar/include -isystem /home/kefu/dev/scylladb/build/Debug/seastar/gen/include -isystem /usr/include/p11-kit-1 -isystem /home/kefu/dev/scylladb/abseil -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=westmere -Xclang -fexperimental-assignment-tracking=disabled -std=c++23 -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -DSEASTAR_API_LEVEL=7 -DSEASTAR_BUILD_SHARED_LIBS -DSEASTAR_SSTRING -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_DEBUG -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEBUG_PROMISE -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_TYPE_ERASE_MORE -DFMT_SHARED -DWITH_GZFILEOP -MD -MT lang/CMakeFiles/lang.dir/Debug/lua.cc.o -MF lang/CMakeFiles/lang.dir/Debug/lua.cc.o.d -o lang/CMakeFiles/lang.dir/Debug/lua.cc.o -c /home/kefu/dev/scylladb/lang/lua.cc
In file included from /home/kefu/dev/scylladb/lang/lua.cc:18:
/home/kefu/dev/scylladb/utils/date.h:836:34: error: identifier '_d' preceded by whitespace in a literal operator declaration is deprecated [-Werror,-Wdeprecated-literal-operator]
  836 | CONSTCD11 date::day  operator "" _d(unsigned long long d) NOEXCEPT;
      |                      ~~~~~~~~~~~~^~
      |                      operator""_d
```

because, in
[CWG2521](https://wg21.link/CWG2521), it proposes that compiler should
consider
```c++
  string operator "" _i18n(const char*, std::size_t); // OK, deprecated
```
as "OK, deprecated".

and Clang implemented this proposal, as it was accepted by C++23. since
scylladb uses C++23 standard. let's remove the space between `"` and
`_` to be more compliant to the C++23 standard and to silence the
warning, which is taken as an error.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21194
2024-10-21 11:21:52 +03:00
Kefu Chai
8355056453 build: cmake: expose and use the path to iotune correctly
in 415c83fa, we introduced a regression which broke the build of
target of "package". because

- the IMPORT_LOCATION_<CONFIG> of the imported target of
  "Seastar::iotune" includes a literal `$<CONFIG>`
- we retrieve the property named "IMPORTED_LOCATION" from
  this target. but value of this property is empty.

so, when we copied this file, the "src" parameter passed to
`cmake -E copy` is actually an empty string.

in this change, we

- set the `IMPORTED_LOCATION_${CONFIG}` property with a
  correct path.
- retrieve the property with the right approach -- to use
  `TARGET_FILE` generator expression.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21181
2024-10-21 10:32:51 +03:00
Avi Kivity
b5a1173880 utils: small_vector: support from_range_t
std::ranges::to<>() has a little protocol with containers to
allow them to optimize their construction from ranges. Implement it
for small_vector. It optimizes ranges that can have their size determined
quickly, or that can be traversed twice to determine the size by reserving
up front. Single-pass ranges (std::ranges::input_range) use the less
efficient push_back method.

A unit test (which fails without the new constructor) is added.

Closes scylladb/scylladb#21094
2024-10-21 09:31:38 +03:00
Kefu Chai
d28d64f7fe service: remove extraneous space in #pragma once
to be more consistent with the rest of the tree.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21188
2024-10-20 20:27:38 +03:00
Avi Kivity
c3be2489ce treewide: drop includes of <boost/range/adaptors.hpp>
This includes way too much, including <boost/regex.hpp>, which is huge.
Drop includes of adaptors.hpp and replace by what is needed.

Closes scylladb/scylladb#21187
2024-10-20 17:17:11 +03:00
Aleksandra Martyniuk
29c2d4e7eb tasks: add comments about map_each_task safety
Closes scylladb/scylladb#21172
2024-10-19 21:16:38 +03:00
Avi Kivity
9a521c25b5 Merge 'test/boost: stop using ranges::to()' from Kefu Chai
now that we are able to use ranges library provided by the C++ standard library. there is no need to use the homebrew `ranges::to()`.

in this series, we

- switch to `std::ranges::to()` in favor of `ranges::to()`.
- and drop the unused `utils/ranges.hh` header file.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#21182

* github.com:scylladb/scylladb:
  utils: remove unused ranges.hh
  test/boost: stop using ranges::to()
2024-10-19 16:57:51 +03:00
Kefu Chai
c5e666b7b1 column_computation.hh: include used header
when building the check-header target, we have following failure:

```
FAILED: CMakeFiles/check-headers-scylla-main.dir/Dev/check-headers/column_computation.hh.cc.o
/home/kefu/.local/bin/clang++ -DDEVEL -DSCYLLA_BUILD_MODE=dev -DSCYLLA_ENABLE_ERROR_INJECTION -DSCYLLA_ENABLE_PREEMPTION_SOURCE -DSEASTAR_ENABLE_ALLOC_FAILURE_INJECTION -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Dev\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -isystem /home/kefu/dev/scylladb/seastar/include -isystem /home/kefu/dev/scylladb/build/Dev/seastar/gen/include -isystem /usr/include/p11-kit-1 -isystem /home/kefu/dev/scylladb/abseil -O2 -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=westmere -Xclang -fexperimental-assignment-tracking=disabled -Wno-unused-const-variable -Wno-unused-function -Wno-unused-variable -std=c++23 -Werror=unused-result -fstack-clash-protection -DSEASTAR_API_LEVEL=7 -DSEASTAR_BUILD_SHARED_LIBS -DSEASTAR_SSTRING -DSEASTAR_ENABLE_ALLOC_FAILURE_INJECTION -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_TYPE_ERASE_MORE -DFMT_SHARED -DWITH_GZFILEOP -MD -MT CMakeFiles/check-headers-scylla-main.dir/Dev/check-headers/column_computation.hh.cc.o -MF CMakeFiles/check-headers-scylla-main.dir/Dev/check-headers/column_computation.hh.cc.o.d -o CMakeFiles/check-headers-scylla-main.dir/Dev/check-headers/column_computation.hh.cc.o -c /home/kefu/dev/scylladb/build/check-headers/column_computation.hh.cc
/home/kefu/dev/scylladb/build/check-headers/column_computation.hh.cc:24:37: error: no template named 'unique_ptr' in namespace 'std'
   24 | using column_computation_ptr = std::unique_ptr<column_computation>;
      |                                ~~~~~^
/home/kefu/dev/scylladb/build/check-headers/column_computation.hh.cc:40:12: error: unknown type name 'column_computation_ptr'; did you mean 'column_computation'?
   40 |     static column_computation_ptr deserialize(bytes_view raw);
      |            ^~~~~~~~~~~~~~~~~~~~~~
      |            column_computation
```

it turns out we failed to include `<memory>`.

in this change, we include `<memory>` so that this header is
self-contained.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21185
2024-10-19 16:56:02 +03:00
Raphael S. Carvalho
dfc217f99a locator: Always preserve balancing_enabled in tablet_metadata::copy()
When there are zero tablets, tablet_metadata::_balancing_enabled
is ignored in the copy.

The property not being preserved can result in balancer not
respecting user's wish to disable balancing when a replica is
created later on.

Fixes #21175.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>

Closes scylladb/scylladb#21177
2024-10-19 14:51:36 +02:00
Kefu Chai
4d4b0b35b7 utils: remove unused ranges.hh
now that this header is not used, let's drop it.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-19 13:21:20 +08:00
Kefu Chai
85518463a9 test/boost: stop using ranges::to()
now that we are able to use ranges library provided by the C++
standard library. there is no need to use the homebrew `ranges::to()`.

in this change, we switch to `std::ranges::to()` in favor of
`ranges::to()`.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-19 13:21:20 +08:00
Kefu Chai
5c0db8a49e sstable_directory: remove extraneous semicolon
one semicolon is enough to mark the end of a statement. so let's
remove the extraneous one.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21171
2024-10-18 21:58:04 +03:00
Kefu Chai
e2b18eb7eb data_dictionary: compose the location with "/"
in 787ea4b1, we construct a new `storage_options` for each sstable
to be restored. the `location` of the new `storage_option` instances
is composed of the configured `prefix` and the dirname of each toc
component. but instead of separating them with "/", we just concatenate
them. this breaks the test if the specified key representing toc
components includes "dirname" in them.

in this change

- data_directory: instead of using "{prefix}{dirname}", we use
  "{prefix}/{dirname}".
- test/object_store: update the existing test to add a suffix
  in the keys of the toc objects to mimic the typical use case.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21170
2024-10-18 21:57:56 +03:00
Lakshmi Narayanan Sreethar
afad1b3c85 topology-custom: add test to verify tombstone gc in read path
Co-authored-by: Raphael S. Carvalho <raphaelsc@scylladb.com>

Signed-off-by: Lakshmi Narayanan Sreethar <lakshmi.sreethar@scylladb.com>
2024-10-18 19:20:03 +05:30
Lakshmi Narayanan Sreethar
5a93277904 replica/table: check memtable before discarding tombstone during read
On the read path, the compacting reader is applied only to the sstable
reader. This can cause an expired tombstone from an sstable to be purged
from the request before it has a chance to merge with deleted data in
the memtable leading to data resurrection.

Fix this by checking the memtables before deciding to purge tombstones
from the request on the read path. A tombstone will not be purged if a
key exists in any of the table's memtables with a minimum live timestamp
that is lower than the maximum purgeable timestamp.

Fixes #20916

Signed-off-by: Lakshmi Narayanan Sreethar <lakshmi.sreethar@scylladb.com>
2024-10-18 19:19:58 +05:30
Lakshmi Narayanan Sreethar
6a357b55e3 compaction_group: track maximum timestamp across all sstables
This will be used in a following patch to decide if the compacting
reader has to check the memtables before purging a tombstone.

Signed-off-by: Lakshmi Narayanan Sreethar <lakshmi.sreethar@scylladb.com>
2024-10-18 19:19:11 +05:30
Pavel Emelyanov
b11d50f591 Merge 'multishard reader: make it safe to create with admitted permits' from Botond Dénes
Passing an admitted permit -- i.e. one with count resources on it -- to the multishard reader, will possibly result in a deadlock, because the permit of the multishard reader is destroyed after the permits of its child readers. Therefore its semaphore resources won't be automatically released until children acquire their own resources. This creates a dependency (an edge in the "resource allocation graph"), where the semaphore used by the multishard reader depends on the semaphores used by children. When such dependencies create a cycle, and permits are acquired by different reads in just the right order, a deadlock will  happen.

Users of the multishard reader have to be aware of this gotcha -- and of course they aren't. This is small wonder, considering that not even the documentation on the multishard reader mentions this problem. To work around this, the user has to call `reader_permit::release_base_resources()` on the permit, before passing it to the multishard reader. On multiple occasions, developers (including the very author of the multishard reader), forgot or didn't know about this and this resulted in deadlocks down the line. This is a design-flaw of the multishard reader, which is addressed in this PR, after which, it is safe to pass admitted or not admitted permits to the multishard reader, it will handle the call to `release_base_resources()` if needed.

After fixing the problem in the multishard reader, the existing calls to `release_base_resources()` on permits passed to multishard readers are removed. A test is added which reproduces the problem and ensures we don't regress.

Refs: https://github.com/scylladb/scylladb/issues/20885 (partial fix, there is another deadlock in that issue, which this PR doesn't fix)

This fixes (indirectly) a regression introduced by d98708013c so it has to be backported to 6.2

Closes scylladb/scylladb#21058

* github.com:scylladb/scylladb:
  test/boost/mutation_test: add test for multishard permit safety
  test/lib/reader_lifecycle_policy: add semaphore factory to constructor
  test/lib/reader_lifecycle_policy: rename factory_function
  repair/row_level: drop now unneeded release_base_resource() calls
  readers/multishard: make multishard reader safe to create with admitted permits
2024-10-18 13:30:21 +03:00
Pavel Emelyanov
280cd23c13 Merge 'Allow specifying TLS options with internode_encryption=none + add "transitional" mode' from Calle Wilund
Fixes #18903

Adds a "transitional" internode encryption mode, under which all _outgoing_ RPC connections will use TLS, but we will still accept any incoming non-tls connection.

This allows an operator to perform a move to TLS RPC without cluster downtime:

1. For each server, add certificate etc options to server_encryption_options + internode_encryption=none + set ssl_storage_port + restart (rolling)

2. For each server, set internode_encryption=transitional + RR
3. For each server, set internode_encryption=all + RR

Closes scylladb/scylladb#18939

* github.com:scylladb/scylladb:
  test::topology: Add test for TLS upgrade and downgrade of internode encryption
  docs: Add internode_encryption=transitional documentation
  messaging_service: Add "transitional" internode encryptipn mode
  messaging_service: Create TLS connector even if internode_enc=none when certs set
2024-10-18 11:01:07 +03:00
Avi Kivity
1bbd1436b4 types: move from boost ranges to standard ranges
Reduce depdendency load.

tuple_deserializing_iterator gained a default constructor so it
matches iterator constraints.

Closes scylladb/scylladb#21029
2024-10-18 11:00:49 +03:00
Botond Dénes
b6da82dba3 Merge 'build: build seastar as an external project' from Kefu Chai
before this change, scylla's CMake-based system consumes Seastar
library by including it directly. but this failed to address the needs
of linking against Seastar shared libraries in Debug and Dev builds, while
linking against the static libraries in other builds. because Seastar
uses `BUILD_SHARED_LIBS` CMake variable to determine if it builds
shared libraries. and we cannot assign different values to this
CMake variable based on current configure type -- CMake does not
support. see https://gitlab.kitware.com/cmake/cmake/-/issues/19467

in order to address this problem, we have a couple possible
solutions:

- to enable Seastar to build both shared and static libraries in a
  pass. without sacrificing the performance, we have to build
  all object files twice: once with -fPIC, once without. in order
  to accompolish this goal, we need to develop a machinary to
  populate the same settings to these two builds. this would
  complicate the design of Seastar's building system further.
- to build Seastar libraries twice in scylla, we could use
  the ExternalProject module to implement this. but it'd be
  complicate to extract the compile options, and link options
  previously populated by Seastar's targets with CMake --
  we would have to replicate all of them in scylla. this is
  out of the question.
- to build Seastar libraries twice before building scylla,
  and let scylla to consume them using CMake config files or
  .pc files. this is a compromise. it enables scylla to
  drive the build of Seastar libraries and to consume
  the compile options and link options. the downside is:

  * the generated compilation database (compile_commands.json)
    does not include the commands building Seastar anymore.
  * the building system of scylla does not have finer graind
    control on the building process of seastar. for instance,
    we cannot specify the build dependency to a certain seastar
    library, and just build it instead of building the whole
    seastar project.

turns out the last approach is the best one we can have
at this moment. this is also the approach used by the existing
`configure.py`.

in this change, we

- add FindSeastar.cmake to

  * detect the preconfigured Seastar builds, and
  * extract the build options from .pc files
  * expose library targets to be consumed by parent project
- add Seastar as an external project, so we can build it from
  the parent project.

  this is atypical compared to standard ExternalProject usage:
  - Seastar's build system should already be configured at this point.
  - We maintain separate project variants for each configuration type.

  Benefits of this approach:
  - Allows the parent project to consume the compile options exposed by
    .pc file. as the compile options vary from one config to another.
  - Allows application of config-specific settings
  - Enables building Seastar within the parent project's build system
  - Facilitates linking of artifacts with the external project target,
    establishing proper dependencies between them

we will update `configure.py` to merge the compilation database
of scylla and seastar.

Refs scylladb/scylladb#2717

---

this is a CMake-related change, hence no need to backport.

Closes scylladb/scylladb#21131

* github.com:scylladb/scylladb:
  build: cmake: use GENERATOR_IS_MULTI_CONFIG property to detect mult-config
  build: cmake: consume Seastar using its .pc files
  build: do not use `mode` as the index into `modes`
  build: cmake: detect and link against GnuTLS library
  build: cmake: detect and link against yaml-cpp
  build: cmake: link Seastar with Seastar::<COMPONENT>
  build: cmake: define CMake generate helper funcs in scylla
2024-10-18 09:42:59 +03:00
Amnon Heiman
09fa625672 scripts/get_description.py: param_mapping was missing
get_description.py was moved from a standalone script to a library.
During the transition, param_mapping was not included in the script
option.

This patch makes it possible to use the file as a standalone script
again.
2024-10-18 08:58:04 +03:00
Amnon Heiman
10af854ec4 scripts/metrics-config.yml: no need to get metrics from the tests 2024-10-18 08:57:53 +03:00
Kefu Chai
b5f5a963ca build: do not pass Seastar_CXX_DIALECT=gnu++23 when building Seastar
Seastar now respect CMAKE_CXX_STANDARD in favor of Seastar_CXX_DIALECT,
which has been dropped in Seastar's commit of
60bc8603bd438232614e9b3dcd7537dc83c85206 .

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21130
2024-10-18 08:57:23 +03:00
Botond Dénes
6811411288 Merge 'Sanitize commitlog API endpoints' from Pavel Emelyanov
Endpoints are registered next to the service they use, and the unregistration deferred action is created right after it. When registered, the service in question is passed as argument and then captured by enpoints lambdas. This makes sure that service is not used by endpoints after being stopped.

That's not so for commitlog endpoints. These are registered in several places, and /commitlog "function" is not unregistered on stop. This patch fixes some of this misbehavior, in particular:

 -  adds unregistration of commitlog API function
 -  uses sharded<database>& argument in endpoints instead of ctx.db
 -  moves some endpoints from storage_service.cc to commitlog.cc

Closes scylladb/scylladb#21053

* github.com:scylladb/scylladb:
  api: Use captured database, not the one from ctx
  api: Pass sharded<database> to commitlog endpoints registration
  api: Move commitlog-related from storage_service.cc
  api: Unset commitlog API endpoints
  api: Extract set_server_commitlog() from set_server_done()
2024-10-18 08:56:13 +03:00
Botond Dénes
568b767ec3 Merge 'schema: convert from boost ranges to std ranges' from Avi Kivity
To reduce dependency load, change uses of boost ranges to std::ranges.

The first patch is preparation, replacing a construct that isn't easy to support with std ranges with something simpler.

No backport as this is a code cleanup.

Closes scylladb/scylladb#21122

* github.com:scylladb/scylladb:
  schema: replace boost ranges with std ranges
  schema: precompute all_columns_in_select_order()
2024-10-18 08:42:50 +03:00
Pavel Emelyanov
df6991edd3 test: Do not duplicate sstable twice
The statistics_rewrite test case copies an sstable from resources two
times:

- first time -- explicitly by listing resource components and copying
  files to the test temp dir
- second time -- implicitly, by calling create_links() linking copied
  files by new set in the staging/ subdirectory

The 2nd step is not needed and the history of changes justifies that.

The test itself appeared with 70b793e4d3 and it only contained the 2nd
"copying" -- test linked files from resource directory and then worked
in the newly created set.

Later, commit 59c57861ae added the first step and copied the files
from resource into test temp dir. At this point linking copied files
because pointless, but was preserved. Let's remove it now.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21097
2024-10-18 08:31:08 +03:00
Kefu Chai
26a5a00b20 interval: include used header
when building the tree with Clang-20 and libstdc++ shippped with
GCC-14.2, we have following build failure:

```
/home/kefu/dev/scylladb/interval.hh:638:14: error: no member named 'sort' in namespace 'std'
  638 |         std::sort(intervals.begin(), intervals.end(), [&](auto&& r1, auto&& r2) {
      |         ~~~~~^
/home/kefu/dev/scylladb/interval.hh:691:21: error: no member named 'upper_bound' in namespace 'std'
  691 |         return std::upper_bound(r.begin(), r.end(), value, std::forward<LessComparator>(cmp));
      |                ~~~~~^
/home/kefu/dev/scylladb/interval.hh:723:18: error: no member named 'minmax' in namespace 'std'; did you mean 'fminmag'?
  723 |         auto p = std::minmax(_interval, other._interval, [&cmp] (auto&& a, auto&& b) {
      |                  ^~~~~~~~~~~
      |                  fminmag
```

it turns out we failed to include the used header.

in this change, we include `<algorithm>` so that this header is
self-contained.

after this change, the build passes.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21168
2024-10-18 08:26:27 +03:00
Kefu Chai
e73b0c942f build: cmake: use GENERATOR_IS_MULTI_CONFIG property to detect mult-config
this is more reliable way to check if we are configured to use a
mult-config generator.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
415c83fa67 build: cmake: consume Seastar using its .pc files
before this change, scylla's CMake-based system consumes Seastar
library by including it directly. but this failed to address the needs
of linking against Seastar shared libraries in Debug and Dev builds, while
linking against the static libraries in other builds. because Seastar
uses `BUILD_SHARED_LIBS` CMake variable to determine if it builds
shared libraries. and we cannot assign different values to this
CMake variable based on current configure type -- CMake does not
support. see https://gitlab.kitware.com/cmake/cmake/-/issues/19467

in order to address this problem, we have a couple possible
solutions:

- to enable Seastar to build both shared and static libraries in a
  pass. without sacrificing the performance, we have to build
  all object files twice: once with -fPIC, once without. in order
  to accompolish this goal, we need to develop a machinary to
  populate the same settings to these two builds. this would
  complicate the design of Seastar's building system further.
- to build Seastar libraries twice in scylla, we could use
  the ExternalProject module to implement this. but it'd be
  complicate to extract the compile options, and link options
  previously populated by Seastar's targets with CMake --
  we would have to replicate all of them in scylla. this is
  out of the question.
- to build Seastar libraries twice before building scylla,
  and let scylla to consume them using CMake config files or
  .pc files. this is a compromise. it enables scylla to
  drive the build of Seastar libraries and to consume
  the compile options and link options. the downside is:

  * the generated compilation database (compile_commands.json)
    does not include the commands building Seastar anymore.
  * the building system of scylla does not have finer graind
    control on the building process of seastar. for instance,
    we cannot specify the build dependency to a certain seastar
    library, and just build it instead of building the whole
    seastar project.

turns out the last approach is the best one we can have
at this moment. this is also the approach used by the existing
`configure.py`.

in this change, we

- add FindSeastar.cmake to

  * detect the preconfigured Seastar builds, and
  * extract the build options from .pc files
  * expose library targets to be consumed by parent project
- add Seastar as an external project, so we can build it from
  the parent project. BUILD_AWAYS is set to ensure that Seastar is
  rebuilt, as scylla developers are expected to modify Seastar
  occasionally. since the change in Seastar's SOURCE_DIR is not
  detectable via the ExternalProject, we have to rebuild it.

  this is atypical compared to standard ExternalProject usage:
  - Seastar's build system should already be configured at this point.
  - We maintain separate project variants for each configuration type.

  Benefits of this approach:
  - Allows the parent project to consume the compile options exposed by
    .pc file. as the compile options vary from one config to another.
  - Allows application of config-specific settings
  - Enables building Seastar within the parent project's build system
  - Facilitates linking of artifacts with the external project target,
    establishing proper dependencies between them
- preserve the existing machinery of including Seastar only when
  building without multi-config generator. this allows users who don't
  use mult-config generator to build Seastar in-the-tree. the typical
  use case is the CI workflows performing the static analysis.

we will update `configure.py` to merge the compilation database
of scylla and seastar.

Refs scylladb/scylladb#2717
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
7cb74df323 build: do not use mode as the index into modes
before this change, in `configure_seastar()`, we use `mode` as
a component in the build directory, and use it as the index into `modes`
dict. but in a succeeding commit, we will reuse `configure_seastar()`
when preparing for the CMake-based building system, in which,
`mode` will be the CMake configure type, like "Debug" instead of
scylla's build mode, like "debug". to be prepared for this change,
let's use `mode_config` directly. it's identical to `modes[mode]`.

this also improves the readability.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
1bd2ed7826 build: cmake: detect and link against GnuTLS library
before this change, in the CMake-based building system, we rely on
Seastar to provide this linkage, but this is wrong and fragile. as
Seastar is not supposed to expose and provide GnuTLS symbols. that's
why we have following build failure:

```
: && /home/kefu/.local/bin/clang++ -g -Og -g -gz -Xlinker --build-id=sha1 --ld-path=ld.lld -dynamic-linker=/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////lib64/ld-linux-x86-64.so.2 /home/kefu/dev/scylladb/build/Debug/seastar/libseastar.so -fsanitize=address -fsanitize=undefined /usr/lib64/libboost_program_options.so /usr/lib64/libboost_thread.so /usr/lib64/libcares.so /usr/lib64/libfmt.so.11.0.2 -L/usr/lib64 -llz4 CMakeFiles/scylla_version.dir/Debug/release.cc.o CMakeFiles/scylla.dir/Debug/main.cc.o -o Debug/scylla -L/home/kefu/dev/scylladb/idl/absl::headers -Wl,-rpath,/home/kefu/dev/scylladb/idl/absl::headers:/home/kefu/dev/scylladb/build/Debug/seastar  Debug/libscylla-main.a  api/Debug/libapi.a  alternator/Debug/libalternator.a  db/Debug/libdb.a  cdc/Debug/libcdc.a  compaction/Debug/libcompaction.a  cql3/Debug/libcql3.a  data_dictionary/Debug/libdata_dictionary.a  gms/Debug/libgms.a  index/Debug/libindex.a  lang/Debug/liblang.a  message/Debug/libmessage.a  mutation/Debug/libmutation.a  mutation_writer/Debug/libmutation_writer.a  raft/Debug/libraft.a  readers/Debug/libreaders.a  redis/Debug/libredis.a  repair/Debug/librepair.a  replica/Debug/libreplica.a  schema/Debug/libschema.a  service/Debug/libservice.a  sstables/Debug/libsstables.a  streaming/Debug/libstreaming.a  test/perf/Debug/libtest-perf.a  tools/Debug/libtools.a  transport/Debug/libtransport.a  types/Debug/libtypes.a  utils/Debug/libutils.a  Debug/seastar/libseastar.so  /usr/lib64/libyaml-cpp.so  /usr/lib64/libboost_program_options.so.1.83.0  test/lib/Debug/libtest-lib.a  -Xlinker --push-state -Xlinker --whole-archive  auth/Debug/libscylla_auth.a  -Xlinker --pop-state  /usr/lib64/libcrypt.so  cdc/Debug/libcdc.a  compaction/Debug/libcompaction.a  mutation_writer/Debug/libmutation_writer.a  -Xlinker --push-state -Xlinker --whole-archive  dht/Debug/libscylla_dht.a  -Xlinker --pop-state  index/Debug/libindex.a  -Xlinker --push-state -Xlinker --whole-archive  locator/Debug/libscylla_locator.a  -Xlinker --pop-state  message/Debug/libmessage.a  gms/Debug/libgms.a  sstables/Debug/libsstables.a  readers/Debug/libreaders.a  schema/Debug/libschema.a  -Xlinker --push-state -Xlinker --whole-archive  tracing/Debug/libscylla_tracing.a  -Xlinker --pop-state  Debug/libscylla-main.a  -Xlinker --push-state -Xlinker --whole-archive  Debug/libscylla-zstd.a  -Xlinker --pop-state  /usr/lib64/libzstd.so  abseil/absl/strings/Debug/libabsl_cord.a  abseil/absl/strings/Debug/libabsl_cordz_info.a  abseil/absl/strings/Debug/libabsl_cord_internal.a  abseil/absl/strings/Debug/libabsl_cordz_functions.a  abseil/absl/strings/Debug/libabsl_cordz_handle.a  abseil/absl/crc/Debug/libabsl_crc_cord_state.a  abseil/absl/crc/Debug/libabsl_crc32c.a  abseil/absl/crc/Debug/libabsl_crc_internal.a  abseil/absl/crc/Debug/libabsl_crc_cpu_detect.a  abseil/absl/strings/Debug/libabsl_str_format_internal.a  service/Debug/libservice.a  node_ops/Debug/libnode_ops.a  service/Debug/libservice.a  node_ops/Debug/libnode_ops.a  raft/Debug/libraft.a  repair/Debug/librepair.a  streaming/Debug/libstreaming.a  replica/Debug/libreplica.a  abseil/absl/container/Debug/libabsl_raw_hash_set.a  abseil/absl/hash/Debug/libabsl_hash.a  abseil/absl/hash/Debug/libabsl_city.a  abseil/absl/types/Debug/libabsl_bad_variant_access.a  abseil/absl/hash/Debug/libabsl_low_level_hash.a  abseil/absl/types/Debug/libabsl_bad_optional_access.a  abseil/absl/container/Debug/libabsl_hashtablez_sampler.a  abseil/absl/profiling/Debug/libabsl_exponential_biased.a  abseil/absl/synchronization/Debug/libabsl_synchronization.a  abseil/absl/debugging/Debug/libabsl_stacktrace.a  abseil/absl/synchronization/Debug/libabsl_graphcycles_internal.a  abseil/absl/synchronization/Debug/libabsl_kernel_timeout_internal.a  abseil/absl/debugging/Debug/libabsl_symbolize.a  abseil/absl/debugging/Debug/libabsl_debugging_internal.a  abseil/absl/base/Debug/libabsl_malloc_internal.a  abseil/absl/debugging/Debug/libabsl_demangle_internal.a  abseil/absl/time/Debug/libabsl_time.a  abseil/absl/strings/Debug/libabsl_strings.a  abseil/absl/strings/Debug/libabsl_strings_internal.a  abseil/absl/strings/Debug/libabsl_string_view.a  abseil/absl/base/Debug/libabsl_throw_delegate.a  abseil/absl/numeric/Debug/libabsl_int128.a  abseil/absl/base/Debug/libabsl_base.a  abseil/absl/base/Debug/libabsl_raw_logging_internal.a  abseil/absl/base/Debug/libabsl_log_severity.a  abseil/absl/base/Debug/libabsl_spinlock_wait.a  -lrt  abseil/absl/time/Debug/libabsl_civil_time.a  abseil/absl/time/Debug/libabsl_time_zone.a  -lsystemd  /usr/lib64/libz.so  /usr/lib64/libdeflate.so  types/Debug/libtypes.a  utils/Debug/libutils.a  /usr/lib64/libyaml-cpp.so  /usr/lib64/libcryptopp.so  /usr/lib64/libboost_regex.so.1.83.0  /usr/lib64/libicui18n.so  /usr/lib64/libicuuc.so  -ldl  /usr/lib64/libboost_unit_test_framework.so.1.83.0  Debug/seastar/libseastar_perf_testing.so  /usr/lib64/libjsoncpp.so.1.9.5  db/Debug/libdb.a  data_dictionary/Debug/libdata_dictionary.a  cql3/Debug/libcql3.a  transport/Debug/libtransport.a  cql3/Debug/libcql3.a  transport/Debug/libtransport.a  lang/Debug/liblang.a  /usr/lib64/liblua-5.4.so  -lm  rust/Debug/libwasmtime_bindings.a  rust/librust_combined.a  /usr/lib64/libsnappy.so.1.2.1  mutation/Debug/libmutation.a  Debug/seastar/libseastar.so  /usr/lib64/liblz4.so  /usr/lib64/libxxhash.so && :
ld.lld: error: undefined symbol: gnutls_hmac_fast
>>> referenced by aws_sigv4.cc:21 (/home/kefu/dev/scylladb/utils/aws_sigv4.cc:21)
>>>               aws_sigv4.cc.o:(utils::aws::hmac_sha256(std::basic_string_view<char, std::char_traits<char>>, std::basic_string_view<char, std::char_traits<char>>)) in archive utils/Debug/libutils.a

ld.lld: error: undefined symbol: gnutls_strerror
>>> referenced by aws_sigv4.cc:23 (/home/kefu/dev/scylladb/utils/aws_sigv4.cc:23)
>>>               aws_sigv4.cc.o:(utils::aws::hmac_sha256(std::basic_string_view<char, std::char_traits<char>>, std::basic_string_view<char, std::char_traits<char>>)) in archive utils/Debug/libutils.a
```

in this change, we detect this library, and link its caller against it.
this addresses the link failure.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
fc8212483e build: cmake: detect and link against yaml-cpp
in main.cc, we use yaml-cpp library directly. so we are obliged to
detect this library in scylla and link against it instead of relying
on other library to do this. currently, Seastar detects it and pulls
in yaml-cpp for us, but we should not take this for granted and rely
on this.

in this change, we detect and link against yaml-cpp to make this
dependency explicit.

the same applies to the "utils" library.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
2e4be56112 build: cmake: link Seastar with Seastar::<COMPONENT>
before this change, we link against the targets defined in Seastar's
source tree. but these targets are not part of Seastar's public
interface -- they are not exposed by Seastar's CMake config files.

so, let link against the target names qualified by the library module
name. this also prepares for the transition to using Seastar without
including it directly.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Kefu Chai
b2dc261841 build: cmake: define CMake generate helper funcs in scylla
before this change, we assume that scylla's CMake script includes
Seastar's CMake script.

but we are going to consume Seastar using its .pc files or its CMake
config files instead of including it directly. more over these helper
functions are not part of Seastar's public interface.

actually the same applies to the `check_headers()` helper, which was
adapted from seastar's CheckHeaders.cmake.

so to be prepared for this change, let's define these generate helper
functions in scylla.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-18 08:36:52 +08:00
Avi Kivity
f4acaa5473 cql3: index_target: forward declare boost::regex
No need to burden everyone with the full boost::regex code.

Closes scylladb/scylladb#21148
2024-10-17 19:14:40 +02:00
Botond Dénes
e1d8cddd09 test/boost/mutation_test: add test for multishard permit safety
Add a test checking that the multishard reader will not deadlock, when
created with an admitted permit, on a semaphore with a single count
resource.
2024-10-17 08:47:50 -04:00
Botond Dénes
5a3fd69374 test/lib/reader_lifecycle_policy: add semaphore factory to constructor
Allowing callers to specify how the semaphore is created and stopped,
instead of doing so via boolean flags like it is done currently. This
method doesn't scale, so use a factory instead.
2024-10-17 08:47:50 -04:00
Botond Dénes
c8598e21e8 test/lib/reader_lifecycle_policy: rename factory_function
To reader_factor_function. We are about to add a new factory function
parameters, so the current factory_function has to be renamed to
something more specific.
2024-10-17 08:47:50 -04:00
Botond Dénes
76a5ba2342 repair/row_level: drop now unneeded release_base_resource() calls
The multishard reader now does this itself, no need to do it here.
2024-10-17 08:47:50 -04:00
Botond Dénes
218ea449a5 readers/multishard: make multishard reader safe to create with admitted permits
Passing an admitted permit -- i.e. one with count resources on it -- to
the multishard reader, will possibly result in a deadlock, because the
permit of the multishard reader is destroyed after the permits of its
child readers. Therefore its semaphore resources won't be automatically
released until children acquire their own resources.
This creates a dependency (an edge in the "resource allocation graph"),
where the semaphore used by the multishard reader depends on the
semaphores used by children. When such dependencies create a cycle, and
permits are acquired by different reads in just the right order, a
deadlock will happen.

Users of the multishard reader have to be aware of this gotcha -- and of
course they aren't. This is small wonder, considering that not even the
documentation on the multishard reader mentions this problem.
To work around this, the user has to call
`reader_permit::release_base_resources()` on the permit, before passing
it to the multishard reader.
On multiple occasions, developers (including the very author of the
multishard reader), forgot or didn't know about this and this resulted
in deadlocks down the line.
This is a design-flaw of the multishard reader, which is addressed in
this patch, after which, it is safe to pass admitted or not admitted
permits to the multishard reader, it will handle the call to
`release_base_resources()` if needed.
2024-10-17 08:45:21 -04:00
Raphael S. Carvalho
f3ab5e1f1e tests: Fix perf test for load balancer
Broken after introduction of zero-token nodes.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>

Closes scylladb/scylladb#21156
2024-10-17 14:02:31 +02:00
Kamil Braun
f02afefd34 Merge 'raft: consider the gossiper state then sending the group0 state id' from Emil Maskovsky
Skip the advertisement of the group0 state id in case the gossiper is
not active (ready).

Sending the application state when the gossiper is not active caused
a warning being shown in the log about the local endpoint not being
found in the gossiper endpoint state map on a (graceful) node restart.

The local endpoint is initialized on the gossiper startup, so we skip
the state id advertisement until the startup is finished.

Fixes: scylladb/scylladb#21117

No backport: Fixes an issue that is currently only present in master

Closes scylladb/scylladb#21119

* github.com:scylladb/scylladb:
  raft: consider the gossiper state then sending the group0 state id
  raft: add the test for GROUP0_STATE_ID gossip application state
2024-10-17 13:41:15 +03:00
Kefu Chai
5ef0cbb693 tools/scylla-nodetool: s/vm.count()/vm.contains()/
this change is created in the same spirit of 0104c7d3, which used
`std::map::contains()` in the place of `std::map::count()` when
checking for the existence of a paramter with given name for better
readability.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21158
2024-10-17 13:41:15 +03:00
Alexey Novikov
b965729f0a replica: implement memtable_flush_period_in_ms schema option
implement cassandra original schema option memtable_flush_period_in_ms:
Milliseconds before memtables associated with the table are flushed.

there are few things concerning this patch:
* milliseconds look strange and scary for this option. Unlike Cassandra
  we use 60000ms (1min) minimum value for this option.
* This is limitation of Cassandra but it is impossible to set this option
  for system tables. However sometimes it could be very useful to use
  automatic flushing for such a tables: some system tables have small
  traffic and as a result prevent tombstone garbage collection.

Fixes #20270

Closes scylladb/scylladb#20999
2024-10-17 13:41:15 +03:00
Anna Stuchlik
b54ce3b0c0 doc: remove the redundant raw:: html directive
This commit removes the raw:: html directive (with the exception of an embedded animation) because:
- It is not supported by the dark theme and looks bad.
- It's a legacy directive, and we no longer need it on index pages.

Fixes https://github.com/scylladb/scylladb/issues/20881

Closes scylladb/scylladb#21062
2024-10-17 13:41:15 +03:00
Kefu Chai
d7f315ef63 tool/scylla-nodetool: check for positional argument passed to "restore"
before this change, if no positional arguments are passed to "restore"
subcommand, the tool fails with following error message:

```
error running operation: boost::wrapexcept<boost::bad_any_cast> (boost::bad_any_cast: failed conversion using boost::any_cast)
```

this is difficult to digest.

after this change, if no sstables are specified:

```
error processing arguments: missing required parameter: sstables
```

this is slightly better from user experience's perspective.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21136
2024-10-17 13:41:15 +03:00
Kefu Chai
9355a32b5c utils/loading_cache: s/typeof/decltype/
`typeof` is a GNU extension, and is part of C23, but it is not included
by C++23.

if we compile the tree with c++23 instead of gnu++23, the compilation
fails like:

```
FAILED: repair/CMakeFiles/repair.dir/RelWithDebInfo/repair.cc.o
/home/kefu/.local/bin/clang++ -DSCYLLA_BUILD_MODE=release -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"RelWithDebInfo\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -isystem /home/kefu/dev/scylladb/abseil -isystem /home/kefu/dev/scylladb/seastar/include -isystem /home/kefu/dev/scylladb/build/RelWithDebInfo/seastar/gen/include -isystem /usr/include/p11-kit-1 -ffunction-sections -fdata-sections -O3 -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=westmere -Xclang -fexperimental-assignment-tracking=disabled -mllvm -inline-threshold=2500 -fno-slp-vectorize -std=c++23 -Werror=unused-result -DSEASTAR_API_LEVEL=7 -DSEASTAR_SSTRING -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_LOGGER_TYPE_STDOUT -DFMT_SHARED -DWITH_GZFILEOP -MD -MT repair/CMakeFiles/repair.dir/RelWithDebInfo/repair.cc.o -MF repair/CMakeFiles/repair.dir/RelWithDebInfo/repair.cc.o.d -o repair/CMakeFiles/repair.dir/RelWithDebInfo/repair.cc.o -c /home/kefu/dev/scylladb/repair/repair.cc
In file included from /home/kefu/dev/scylladb/repair/repair.cc:21:
In file included from /home/kefu/dev/scylladb/service/storage_service.hh:19:
In file included from /home/kefu/dev/scylladb/service/qos/service_level_controller.hh:19:
In file included from /home/kefu/dev/scylladb/auth/service.hh:23:
In file included from /home/kefu/dev/scylladb/auth/permissions_cache.hh:22:
/home/kefu/dev/scylladb/utils/loading_cache.hh:754:66: error: use of undeclared identifier 'typeof'; did you mean 'typeid'?
  754 |         static_assert(SectionHitThreshold <= std::numeric_limits<typeof(_touch_count)>::max() / 2, "SectionHitThreshold value is too big");
      |                                                                  ^
/home/kefu/dev/scylladb/utils/loading_cache.hh:754:66: error: template argument for template type parameter must be a type
  754 |         static_assert(SectionHitThreshold <= std::numeric_limits<typeof(_touch_count)>::max() / 2, "SectionHitThreshold value is too big");
      |                                                                  ^~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/limits:311:21: note: template parameter is declared here
  311 |   template<typename _Tp>
      |                     ^
2 errors generated.
```

in this change, we trade `typeof` for a more standard compliant
`decltype`.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21116
2024-10-17 13:41:15 +03:00
Pavel Emelyanov
df83fe2dae Merge 'interval: replace boost ranges with std ranges' from Avi Kivity
To reduce dependency load, replace use of boost ranges with std ranges.

Since std ranges are more particular about what iterators they accept, a custom iterator
in size_estimates_virtual_reader has to be fixed first.

No backport; code cleanup.

Closes scylladb/scylladb#21143

* github.com:scylladb/scylladb:
  interval: change boost ranges to std ranges
  size_estimates_virtual_reader: make virtual_row_iterator more conforming
2024-10-17 13:41:15 +03:00
Avi Kivity
6fd219d982 sstables: generation_type: deinline from_string()
This is not performance sensitive and penalizes everyone by including
boost/regex.hpp. Fix by deinlining.

Closes scylladb/scylladb#21147
2024-10-17 13:41:15 +03:00
Emil Maskovsky
e082fef32c raft: remove the group0 state id handler stop check
The stop assertion check in the group0 state id handler was triggering
under some circumstances (stopping server during restart). In that case
it might be that the stop is initiated before the server is fully
initialized, and then the handler destructor is being called without
calling to the `stop()` method first. This is a valid scenario.

The whole `stop()` in the group0 state id handler is not necessary,
as the only operation being done is cancelling the timer which is done
by the timer destructor automatically anyway.

There is the concern of a currently running timer callback, but it
doesn't preempt (not async) so the timer shouldn't be destroyed before
the callback finishes.

Fixes: scylladb/scylladb#21074

Closes scylladb/scylladb#21127
2024-10-17 13:41:15 +03:00
Emil Maskovsky
3f1af268c2 raft: consider the gossiper state then sending the group0 state id
Skip the advertisement of the group0 state id in case the gossiper is
not active (ready).

Sending the application state when the gossiper is not active caused
a warning being shown in the log about the local endpoint not being
found in the gossiper endpoint state map on a (graceful) node restart.

The local endpoint is initialized on the gossiper startup, so we skip
the state id advertisement until the startup is finished.

Fixes: scylladb/scylladb#21117
2024-10-16 19:26:25 +02:00
Emil Maskovsky
65d3d4fd93 raft: add the test for GROUP0_STATE_ID gossip application state
Test that the GROUP0_STATE_ID gossip application state is not causing
the "endpoint_state_map does not contain endpoint" error.

Refs: scylladb/scylladb#21117
2024-10-16 19:21:14 +02:00
Calle Wilund
f2ef75c3da commitlog_test: Up timeout for large entry tests
Fixes #21150

Apparently, on some CI, in debug, these tests can time out (large alloc)
without actually failing what they do. Up the timeout (could consider removing
as well, but...) so they hopefully pass.

Closes scylladb/scylladb#21151
2024-10-16 18:13:04 +03:00
Avi Kivity
f799234c82 Update tools/java submodule (deprecation notice)
* tools/java b2d025fd6b...807e991de7 (1):
  > README.md: add deprecation notice for java tools
2024-10-16 17:09:48 +03:00
Avi Kivity
b73f0197a8 Merge 'micro-updates to documentation development, on python-poetry' from Laszlo Ersek
- `docs/Makefile`: work around python-poetry issue https://github.com/python-poetry/poetry/issues/8761
- `docs/README.md`: fix minimum poetry version

No backporting needed (docs development).

Closes scylladb/scylladb#21118

* github.com:scylladb/scylladb:
  docs/README.md: fix minimum poetry version
  docs/Makefile: work around python-poetry issue #8761
2024-10-16 14:16:29 +03:00
Nadav Har'El
ee0e7a7adf mv: test that operations that should not be allowed on a view, aren't
This patch adds test/cql-pytest tests which verify that all CQL operations
that shouldn't be allowed on a materialized view, actually aren't:

* All operations writing to a table - INSERT, UPDATE, BATCH, DELETE,
  and TRUNCATE - should be rejected when asked to operate on a view.

* All operations with "TABLE" in their name (DROP TABLE, ALTER TABLE,
  DESC TABLE) should be rejected on a view - the ".. MATERIALIZED VIEW"
  operation should be used instead.

* A materialized view cannot get materialized views or indexes of its
  own.

All tests pass on Cassandra (Cassandra 4 or above is needed for the
"DESC" test), and all but one pass on Scylla - Scylla does allow
"DESC TABLE" on a materialized view, unlike Cassandra. I opened an
issue to track that difference: Refs #21026

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#21028
2024-10-16 13:43:36 +03:00
Avi Kivity
d58cd262ca interval: change boost ranges to std ranges
Reduce dependency load.

size_estimates_virtual_reader is adjusted due to poor boost ranges
and std ranges interoperability.
2024-10-16 13:21:43 +03:00
Avi Kivity
3a75efd6d4 size_estimates_virtual_reader: make virtual_row_iterator more conforming
To work with std::ranges, an iterator has to have a default constructor,
and be assignable. Add the default constructor and convert references
to pointers to support this.
2024-10-16 13:21:25 +03:00
Pavel Emelyanov
4a8ab9b3bc s3/client: Restore indentation after previous patch
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-16 12:27:29 +03:00
Pavel Emelyanov
a15dfe0154 s3/client: Catch do_upload_file::upload_part() exceptions
This method spawns part uploading in the background, but still may
throw, e.g. preparing http request or claiming memory. In this case any
outstanding part upload fibers are not waited on, and the whole
do_upload_file object can be freed from under their feet. Also, the
multipart upload is not aborted, thus losing track of it until g.c.
happens.

To fix it, catch any exception from upload_part() too, and if it
happens, do what the regular upload_sink would do -- close the gate thus
picking up any outstanding activity that may happen there and abort the
multipart upload.

Indentation is deliberately left broken

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-16 12:23:31 +03:00
Nadav Har'El
210d53070e docs/alternator: explain service discovery HTTP requests
In this patch we add to docs/new-apis.md (Alternator-specific API)
a description of the service discovery HTTP requests - `/` and
`/localnodes` that was previously not documented except in a design
document that is unfortunately no longer available publically.

The description also includes the recently added `dc` and `rack`
parameters for the `/localnodes` request.

Fixes #20989

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-10-16 10:15:04 +03:00
Nadav Har'El
367e18ed4a docs/alternator: split Alternator-specific APIs from alternator.md
Before this patch, the documentation of Alternator-specific APIs (APIs
which are unique to Alternator and don't exist in DynamoDB) appear as
a section of the main document alternator.md. In the next patch we
want to describe yet another Alternator feature and make this section
even longer. But there is growing sentiment that the Alternator
documentation should be split into more, shorter, pages (Refs #19822)
so this patch splits the Alternator-specific API documentation into a
new file, new-apis.md.

There is no new content in the patch - just movement of existing content
plus a reference to the new page.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-10-16 10:14:31 +03:00
Kefu Chai
32f508d450 raft: fix typo in logging message
s/miminum/minimum/

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21073
2024-10-16 06:33:43 +03:00
Avi Kivity
d59038fa93 storage_proxy: convert boost range algorithms to std::ranges
Standardize on a single range library.

The changes are mostly mechanical. The only exception is boost::join,
which has no analog in std::ranges (rightly so, since it cannot be
implemented efficiently). A variety of tricks were used to convert it:

 - use std::ranges::join() on an std::array of std::span (when the
   inputs were all contiguous)
 - copy to a utils::small_vector (when it is expected that there will
   be no allocation)
 - use a small_vector of pointers and iterate+dereference that

Closes scylladb/scylladb#21082
2024-10-15 16:52:27 +02:00
Avi Kivity
820509026f schema: replace boost ranges with std ranges
To reduce dependency load, use std ranges instead of boost ranges.

The std::ranges::{lower,upper}_bound don't support heterogeneous lookup,
but a more natural solution is to use a projection to search for the name,
so we use that and the custom comparator is removed.

Many callers are converted as well due to poor interoperability between
boost ranges and std ranges.
2024-10-15 16:42:54 +03:00
Piotr Dulikowski
a380a2efd9 test/test_view_build_status: properly wait for v2 in migration test
The test_view_build_status_migration_to_v2 test case creates a new view
(vt2) after peforming the view_build_status -> view_build_status_v2
migration and waits until it is built by `wait_for_view_v2` function. It
works by waiting until a SELECT from view_build_status_v2 will return
the expected number of rows for a given view.

However, if the host parameter is unspecified, it will query only one
node on each attempt. Because `view_build_status_v2` is managed via
raft, queries always return data from the queried node only. It might
happen that `wait_for_view_v2` fetches expected results from one node
while a different node might be lagging behind the group0 coordinator
and might not have all data yet.

In case of test_view_build_status_migration_to_v2 this is a problem - it
first uses `wait_for_view_v2` to wait for view, later it queries
`view_build_status_v2` on a random node and asserts its state - and
might fail because that node didn't have the newest state yet.

Fix the issue by issuing `wait_for_view_v2` in parallel for all nodes in
the cluster and waiting until all nodes have the most recent state.

Fixes: scylladb/scylladb#21060

Closes scylladb/scylladb#21091
2024-10-15 14:57:47 +03:00
Pavel Emelyanov
63725b10a8 Merge 'cql: create default superuser if it doesn't exist' from Paweł Zakrzewski
This change reorganizes the way standard_role_manager startup is handled: role_manager::ensure_superuser_is_created() is added, which returns a future that resolves once the superuser is available. We wait for this future before starting the CQL server.

There is a change in behavior auth::do_after_system_ready is potentially an infinite loop, and we await its result.

Fixes #10481

Reason for no backports: it's not a regresson and it's an issue that may only affect a tiny time window during the cluster startup.

Closes scylladb/scylladb#20137

* github.com:scylladb/scylladb:
  test: test_restart_cluster: create the test
  auth: standard_role_manager allows awaiting superuser creation
  auth: coroutinize the standard_role_manager start() function
  auth: don't start server until the superuser is created
2024-10-15 14:56:04 +03:00
Avi Kivity
a5c37a110f schema: precompute all_columns_in_select_order()
all_columns_in_select_order() returns a complicated boost range type
that has no analog in std::ranges. To ease the transition to std::ranges,
precompute most of the work done in that function, and only convert
pointers to references in the function itself.

Since boost ranges and std::ranges don't fully interoperate, one of
the user has to be adjusted.
2024-10-15 14:04:12 +03:00
Pavel Emelyanov
6e0899c2b4 data_dictionary: Replace boost ranges with std ranges
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21105
2024-10-15 13:22:08 +03:00
Laszlo Ersek
a0ffbd5bcf docs/README.md: fix minimum poetry version
Commit 2a3012db7f ("docs/README.md: expand prerequisites list",
2022-08-31) referenced poetry release 1.12, which does not exist even
today (as of this writing, the latest release is 1.8.4). The intent was
probably 1.1.12.

Copy the minimum version from "sphinx-scylladb-theme": 1.8.1 (see
"docs/source/getting-started/installation.rst" and
"docs/source/getting-started/quickstart.rst" at commit f7c26b422572).

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>
2024-10-15 12:19:21 +02:00
Laszlo Ersek
e5c2d4bd1d docs/Makefile: work around python-poetry issue #8761
Python-poetry is affected by bug
<https://github.com/python-poetry/poetry/issues/8761>. Namely, if you have
"keyring" <https://pypi.org/project/keyring/> installed, poetry will try
to gain access to the Default collection in the (ex. GNOME) keyring, even
if poetry only needs read-only access to package repositories, and even if
those repos are public.

Consequently, you either unlock your Default collection for poetry
(unjustifiedly), or your GUI session gets effectively locked up, because
any time you hit Cancel on the keyring unlock dialog, poetry immediately
pops up another, and this dialog grabs the keyboard -- you cannot even
switch to a character VT, for killing poetry; you have to log in via ssh
for that.

This issue is not visible to users who don't use "keyring" (GNOME or
otherwise). For those who do, work around the problem by selecting the
"null" keyring back-end, in the environment of every poetry invocation.

Note: I have not regression-tested the workaround in a desktop environment
where "keyring" is unavailable to begin with.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>
2024-10-15 12:07:00 +02:00
Botond Dénes
f93abebbb9 Merge 'Sanitize compaction manager API endpoints' from Pavel Emelyanov
Endpoints are registered next to the service they use, and the unregistration deferred action is created right after it. When registered, the service in question is passed as argument and then captured by enpoints lambdas. This makes sure that service is not used by endpoints after being stopped.

That's not quite the case for compaction manager. Its endpoints can be registered in several places, and compaction_manager "function" is not unregistered on stop. This patch fixes some of this misbehavior, in particular:
- adds unregistration of compaction_manager API function
- uses sharded<compaction_manager>& argument in endpoints instead of ctx.db.local().get_compaction_manager() chain
- moves some endpoints from storage_service.cc to compaction_manager.cc

Closes scylladb/scylladb#20962

* github.com:scylladb/scylladb:
  api: Use captured compaction_manager in get_cm_stats() helper
  api: Use captured compaction_manager in endpoints
  api: Add sharded<compaction_manager> argument to compaction_manager API reg/unreg
  api: Move some endpoints from storage_service.cc to compaction_manager.cc
  api: Unset compaction_manager endpoints
  api: Use shorter registration method for compaction_manager function
2024-10-15 10:20:58 +03:00
Daniel Reis
28a265ccd8 docs: fix redirect from cert-based auth to security/enable-auth page
Closes scylladb/scylladb#19943
2024-10-15 09:29:05 +03:00
Kefu Chai
a82706eb8f Update seastar submodule
* seastar 3c9c2696...abd20efd (44):
  > Revert "build: enable Seastar to build shared and static libs in a single build"
  > dns: Support c-ares before 1.22
  > build: improve c-ares version extraction method
  > Minor typos fix in doc: reference_wrapper.hh
  > build: enable Seastar to build shared and static libs in a single build
  > build: include -fno-semantic-interposition in CXXFLAGS
  > loop: add Sentinel iterator support to parallel_for_each()
  > dns: use ARES_LIB_INIT_NONE instead of a magic number
  > dns: use struct typedef for `_channel`
  > doc/testing.md: explain seastar + boost test colocation
  > build: extract c-ares version from header file
  > dns: replace deprecated ares_process() with ares_process_fd()
  > build: do not support c-ares >= 1.33
  > http: fix indentation
  > http: Add non-owning `make_request` to http client
  > treewide: replace boost::irange with std::views::iota where possible
  > Added unit test for "http_content_length_data_sink_impl"
  > sharded.hh: migrate to concepts
  > file, scheduling: remove non-unified I/O and CPU scheduling
  > http: Add more HTTP response codes
  > http: add constness to `response_line`
  > http: refactor response_line to use `seastar::format`
  > httpd/file_handler: Always close stream
  > build: add compiler and C++ standard compatibility checks
  > rpc: rpc_types: replace boost::any with std::any
  > tls: drop dependency on boost::any
  > rpc: drop unnecessaty includes to boost libraries
  > rpc: compressor factory: deinline some boost-using functions
  > sharded: replace boost ranges with <ranges>
  > scheduling_specific: drop dependency on boost range adaptors
  > prefetch: drop dependency on boost::mpl
  > resource: drop unused dependency on boost::any
  > smp: drop dependency on boost ranges
  > reactor: remove unnecessary boost includes
  > execution_stage: remove unnecessary boost includes
  > sharded.hh: add invoke_on variant for a shard range
  > shared_ptr: remove deprecated lw_shared_ptr assignment operator
  > seastar-addr2line: add --debug arg
  > addr2line: add type checking
  > warnings: fix unused result warnings
  > thread_pool: fix includes
  > signal: remove trailing spaces
  > tests/unit: chmod -x signal_test.cc
  > iostream/http: Fix output_stream::write(temporary_buffer) overload

Closes scylladb/scylladb#21109
2024-10-15 09:09:29 +03:00
Tomasz Grabiec
3e438d23e1 Merge 'Check system.tablets update before putting it into the table' from Pavel Emelyanov
Having tablet metadata with more than 1 pending replica will prevent this metadata from being (re)loaded due to sanity check on load. This patch fails the operation which tries to save the wrong metadata with a similar sanity check. For that, changes submitted to raft are validated, and if it's topology_change that affects system.tablets, the new "replicas" and "new_replicas" values are checked similarly to how they will be on (re)load.

fixes #20043

Closes scylladb/scylladb#21020

* github.com:scylladb/scylladb:
  tablets: Validate system.tablets update
  group0_client: Introduce change validation
  group0_client: Add shared_token_metadata dependency
2024-10-15 00:38:59 +02:00
Piotr Smaron
3969ffb39f test: fix flaky test_multidc_alter_tablets_rf
The testcase is flaky due to a known python driver issue:
https://github.com/scylladb/python-driver/issues/317.
This issue causes the `CREATE KEYSPACE` statement to be sometimes
executed twice in a row, and the 2nd CREATE statement causes the test to
fail.
In order to work around it, it's enough to add `if not exists` when
creating a ks.

Fixes: scylladb/scylladb#21034

Needs to be backported to all 6.x branches, as the PR introducing this flakiness is backported to every 6.x branch.

Closes scylladb/scylladb#21056
2024-10-14 16:18:44 +02:00
Avi Kivity
c286ddab38 test: lib: rest_client: use 'http' scheme even when connecting via a unix socket
aiohttp 3.10.5 complains when 'unix+http' is used for a unix-domain
socket. USe 'http', which work with 3.10.5 and the toolchain's 3.9.5.

Closes scylladb/scylladb#21080
2024-10-14 15:32:56 +02:00
Piotr Dulikowski
48d75818fd SCYLLA-VERSION-GEN: correct the logic for skipping SCYLLA-*-FILE
The SCYLLA-VERSION-GEN file skips updating the SCYLLA-*-FILE files if
the commit hash from SCYLLA-RELEASE-FILE is the same. The original
reason for this was to prevent the date in the version string from
changing if multiple modes are built across midnight
(scylladb/scylla-pkg#826). However - intentionally or not - it serves
another purpose: it prevents an infinite loop in the build process.

If the build.ninja file needs to be rebuilt, the configure.py script
unconditionally calls ./SCYLLA-VERSION-GEN. On the other hand, if one
of the SCYLLA-*-FILE files is updated then this triggers rebuild
of build.ninja. Apparently, this is sufficient for ninja to enter an
infinite loop.

However, the check assumes that the RELEASE is in the format

  <build identifier>.<date>.<commit hash>

and assumes that none of the components have a dot inside - otherwise it
breaks and just works incorrectly. Specifically, when building a private
version, it is recommended to set the build identifier to
`count.yourname`.

Previously, before 85219e9, this problem wasn't noticed most likely
because reconfigure process was broken and stopped overwriting
the build.ninja file after the first iteration.

Fix the problem by fixing the logic that extracts the commit hash -
instead of looking at the third dot-separated field counting from the
left side, look at the last field.

Fixes: scylladb/scylladb#21027

Closes scylladb/scylladb#21049
2024-10-14 13:49:15 +03:00
Calle Wilund
8eaf00ff11 test::topology: Add test for TLS upgrade and downgrade of internode encryption
Test a rolling upgrade of cluster while active.
Note: This is a unit test version of dtest test. Has the big drawback of not
being able to use cassandra-stress to work and verify the cluster and results

Test moves from none to all to none encryption while writing and then checking
written data.
2024-10-13 23:54:06 +00:00
Calle Wilund
a557f699a2 docs: Add internode_encryption=transitional documentation
Describing upgrading cluster(s) without downtime.
2024-10-13 23:54:06 +00:00
Calle Wilund
390b9759b6 messaging_service: Add "transitional" internode encryptipn mode
Fixes #18903

Adds a "transitional" internode encryption mode, under which all
_outgoing_ RPC connections will use TLS, but we will still accept
any incoming non-tls connection.

This allows an operator to perform a move to TLS RPC without cluster
downtime:

1. For each server, add certificate etc options to
   server_encryption_options
   + internode_encryption=none
   + set ssl_storage_port
   + restart (rolling)

2. For each server, set internode_encryption=transitional + RR
3. For each server, set internode_encryption=all + RR
2024-10-13 23:54:06 +00:00
Calle Wilund
503a71f9b8 messaging_service: Create TLS connector even if internode_enc=none when certs set
Refs #18903

If ssl_storage_port is non-zero _and_ we have specified actual certificates
are set/exists, create TLS connector for RPC regardless of whether internode
encryption is enables. I.e. potentially unused. For transitioning cluster to
TLS.
2024-10-13 23:54:05 +00:00
Avi Kivity
db14a01901 Merge 'Use table id as system.sstables partition key' from Pavel Emelyanov
The system.sstables (a.k.a. sstables registry) primary key is "string location" as partition key and "uuid generation" as clustering one. The "location" part was taken from table.config.datadir value which, in turn, a string containing path to on-disk files if the table was located locally, e.g. /var/lib/scylla/data/ks/cf-abc123 one. Recently [1] the datadir was moved from table config onto storage options, but this string is still used as registry key.

Other than being owned by a table with ID, sstables are accessed by restore-from-object-storage code [2]. To make it work, both storage driver and sstable_directory helper class maintain two formats of object prefixes for sstables components. For S3-backed sstables having a record in registry, the path used is s3://bucket/generation/component. For restore code there are user-provided prefixes that do not match the aforementioned pattern. The selection between those two is now made by checking sstable state, which is not obvious and may cause troubles for tiered storage driver.

This patch changes  the registry schema so that partition key becomes "uuid owner" and is set to be table.id() value. This is to stop using the local path by S3 backed sstables. Also this change makes it possible for storage driver and sstable directory to rely on the storage options only to tell different bucket prefixes formats from each other.

As a side effect, the make_s3_object_name() helper, that generates the proper object name, becomes explicit for restore-from-S3 usage. Now it relies on the sstable::filename() calling this->prefix() behind the scenes and the latter to return the user-provided prefix, which is pretty fragile construction.

No need to backport (and it's not going to be easy to do it), storage options feature is still experimental

Refs #20675 [1]
Refs #20305 [2]

Closes scylladb/scylladb#20998

* github.com:scylladb/scylladb:
  sstables: Flatten S3 object name making
  sstable_directory: Flatten directory lister creation
  treewide: Rename sstable registry location field to be owner
  system_keyspace: Change sstables registry partition key type
  sstables: Keep location variant on s3 backend too
  storage_options: Use variant on S3 options
  sstables: Split sstable::filename() helper
  sstables: Add s3_storage::owner() helper
2024-10-13 20:08:43 +03:00
Kefu Chai
7d2d44883b install.sh: install seastar/scripts/addr2line.py as well
seastar extracted `addr2line` python module out back in
e078d7877273e4a6698071dc10902945f175e8bc. but `install.sh` was
not updated accordingly. it still installs `seastar-addr2line`
without installing its new dependency. this leaves us with a
broken `seastar-addr2line` in the relocatable tarball.
```console
$ /opt/scylladb/scripts/seastar-addr2line
Traceback (most recent call last):
  File "/opt/scylladb/scripts/libexec/seastar-addr2line", line 26, in <module>
    from addr2line import BacktraceResolver
ModuleNotFoundError: No module named 'addr2line'
```

in this change, we redistribute `addr2line.py` as well. this
should address the issue above.

Fixes scylladb/scylladb#21077

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21078
2024-10-13 19:35:14 +03:00
Kefu Chai
519b4a2934 utils/s3: include used header
when building the tree with clang-19 and libstdc++ shipped along with
GCC 14.2.1, we have

```
clang++ -MD -MT build/release/utils/s3/aws_error.o -MF build/release/utils/s3/aws_error.o.d -std=c++23 -I/home/kefu/dev/scylladb/master/seastar/include -I/home/kefu/dev/scylladb/master/build/release/seastar/gen/include -Werror=unused-result -DSEASTAR_API_LEVEL=7 -DSEASTAR_SSTRING -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_LOGGER_TYPE_STDOUT -DFMT_SHARED -I/usr/include/p11-kit-1 -DWITH_GZFILEOP -ffile-prefix-map=/home/kefu/dev/scylladb/master=. -march=westmere -ffunction-sections -fdata-sections  -O3 -mllvm -inline-threshold=2500 -fno-slp-vectorize -DSCYLLA_BUILD_MODE=release -g -gz -Xclang -fexperimental-assignment-tracking=disabled -iquote. -iquote build/release/gen -std=gnu++23  -ffile-prefix-map=/home/kefu/dev/scylladb/master=. -march=westmere -DBOOST_ALL_DYN_LINK    -fvisibility=hidden -isystem abseil -Wall -Werror -Wextra -Wimplicit-fallthrough -Wno-mismatched-tags -Wno-c++11-narrowing -Wno-overloaded-virtual -Wno-unused-parameter -Wno-unsupported-friend -Wno-missing-field-initializers -Wno-deprecated-copy -Wno-psabi -Wno-error=deprecated-declarations -DXXH_PRIVATE_API -DSEASTAR_TESTING_MAIN  -c -o build/release/utils/s3/aws_error.o utils/s3/aws_error.cc
utils/s3/aws_error.cc:33:21: error: no member named 'make_unique' in namespace 'std'
   33 |     auto doc = std::make_unique<rapidxml::xml_document<>>();
      |                ~~~~~^
utils/s3/aws_error.cc:33:57: error: expected '(' for function-style cast or type construction
   33 |     auto doc = std::make_unique<rapidxml::xml_document<>>();
      |                                 ~~~~~~~~~~~~~~~~~~~~~~~~^
utils/s3/aws_error.cc:33:59: error: expected expression
   33 |     auto doc = std::make_unique<rapidxml::xml_document<>>();
      |                                                           ^
3 errors generated.
ninja: build stopped: subcommand failed.
```

in order to address the build failure, let's include the used header.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#21064
2024-10-13 18:32:34 +03:00
Patryk Jędrzejczak
18d3a6480d test: test_read_required_hosts: run with the raft-based topology
When we made the raft-based topology mandatory, all boost test
tests started using it. Then, `test_read_required_hosts` started
failing. We left investigating it for later and started running it
with `force-gossip-topology-changes` to make it pass.

Currently, the test doesn't fail with the raft-based topology
anymore. Hence, we remove the FIXME and run the test with a normal
config.

We don't know when and why the test stopped failing. Investigating
it wouldn't be easy, since we don't even know why it failed in the
first place. We suspect that there was some bug that is now fixed.

This patch only fixes a test, there is no need to backport it.

Fixes scylladb/scylladb#18463

Closes scylladb/scylladb#20960
2024-10-11 17:01:20 +02:00
Kamil Braun
96070bb5b3 Merge 'storage_proxy: Add conditions checking to avoid UB in speculating read executors.' from Sergey Zolotukhin
During the investigation of scylladb/scylladb#20282, it was discovered that implementations of speculating read executors have undefined behavior when called with an incorrect number of read replicas. This PR introduces two levels of condition checking:

- Condition checking in speculating read executors for the number of replicas.
- Checking the consistency of the Effective Replication Map in  filter_for_query(): the map is considered incorrect if the list  of replicas contains a node from a data center whose replication factor is 0.

 Please note: This PR does not fix the issue found in scylladb/scylladb#20282;   it only adds condition checks to prevent undefined behavior in cases of  inconsistent inputs.

Refs scylladb/scylladb#20625

As this issue applies to the releases versions and can affect clients, we need backports to 6.0, 6.1, 6.2.

Closes scylladb/scylladb#20851

* github.com:scylladb/scylladb:
  Add conditions checking for get_read_executor
  Avoid an extra call to block_for in db::filter_for_query.
  Improve code readability in consistency_level.cc and storage_proxy.cc
  tools: Add build_info header with functions providing build type information
  tests: Add tests for alter table with RF=1 to RF=0
2024-10-11 15:02:02 +02:00
Paweł Zakrzewski
900a6706b8 test: test_restart_cluster: create the test
The purpose of this test that the cluster is able to boot up again after
a full cluster shutdown, thus exhibiting no issues when connecting to
raft group 0 that is larger than one.
2024-10-11 13:25:07 +02:00
Paweł Zakrzewski
7008b71acc auth: standard_role_manager allows awaiting superuser creation
This change implements the ability to await superuser creation in the
function ensure_superuser_is_created(). This means that Scylla will not
be serving CQL connections until the superuser is created.

Fixes #10481
2024-10-11 13:25:07 +02:00
Paweł Zakrzewski
04fc82620b auth: coroutinize the standard_role_manager start() function
This change is a preparation for the next change. Moving to coroutines
makes the code more readable and easier to process.
2024-10-11 13:25:07 +02:00
Paweł Zakrzewski
f525d4b0c1 auth: don't start server until the superuser is created
This change reorganizes the way standard_role_manager startup is
handled: now the future returned by its start() function can be used to
determine when startup has finished. We use this future to ensure the
startup is finished prior to starting the CQL server.

Some clusters are created without auth, and auth is added later. The
first node to recognize that auth is needed must create the superuser.
Currently this is always on restart, but if we were to ever make it
LiveUpdate then it would not be on restart.

This suggests that we don't really need to wait during restart.

This is a preparatory commit, laying ground for implementation of a
start() function that waits for the superuser to be created. The default
implementation returns a ready future, which makes no change in the code
behavior.
2024-10-11 13:25:07 +02:00
Pavel Emelyanov
a7042d66e3 sstables: Flatten S3 object name making
The s3_storage backend driver has a method that generates object path
within the bucket. Depending on options alternative it picks one of two
formats:

- for string prefix, it uses it implicitly via sstable::filename() call
  that calls storage->prefix() which, in turn, returns prefix value

- for registry-backed sstables, the /bucket/generation/component path is
  generated

This patch bruses this place up. Similarly to previous patch, this
change also makes the selection based on the location alternative, not
on the sstable state. As well it's idempotent change, as S3 sstables
with 'upload' state only appear when restoring from object store, and in
this case the string location is in use.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 14:11:28 +03:00
Pavel Emelyanov
8d5537a439 sstable_directory: Flatten directory lister creation
After previous patchin, the way components lister is created for S3
storage options became quite hairy. This patch brushes things up to be
easier to read.

The only "functional" change here, is that selection between registry
lister and S3 lister is made based on options' location held
alternative, not on the sstable state value. That's in fact idempotent
change, the only caller that provides string location on options is the
"restore from object store" code that also sets state to be 'upload'.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 14:11:28 +03:00
Pavel Emelyanov
031893259a treewide: Rename sstable registry location field to be owner
This is sort of continuation of the previous patch. The partition key in
the registry is now table_id, not string, and is better called "owner",
not "location". This patch is s/location/owner/ over specific places
that include field name in the schema, argument names in registry
maintenance classes and tests accessing the selected row fields by name.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 14:11:28 +03:00
Pavel Emelyanov
3315e3a2a9 system_keyspace: Change sstables registry partition key type
Today, the system.sstables schema uses string as partition key. Callers,
in turn, use table's datadir value to reference entries in it. That's
wrong, S3-backed sstables don't have any local paths to work with. The
table's ID is better in this role.

This patch only changes the field type to be table_id and fixes the
callers to provide one. In particular, see init_table_storage() change
-- instead of generating a datadir string, it sets table.id() as the
options' location. Other fixed places are tests. Internally, this id
value is propagated via s3_storage::owner() method, that's fixed as
well.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 13:48:09 +03:00
pehala
a2f9136e36 test.py: Use "python -m pytest" for pytest invocation for PythonTest
Enables debugging inside pytest subprocesses as well. It seems that pydev automatically attaches itself also to all python subprocesses. Since we used to call "pytest" wrapper it was deemed a different program, and we could not debug individual tests.

Closes scylladb/scylladb#21050
2024-10-11 13:38:47 +03:00
Pavel Emelyanov
bb13b7bf72 sstables: Keep location variant on s3 backend too
Previous patch put variant<string, table_id> as location of S3 options.
This patch makes the S3 sstables backend driver keep variant as sstable
location. As with the previous patch, driver only keeps variant, but
continues using its string alternative internally. This will be changed
later on.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 13:09:47 +03:00
Pavel Emelyanov
1181b6b082 storage_options: Use variant on S3 options
Describing S3 storage for an sstables nowadays has two options -- via
sstables registry entry and by using the direct prefix string. The
former is used when putting a keyspace on S3. In this case each sstable
has the corresponding entry in the system.sstables table. The latter is
used by "restore from object storage" code. In that case, sstables don't
have entries in the registry, but are accessed by a specific S3 object
path.

This patch reflects this difference by making s3_options::location be
variant of string prefix and table_id owner. The owner needs more
explanation, here it is.

Today, the system.sstables schema defines partition key to be "string
location" and clustering key to be "UUID generation". The partition key
is table's datadir string, but it's wrong to use it this way. Next
patches will change the partition key to be table's ID (there's table_id
type for it), and before doing it storage options must be prepared to
carry it onboard. This patch does it, but the table_id alternative of
the location is still unused, the rest of the code keeps using the
string location to reference a row in the registry table. Next patches
will eventually make use of the table_id value.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 13:04:52 +03:00
Kamil Braun
4d99cd2055 Merge 'raft: fast tombstone GC for group0-managed tables' from Emil Maskovsky
Add the gossip state for broadcasting the nodes state_id.

Implemented the Group0 state broadcaster (based on the gossip) that will broadcast the state id of each node and check the minimal state id for the tombstone GC.

When there is a change in the tombstone GC minimal state id, the state broadcaster will update the tombstone GC time for the group0-managed tables.

The main component of the change is the newly added `group0_state_id_handler` that keeps track, broadcasts and receives the last group0 state_ids across all nodes and sets the tombstone GC deletion time accordingly:
* on each group0 change applied, the state_id handler broadcasts the state_id as a gossip state (only if the value has changed)
* the handler checks for the node state ids every refresh period (configurable, 1h by default)
* on every check, the handler figures out the lowest state_id (timeuuid), which is state_id that all of the nodes already have
* the timestamp of this minimum state_id is then used to set the tombstone GC deletion time
* the tombstone GC calculation then uses that deletion time to provide the GC time back to the callers, e.g. when doing the compaction
* (as the time for tombstone GC calculation has the 1s granularity we actually deduce 1s from the determined timestamp, because it can happen that there were some newer mutations received in the same second that were not distributed across the nodes yet)

This change introduces a new flag to the static schema descriptor (`is_group0_table`) that is being checked for this newly added mode in the tombstone GC. We also add a check (in non-release builds only) on every group0 modification that the table has this flag set.

The group0 tombstone GC handling is similar to the "repair" tombstone GC mode in a sense (that the tombstone GC time is determined according to a reconciliation action), however it is not explicitly visible to (nor editable by) the user. And also the tombstone GC calculation is much simpler than the "repair" mode calculation - for example, we always use the whole range (as opposed to the "repair" mode that can have specific repair times set for specific ranges).

We use the group0 configuration to determine the set of nodes (both current and previous in case of joint configuration) - we need to make sure that we account for all the group0 nodes (if any node didn't provide the state_id yet, the current check round will be skipped, i.e. no GC will be done until all known nodes provide their state_id timestamp value).

Also note that the group0 state_id handling works on all nodes independently, i.e. each node might have its own (possibly different) state depending on the gossip application state propagation. This is however not a problem, as some nodes might be behind, but they will catch up eventually, and this solution has the benefit of being distributed (as opposed to having a central point to handle the state, like for example the topology coordinator that has been considered in the early stages of the design).

Fixes: scylladb/scylla#15607

New feature, should not be backported.

Closes scylladb/scylladb#20394

* github.com:scylladb/scylladb:
  raft: add the check for the group0 tables
  raft: fast tombstone GC for group0-managed tables
  tombstone_gc: refactor the repair map
  raft: flag the group0-managed tables
  gossip: broadcast the group0 state id
  raft/test: add test for the group0 tombstone GC
  treewide: code cleanup and refactoring
2024-10-11 11:52:27 +02:00
Pavel Emelyanov
ba97072709 sstables: Split sstable::filename() helper
To have the filename(type, prefix) one, next patches will provide prefix
on their own, to avoid storage->prefix() call.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 12:47:13 +03:00
Pavel Emelyanov
6f9cb51259 sstables: Add s3_storage::owner() helper
This driver uses sstring _location as part of the lookup key in the
sstables registry. Next patches will need to change that and put more
checks on the registry access, so introduce a helper method beforehand.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-11 12:47:12 +03:00
Sergey Zolotukhin
c373edab2d Add conditions checking for get_read_executor
During the investigation of scylladb/scylladb#20282, it was discovered that
implementations of speculating read executors have undefined behavior
when called with an incorrect number of read replicas. This PR
introduces two levels of condition checking:

- Condition checking in speculating read executors for the number of replicas.
- Checking the consistency of the Effective Replication Map in
  get_endpoints_for_reading(): the map is considered incorrect the number of
  read replica nodes is higher than replication factor. The check is
  applied only when built in non release mode.

Please note: This PR does not fix the issue found in scylladb/scylladb#20282;
it only adds condition checks to prevent undefined behavior in cases of
inconsistent inputs.

Refs scylladb/scylladb#20625
2024-10-11 09:38:25 +02:00
Sergey Zolotukhin
8db6d6bd57 Avoid an extra call to block_for in db::filter_for_query. 2024-10-11 09:38:25 +02:00
Sergey Zolotukhin
ad93cf5753 Improve code readability in consistency_level.cc and storage_proxy.cc
Add const correctness and rename some variables to improve code readability.
2024-10-11 09:38:25 +02:00
Sergey Zolotukhin
ae23d42889 tools: Add build_info header with functions providing build type information
A new header provides `constexpr` functions to retrieve build
type information: `get_build_type()`, `is_release_build()`,
and `is_debug_build()`. These functions are useful when adding
changes that should be enabled at compile time only for
specific build types.
2024-10-11 09:38:24 +02:00
Sergey Zolotukhin
132358dc92 tests: Add tests for alter table with RF=1 to RF=0
Adding Vnodes and Tablets tests for alter keyspace operation that decreases replication factor
from 1 to 0 for one of two data centers. Tablet version fails due to issue described in
scylladb/scylladb#20625.

Test for scylladb/scylladb#20625
2024-10-11 09:38:24 +02:00
Pavel Emelyanov
77eb9ddb0f sstable_set: Reserve vector of readers
When generating readers for the set of sstables, the end size of this
vector is known in advance and its storage can be reserved.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21055
2024-10-11 09:56:17 +03:00
Pavel Emelyanov
551da72492 api: Use captured database, not the one from ctx
Continuation of the previous patch -- not commitlog-related endpoints
can use provided database reference, that was captured from main.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 17:53:30 +03:00
Pavel Emelyanov
74f7071db8 api: Pass sharded<database> to commitlog endpoints registration
This is to make registered enpoints with with the database without
grabbing one from ctx.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 17:52:56 +03:00
Pavel Emelyanov
14ab6d2615 api: Move commitlog-related from storage_service.cc
It registers itself in /storage_service function, but works with
commitlog, so should be located next to commitlog endpoints.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 17:52:25 +03:00
Pavel Emelyanov
ba73704774 api: Unset commitlog API endpoints
Most of other set_...()-s has the unset_...() scheduled right
afterwards, so here's one for set_server_commitlog().

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 17:50:37 +03:00
Pavel Emelyanov
44ec6d36f3 api: Extract set_server_commitlog() from set_server_done()
The latter collects a bunch of endpoints including commitlog ones.
Extract it as snandalone call in main. It's currently not located next
to "commitlog server" as it should, because there's no standalone
commitlog service in main. It will be addressed as a followup together
with other endpoints that work with sharded<database>.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 17:49:10 +03:00
Pavel Emelyanov
1863ccd900 tablets: Validate system.tablets update
Implement change validation for raft topology_change command. For now
the only check is that the "pending replicas" contains at most one
entry. The check mirrors similar one in `process_one_row` function.

If not passed, this prevents system.tablets from being updated with the
mutation(s) that will not be loaded later.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 12:39:58 +03:00
Pavel Emelyanov
e5bf376cbc group0_client: Introduce change validation
Add validate_change() methods (well, a template and an overload) that
are called by prepare_command() and are supposed to validate the
proposed change before it hits persistent storage

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 12:31:52 +03:00
Pavel Emelyanov
f09fe4f351 group0_client: Add shared_token_metadata dependency
It will be needed later to get tablet_metadata from.
The dependency is "OK", shared_token_metadata is low-level sharded
service. Client already references db::system_keyspace, which in turn
references replica::database which, finally, references token_metadata

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-10 12:27:46 +03:00
Botond Dénes
86fd9ce8fd schema/schema: break circular dependency with replica::database
The schema module (everything in schema/) is supposed to be towards the
leafs in the ScyllaDB inter-module dependency graph. In other words, it
should not depend on many other modules. On the other hand, almost the
entire codebase depends on the schema module itself.
Currently there is a circular dependency between schema and
replica::database, as the latter is a required argument for
schema::describe(). This is bad, not just because of the dependency mess
it introduces, but also because now schema::describe() can only be used
by code which has a reference to the database handy.

This patch breaks this circular dependency, by introducing the
schema_describe_helper interface and providing an implementation for it
in database.hh.

There is another circular dependency: schema <-> replica::table. This is
not addressed by this patch.

Closes scylladb/scylladb#20893
2024-10-10 10:07:26 +03:00
Botond Dénes
81423e8e76 Merge 'repair: Fix stall in repair_get_row_diff_with_rpc_stream_process_op_slow_path' from Asias He
Use clear_gently to avoid the following stalls.

```
~frozen_mutation_fragment at ././frozen_mutation.hh:268

std::destroy_at<frozen_mutation_fragment> at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/stl_construct.h:88

std::allocator_traits<std::allocator<std::_List_node<frozen_mutation_fragment>
> >::destroy<frozen_mutation_fragment> at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/alloc_traits.h:537

std::__cxx11::_List_base<frozen_mutation_fragment,
std::allocator<frozen_mutation_fragment> >::_M_clear at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/list.tcc:77

~_List_base at /usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/stl_list.h:499
~partition_key_and_mutation_fragments at ././repair/repair.hh:298
~repair_row_on_wire_with_cmd at ././repair/repair.hh:335
operator() at ./repair/row_level.cc:1881
```

Fixes #21016

Performance improvement only. No backport.

Closes scylladb/scylladb#21017

* github.com:scylladb/scylladb:
  repair: Fix stall in repair_get_row_diff_with_rpc_stream_process_op_slow_path
  repair: Add clear_gently for partition_key_and_mutation_fragments
2024-10-10 09:27:27 +03:00
Benny Halevy
3a12ad96c7 sstables: scylla_metadata: add sstable identifier
Keep a copy of the sstable uuid generation in a new
scylla_metadata sstable_identifier attribute.

If the SSTable happens to have a numerical generation
just create a new time-uuid and log a message about that.

Dump this new attribute in scylla sstable dump tool.

And add a unit test to verify that the written (and then
loaded) sstable identifier matches the sstable's generation.

The motivatrion for this change stems from backup
deduplication.  In essence, an sstable may already have been
backed up in a previous snapshot, and we don't want to
abck it up again if it's already present on external storage.

Today this is based on rclone that compares files checksums,
but once scylla will backup the sstables using the native
object-storage stack (#19890), we would like to use the sstable
globally-unique identifier for deduplication.  Although the
uuid-generation is encoded in the sstable path, the latter
may change, e.g. due to intra-node migration, so keep a copy
of the original unique identifier in scylla-metadata, and that
attribute would survive file-based or intra-node migrations.

Fixes scylladb/scylladb#20459

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#21002
2024-10-10 08:52:46 +03:00
Avi Kivity
b66479ea98 Merge 'compaction: fix potential data resurrection with file-based migration' from Ferenc Szili
When tablets are migrated with file-based streaming, we can have a situation where a tombstone is garbage collected before the data it shadows lands. For instance, if we have a tablet replica with 3 sstables:

1. sstable containing an expired tombstone
2. sstable with additional data
3. sstable containing data which is shadowed by the expired tombstone in sstable 1

If this tablet is migrated, and the sstables are streamed in the order listed above, the first two sstables can be compacted before the third sstable arrives. In that case, the expired tombstone will be garbage collected, and data in the third sstable will be resurrected after it arrives to the pending replica.

This change fixes this problem by disabling tombstone garbage collection for pending replicas.

This fixes a problem in Enterprise, but the change is in OSS in order to have as few differences between OSS and Enterprise and to have a common infrastructure for disabling tombstone GC on pending replicas.

This change has to be backported to all active versions: 6.0, 6.1 and 6.2, as well as Enterprise 2024.2

Closes scylladb/scylladb#20788

* github.com:scylladb/scylladb:
  test: test tombstone GC disabled on pending replica
  tablet_storage_group_manager: update tombstone_gc_enabled in compaction group
  database::table: add tombstone_gc_enabled(locator::tablet_id)
2024-10-09 21:49:49 +03:00
Avi Kivity
bb1867c7c7 Merge 'sstables: Add digest checking in the validation path of the sstable layer' from Nikos Dragazis
This PR builds upon the PR for checksum validation (#20207) to further enhance scrub's corruption detection capabilities by validating digests as well. The digest (full checksum) is the checksum over the entire data, as opposed to per-chunk checksums which apply to individual chunks. Until now, digests were not examined on any code paths. This PR integrates digest checking into the compressed/checksummed data sources as an optional feature and enables it only through the validation path of the sstable layer (`sstable::validate()`). The validation path is used by the following tools:

* scrub in validate mode
* `sstable validate`

All other reads, including normal user reads, are unaffected by this change.

The PR consists of:
* Extensions to the compressed and checksummed data sources to support digest checking. The data sources receive the expected digest as a parameter and calculate the actual digest incrementally across multiple get() calls. The check happens on the get() call that reaches EOF and results to an exception if the digest is invalid. A digest check requires reading the whole file range. Therefore, a partial read or skip() is treated as an internal error.
* A new shareable digest component loaded on demand by the validation code. No lifecycle management.
* Grouping of old scrub/validate tests for compressed and uncompressed SSTables to reduce code duplication.
* scrub/validate tests for SSTables with valid checksums but invalid digests, and SSTables with no digests at all.
* scrub/validate tests with 3.x Cassandra SSTables to ensure compatibility.

Refs #19058.

New feature, no backport is needed.

Closes scylladb/scylladb#20720

* github.com:scylladb/scylladb:
  test: Test scrub/validate with SSTables from Cassandra
  compaction: Make quarantine optional for perform_sstable_scrub()
  test: Make random schema optional in scrub_test_framework
  test: Add tests for invalid digests
  test: Merge scrub/validate tests for compressed and uncompressed cases
  sstables: Verify digests on validation path
  sstables: Check if digest component exists
  sstables: Add digest in the SSTable components
  sstables: Add digest check in compressed data source
  sstables: Add digest check in checksummed data source
2024-10-09 21:33:08 +03:00
Benny Halevy
d34878e96c view: check_needs_view_update_path: get token_metadata_ptr
check_needs_view_update_path is async and might yield
so the token_metadata reference passed to it must be kept
alive throughout the call.

Fixes scylladb/scylladb#20979

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#20980
2024-10-09 20:56:21 +03:00
Nadav Har'El
a1999cd5d5 cql-pytest: fix run-cassandra on systems with default Java 8
The test/cql-ptest/run-cassandra prefers to use Java 11 if installed on
the system because this is the only version of Java that all modern
versions of Cassandra run on (Cassandra 3 and 4 can run on Java 8 and 11,
Cassandra 5 can run on Java 11 and 17).

However, in our search order we tried the "java" in the user's path
first, before trying Java 11. This means that if the user for some
reason had the ancient Java 8 (which is now a decade old) as his
default "java" got that, instead of Java 11, and couldn't run Cassandra 5.

While at it, update the comments to reflect the new reality that
Cassandra 5 needs Java 17 or 11 - *not* 11 or 8 as the older Cassandra.
We should eventually change the code logic as well (searching for
versions that depend on the Cassandra version - not always Java 8 and
11), but let's do it later. This patch already fixes a real bug for
developers that did install Java 11 but their default "java" pointed to
Java 8.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#21001
2024-10-09 20:51:56 +03:00
David Garcia
2247bdbc8c docs: Fix confgroup links
It was not possible to link to configuration parameters groups in docs/reference/configuration-parameters.rst if they contained a space.

Closes scylladb/scylladb#21018
2024-10-09 20:16:15 +03:00
Pavel Emelyanov
3dcf3d65d7 replica: Use substract_sets() helper
The process_one_row() evaluates pending_replica by subtracting replicas
from new_replicas. There's a convenience helper for that.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#21019
2024-10-09 20:02:16 +03:00
Gleb Natapov
f7e7e61fa7 raft: add more information to start_read_barrier error
Add requester into to the error about requester being out of config.
Also fix a typo while we are at it.

Message-ID: <ZwVDtOty2cWy3vqD@scylladb.com>
2024-10-09 16:24:34 +02:00
Pavel Emelyanov
7163fbcef5 Merge 'utils: replace dependency on boost ranges with <ranges>' from Avi Kivity
To avoid depending on two similar libraries (boost ranges and std \<ranges), replace
uses of the former with the latter. This series tackles the utils/ directory.

Code cleanup, no backport.

Closes scylladb/scylladb#20997

* github.com:scylladb/scylladb:
  utils: logalloc: replace boost with std
  utils: lsa: chunked_managed_vector: replace boost with std
  utils: config_file: replace boost with std
  utils: loading_cache: replace boost with std
  utils: fragment_range: replace boost with std
  utils: error_injector: replace boost with std
  utils: crc: replace boost for_each with built-in range for
  utils: class_registrator: replace boost with std
  utils: chunked_vector: replace boost with std
  utils: observable: replace boost with std
2024-10-09 16:04:48 +03:00
Botond Dénes
3e468608e7 Merge 'Collect sstables on boot from all datadirs (and don't collect from S3 twice)' from Pavel Emelyanov
There's a long-pending issue in distributed loader. When it populates sstables on boot it loops over table.config.all_datadirs, but ignores the loop cursor (the datadir itslef), instead loading sstables from table.config.dir, which is 0th element of all_datadirs. There's a test for that, but it's also broken. Effectively collection happens from table.config.dir several times. For local sstables that's just wasted work and potentially lost sstables (but nobody seems to configure more than 1 datadir anyway). For S3 sstables it's also wasted work and incorrectness.

The fix is for both -- populator and test. The former is to use all_datadirs to construct sstable_directory. To make it happen, creation of sstable_directory now depends on the storage options, the loop is moved into the branch that creates sstable_directory for local storage type. The test fix is to make sure that some sstables in non-default datadir before running population code.

Closes scylladb/scylladb#20819

* github.com:scylladb/scylladb:
  test: Fix test_multiple_data_dirs
  distributed_loader: Indentation fix after previous patch
  distributed_loader: Use correct datadir to collect local sstable
  distributed_loader: Move all-datadirs loop to local storage collecting
  distributed_loader: Collect table subdirs based on its storage options
  distributed_loader: Indentation fix after previous patch
  distributed_loader: Squash loop of collect_subdir into one method
  distributed_loader: Convert map of directories into a vector
  distributed_loader: Make start_subdir() method work with directory
  distributed_loader: Drop local reference variable
  distributed_loader: Split start_subdir()
  distributed_loader: Remove allow-offstrategy argument
  distributed_loader: Make populate() method work with directory
  distributed_loader: Remove check for sstable_directory presense
  distributed_loader: Out-line table_populator() methods
  distributed_loader: Print storage options, not datadir
  distributed_loader: Print prepared message
  sstable_directory: Add sstable_state argument ot one of constructors
  sstable_directory: Add state() method
2024-10-09 14:43:34 +03:00
Michał Chojnowski
c2ba300f1c reader_concurrency_semaphore: in stats, fix swapped count_resources and memory_resources
can_admit_read() returns reason::memory_resources when the permit is queued due
to lack of count resources, and it returns reason::count_resources when the
permit is queued due to lack of memory resources. It's supposed to be the other
way around.

This bug is causing the two counts to be swapped in the stat dumps printed to
the logs when semaphores time out.

Closes scylladb/scylladb#20714
2024-10-09 14:12:01 +03:00
Lakshmi Narayanan Sreethar
69c385f540 compaction: make drain wait for compactions to stop during shutdown
During shutdown, the compaction_manager starts stopping ongoing
compaction tasks through `really_do_stop()` method as soon as it
receives a signal from the abort source. Later, when the database object
shuts down, it calls `compaction_manager::drain` to ensure that all
compaction tasks have stopped. However, `compaction_manager::drain` is
currently implemented in such a way that, during shutdown, it
effectively becomes a no-op because the compaction_manager has already
initiated the stopping of tasks. As a result the caller assumes that all
the compaction tasks have stopped and proceeds to close all the tables.
This can lead to race conditions where table closures overlap with
compaction tasks that are still running, resulting in exceptions like :

```
exception during mutation write to 127.0.0.1:
utils::internal::nested_exception<std::runtime_error> (Could not write
mutation system:compaction_history
(pk{0010b70d31705e0411efb2edf6467f094c8b}) to commitlog):
seastar::gate_closed_exception (gate closed)
```

This commit fixes the issue by updating `compaction_manager::drain` to
invoke `stop_ongoing_compactions` even during shutdown to ensure that it
waits for the ongoing compaction tasks to complete. The
`stop_ongoing_compactions` method will also send a stop request to these
tasks before waiting, but the request will be ignored by the tasks as
they would have already received one earlier from `really_do_stop()`.

Fixes #20197

Signed-off-by: Lakshmi Narayanan Sreethar <lakshmi.sreethar@scylladb.com>

Closes scylladb/scylladb#20715
2024-10-09 12:08:32 +03:00
Pavel Emelyanov
17ec416178 Merge 'Make sure S3 upload completion parses possible error' from Ernest Zaslavsky
fixes #20517
Adds `aws_error` which possibly can contain errors from the S3 response body. Adds to the multipart upload completion a check for possible error and issues a retry if the error is retryable

Closes scylladb/scylladb#20518

* github.com:scylladb/scylladb:
  test: add complete_multipart_upload completion tests
  code: s3 client error handling
  code: add response parsing and error handling to the complete_multipart_upload
  code: Introduce AWS errors parsing
2024-10-09 12:01:27 +03:00
Piotr Smaron
e0c1a51642 cql/tablets: handle MVs in ALTER tablets KEYSPACE
ALTERing tablets-enabled KEYSPACES (KS) didn't account for materialized
views (MV), and only produced tablets mutations changing tables.
With this patch we're producing tablets mutations for both tables and
MVs, hence when e.g. we change the replication factor (RF) of a KS, both the
tables' RFs and MVs' RFs are updated along with tablets replicas.
The `test_tablet_rf_change` testcase has been extended to also verify
that MVs' tablets replicas are updated when RF changes.

Fixes: #20240

Closes scylladb/scylladb#21007
2024-10-09 10:51:18 +02:00
Pavel Emelyanov
0bc8d0c620 Merge 'utils: unconst: wean away from boost range library' from Avi Kivity
As part of the effort to standardize on a single range library, convert the unconst helper
and its only user to \<ranges>.

The only user, mutation_partitions, happens to use intrusive_btree::iterator as the payload. That
iterator wasn't fully conform to iterator requirements, so it's fixed in a preliminary patch.

Code cleanup; no backport.

Closes scylladb/scylladb#20986

* github.com:scylladb/scylladb:
  utils/unconst, mutation_partition: switch to ranges
  utils: intrusive_btree: improve conformity with iterator requirements
2024-10-09 10:06:52 +03:00
Yuao Ma
1cc7821d12 tools: fix typos in the code
This patch corrects a minor typo without any functional changes.

Signed-off-by: Yuao Ma <c8ef@outlook.com>

Closes scylladb/scylladb#20975
2024-10-09 08:18:36 +03:00
Asias He
2d8442f663 repair: Fix stall in repair_get_row_diff_with_rpc_stream_process_op_slow_path
Use clear_gently to avoid the following stalls.

```
~frozen_mutation_fragment at ././frozen_mutation.hh:268

std::destroy_at<frozen_mutation_fragment> at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/stl_construct.h:88

std::allocator_traits<std::allocator<std::_List_node<frozen_mutation_fragment>
> >::destroy<frozen_mutation_fragment> at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/alloc_traits.h:537

std::__cxx11::_List_base<frozen_mutation_fragment,
std::allocator<frozen_mutation_fragment> >::_M_clear at
/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/list.tcc:77

~_List_base at /usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/stl_list.h:499
~partition_key_and_mutation_fragments at ././repair/repair.hh:298
~repair_row_on_wire_with_cmd at ././repair/repair.hh:335
operator() at ./repair/row_level.cc:1881
```

Fixes #21016
2024-10-09 09:37:49 +08:00
Asias He
f5f26e1bba repair: Add clear_gently for partition_key_and_mutation_fragments
It is used to clear mutation_fragments to avoid stalls.
2024-10-09 09:31:14 +08:00
Emil Maskovsky
0c9308cf48 raft: add the check for the group0 tables
Added the runtime check to ensure that all the tables that are used with
the group0 commands are marked as group0 tables.
2024-10-08 21:08:11 +02:00
Emil Maskovsky
a03e98d6e8 raft: fast tombstone GC for group0-managed tables
Set the tombstone GC time for group0-managed tables to the minimal state
id of the group0 nodes.

The check is being done based on a timer, iterating through each node
(according to the group0 topology configuration) and taking the minimum
across all nodes.

This miminum timestamp is then be used to set the tombstone GC time
for the tombstone GC of all the group0-managed tables.

Fixes: scylladb/scylla#15607
2024-10-08 21:07:30 +02:00
Emil Maskovsky
74bd79bbb3 tombstone_gc: refactor the repair map
Move the repair_map definition to the tombstone_gc file where it is
mostly being used.

Refactor and add the accessors and setters for the group0 tombstone GC
time.
2024-10-08 20:53:54 +02:00
Emil Maskovsky
22471410e7 raft: flag the group0-managed tables
Add the schema flag to indicate the group0-managed tables.

This is to be used to identify and list the group0-managed tables.
2024-10-08 20:53:54 +02:00
Emil Maskovsky
baea9cfa67 gossip: broadcast the group0 state id
Implemented the group0 state_id handler (based on the gossip) that will
broadcast the group0 state id of each node.

This will be used to set the tombstone GC time for the group0 tables.
2024-10-08 20:53:54 +02:00
Emil Maskovsky
fa45fdf5f7 raft/test: add test for the group0 tombstone GC
Test that the group0 fast tombstone GC works correctly.
2024-10-08 20:53:54 +02:00
Emil Maskovsky
a840949ea0 treewide: code cleanup and refactoring
Fix the clang-tidy warnings, code cleanup and improvements.

Applied the clang format to the updated places.
2024-10-08 20:53:54 +02:00
Nadav Har'El
b4df07df71 Merge 'cql3: Print arguments and return type without frozen when describing UDF' from Dawid Mędrek
Scylla doesn't allow for the types of arguments or the return type of a UDF
to be frozen. As a result, before these changes, create statements
produced to restore UDFs as part of `DESCRIBE` statements could not
be executed.

Fixes scylladb/scylladb#20256

Backport: necessary as the restore process may not work correctly without these changes. The affected versions span from 5.2 to the current master, but we only want to apply the fix to the live versions, so 6.0, 6.1, and 6.2.

Closes scylladb/scylladb#20816

* github.com:scylladb/scylladb:
  cql3/functions/user_function: Print arguments and return type without frozen
  cql3/functions/user_function: Use fmt to format create statement
2024-10-08 16:05:28 +03:00
Kamil Braun
2d9b8f269f Merge 'cql: improve validating RF's change in ALTER tablets KS' from Piotr Smaron
This patch series fixes a couple of bugs around validating if RF is not changed by too much when performing ALTER tablets KS.
RF cannot change by more than 1 in total, because tablets load balancer cannot handle more work at once.

Fixes: #20039

Should be backported to 6.0 & 6.1 (wherever tablets feature is present), as this bug may break the cluster.

Closes scylladb/scylladb#20208

* github.com:scylladb/scylladb:
  cql: sum of abs RFs diffs cannot exceed 1 in ALTER tablets KS
  cql: join new and old KS options in ALTER tablets KS
  cql: fix validation of ALTERing RFs in tablets KS
  cql: harden `alter_keyspace_statement.cc::validate_rf_difference`
  cql: validate RF change for new DCs in ALTER tablets KS
  cql: extend test_alter_tablet_keyspace_rf
  cql: refactor test_tablets::test_alter_tablet_keyspace
  cql: remove unused helper function from test_tablets
2024-10-08 14:33:45 +02:00
Kamil Braun
1b9337bf99 Merge 'Wait for all users of group0 server to complete before destroying it' from Gleb Natapov
Group0 server is often used in asynchronous context, but we do not wait
for them to complete before destroying the server. We already have
shutdown gate for it, so lets use it in those asynch functions.

Also make sure to signal group0 abort source if initialization fails.

Fixes scylladb/scylladb#20701

Backport to 6.2 since it contains af83c5e53e and it made the race easier to hit, so tests became flaky.

Closes scylladb/scylladb#20891

* github.com:scylladb/scylladb:
  group: hold group0 shutdown gate during async operations
  group0: Stop group0 if node initialization fails
2024-10-08 13:46:54 +02:00
Avi Kivity
48ea51029f Merge 'time_window_compaction_strategy: estimated_pending_compactions: reestimate compactions rather than using cached value' from Benny Halevy
Currently, `estimated_pending_compactions` uses a precalculated value calculated by `update_estimated_compaction_by_tasks`, which, in turn, is called by `get_compaction_candidates`.  That means that, if `estimated_pending_compactions` is called, e.g. right after major compaction, it will return an outdated value that was calculated prior to major compaction, and so, it is no longer relevant.

Instead, just recalculate the value in `estimated_pending_compactions` and drop `update_estimated_compaction_by_tasks`.

* Enhancement, no backport required

Closes scylladb/scylladb#20892

* github.com:scylladb/scylladb:
  test: cql-pytest: test_compaction: add test_compactionstats_after_major_compaction
  test/cql-pytest: rename test_compaction{_tombstone_gc,}
  time_window_compaction_strategy: estimated_pending_compactions: reestimate compactions rather than using cached value
2024-10-08 13:29:51 +03:00
Gleb Natapov
d62fbd795b storage_proxy: make sure there is no end iterator in _live_iterators array
storage_proxy::cancellable_write_handlers_list::update_live_iterators
assumes that iterators in _live_iterators can be dereferenced, but
the code does not make any attempt to make sure this is the case. The
iterator can be the end iterator which cannot be dereferenced.

The patch makes sure that there is no end iterator in _live_iterators.

Fixes scylladb/scylladb#20874

Closes scylladb/scylladb#20977
2024-10-08 13:16:27 +03:00
Avi Kivity
656dc438ab utils: logalloc: replace boost with std 2024-10-08 12:07:14 +03:00
Avi Kivity
84b25a51f5 utils: lsa: chunked_managed_vector: replace boost with std 2024-10-08 12:03:30 +03:00
Avi Kivity
fa772701be utils: config_file: replace boost with std 2024-10-08 12:03:15 +03:00
Avi Kivity
b62fadae5f utils: loading_cache: replace boost with std
Unfortunately, the replacement for boost::range::join(),
std::views::concat(), is in C++26 (and not implemented in libstdc++ 14).
We use array/transform/join to simulate it.
2024-10-08 11:54:34 +03:00
Laszlo Ersek
934b42c6a8 cmake/check_headers: correct typos
Commit efd65aebb2 ("build: cmake: add check-header target", 2023-11-13)
introduced three typos:

- In "cmake/check_headers.cmake", it checked whether the
  "parsed_args_GLOB_RECURSE" argument was defined, but then it referenced
  the same under the wrong name "parsed_args_RECURSIVE".

- The above error masked two further typos; namely the duplicate use of
  "api" and "streaming" each, as targets. With "parsed_args_GLOB_RECURSE"
  above fixed, CMake now reports these conflicting arguments (target
  names). They should have been "node_ops" and "sstables", respectively.

Correct the typos.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>

Closes scylladb/scylladb#20992
2024-10-08 09:38:16 +03:00
Dawid Mędrek
8582ed513b cql3/functions/user_function: Print arguments and return type without frozen
Scylla doesn't allow for the types of arguments or the return type
to be frozen. As a result, before these changes, create statements
produced to restore UDFs as part of `DESCRIBE` statements could not
be executed.

We fix that and add a reproducer test and another one to verify that
the implementation is correct.
2024-10-07 20:53:10 +02:00
Avi Kivity
72a39b84b0 utils: fragment_range: replace boost with std 2024-10-07 21:32:16 +03:00
Avi Kivity
c8a68c4cf7 utils: error_injector: replace boost with std 2024-10-07 21:28:36 +03:00
Avi Kivity
c560686d92 utils: crc: replace boost for_each with built-in range for
Simpler.
2024-10-07 21:19:14 +03:00
Avi Kivity
44419fc5ec utils: class_registrator: replace boost with std 2024-10-07 21:16:03 +03:00
Avi Kivity
adb92a6c16 utils: chunked_vector: replace boost with std 2024-10-07 21:11:23 +03:00
Avi Kivity
b259389a3e utils: observable: replace boost with std 2024-10-07 21:11:07 +03:00
Nadav Har'El
45ccceb137 alternator: add "dc" and "rack" options to "/localnodes" request
Before this patch, the "/localnodes" HTTP request to the Alternator server
lists all the live nodes of the current DC. This patch adds two optional
parameters to this query:

  dc: allows to list the live nodes of a specific named DC instead of the
      current DC of the server.

  rack: allows to restrict the results to just the nodes belonging to a
      specific named rack.

For both options, if no live node exists in the given dc or rack (in
particular, if such a dc or rack doesn't even exist), an empty list is
returned - it's not an error.

The default, if dc or rack is not specified - remains exactly as it is
today - look at the current DC (the one of the node being request), and
do not restrict the list to any specific rack.

We expect the new options that we added here to be useful for two use cases:

1. A client that knows of *some* Scylla node (belonging to an unknown DC),
   but wants to list the nodes in *its* DC, which it knows by name.

2. A client in a multi-rack DC (e.g., multi-AZ region in AWS) that wants
   to send requests to nodes in its own rack (which it knows by name),
   to avoid cross-rack networking costs.

Note that in both cases, this requires clients to know the names of DCs
and AZs via some out-of-band means. The client can also get a list of DCs
and racks using the system.local system table, as the tests included in
this patch demonstrate.

This patch includes two set of tests for these new options: One in the the
single-node test/alternator framework that has a single dc and rack but
can still check the case of an unknown dc or rack (in which case an empty
list is returned). The second test is in the topology framework, and runs
an 8-node cluster with two DCs, two racks, and two nodes in each, and
checks all the combinations of "/localnodes" requests with and without
dc and rack options. This test also resolves a longstanding TODO that
asked for such a multi-DC test for "/localnodes" to be written.

Fixes #12147

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20915
2024-10-07 20:53:47 +03:00
Pavel Emelyanov
8bfbc563cc test: Remove sstable factory from test_min_max_clustering_key()
The helper makes sstables from env directly. Callers may not create the
factor after that. Less code the better.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20983
2024-10-07 20:08:05 +03:00
Kefu Chai
a6ec6d32ab auth: add "IWYU pragma: keep" to keep boost/regex_fwd.hpp
clang-include-cleaner is not able to tell that the header provides
the template parameter of `std::vector<std::pair<query_source, boost::regex>>`.
and suggest us to remove this include. but it's wrong.

so, in this change we apply the "pragma" to keep it.
see
https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md
for the explanations on what this pragma is for.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-07 20:08:05 +03:00
Kefu Chai
3d31835949 auth: include boost/regex_fwd.hpp in header
since we only need the full definition of boost::regex in the .cc
file, where we

- define the constructor and destructor
- and actually use the regex.

there is no need to include boost/regex.hpp in the header, in order
to keep the preprocessed header smaller. let's use a header only
contains forward declarations in header, and include the full
definition in the .cc file.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-07 20:08:05 +03:00
Piotr Smaron
ee56bbfe61 cql: sum of abs RFs diffs cannot exceed 1 in ALTER tablets KS
Tablets load balancer is unable to process more than a single pending
replica, thus ALTER tablets KS cannot accept an ALTER statement which
would result in creating 2+ pending replicas, hence it has to validate
if the sum of absoulte differences of RFs specified in the statement is
not greter than 1.
2024-10-07 17:02:50 +02:00
Piotr Smaron
2aabe7f09c cql: join new and old KS options in ALTER tablets KS
A bug has been discovered while trying to ALTER tablets KS and
specifying only 1 out of 2 DCs - the not specified DC's RF has been
zeroed. This is because ALTER tablets KS updated the KS only with the
RF-per-DC mapping specified in the ALTER tablets KS statement, so if a
DC was ommitted, it was assigned a value of RF=0.
This commit fixes that plus additionally passes all the KS options, not
only the replication options, to the topology coordinator, where the KS
update is performed.
`initial_tablets` is a special case, which requires a special handling
in the source code, as we cannot simply update old initial_tablet's
settings with the new ones, because if only ` and TABLETS = {'enabled':
true}` is specified in the ALTER tablets KS statement, we should not zero the `initial_tablets`, but
rather keep the old value - this is tested by the
`test_alter_preserves_tablets_if_initial_tablets_skipped` testcase.
Other than that, the above mentioned testcase started to fail with
these changes, and it appeared to be an issue with the test not waiting
until ALTER is completed, and thus reading the old value, hence the
test's body has been modified to wait for ALTER to complete before
performing validation.
2024-10-07 17:02:45 +02:00
Avi Kivity
d12ba753e0 utils/unconst, mutation_partition: switch to ranges
unconst is a small help that converts a const iterator to a non-const
iterator with the help of the container. Currently it is using the
boost iterator/range libraries.

Convert it to <ranges> as part of an effort to standardize on a single
range library. Its only user in mutation_partition is converted as well.

Due to more iteroperability problems between <range> and boost, some
calls to boost::adaptors::reversed have to be converted as well.
2024-10-07 17:30:12 +03:00
Avi Kivity
75f4ea1b68 utils: intrusive_btree: improve conformity with iterator requirements
The <ranges> library checks that an iterator's operator++() returns
a reference to the same type. intrusive_btree's iterator do not; instead
they return some base type and rely on implicit conversion to the real
iterator type. This causes interoperatibility problems with <range>.

Fix by using the CRTP pattern to inform iterator_base about what
type we really are, and cast to it. Enforce it with static_assert.

Note we can't static_assert in class scope since it is checked too
early and fails. Checking in function scope delays the check.
2024-10-07 17:26:01 +03:00
Piotr Smaron
6676e47371 cql: fix validation of ALTERing RFs in tablets KS
The validation has been corrected with:
1. Checking if a DC specified in ALTER exists.
2. Removing `REPLICATION_STRATEGY_CLASS_KEY` key from a map of RFs that
   needs their RFs to be validated.
2024-10-07 16:02:01 +02:00
Piotr Smaron
93d61d7031 cql: harden alter_keyspace_statement.cc::validate_rf_difference
This function assumed that strings passed as arguments will be of
integer types, but that wasn't the case, and we missed that because this
function didn't have any validation, so this change adds proper
validation and error logging.
Arguments passed to this function were forwarded from a call to
`ks_prop_defs::get_replication_options`, which, among rf-per-dc mapping, returns also
`class:replication_strategy` pair. Second pair's member has been casted
into an `int` type and somehow the code was still running fine, but only
extra testing added later discovered a bug in here.
2024-10-07 16:02:01 +02:00
Piotr Smaron
47acdc1f98 cql: validate RF change for new DCs in ALTER tablets KS
ALTER tablets KS validated if RF is not changed by more than 1 for DCs
that already had replicas, but not for DCs that didn't have them yet, so
specifying an RF jump from 0 to 2 was possible when listing a new DC in
ALTER tablets KS statement, which violated internal invariants of
tablets load balancer.
This PR fixes that bug and adds a multi-dc testcases to check if adding
replicas to a new DC and removing replicas from a DC is honoring the RF
change constraints.

Refs: #20039
2024-10-07 16:02:01 +02:00
Piotr Smaron
9c5950533f cql: extend test_alter_tablet_keyspace_rf
Added cases to also test decreasing RF and setting the same RF.
Also added extra explanatory comments.
2024-10-07 16:02:00 +02:00
Piotr Smaron
adf453af3f cql: refactor test_tablets::test_alter_tablet_keyspace
1. Renamed the testcase to emphasize that it only focuses on testing
   changing RF - there are other tests that test ALTER tablets KS
in general.
2. Fixed whitespaces according to PEP8
2024-10-07 16:02:00 +02:00
Piotr Smaron
042825247f cql: remove unused helper function from test_tablets
`change_default_rf` is not used anywhere, moreover it uses
`replication_factor` tag, which is forbidden in ALTER tablets KS
statement.
2024-10-07 16:02:00 +02:00
Nikos Dragazis
7a1ec3aa41 test: Test scrub/validate with SSTables from Cassandra
All current unit tests for scrub in validate mode generate random
SSTables on the fly.

Add some more tests with frozen Cassandra SSTables from the source tree
to verify compatibility with Cassandra. Use some of the existing 3.x
Cassandra SSTables to test the valid case, and use the same schema to
generate some corrupted SSTables for the invalid case. Overall, the new
tests cover the following scenarios:

* valid compressed/uncompressed
* compressed/uncompressed with invalid checksums
* compressed/uncompressed with invalid digest

For the compressed SSTable with invalid checksums, a small chunk length
was used (4KiB) to have more chunks with less disk space. For
uncompressed SSTables the chunk length is not configurable.

Finally, since the SSTables live in the source tree, the quarantine
mechanism was disabled.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:38 +03:00
Nikos Dragazis
7090e2597f compaction: Make quarantine optional for perform_sstable_scrub()
Allow `perform_sstable_scrub()` to disable quarantine for invalid
SSTables detected by scrub in validate mode. This is already supported
by the lower-level function `scrub_sstables_validate_mode()` via the
flag `quarantine_sstables` and is being used by sstable-scrub.

Propagate the flag up to `perform_sstable_scrub()`. This will allow to
test scrub/validate against read-only SSTables from the source tree.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:38 +03:00
Nikos Dragazis
5f2be2924e test: Make random schema optional in scrub_test_framework
The scrub_test_framework, which is the foundation for all scrub-related
tests, always generates a random schema upon initialization and makes it
available to the user. This is useful for running tests with ephemeral
SSTables, but is redundant when the creation of the SSTable predates the
test (e.g., it lives in the source tree).

Turn scrub_test_framework into a template with a boolean parameter to
optionally switch off the random schema generation. Also, add an
overload for run() to support passing a ready-to-use SSTable instead of
mutation fragments.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:38 +03:00
Nikos Dragazis
07ed0a48aa test: Add tests for invalid digests
In a previous patch we extended the validation path of the SSTable layer
to validate the digests along with the checksums.

Add two tests for compressed and uncompressed SSTables to test the
validation API against SSTables with valid checksums but corrupted
digests.

Add two more tests to ensure that the absence of digest does not affect
checksum validation.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:38 +03:00
Nikos Dragazis
39a74fb692 test: Merge scrub/validate tests for compressed and uncompressed cases
Currently, every scrub/validate test is duplicated to cover both
compressed and uncompressed SSTables. However, except for the
compression type, the tests are identical. This leads to some code
bloat.

Introduce common functions parameterized by the compression type to
reduce code duplication. Also, group together the compressed and
uncompressed variants into one compression-agnostic test.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:38 +03:00
Nikos Dragazis
3a3783ee23 sstables: Verify digests on validation path
Extend the validation path to perform digest checking on all SSTables.
This is achieved by loading the digest component on demand and passing
it to the underlying data sources only during validation. The data
sources for compressed and uncompressed SSTables were modified in
previous patches to support digest checking.

Consider digest checking as part of the integrity checking mechanism
(i.e., requires `integrity_check::yes`) to ensure it remains disabled
for all reads happening outside of the validation path (i.e.,
`sstable::validate()`). This practically means that digest checking is
enabled only for:

* scrub in validate mode
* sstable validate

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-07 15:21:09 +03:00
Avi Kivity
7dad248ac7 Merge 'Fix sstables registry mock' from Pavel Emelyanov
There are two issues in it. First, listing the registry with a consumer callback passes wrong argument to the consumer. Second, the primary key of the registry is wrong. Both issues don't show up, because existing tests that use mock don't read from it, only write. Tests that read from registry are python tests that start scylla and thus use real registry.

Closes scylladb/scylladb#20946

* github.com:scylladb/scylladb:
  test: Use corrcet key in sstables registry mock
  test: Pass entry status to mock registry consumer
2024-10-07 13:56:26 +03:00
Anna Stuchlik
a601845780 doc: remove outdated JMX references
This commit removes references to JMX from the docs.

Context:
The JMX server has been dropped and removed from installation. The user can
install it manually if needed, as documented with https://github.com/scylladb/scylladb/issues/18687.

This commit removes the outdated information about JMX from other pages
in the documentation, including the docs for nodetool, the list of ports,
and the admin section.

Also, the no longer relevant JMX information is removed from
the Docker Hub docs.

Fixes https://github.com/scylladb/scylladb/issues/18687
Fixes https://github.com/scylladb/scylladb/issues/19575

Closes scylladb/scylladb#20917
2024-10-07 13:55:15 +03:00
Nadav Har'El
987042be68 mv, test: reproduce missing validation for view name
This patch adds reproducer tests (still failing) for issue #20755, which
is about missing validation of materialized view names:

1. Unlike table and keyspace names which are limited to 48 characters,
   we forgot to limit view name length, and an excessively long name can
   cause Scylla to shut down :-(

2. Unlike table and keyspace names which only allow alphanumeric
   characters, view names are missing this check and can include any
   characters.

3. Luckily, even though we are missing the alphanumeric check, we at
   least don't allow "/" in view names (if we allowed them, it could
   allow users to write in any directory in the filesystem!). But when
   this happens, we get an internal error instead of the expected
   errors.

The first test also fails on Cassandra (it doesn't crash it, but leaves
the table in a strange state), but the other two pass.

Refs #20755

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20761
2024-10-07 13:49:58 +03:00
Avi Kivity
73eeb6d274 Merge 'clang-format: adjustments to avoid unwanted refactors and better match the Seastar coding style' from Emil Maskovsky
Some adjustments to the `.clang-format` options to better match the current code:

* don't sort the include headers: causes large diffs especially in files with a lot of includes, and the `#include` ordering is not prescribed by the Seastar coding style
* binpack the arguments in function declarations and calls: allow binpacking (as opposed to forcing each parameter on a separate line if they don't fit into the line length)
* indented parameter continuation (as opposed to aligning to the open parenthesis) - aligning to the open parenthesis causes alignment issues especially with lambdas

Fixes: scylladb/scylladb#20951

No backport: Not a product issue, just applies to master.

Closes scylladb/scylladb#20968

* github.com:scylladb/scylladb:
  clang-format: argument and function packing
  clang-format: don't sort the include headers
2024-10-07 13:21:31 +03:00
Pavel Emelyanov
1870873538 test: Fix test_multiple_data_dirs
The one was broken from the very beginning. It only checked that after
creating a table, its directory is created in all datadirs. But it
didn't check that after restart populating happens from the all. That's
because all directories by 0th were always empty, so not-populating from
them didn't skip any data.

Fix it by moving all sstables from datadirs[0] to datadirs[1] before
restart. With that update not-populating data from datadirs[1] will
be noticed instantly. Fortunately, previous patches fixed that, so the
test still passes.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
aa0c20a0e7 distributed_loader: Indentation fix after previous patch
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
792c0060c7 distributed_loader: Use correct datadir to collect local sstable
Current code uses datadir it gets from table itself, which is the 0th
element in the all-datadirs config. So populating local sstables happens
several times from the same directory. Fix it by starting sstable
directory with correct datadir -- the one obtained from the all-datadirs
loop.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
bf654f45bd distributed_loader: Move all-datadirs loop to local storage collecting
It now happens in the outer loop, but it's not correct for S3 storage,
which is thus asked to collect its data twice. Also it's broken for
local storage as well, because the datadir argument is ignored. Next
patch will fix it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
fe779ab1a2 distributed_loader: Collect table subdirs based on its storage options
Collecting sstables for local storage and for S3 storage differs. First,
the populator collects sstables for each datadir configured in
scylla.yaml, but S3 storage doesn't care, so it's effectively asked to
collect the same data twice. Second, S3 collector code uses
sstable_directory simply because that class is used by reshape and
reshard code, but in fact collecting of S3 sstable can be made much
simpler (but that's for later).

Having said that, split preparation of sstables population for local
and S3 storage types.

Indentation is deliberately left broken for local storage collecting
mathod. That's because otherwise next patch will need move it back
anyway.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
ee91cae5b9 distributed_loader: Indentation fix after previous patch
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
6ae486100c distributed_loader: Squash loop of collect_subdir into one method
This prepares the gound for the next patch.
Indentation is left broken.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
4db2929afd distributed_loader: Convert map of directories into a vector
Knowledge of sstable state is no longer needed in the table_populator
start/stop methods, so the map<state, directory> can be converted into
vector<directory>.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
89e9231653 distributed_loader: Make start_subdir() method work with directory
Similarly to populate_subdir() one, it also accepts state and gets
directory out of it. Patch is the same way -- caller now passes it the
reference to directory and doesn't care about the state (in fact, the
start_subdir() doesn't care of the state either).

While at it -- rename the method to reflect what it does.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
999ec88765 distributed_loader: Drop local reference variable
Cleanup after previous patch.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
50024ef62a distributed_loader: Split start_subdir()
It does two things -- starts sstable_directory and prepares it. Split it
accordingly.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
abdc0bb02d distributed_loader: Remove allow-offstrategy argument
This is to make populate_subdir() be self-contained in a way it uses
passed sstable_directory and make caller not care about the state.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
3b583b9d9f distributed_loader: Make populate() method work with directory
The populate_subdir() accepts sstable_state argument and picks the
corresponding sstable_directory object from the map. Patch it so that
caller passes it the sstable_directory reference. For now it makes
things more complicated, but next patches will simplify it back.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
051ac3a737 distributed_loader: Remove check for sstable_directory presense
In the old days the set of sstable_directory-s used by populator could
skip some of them. Now they are all present and the checks is always
false.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
4752a504cd distributed_loader: Out-line table_populator() methods
To make further patching with less indentation level.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
617b0e3ce3 distributed_loader: Print storage options, not datadir
Tables not necessarily have data in a directory, so it's more correct to
show storage options in logs, not some directory path.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
31b2271f07 distributed_loader: Print prepared message
When population throws, the catch block prepares a message to re-throw
another exception and prints the same message into logs. Presumably the
intent was to print the prepared message as well.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:04:23 +03:00
Pavel Emelyanov
87d392d071 sstable_directory: Add sstable_state argument ot one of constructors
There's one constructor that became unused after 787ea4b1. Modify it
with the 'state' argument so that it could be used later.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 12:03:36 +03:00
Pavel Emelyanov
b56483ab67 sstable_directory: Add state() method
The one will expose sstables state the directory works with. For
convenience.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-07 11:23:50 +03:00
Kefu Chai
abda779a5b compaction: return created sst without using a temporary variable
simpler this way. `sst` does not help with the readability or
performance, but let's drop it. simpler this way. also, remove the
unused parameter.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20961
2024-10-07 10:56:25 +03:00
Pavel Emelyanov
8ccb4a1045 Merge 'db: remove unused includes ' from Kefu Chai
these unused includes are identified by clang-include-cleaner.
after auditing the source files, all of the reports have been
confirmed.

please note, since we have `using seastar::shared_ptr` in
`seastarx.h`, this renders `#include <seastar/core/shared_ptr.hh>`
unnecessary if we don't need the full definition of `seastar::shared_ptr`.

so, in this change, all the unused includes are removed.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#20963

* github.com:scylladb/scylladb:
  .github: add db to iwyu's CLEANER_DIR
  db: remove unused includes
2024-10-07 10:55:48 +03:00
Kefu Chai
cd05f61607 api/storage_service: use ranges when handlging restore API
this change is a follow up of 787ea4b1, to modernize the code base.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20972
2024-10-07 10:54:37 +03:00
Avi Kivity
946bb870f3 utils: hashers: include <memory>
hashers.hh uses std::unique_ptr, so include its header.

Closes scylladb/scylladb#20974
2024-10-07 10:52:36 +03:00
Kefu Chai
c6bc5b2706 sstable_loader: Remove unused _snapshot_name from download_task_impl
in 787ea4b1, we introduced `_prefix` and `_sstables` member  variables
to `sstables_loader::download_task_impl`, replacing the functionality
of `_snapshot_name`. However, we overlooked removing the now-obsolete
`_snapshot_name` variable.

this commit removes the unused `_snapshot_name` member variable to
improve code cleanliness and prevent potential confusion.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20969
2024-10-07 10:43:13 +03:00
Benny Halevy
fa8fe62e90 test: cql-pytest: test_compaction: add test_compactionstats_after_major_compaction
Test that compactionstats are empty, i.e.
there are no required compactions following
major compaction.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-07 10:24:06 +03:00
Benny Halevy
630b792bd0 test/cql-pytest: rename test_compaction{_tombstone_gc,}
Prepare to add more tests related to compaction to
this test suite.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-07 10:18:30 +03:00
Benny Halevy
284dbc51c3 time_window_compaction_strategy: estimated_pending_compactions: reestimate compactions rather than using cached value
Currently, `estimated_pending_compactions` uses a precalculated value
calculated by `update_estimated_compaction_by_tasks`, which, in turn,
is called by `get_compaction_candidates`.  That means that, if
`estimated_pending_compactions` is called, e.g. right after
major compaction, it will return an outdated value that was
calculated prior to major compaction, and so, it is no longer
relevant.

Instead, just recalculate the value in `estimated_pending_compactions`
and drop `update_estimated_compaction_by_tasks`.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-07 10:15:19 +03:00
Gleb Natapov
e642f0a86d group: hold group0 shutdown gate during async operations
Wait for all outstanding async work that uses group0 to complete before
destroying group0 server.

Fixes scylladb/scylladb#20701
2024-10-06 17:20:52 +03:00
Gleb Natapov
ba22493a69 group0: Stop group0 if node initialization fails
Commit af83c5e53e moved aborting of group0 into the storage service
drain function. But it is not called if node fails during initialization
(if it failed to join cluster for instance). So lets abort on both
paths (but only once).
2024-10-06 17:20:52 +03:00
Kefu Chai
960aa38cf3 utils/i_filter: include used header
when compiling with clang-19 and the standard library from GCC-14.2,
we have:

```
/usr/bin/cmake -E __run_co_compile --tidy="clang-tidy;--checks=-*,bugprone-use-after-move;--extra-arg-before=--driver-mode=g++" --source=/__w/scylladb/scylladb/utils/bloom_filter.cc -- /usr/bin/clang++ -DBOOST_REGEX_DYN_LINK -DBOOST_REGEX_NO_LIB -DFMT_SHARED -DSCYLLA_BUILD_MODE=release -DSEASTAR_API_LEVEL=7 -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SSTRING -DXXH_PRIVATE_API -I/__w/scylladb/scylladb -I/__w/scylladb/scylladb/seastar/include -I/__w/scylladb/scylladb/build/seastar/gen/include -I/__w/scylladb/scylladb/build/seastar/gen/src -ffunction-sections -fdata-sections -O3 -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-enum-constexpr-conversion -Wno-unused-parameter -ffile-prefix-map=/__w/scylladb/scylladb/build=. -march=wes
Error: /__w/scylladb/scylladb/utils/bloom_filter.cc:81:1: error: unknown type name 'filter_ptr' [clang-diagnostic-error]
   81 | filter_ptr create_filter(int hash, large_bitset&& bitset, filter_format format) {
      | ^
Error: /__w/scylladb/scylladb/utils/bloom_filter.cc:82:12: error: no viable conversion from returned value of type '__detail::__unique_ptr_t<murmur3_bloom_filter>' (aka 'unique_ptr<utils::filter::murmur3_bloom_filter>') to function return type 'int' [clang-diagnostic-error]
   82 |     return std::make_unique<murmur3_bloom_filter>(hash, std::move(bitset), format);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error: /__w/scylladb/scylladb/utils/bloom_filter.cc:85:1: error: unknown type name 'filter_ptr' [clang-diagnostic-error]
   85 | filter_ptr create_filter(int hash, int64_t num_elements, int buckets_per, filter_format format) {
      | ^
Error: /__w/scylladb/scylladb/utils/bloom_filter.cc:86:12: error: no viable conversion from returned value of type '__detail::__unique_ptr_t<murmur3_bloom_filter>' (aka 'unique_ptr<utils::filter::murmur3_bloom_filter>') to function return type 'int' [clang-diagnostic-error]
   86 |     return std::make_unique<murmur3_bloom_filter>(hash, large_bitset(get_bitset_size(num_elements, buckets_per)), format);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error: /__w/scylladb/scylladb/utils/bloom_filter.hh:93:1: error: unknown type name 'filter_ptr' [clang-diagnostic-error]
   93 | filter_ptr create_filter(int hash, large_bitset&& bitset, filter_format format);
      | ^
Error: /__w/scylladb/scylladb/utils/bloom_filter.hh:94:1: error: unknown type name 'filter_ptr' [clang-diagnostic-error]
   94 | filter_ptr create_filter(int hash, int64_t num_elements, int buckets_per, filter_format format);
      | ^
Error: /__w/scylladb/scylladb/utils/i_filter.hh:17:25: error: no template named 'unique_ptr' in namespace 'std' [clang-diagnostic-error]
   17 | using filter_ptr = std::unique_ptr<i_filter>;
      |                    ~~~~~^
Error: /__w/scylladb/scylladb/utils/i_filter.hh:54:12: error: unknown type name 'filter_ptr' [clang-diagnostic-error]
   54 |     static filter_ptr get_filter(int64_t num_elements, double max_false_pos_prob, filter_format format);
      |            ^
4 warnings and 8 errors generated.
```

apparently, the definition of `std::unique_ptr` is missing where it is
used. so let's include `<memory>`, so that `i_filter.hh` is more
self-contained.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20971
2024-10-06 14:20:41 +03:00
Michał Chojnowski
5884c9d2fc utils/rjson.cc: correct a comment about assert()
Commit aa1270a00c changed most uses
of `assert` in the codebase to `SCYLLA_ASSERT`.

But the comment fixed in this patch is talking specifically about
`assert`, and shouldn't have been changed. It doesn't make sense
after the change.

Closes scylladb/scylladb#20967
2024-10-06 12:47:51 +03:00
Michał Chojnowski
882a3c60e4 utils/cached_file: reduce latency (and increase overhead) of partially-cached reads
Currently, `cached_file::stream` (currently used only by index_reader,
to read index pages), works as follows.

Assume that the caller requested a read of the range [pos, pos + size).
Then:

- If the first page of the requested range is uncached,
  the entire [pos, pos + size) range is read from disk (even if some
  later pieces of it are cached), the resulting pages are added to the cache,
  and the read completes (most likely) from the cached pages.
- If the first page of the read is cached, then the rest of the read
  is handled page-by-page, in a sequential loop, serving each page
  either from cache (if present) or from disk.

For example, assume that pages 0, 1, 2, 3, 4 are requested.

If exactly pages 1, 2 are cached, then `stream` will read the entire [0, 4] range
from disk and insert the missing 0, 3, 4, and then it will continue serving the
read from cache.

If exactly pages 0 and 3 are cached, then it will serve 0 from cache,
then it will read 1 from disk and insert it into cache,
then it will read 2 from disk and insert it into cache,
then it will serve 3 from cache,
then it will read 4 from disk and insert it into cache.

If exactly the first page is cached, a 128 kiB read turns
into 31 I/O sequential read ops.

This is weird, and doesn't look intended. In one case, we are reading even pages
we already have, just to avoid fragmenting the read, and in the other case
we are reading pages one-by-one (sequentially!) even if they are neighbours.

I'm not sure if cached_file should minimize IOPS or byte throughput,
but the current state is surely suboptimal. Even if its read strategy
is somehow optimal, it should still at least coalesce contiguous reads
and perform the non-contiguous reads in parallel.

This patch leans into minimizing IOPS. After the patch, we serve
as many front pages from the cache as we can, but when we see
an uncached page, we read the entire remainder of the read from disk.

As if we trimmed the read request by the longest cached prefix,
and then performed the rest using the logic from before the patch.

For example, if exactly pages 0 and 3 are cached,
then we serve 0 from cache,
then we read [1, 4] from disk and insert everything into cache.

For partially-cached files, this will result in more bytes read
from disk, but less IOPS. This might be a bad thing. But if so,
then we should lean the other way in a more explicit and efficient
way than we currently do.

Closes scylladb/scylladb#20935
2024-10-04 17:39:38 +02:00
Emil Maskovsky
a11ede758e clang-format: argument and function packing
Changes to better match the Seastar code style and the current codebase.

Allow parameter binpacking and continuation indenting.

Refs: scylladb/scylladb#20951
2024-10-04 14:52:41 +02:00
Emil Maskovsky
b4f28b3e0e clang-format: don't sort the include headers
Sorting the include headers causes reordering of all headers and thus
large diffs, especially in the files that include a lot of headers that
have not been sorted before. This makes it harder to review the changes
and to understand the history of the file.

The Seastar code style doesn't prescribe any include headers ordering.

Refs: scylladb/scylladb#20951
2024-10-04 14:51:54 +02:00
Kefu Chai
d72c8fc047 .github: add db to iwyu's CLEANER_DIR
to avoid future violations of include-what-you-use.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-04 20:48:18 +08:00
Kefu Chai
ee36358a60 db: remove unused includes
these unused includes are identified by clang-include-cleaner.
after auditing the source files, all of the reports have been
confirmed.

please note, since we have `using seastar::shared_ptr` in
`seastarx.h`, this renders `#include <seastar/core/shared_ptr.hh>`
unnecessary if we don't need the full definition of `seastar::shared_ptr`.

so, in this change, all the unused includes are removed. but there are
some headers which are actually used, while still being identified by
this tool. these includes are marked with "IWYU pragma: keep".

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-04 20:48:18 +08:00
Botond Dénes
af124993a4 Merge 'Do not remove objects from backup storage after restore' from Pavel Emelyanov
The restore-from-s3 task uses load-and-stream internally which, in turn, unlinks loaded sstables on success. That's not what user expects when it restores from backup, objects should remain in bucket afterwards.

Closes scylladb/scylladb#20947

* github.com:scylladb/scylladb:
  test: Add check that restored-from objects are not removed
  sstables_loader: Dont unlink sstables when restoring from S3
  sstables_loader: Make primary_replica_only bool_class RAII field
2024-10-04 14:59:40 +03:00
Nikita Kurashkin
874cafefab SStables: replace assertion with malformed_sstable_exception for invalid chunk_size
This will allow to see underlying sstable file
Fixes #20277

Closes scylladb/scylladb#20784
2024-10-04 14:48:35 +03:00
Pavel Emelyanov
6b480589fe Merge 'treewide: accept list of sstables in "restore" API ' from Kefu Chai
before this change, we enumerate the sstables tracked by the
system.sstables table, and restore them when serving
requests to "storage_service/restore" API. this works fine with
"storage_service/backup" API. but this "restore" API cannot be
used as a drop-in replacement of the rclone based API currently
used by scylla-manager.

in order to fill the gap, in this change:

* add the "prefix" parameter for specifying the shared prefix of
  sstables
* add the "sstables" parameter for specifying the list of  TOC
  components of sstables
* remove the "snapshot" parameter, as we don't encode the prefix
  on scylla's end anymore.
* make the "table" parameter mandatory.

Fixes https://github.com/scylladb/scylladb/issues/20461

----

this change is a part of the efforts to bring the native backup/restore to scylla, no need to backprt.

Closes scylladb/scylladb#20685

* github.com:scylladb/scylladb:
  treewide: accept list of sstables in "restore" API
  sstable: pass get_storage_option to sstable_directory::load_sstable()
  test/nodetool: add body parameter to `expected_request`
  tools/scylla-nodetool: enable nodetool to write HTTP body
2024-10-04 12:38:08 +03:00
Pavel Emelyanov
0f6e76f92f api: Use captured compaction_manager in get_cm_stats() helper
This is continuation of the previous patch that also need to touch the
helper function argument.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 12:28:15 +03:00
Pavel Emelyanov
f99d8e07ae api: Use captured compaction_manager in endpoints
Instead of getting via ctx -> database chain.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 12:28:15 +03:00
Pavel Emelyanov
05b4a8e710 api: Add sharded<compaction_manager> argument to compaction_manager API reg/unreg
To be used by next patch.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 12:28:15 +03:00
Pavel Emelyanov
58c4c21581 api: Move some endpoints from storage_service.cc to compaction_manager.cc
Those setting and getting bandiwdth need compaction manager to work with
and thus should sit next to other enpoints working with it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 11:36:07 +03:00
Pavel Emelyanov
43fe482204 api: Unset compaction_manager endpoints
Similarly to other .cc files, compaction manager should have its
endpoints unset. For now, no batch unsetting exists, so need to do it
one-by-one.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 11:35:19 +03:00
Pavel Emelyanov
aa13be15b0 api: Use shorter registration method for compaction_manager function
The register_api() helper does exatly what's needed here -- registers
function and calls a method to set routes.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-04 11:34:33 +03:00
Botond Dénes
07094c3e44 Merge 'replica: Fix tombstone GC during tablet split preparation' from Raphael "Raph" Carvalho
During split prepare phase, there will be more than 1 compaction group with
overlapping token range for a given replica.

Assume tablet 1 has sstable A containing deleted data, and sstable B containing
a tombstone that shadows data in A.

Then split starts:
1) sstable B is split first, and moved from main (unsplit) group to a
split-ready group
2) now compaction runs in split-ready group before sstable A is split

tombstone GC logic today only looks at underlying group, so compaction is step
2 will discard the deleted data in A, since it belongs to another group (the
unsplit one), and so the tombstone can be purged incorrectly.

To fix it, compaction will now work with all uncompacting sstables that belong
to the same replica, since tombstone GC requires all sstables that possibly
contain shadowed data to be available for correct decision to be made.

Fixes https://github.com/scylladb/scylladb/issues/20044.

Branches 6.0, 6.1 and 6.2 are vulnerable, so backport is needed.

Closes scylladb/scylladb#20939

* github.com:scylladb/scylladb:
  replica: Fix tombstone GC during tablet split preparation
  service: Improve error handling for split
2024-10-04 10:29:42 +03:00
Nikos Dragazis
347f5ee166 sstables: Check if digest component exists
Extend `read_digest()` to first check if the digest component exists
before attempting to load it from disk.

Make `validate_checksums()` throw an error if the component does not
exist to preserve its current behavior.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-03 18:09:05 +03:00
Nikos Dragazis
7e738bcd2d sstables: Add digest in the SSTable components
SSTables store their digest in a Digest file. Add this in the list of
SSTable components. In a follow-up patch we will use this component to
enable digest checking in the validation path.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-03 18:09:05 +03:00
Nikos Dragazis
c893f06409 sstables: Add digest check in compressed data source
Following the addition of digest check in the checksummed data source,
add the same feature to the compressed data source as well. This ensures
consistent behavior across any type of SSTable.

This is added as an optional feature so that we can preserve the current
behavior, that is verify only the per-chunk checksums during normal user
reads. To ensure zero cost at runtime when disabled, we introduce the
on/off switch as a template parameter.

The digest calculation for compressed SSTables depends on the SSTable
format, hence the new template argument for the checksum mode. This is
consistent with the compressed data sink.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-03 18:09:01 +03:00
Nikos Dragazis
0df1c01759 sstables: Add digest check in checksummed data source
The checksummed data source verifies the checksum of each chunk in the
data files of uncompressed SSTables. This is being leveraged by scrub
in validation mode.

Extend the data source to check the digest (full checksum) as well.
Unlike checksums, this is added as an optional feature so that SSTables
without a digest can still be validated in a per-chunk basis. To enable
this, the caller needs to set the template parameter `check_digest` to
true, and provide the expected digest.

The data source calculates the digest incrementally through multiple
get() calls and compares against the expected digest after reading the
whole file range. If there is a mismatch, it throws an exception.

Checking the digest requires reading the whole data file. If this cannot
be satisfied (e.g., due to partial read or skip()), the data source
fails immediately. If the user has successfully read the whole file
range, it can be safely assumed that the digest is valid.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-10-03 18:08:56 +03:00
Tomasz Grabiec
62f3d9e173 perf: perf_fast_forward: Add test case for querying missing rows 2024-10-03 16:26:41 +02:00
Tomasz Grabiec
4602ba90df perf-fast-forward: Allow overriding promoted index block size
For testing dense clustering index.
2024-10-03 16:26:41 +02:00
Tomasz Grabiec
1782456a52 perf-fast-forward: Test subsequent key reads from the middle in test_large_partition_select_few_rows 2024-10-03 16:26:41 +02:00
Tomasz Grabiec
751fa10de8 perf-fast-forward: Allow adding key offset in test_large_partition_select_few_rows 2024-10-03 16:26:41 +02:00
Tomasz Grabiec
10c6990e41 perf-fast-forward: Use single-partition reads in test_large_partition_select_few_rows
It's a more realistic scenario than a full scan.
2024-10-03 16:26:28 +02:00
Tomasz Grabiec
753f6a61fd sstables: bsearch_clustered_cursor: Add more tracing points 2024-10-03 16:24:18 +02:00
Botond Dénes
38088daa1f scylla-gdb.py: drop compatibility code for EOL releases
Any release < 6.0 or < 2023.1 is EOL and need not be supported by
scylla-gdb.py anymore. Remove compatibility code for these releases.

Closes scylladb/scylladb#20918
2024-10-03 15:42:08 +03:00
Avi Kivity
494561c4f3 cql3: expr: drop boost usage
Replace boost usage with <ranges>, modernizing the code a little
and reducing dependencies on a redundant library.

Closes scylladb/scylladb#20919
2024-10-03 15:39:40 +03:00
Kefu Chai
7b82f3a375 test/lib: remove redundant fmt::to_string() in seastar::format()
previously change, implementation was unnecessarily verbose and less
efficient, as it created and immediately discarded temporary strings.
remove unnecessary use of `fmt::to_string()` when arguments are already
being formatted by `seastar::format()`.

in this this change:

- eliminates creation of temporary `std::string` instances
- reduces memory allocations and copies
- improves performance
- simplifies the code

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20923
2024-10-03 15:36:55 +03:00
Tomasz Grabiec
95b864497a sstables: reader: Log data file range 2024-10-03 14:16:05 +02:00
Tomasz Grabiec
41d3ae5e81 sstables: bsearch_clustered_cursor: Unify skip_info logging
Now all exit paths which return skip_info will print it in the same
way which makes for easier log parsing.
2024-10-03 14:16:05 +02:00
Tomasz Grabiec
1b82d5117a sstables: bsearch_clustered_cursor: Narrow down range using "end" position of the block
This is optimization.

Example:

  block0: start=aaa, end=aaA
  block1: start=bbb, end=bbB
  block2: whatever

Before the patch, advance_to("aAA") would skip to block0, and upper
bound probe would skip to block1. This way, the reader would read the
range of block0 from the data file.

After the patch, "end" position is taken into account, so
advance_to("aAA") will notice that block0 doesn't contain the position
and will skip to block1. This is especially important for dense
indexes, as it allows us to skip accessing data file if the search key
is missing.

It also solves the edge case problem related to the fact that single
row reads are using a range which with positions which are not equal
to the key, but are before(key) and after(key) for the lower bound and
upper bound respectively. Before the patch, advance_to(before("bbb"))
would skip to block0, before the position is before the block1's
start. And upper bound probe for after("bbb") would point to
block2. This way the read would scan block0 needlessly. After the
patch, advance_to(before("bbb")) will skip to block1 because we notice
based on "end" that block0 doesn't contain the position.

This change also ensures that the start position of the upper bound
entry of the after_key(pos), where pos is the last advance_to()
position, is warm in cache. This is needed to optimize single-row
reads with a dense index so that they always read exactly one promoted
index block. For this to work, probe_upper_bound() for the
after_key(row) always needs to find the upper bound block in
cache.
2024-10-03 14:16:05 +02:00
Tomasz Grabiec
b03f23a09b sstables: bsearch_clustered_cursor: Skip even to the first block
It was unnecessary to emit a skip info for the first block since it
follows immediately the partition start, but it is relevant to the
optimization of avoiding data reads for missing keys. This
optimization relies on the fact that lower bound position equals upper
bound position. If the reader's key is before the first key in the
partition and we don't arm the skip info for the first block, lower
bound would be equal to the partition start, and upper bound would be
equal to the first row's position, which are not equal.
2024-10-03 14:16:05 +02:00
Tomasz Grabiec
c905554121 test: sstables: sstable_3_x_test: Improve failure message 2024-10-03 14:16:05 +02:00
Tomasz Grabiec
7f077893ed sstables: mx: writer: Never include partition_end marker in promoted index block width
Currently, it may happen that the last promoted index block includes
the partition_end marker. That's because we first write the partition
end marker and then emit the unclosed block. This behavior matches
Cassandra (checked in 3.x and 5.0.1).

This is problematic for ruling out data file reads based on index.
The width field is currently unused, but it will be used later where
the width of the last block is used to compute the skip position past
the last block for lookups which land after all keys in the
partition. If width includes the marker then such a skip would land in
the next partition, which is incorrect, as the reader context expects
a cell element. Even if that was recognized, it's wrong - if this is
not a single partition read (so upper bound is not at the next
partition too), then we would read from the wrong (next) partition.

We want to be able to make such skips in order to avoid unnecessary
data file IO for reads of missing rows. Currently, we would always
read the last block even if the key is past its "end" position.

Another way to solve this would be to propagate the "past the last
block" condition from the index cursor to the reader and let it deal
with it, but the logic for that would be complicated. With this fix,
there is no special logic required.
2024-10-03 14:09:57 +02:00
Pavel Emelyanov
4465bd9e5e test: Add check that restored-from objects are not removed
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-03 13:37:04 +03:00
Botond Dénes
3ebb124eb2 repair/row_level: remove reader timeout
This timeout was added to catch reader related deadlocks. We have not
seen such deadlocks for a long time, but we did see false-timeouts
caused by this, see explanation below. Since the cost now outweight the
benefit, remove the timeout altogether.

The false timeout happens during mixed-shard repair. The
`reader_permit::set_timeout()` call is called on the top-level permit
which repair has a handle on. In the case of the mixed-shard repair,
this belongs to the multishard reader. Calling set_timeout() on the
multishard reader has no effect on the actual shard readers, except in
one case: when the shard reader is created, it inherits the multishard
reader's current timeout. As the shard reader can be alive for a long
time, this timeout is not refreshed and ultimately causes a timeout and
fails the repair.

Refs: #18269

Closes scylladb/scylladb#20703
2024-10-03 11:26:29 +02:00
Kamil Braun
e67016540c Merge 'Node replace and remove operations: Add deprecate IP addresses usage warning.' from Sergey Zolotukhin
- As part of deprecation of IP address usage, warning messages were added when IP addresses specified in the `ignore-dead-nodes` and `--ignore-dead-nodes-for-replace` options for scylla and nodetool.
- Slight optimizations for `utils::split_comma_separated_list`, ` host_id_or_endpoint lists` and `storage_service` remove node operations, replacing `std::list` usage with `std::vector`.

Fixes scylladb/scylladb#19218

Backport: 6.2 as it's not yet released.

Closes scylladb/scylladb#20756

* github.com:scylladb/scylladb:
  config: Add a warning about use of IP address for join topology and replace operations.
  nodetool: Add IP address usage warning for 'ignore-dead-nodes'.
  tests: Fix incorrect UUIDs in test_nodeops
  utils: Optimizations for utils::split_comma_separated_list and usage of host_id_or_endpoint lists
2024-10-03 11:08:28 +02:00
Kamil Braun
d2233d4400 Merge 'test: update cql/ tests to work with tablets enabled by default' from Konstantin Osipov
Explicitly disable tablets for features which still dont' work with tablets: cdc, lwt, coutners.

Closes scylladb/scylladb#20858

* github.com:scylladb/scylladb:
  test: make cdc tests pass with tablets on by default
  test: make cql/counters* pass with and without tablets
  test: make cql/lwt_* pass with and without tablets
  test: rename cql/list_test to cql/lwt_list_test
2024-10-03 10:53:17 +02:00
Kefu Chai
f9091066b7 treewide: replace boost::irange with std::views::iota where possible
when building scylla with the standard library from GCC-14.2, shipped by
fedora 41, we have following build failure:

```
/home/kefu/.local/bin/clang++ -DDEBUG -DDEBUG_LSA_SANITIZER -DFMT_SHARED -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DSEASTAR_API_LEVEL=7 -DSEASTAR_DEBUG -DSEASTAR_DEBUG_PROMISE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_SSTRING -DSEASTAR_TYPE_ERASE_MORE -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -isystem /home/kefu/dev/scylladb/abseil -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=x86-64-v3 -mpclmul -Xclang -fexperimental-assignment-tracking=disabled -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -MD -MT CMakeFiles/scylla-main.dir/Debug/init.cc.o -MF CMakeFiles/scylla-main.dir/Debug/init.cc.o.d -o CMakeFiles/scylla-main.dir/Debug/init.cc.o -c /home/kefu/dev/scylladb/init.cc
In file included from /home/kefu/dev/scylladb/init.cc:12:
In file included from /home/kefu/dev/scylladb/db/config.hh:20:
In file included from /home/kefu/dev/scylladb/locator/abstract_replication_strategy.hh:26:
/home/kefu/dev/scylladb/locator/tablets.hh:410:30: error: unexpected type name 'size_t': expected expression
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                              ^
/home/kefu/dev/scylladb/locator/tablets.hh:410:23: error: no member named 'irange' in namespace 'boost'
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                ~~~~~~~^
/home/kefu/dev/scylladb/locator/tablets.hh:410:38: error: left operand of comma operator has no effect [-Werror,-Wunused-value]
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                                      ^
3 errors generated.
[16/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/keys.cc.o
[17/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/counters.cc.o
[18/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/partition_slice_builder.cc.o
[19/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o
FAILED: CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o
/home/kefu/.local/bin/clang++ -DDEBUG -DDEBUG_LSA_SANITIZER -DFMT_SHARED -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DSEASTAR_API_LEVEL=7 -DSEASTAR_DEBUG -DSEASTAR_DEBUG_PROMISE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_SSTRING -DSEASTAR_TYPE_ERASE_MORE -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -isystem /home/kefu/dev/scylladb/abseil -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=x86-64-v3 -mpclmul -Xclang -fexperimental-assignment-tracking=disabled -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -MD -MT CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o -MF CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o.d -o CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o -c /home/kefu/dev/scylladb/mutation_query.cc
In file included from /home/kefu/dev/scylladb/mutation_query.cc:12:
In file included from /home/kefu/dev/scylladb/schema/schema_registry.hh:17:
In file included from /home/kefu/dev/scylladb/replica/database.hh:11:
In file included from /home/kefu/dev/scylladb/locator/abstract_replication_strategy.hh:26:
/home/kefu/dev/scylladb/locator/tablets.hh:410:30: error: unexpected type name 'size_t': expected expression
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                              ^
/home/kefu/dev/scylladb/locator/tablets.hh:410:23: error: no member named 'irange' in namespace 'boost'
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                ~~~~~~~^
/home/kefu/dev/scylladb/locator/tablets.hh:410:38: error: left operand of comma operator has no effect [-Werror,-Wunused-value]
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                                      ^
In file included from /home/kefu/dev/scylladb/mutation_query.cc:12:
In file included from /home/kefu/dev/scylladb/schema/schema_registry.hh:17:
In file included from /home/kefu/dev/scylladb/replica/database.hh:37:
In file included from /home/kefu/dev/scylladb/db/snapshot-ctl.hh:20:
/home/kefu/dev/scylladb/tasks/task_manager.hh:403:54: error: no member named 'irange' in namespace 'boost'
  403 |         co_await coroutine::parallel_for_each(boost::irange(0u, smp::count), [&tm, id, &res, &func] (unsigned shard) -> future<> {
      |                                               ~~~~~~~^
4 errors generated.
```

so let's take the opportunity to switch from `boost::irange` to
`std::views::iota`.

in this change, we:

- switch from boost::irange to std::views::iota for better standard library compatibility
- retain boost::irange where step parameter is used, as std::views::iota doesn't support it
- this change partially modernizes our range usage while maintaining
- existing functionality

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20924
2024-10-03 10:33:33 +03:00
Pavel Emelyanov
7389f4275d sstables_loader: Dont unlink sstables when restoring from S3
When load_and_stream() completes, all sstables that were loaded (and
streamed) are unlinked. This is wrong for the restore-from-s3 task, as
removing objects from backup storage is not what user expects.

Fix it by adding a boolean to streamer class, and set it to false (well,
bool_class<>::no) for restore task.

fixes: #20938

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-03 10:15:22 +03:00
Pavel Emelyanov
7eb48358e9 sstables_loader: Make primary_replica_only bool_class RAII field
This boolean is currently passed all the way around as pure bool
argument. And it's only needed in a single get_endpoints() method that
calculates the target endpoints.

This patch places this bool on class streamer, so that the call chain
arguments are not polluted, and converts it to bool_class.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-03 10:13:37 +03:00
Pavel Emelyanov
1da1d131b2 test: Use corrcet key in sstables registry mock
The "real" registry defines its primary key as (location, generation)
pair, where location is the partition key and generation is clustering
key. The registry mock uses only location part as primary key, while it
must use both.

The buggy mock works simply because the listing API is in fact not used
by unit tests. Those tests that do need it are python tests that start
scylla and thus implicitly use real registry.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-03 10:07:11 +03:00
Pavel Emelyanov
a503e2ab10 test: Pass entry status to mock registry consumer
When sstables registry is listed, the passed consumer accepts entry
status as its first argument, not its location (location is passed as a
search key)

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-10-03 10:06:28 +03:00
Kefu Chai
c7eafc4dc1 auth: capture boost::regex_error not std::regex_error
in a3db5401, we introduced the TLS certi authenticator, which is
configured using `auth_certificate_role_queries` option . the
value of this option contains a regular expression. so there are
chances the regular expression is malformatted. in that case,
when converting its value presenting the regular expression to an
instance of `boost::regex`, Boost.Regex throws a `boost::regex_error`
exception, not `std::regex_error`.

since we decided to use Boost.Regex, let's catch `boost::regex_error`.

Refs a3db5401
Fixes scylladb/scylladb#20941
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20942
2024-10-03 09:57:15 +03:00
Piotr Dulikowski
6778001313 Merge 'cql3: Make creating MV respect ID option' from Dawid Mędrek
Before these changes, we could create a materialized
view specifying its ID, but the option was ignored.

This commit makes Scylla respect the option. Now specifying
the ID results in the MV being created with that specific ID.
This way, Scylla's behavior is consistent with Cassandra's.

Because Cassandra doesn't mention the option in its
user documentation, we don't update it either in case
the semantics of it changes in the future -- we want
to have an open door for any modifications.

Note that Cassandra returns a server error if the provided
ID is already in use, both in the case of regular tables
and MVs. That's most likely a bug. Instead of following that
behavior, we stay consistent with the current semantics of
creating a regular table in Scylla: if the provided ID is
already used, return an InvalidRequest.

The last thing worth pointing out is Cassandra handles
`WITH ID = null` as a special case; normally, specifying
an invalid ID results in a ConfigurationException, but a null
is treated as a syntax error. As in the previous paragraph,
we stay consistent with the semantics of regular tables and
all invalid IDs, null included, lead to a ConfigurationException.

We also add a few short tests verifying that the implementation
works as intended.

Fixes scylladb/scylladb#20616

Backport not needed: the semantics of the option was never documented in either Cassandra, or Scylla.

Closes scylladb/scylladb#20773

* github.com:scylladb/scylladb:
  test/cql-pytest: Get rid of unnecessary processing describe statements
  cql3: Make creating MV respect ID option
2024-10-03 08:31:07 +02:00
Dawid Mędrek
1f1b201fd8 cql3/functions/user_function: Use fmt to format create statement
We replace `std::ostringstream` with views and formatting
using fmt to improve readability of the code.
2024-10-02 19:17:35 +02:00
Ferenc Szili
cdf775d3cc test: test tombstone GC disabled on pending replica
This tests if tombstone GC is disabled on pending replicas
2024-10-02 16:37:57 +02:00
Ferenc Szili
ba6707506d tablet_storage_group_manager: update tombstone_gc_enabled in compaction group
In order to avoid cases during tablet migrations where we garbage
collect tombstones before the data it shadows arrives, we will
disable tombstone GC on pending replicas.

To achieve this we added a tombston_gc_enabled flag to compaction_group.
This flag is updated from updte_effective_repliction_map method of the
tablet_storage_group_manager class.
2024-10-02 16:31:33 +02:00
Raphael S. Carvalho
93815e0649 replica: Fix tombstone GC during tablet split preparation
During split prepare phase, there will be more than 1 compaction group with
overlapping token range for a given replica.

Assume tablet 1 has sstable A containing deleted data, and sstable B containing
a tombstone that shadows data in A.

Then split starts:
1) sstable B is split first, and moved from main (unsplit) group to a
split-ready group
2) now compaction runs in split-ready group before sstable A is split

tombstone GC logic today only looks at underlying group, so compaction is step
2 will discard the deleted data in A, since it belongs to another group (the
unsplit one), and so the tombstone can be purged incorrectly.

To fix it, compaction will now work with all uncompacting sstables that belong
to the same replica, since tombstone GC requires all sstables that possibly
contain shadowed data to be available for correct decision to be made.

Fixes #20044.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2024-10-02 11:26:13 -03:00
Ferenc Szili
e472844a78 database::table: add tombstone_gc_enabled(locator::tablet_id)
This change adds the flag tombstone_gc_enabled to compaction_group.
The value of this flag will be set in
tablet_storage_group_manager::update_effective_replication_map().
2024-10-02 16:24:45 +02:00
Raphael S. Carvalho
bcd358595f service: Improve error handling for split
Retry wasn't really happening since the loop was broken and sleep
part was skipped on error. Also, we were treating abort of split
during shutdown as if it were an actual error and that confused
longevity tests that parse for logs with error level. The fix is
about demoting the level of logs when we know the exception comes
from shutdown.

Fixes #20890.
2024-10-02 11:23:44 -03:00
Konstantin Osipov
1d1777b13a test: make cdc tests pass with tablets on by default
CDC is not supported with tablets, explicitly disable tablets
in CDC keyspace definition.
2024-10-02 06:37:14 -04:00
Konstantin Osipov
0e3dbec277 test: make cql/counters* pass with and without tablets
Counters are not supported with tablets, make sure
the test works in any ScyllaDB configuration.
2024-10-02 06:37:14 -04:00
Konstantin Osipov
92aca17bc5 test: make cql/lwt_* pass with and without tablets
Lightweight transactions don't support tablets, so let's
explicitly disable tablets in LWT tests.
2024-10-02 06:37:14 -04:00
Konstantin Osipov
7c64fc0c4f test: rename cql/list_test to cql/lwt_list_test
This test is actually testing lists with LWT, so should
have the corresponding name. Going forward we'll patch CQL LWT
tests for tablets, so let's group them together.
2024-10-02 06:37:14 -04:00
Sergey Zolotukhin
6398b7548c config: Add a warning about use of IP address for join topology and replace
operations.

When the '--ignore-dead-nodes-for-replace' config option contains
IP addresses, a warning will be logged, notifying the user that
using IP addresses with this option is deprecated and will no
longer be supported in the next release.

Fixes scylladb/scylladb#19218
2024-10-02 11:56:59 +02:00
Sergey Zolotukhin
9c692438e9 nodetool: Add IP address usage warning for 'ignore-dead-nodes'.
Since we are deprecating the use of IP addresses, a warning message will be printed
if 'nodetool removenode --ignore-dead-nodes' is used with IP addresses.
2024-10-02 11:56:59 +02:00
Sergey Zolotukhin
a871321ecf tests: Fix incorrect UUIDs in test_nodeops
It was found that the UUIDs used in test_nodeops were
invalid. This update replaces those UUIDs with newly generated
random UUIDs.
2024-10-02 11:56:59 +02:00
Sergey Zolotukhin
3b9033423d utils: Optimizations for utils::split_comma_separated_list and usage of host_id_or_endpoint lists
- utils::split_comma_separated_list now accepts a reference to sstring instead
  of a copy to avoid extra memory allocations. Additionally, the results of
  trimming are moved to the resulting vector instead of being copied.
- service/storage_service removenode, raft_removenode, find_raft_nodes_from_hoeps,
  parse_node_list and api/storage_service::set_storage_service were changed to use
  std::vector<host_id_or_endpoint> instead of std::list<host_id_or_endpoint> as
  std::vector is a more cache-friendly structure,  resulting in better performance.
2024-10-02 11:56:59 +02:00
Dawid Mędrek
7a7a1e3558 treewide: Prefer bytes_fwd.hh over bytes.hh
CI started reporting warnings about including `bytes.hh` in
several files. The reason is they actually only use code
introduced in `bytes_fwd.hh` (which is also included by `bytes.hh`).
Clang-include-cleaner suggests that we get rid of that indirection
and only include `bytes_fwd.hh`. That's what happens in this commit.

We include `bytes.hh` in `exceptions/exceptions.cc` because
it relies on the formatting utilities declared and defined
in `bytes.hh`.

Closes scylladb/scylladb#20842
2024-10-02 07:29:30 +02:00
Dawid Mędrek
de88c150f6 test/cql-pytest: Get rid of unnecessary processing describe statements
As part of scylladb/scylladb@d42f160, we added a test verifying that
restoring the schema works as intended. Unfortunately, because of
scylladb/scylladb#20616, we had to manually process the results
of `DESCRIBE SCHEMA` to exclude the ID parameter and be able to
compare restore statements corresponding to the same view.

Now that materialized views respect the ID parameter, we can get rid
of that logic.
2024-10-01 22:04:05 +02:00
Dawid Mędrek
552c752005 cql3: Make creating MV respect ID option
Before these changes, we could create a materialized
view specifying its ID, but the option was ignored.

This commit makes Scylla respect the option. Now specifying
the ID results in the MV being created with that specific ID.
This way, Scylla's behavior is consistent with Cassandra's.

Because Cassandra doesn't mention the option in its
user documentation, we don't update it either in case
the semantics of it changes in the future -- we want
to have an open door for any modifications.

Note that Cassandra returns a server error if the provided
ID is already in use, both in the case of regular tables
and MVs. That's most likely a bug. Instead of following that
behavior, we stay consistent with the current semantics of
creating a regular table in Scylla: if the provided ID is
already used, return an InvalidRequest.

The last thing worth pointing out is Cassandra handles
`WITH ID = null` as a special case; normally, specifying
an invalid ID results in a ConfigurationException, but a null
is treated as a syntax error. As in the previous paragraph,
we stay consistent with the semantics of regular tables and
all invalid IDs, null included, lead to a ConfigurationException.

We also add a few short tests verifying that the implementation
works as intended.
2024-10-01 22:03:58 +02:00
Kefu Chai
9b5eab0dde test/lib: include <fmt/std.h> for formatting std::optional
before this change, when compiling with fmtlib v11.0.2 and clang
v19.1.0, the compiler fails like:

```
/usr/bin/clang++ -DBOOST_REGEX_DYN_LINK -DBOOST_REGEX_NO_LIB -DBOOST_UNIT_TEST_FRAMEWORK_DYN_LINK -DBOOST_UNIT_TEST_FRAMEWORK_NO_LIB -DDEBUG -DDEBUG_LSA_SANITIZER -DFMT_SHARED -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DSEASTAR_API_LEVEL=7 -DSEASTAR_DEBUG -DSEASTAR_DEBUG_PROMISE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_SSTRING -DSEASTAR_TYPE_ERASE_MORE -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -I/home/kefu/dev/scylladb/build -isystem /home/kefu/dev/scylladb/abseil -isystem /home/kefu/dev/scylladb/build/rust -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-enum-constexpr-conversion -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=x86-64-v3 -mpclmul -Xclang -fexperimental-assignment-tracking=disabled -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -MD -MT test/lib/CMakeFiles/test-lib.dir/Debug/cql_assertions.cc.o -MF test/lib/CMakeFiles/test-lib.dir/Debug/cql_assertions.cc.o.d -o test/lib/CMakeFiles/test-lib.dir/Debug/cql_assertions.cc.o -c /home/kefu/dev/scylladb/test/lib/cql_assertions.cc
In file included from /home/kefu/dev/scylladb/test/lib/cql_assertions.cc:12:
In file included from /usr/include/fmt/ranges.h:20:
In file included from /usr/include/fmt/format.h:41:
/usr/include/fmt/base.h:2673:45: error: implicit instantiation of undefined template 'fmt::detail::type_is_unformattable_for<std::vector<std::optional<seastar::basic_sstring<signed char, unsigned int, 31, false>>>, char>'
 2673 |     type_is_unformattable_for<T, char_type> _;
      |                                             ^
/usr/include/fmt/base.h:2735:23: note: in instantiation of function template specialization 'fmt::detail::parse_format_specs<std::vector<std::optional<seastar::basic_sstring<signed char, unsigned int, 31, false>>>, fmt::detail::compile_parse_context<char>>' requested here
 2735 |         parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
      |                       ^
/usr/include/fmt/base.h:2884:47: note: in instantiation of member function 'fmt::detail::format_string_checker<char, int, std::vector<std::optional<seastar::basic_sstring<signed char, unsigned int, 31, false>>>, std::vector<std::optional<managed_bytes>>>::format_string_checker' requested here
 2884 |       detail::parse_format_string<true>(str_, checker(s));
      |                                               ^
/home/kefu/dev/scylladb/test/lib/cql_assertions.cc:132:34: note: in instantiation of function template specialization 'fmt::basic_format_string<char, int &, std::vector<std::optional<seastar::basic_sstring<signed char, unsigned int, 31, false>>> &, const std::vector<std::optional<managed_bytes>> &>::basic_format_string<char[35], 0>' requested here
  132 |             fail(seastar::format("row {} differs, expected {} got {}", row_nr, row, actual));
      |                                  ^
/usr/include/fmt/base.h:1616:8: note: template is declared here
 1616 | struct type_is_unformattable_for;
      |        ^
/home/kefu/dev/scylladb/test/lib/cql_assertions.cc:132:34: error: call to consteval function 'fmt::basic_format_string<char, int &, std::vector<std::optional<seastar::basic_sstring<signed char, unsigned int, 31, false>>> &, const std::vector<std::optional<managed_bytes>> &>::basic_format_string<char[35], 0>' is not a constant expression
  132 |             fail(seastar::format("row {} differs, expected {} got {}", row_nr, row, actual));
      |                                  ^
```

because the formatter for `std::optional<>` is defined in fmt/std.h.

so, in this change, we include the used header.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20922
2024-10-01 22:32:16 +03:00
Tomasz Grabiec
a29501ed67 sstables: Reduce amount of I/O for clustering-key-bounded reads from large partitions
Single-row reads from large partition issue 64 KiB reads to the data file,
which is equal to the default span of the promoted index block in the data file.
If users would want to reduce selectivity of the index to speed up single-row reads,
this won't be effective. The reason is that the reader uses promoted index
to look up the start position in the data file of the read, but end position
will in practice extend to the next partition, and amount of I/O will be
determined by the underlying file input stream implementation and its
read-ahead heuristics. By default, that results in at least 2 IOs 32KB each.

There is already infrastructure to lookup end position based on upper
bound of the read, but it's not effective becasue it's a
non-populating lookup and the upper bound cursor has its own private
cached_promoted_index, which is cold when positions are computed. It's
non-populating on purpose, to avoid extra index file IO to read upper
bound. In case upper bound is far-enough from the lower bound, this
will only increase the cost of the read.

The solution employed here is to warm up the lower bound cursor's
cache before positions are computed, and use that cursor for
non-populating lookup of the upper bound.

We use the lower bound cursor and the slice's lower bound so that we
read the same blocks as later lower-bound slicing would, so that we
don't incur extra IO for cases where looking up upper bound is not
worth it, that is when upper bound is far from the lower bound. If
upper bound is near lower bound, then warming up using lower bound
will populate cached_promoted_index with blocks which will allow us to
locate the upper bound block accurately.  This is especially important
for single-row reads, where the bounds are around the same key.  In
this case we want to read the data file range which belongs to a
single promoted index block.  It doesn't matter that the upper bound
is not exactly the same. They both will likely lie in the same block,
and if not, binary search will bring adjacent blocks into cache.  Even
if upper bound is not near, the binary search will populate the cache
with blocks which can be used to narrow down the data file range
somewhat.

Fixes #10030.

The change was tested with perf-fast-forward.

I populated the data set with `column_index_size_in_kb` set to 1

  scylla perf-fast-forward --populate --run-tests=large-partition-slicing --column-index-size-in-kb=1

Test run:

  build/release/scylla perf-fast-forward --run-tests=large-partition-select-few-rows -c1 --keep-cache-across-test-cases --test-case-duration=0

This test reads two rows from the middle of a large partition (1M
rows), of subsequent keys. The first read will miss in the index file
page cache, the second read will hit.

Notice that before the change, the second read issued 2 aio requests worth of 64KiB in total.
After the change, the second read issued 1 aio worth of 2 KiB. That's because promoted index block is larger than 1 KiB.
I verified using logging that the data file range matches a single promoted index block.

Also, the first read which misses in cache is still faster after the change.

Before:

running: large-partition-select-few-rows on dataset large-part-ds1
Testing selecting few rows from a large partition:
stride  rows      time (s)   iterations     frags     frag/s    mad f/s    max f/s    min f/s    avg aio    aio      (KiB) blocked dropped  idx hit idx miss  idx blk    c hit   c miss    c blk    allocs   tasks insns/f    cpu
500000  1         0.009802            1         1        102          0        102        102       21.0     21        196       2       1        0        1        1        0        0        0       568     269 4716050  53.4%
500001  1         0.000321            1         1       3113          0       3113       3113        2.0      2         64       1       0        1        0        0        0        0        0       116      26  555110  45.0%

After:

running: large-partition-select-few-rows on dataset large-part-ds1
Testing selecting few rows from a large partition:
stride  rows      time (s)   iterations     frags     frag/s    mad f/s    max f/s    min f/s    avg aio    aio      (KiB) blocked dropped  idx hit idx miss  idx blk    c hit   c miss    c blk    allocs   tasks insns/f    cpu
500000  1         0.009609            1         1        104          0        104        104       20.0     20        137       2       1        0        1        1        0        0        0       561     268 4633407  43.1%
500001  1         0.000217            1         1       4602          0       4602       4602        1.0      1          2       1       0        1        0        0        0        0        0       110      26  313882  64.1%

(cherry picked from commit dfb339376aff1ed961b26c4759b1604f7df35e54)
2024-10-01 18:40:34 +02:00
Tomasz Grabiec
41be5d1daf sstables: clustered_cursor: Track current block
Will be needed by the reader to jump to the current block even if we
already advanced to it before, when setting up the reader context.

We want to advance to lower bound earlier, before the praser skips to
the lower bound. We want that in order to set input stream data file
range based on index. If we didn't have access to the current block
and used the result from advance_to(), the parser will think we're
already in the block which has lower_bound when it attempts to skip,
and will not skip, falling back to scanning.
2024-10-01 18:40:34 +02:00
Kefu Chai
787ea4b1d4 treewide: accept list of sstables in "restore" API
before this change, we enumerate the sstables tracked by the
system.sstables table, and restore them when serving
requests to "storage_service/restore" API. this works fine with
"storage_service/backup" API. but this "restore" API cannot be
used as a drop-in replacement of the rclone based API currently
used by scylla-manager.

in order to fill the gap, in this change:

* add the "prefix" parameter for specifying the shared prefix of
  sstables
* add the "sstables" parameter for specifying the list of  TOC
  components of sstables
* remove the "snapshot" parameter, as we don't encode the prefix
  on scylla's end anymore.
* make the "table" parameter mandatory.

Fixes scylladb/scylladb#20461
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-01 23:24:56 +08:00
Kefu Chai
17181c2eca sstable: pass get_storage_option to sstable_directory::load_sstable()
before this change, we always pass
`sstable_directory::_storage_opts` to `_manager.make_sstable()` in
`sstable_directory::load_sstable()`. but when loading from object
storage, we need to customize the storage_options on a per-sstable
basis. the way to address this is to allow the caller of
`sstable_directory::process_descriptor()` to pass a functor which
return the `storage_options` to be used when creating the sstable.

so, in this change, we update

- sstable_directory::load_sstable()
- sstable_directory::process_descriptor()

so that they accept another parameter to create the storage_options.
in the next commit we will pass a different functor for customizing
the storage_options on a per-sstable basis when loading sstables.

Refs scylladb/scylladb#20461

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-01 23:24:56 +08:00
Kefu Chai
283697e316 test/nodetool: add body parameter to expected_request
before this change, `expected_request` only includes query strings
for the parameters of requests. but we will add an API
("storage_service/restore") which accepts its parameters in HTTP body
as well.

in this change, we add an optional `body` member to `expected_request`,
so that we can mock the APIs which pass the parameters with the HTTP
body.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-01 23:24:56 +08:00
Kefu Chai
3c19cc9aec tools/scylla-nodetool: enable nodetool to write HTTP body
before this change, we always send the parameters with query strings,
but we will add an API ("storage_service/restore") which accepts its
parameters in HTTP body as well.

in this change, we add an optional parameter to `do_request()` and
`post()`, so that we can send HTTP body when using "POST" method
in nodetool implementation.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-10-01 23:24:56 +08:00
Pavel Emelyanov
7f71371de1 distributed_loader: Get token metadata from e.r.m., not database
Though database can be used to get relevant token metadata, it's better
not to use one service (database) as a proxy to get another one (token
metadata). In case of tokens, there's effective replication map at hand,
which is a more correct source of such topology information.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20894
2024-10-01 14:59:35 +03:00
Anna Stuchlik
7eb1dc2ae5 doc: document the option to run ScyllaDB in Docker on macOS
This commit adds a description of a workaround to create a multi-node ScyllaDB cluster
with Docker on macOS.

Refs https://github.com/scylladb/scylladb/issues/16806
See https://forum.scylladb.com/t/running-3-node-scylladb-in-docker/1057/4

Closes scylladb/scylladb#20857
2024-10-01 14:58:58 +03:00
Botond Dénes
6535283881 .github/CODEOWNERS: add code owners for tools/*
Closes scylladb/scylladb#20702
2024-10-01 14:52:26 +03:00
Yaron Kaikov
ab964bcd5a [script/pull_github_pr.sh] Check Gating status before merging
Maintainers use scripts/pull_github_pr.sh from scylladb.git when merging PRs and before pushing to the next. We want to prevent merges from piling up on top of unstable builds. This change will check Gating's current status and notify the maintainers

Related to scylladb/scylla-pkg#3644

Closes scylladb/scylladb#20742
2024-10-01 14:46:29 +03:00
Anna Stuchlik
a97db03448 doc: add metric updates from 6.1 to 6.2
This commit specifies metrics that are new in version 6.2 compared to 6.1,
as specified in https://github.com/scylladb/scylladb/issues/20176.

Fixes https://github.com/scylladb/scylladb/issues/20176

Closes scylladb/scylladb#20896
2024-10-01 14:41:37 +03:00
muthu90tech
1204d54c5c transport: Dont bypass seastar API when making syscalls
The transport/controller.cc bypasses seastar API when making a few syscalls,
this PR will use the right seastar API to make the syscall and libc calls
this PR relies on few new APIs introduced in
seastar commit : cd7f3b8e8850cd80a4f6899cedc726e576c51abe

Closes scylladb/scylladb#17443

Closes scylladb/scylladb#19565
2024-10-01 14:29:24 +03:00
Benny Halevy
5a0f3889e0 treewide: use std::ranges sort functions rather than boost
Using the standard library is preffered over boost.

In cql3/expr/expression.cc to_sorted_vector got more of a
face-list and was modernized to use also std::unique
and while at it, to move its input range in the uniquely sorted
result vector.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-10-01 14:19:05 +03:00
Avi Kivity
e99426df60 treewide: de-static namespace scope functions in headers
'static inline' is always wrong in headers - if the same header is
included multiple times, and the function happens not to be inlined,
then multiple copies of it will be generated.

Fix by mechanically changing '^static inline' to 'inline'.
2024-10-01 14:02:50 +03:00
Avi Kivity
e9425e15b2 treewide: remove dependency on boost asio address_v4
It's not used. There's a comment mentioning it prevents some type
conflict, but apparently that was fixed some time ago.

Closes scylladb/scylladb#20883
2024-10-01 14:00:50 +03:00
Pavel Emelyanov
24598848a9 Merge 'virtual_tables: snapshots: include all snapshots' from Benny Halevy
Use database::get_snapshot_details to get the details
of all snapshots on disk, in particular those of
deleted tables.

Add test_snapshots_dropped_table to test listing
of snapshots of a deleted table.
And harden the existing test cases to use a unique
snapshot tag and to delete it when the test ends.

Fixes #18313

* No backport required at this time since this is rather minor UX issue that weren't hit in the field AFAIK

Closes scylladb/scylladb#20869

* github.com:scylladb/scylladb:
  cql-pytest: test_virtual_tables: add test_snapshots_multiple_keyspaces
  virtual_tables: snapshots: include all snapshots
2024-10-01 13:56:13 +03:00
Gleb Natapov' via ScyllaDB development
22368b13f2 api: introduce raft stepdown REST API
Also provide test.py util function to trigger it. Can be useful for
testing.
2024-10-01 12:18:49 +02:00
Avi Kivity
f5628be597 Update tools/java submodule
* tools/java 5b0e274f12...b2d025fd6b (1):
  > build.xml: update scylla-tools license
2024-10-01 12:48:45 +03:00
Pavel Emelyanov
1dfe780457 cql: Check that CREATEing tablets/vnodes is consistent with the CLI
There are two bits that control whenter replication strategy for a
keyspace will use tablets or not -- the configuration option and CQL
parameter. This patch tunes its parsing to implement the logic shown
below:

    if (strategy.supports_tablets) {
         if (cql.with_tablets) {
             if (cfg.enable_tablets) {
                 return create_keyspace_with_tablets();
             } else {
                 throw "tablets are not enabled";
             }
         } else if (cql.with_tablets = off) {
              return create_keyspace_without_tablets();
         } else { // cql.with_tablets is not specified
              if (cfg.enable_tablets) {
                  return create_keyspace_with_tablets();
              } else {
                  return create_keyspace_without_tablets();
              }
         }
     } else { // strategy doesn't support tablets
         if (cql.with_tablets == on) {
             throw "invalid cql parameter";
         } else if (cql.with_tablets == off) {
             return create_keyspace_without_tablets();
         } else { // cql.with_tablets is not specified
             return create_keyspace_without_tablets();
         }
     }

closes: #20088

In order to enable tablets "by default" for NetworkTopologyStrategy
there's explicit check near ks_prop_defs::get_initial_tablets(), that's
not very nice. It needs more care to fix it, e.g. provide feature
service reference to abstract_replication_strategy constructor. But
since ks_prop_defs code already highjacks options specifically for that
strategy type (see prepare_options() helper), it's OK for now.

There's also #20768 misbehavior that's preserved in this patch, but
should be fixed eventually as well.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20779
2024-10-01 10:54:29 +02:00
Botond Dénes
e780a3f168 Merge 'fix regressions of building tests with cmake' from Laszlo Ersek
Fix two recent regressions of the cmake build -- found this time in the test suite.

We (presumably) don't build stable releases (and their tests) with CMake, so backporting these fixes appears unnecessary, even if the regressions have been ported to stable branches.

@xemul @dawmd @tchaikov @tgrabiec @scylladb/scylla-maint

Closes scylladb/scylladb#20854

* github.com:scylladb/scylladb:
  test/boost/bptree_test: fix the CMake build
  test/boost/auth_test: fix the CMake build
2024-10-01 11:14:19 +03:00
Kefu Chai
d484121cc8 github: add a trigger to retrigger clang-tidy with comment
before this change, clang-tidy is triggered by a pull request. but
there are chances that user wants to retrigger it. for jenkins
jobs, user can rebuild a job manually. but for workflow, only the
developers with write permission can retrigger a workflow. this
is not convenient to regular contributors.

so, in this change, another trigger is added, so that user can
trigger the clang-tidy workflow with "/clang-tidy" command.
the syntax is inspired by IRC commands.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20841
2024-10-01 11:10:54 +03:00
Ernest Zaslavsky
5a96549c86 test: add complete_multipart_upload completion tests
A primitive python http server is processing s3 client requests and issues either success or error. A multipart uploader should fail or succeed (with or without retries) depending on aforementioned server response
2024-10-01 09:06:24 +03:00
Ernest Zaslavsky
3be6052786 code: s3 client error handling
Handle the `finalize_upload` possible exception to abort the upload (which also can throw) and show the right error originated from the `finalize_upload`
2024-10-01 09:06:24 +03:00
Ernest Zaslavsky
6be2433b5a code: add response parsing and error handling to the complete_multipart_upload
Instead of ignoring the response for multipart upload completion start parsing it and look for a possible errors in the response body. If the error is found throw an exception
2024-10-01 09:06:24 +03:00
Ernest Zaslavsky
826cf5cd4a code: Introduce AWS errors parsing
Add a simple utility class to parse (possible) error response from AWS S3. Stay as close as possible to aws-sdk-cpp ErrorMarshaler https://github.com/aws/aws-sdk-cpp/blob/main/src/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp logic
Also, add a tester for this new class
2024-10-01 09:06:24 +03:00
Michał Chojnowski
c77d00fd8d index_reader: remove a piece of misguided code involved in single-partition reads
This patch removes a piece of code which, according to the comment,
allows for forwarding the index reader even if it was created as a
single-partition reader.

For single-partition reads, the input_stream
used by the reader is limited to the single index page containing the partition,
since reading the index file past that point would be a waste.
Because of this limit, such an index reader can't be forwarded/advanced.

The dubious piece of code gets around that by unsetting the stream and ensuring
it will be re-created, this time without the limit, if the index is advanced.

But there is no use for this. The idea of a "single-partition reader"
exist as an optimization. It's illegal to forward single-partition readers,
and it doesn't make sense to attempt that. (If there's a need for forwarding,
just don't create a single-partition reader).

I suspect this piece of code was written due to a misunderstanding.
Before the previous patch in this series, when the searched partition key
was the first key in its page, the index reader would scan the preceding
page first, realize it made a mistake, and advance to the next, correct page.
I suspect this piece of code was written to make this work.

But this is, in fact, undesirable. The fact that the index reader was working
like this was a performance bug. In the single-partition case there's
never an inherent reason to start with the wrong page. The index logic can be
corrected to always start with the right page, and that's what the previous
patch in this series does. And with that, there is no need to support advancing
anymore, and the dubious piece of code can be erased.

We also add an assert to emphasize that advancing a single-partition reader is
illegal.
2024-09-30 23:43:36 +02:00
Michał Chojnowski
bc30509523 index_reader: in single-partition reads, don't read more than one page
When looking for a partition key in the index, we scan the index from the
first index page which can possibly contain the key.

In a single-partition read, there is never a reason to read beyond that
page. After the previous patch in this series, it's guaranteed that
the first key in the next page is strictly greater than the searched key.
So if the searched key is greater than the last key in the first page,
then it is neither in the first nor the second page -- it must be absent
from the sstable.

But with the current logic, we read the second index page anyway, and
the realization that the key is absent happens higher in the call chain.

This patch optimizes that inefficiency by immediately returning EOF
if a single-partition read doesn't find the key in the first page.

Returning "end of file" even though we didn't actually go beyond the
end of file is hacky, but I don't see any other non-invasive way
of communicating to the caller that the partition is absent.

Some caller of the index could possibly assume that returning EOF
proves that the searched key is greater than all keys in the sstable.
I don't think any such caller exists today, but it's a possible
place for confusion.

Together with the previous patch in this series, this patch guarantees
that a single-partition read only accesses a single index page.
This fixes a weird secondary performance bug.
Due to some misunderstanding in the logic, when during a single-partition read
we scan two index pages, the second index page is scanned via an input_stream
created without an upper I/O limit, which means that we additionally read
a full read-ahead (currently: 64 kiB) past the second index page for no reason
whatsoever.
After this and the previous patch, a single-partition read always reads exactly one
index page, so the above problem cannot occur.
2024-09-30 23:43:36 +02:00
Michał Chojnowski
6b8b7d962c index_reader: fix unnecessary reads of preceding index pages
When setting the index to position X, we first look for the first summary
entry N such that N >= X. Then we load the index page preceding N and
scan it for the first partition key P such that P >= X.
If there is no such key in this page, then we scan the next page
(starting with N) for such key. (In this case it's always the first key).

For example, assume we have:
summary:  A   C   E
index:    A B C D E F

If we look up "B" in the index, then we first locate summary entry "C",
then we scan the index for B, starting from "A". This is all fine.

But when we look for "C" in the index, then we do the exactly the same
-- we scan the index for "C" starting from "A". This is wasteful, because
we can start scanning from "C".

To avoid this inefficiency, we should be looking for N > X, not N >= X.
This patch fixes that.

In addition, this fixes a second, weirder performance bug.
Due to some misunderstanding in the logic, when during a single-partition read
we scan two index pages, the second index page is scanned via an input_stream
created without an upper I/O limit, which means that we additionally read
a full read-ahead (currently: 64 kiB) past the second index page for no reason
whatsoever. After this patch, a single-partition read always reads exactly one
index page, so the above problem cannot occur.
2024-09-30 23:43:36 +02:00
Avi Kivity
fb8743b2d6 Merge 'sstables: Fix use-after-free on page cache buffer when parsing promoted index entries across pages' from Tomasz Grabiec
This fixes a use-after-free bug when parsing clustering key across
pages.

Also includes a fix for allocating section retry, which is potentially not safe (not in practice yet).

Details of the first problem:

Clustering key index lookup is based on the index file page cache. We
do a binary search within the index, which involves parsing index
blocks touched by the algorithm. Index file pages are 4 KB chunks
which are stored in LSA.

To parse the first key of the block, we reuse clustering_parser, which
is also used when parsing the data file. The parser is stateful and
accepts consecutive chunks as temporary_buffers. The parser is
supposed to keep its state across chunks.

In 93482439, the promoted index cursor was optimized to avoid
fully page copy when parsing index blocks. Instead, parser is
given a temporary_buffer which is a view on the page.

A bit earlier, in b1b5bda, the parser was changed to keep shared
fragments of the buffer passed to the parser in its internal state (across pages)
rather than copy the fragments into a new buffer. This is problematic
when buffers come from page cache because LSA buffers may be moved
around or evicted. So the temporary_buffer which is a view on the LSA
buffer is valid only around the duration of a single consume() call to
the parser.

If the blob which is parsed (e.g. variable-length clustering key
component) spans pages, the fragments stored in the parser may be
invalidated before the component is fully parsed. As a result, the
parsed clustering key may have incorrect component values. This never
causes parsing errors because the "length" field is always parsed from
the current buffer, which is valid, and component parsing will end at
the right place in the next (valid) buffer.

The problematic path for clustering_key parsing is the one which calls
primitive_consumer::read_bytes(), which is called for example for text
components. Fixed-size components are not parsed like this, they store
the intermediate state by copying data.

This may cause incorrect clustering keys to be parsed when doing
binary search in the index, diverting the search to an incorrect
block.

Details of the solution:

We adapt page_view to a temporary_buffer-like API. For this, a new concept
is introduced called ContiguousSharedBuffer. We also change parsers so that
they can be templated on the type of the buffer they work with (page_view vs
temporary_buffer). This way we don't introduce indirection to existing algorithms.

We use page_view instead of temporary_buffer in the promoted
index parser which works with page cache buffers. page_view can be safely
shared via share() and stored across allocating sections. It keeps hold to the
LSA buffer even across allocating sections by the means of cached_file::page_ptr.

Fixes #20766

Closes scylladb/scylladb#20837

* github.com:scylladb/scylladb:
  sstables: bsearch_clustered_cursor: Add trace-level logging
  sstables: bsearch_clustered_cursor: Move definitions out of line
  test, sstables: Verify parsing stability when allocating section is retried
  test, sstables: Verify parsing stability when buffers cross page boundary
  sstables: bsearch_clustered_cursor: Switch parsers to work with page_view
  cached_file: Adapt page_view to ContiguousSharedBuffer
  cached_file: Change meaning of page_view::_size to be relative to _offset rather than page start
  sstables, utils: Allow parsers to work with different buffer types
  sstables: promoted_index_block_parser: Make reset() always bring parser to initial state
  sstables: bsearch_clustered_cursor: Switch read_block_offset() to use the read() method
  sstables: bsearch_clustered_cursor: Fix parsing when allocating section is retried
2024-10-01 00:02:55 +03:00
Calle Wilund
b5d167699c commitlog: Fix buffer_list_bytes not updated correctly
Fixes #20862

With the change in 60af2f3cb2 the bookkeep
for buffer memory was changed subtly, the problem here that we would
shrink buffer size before we after flush use said buffer's size to
decrement the buffer_list_bytes value, previously inc:ed by the full,
allocated size. I.e. we would slowly grow this value instead of adjusting
properly to actual used bytes.

Test included.

Closes scylladb/scylladb#20886
2024-09-30 18:04:00 +03:00
Raphael S. Carvalho
cf58674029 replica: Fix schema change during migration cleanup
During migration cleanup, there's a small window in which the storage
group was stopped but not yet removed from the list. So concurrent
operations traversing the list could work with stopped groups.

During a test which emitted schema changes during migrations,
a failure happened when updating the compaction strategy of a table,
but since the group was stopped, the compaction manager was unable
to find the state for that group.

In order to fix it, we'll skip stopped groups when traversing the
list since they're unused at this stage of migration and going away
soon.

Fixes #20699.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>

Closes scylladb/scylladb#20798
2024-09-30 17:30:38 +03:00
David Garcia
b94fbbf30c docs: update command
Removes the update command from the setup command.

This is required because versions now are not strictly pinned in the poetry.lock file since Sphinx ScyllaDB Theme 1.8.

Closes scylladb/scylladb#20876
2024-09-30 17:06:07 +03:00
Andrei Chekun
cdd0c0b7fc test.py: Do not attach logs for passed tests
To reduce the amount of space needed for reports, this PR will modify logs
attachment in allure, so it will attach logs only for the tests that have
status other than PASSED. To simplify the solution, with the current way it's
not possible to switch off these logs completely.

Closes scylladb/scylladb#20786
2024-09-30 14:55:55 +02:00
Kefu Chai
1c8100d3f1 test/unit: remove unused #include
following headers are no longer used by this compilation unit:

- "utils/managed_ref.hh"
- "test/perf/perf.hh"

this was identified by clang-include-cleaner. As the code is audited,
we can safely remove the #include directive.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20850
2024-09-30 14:46:39 +03:00
Kefu Chai
c3be4a36af test.py: pass "count" to re.sub() with kwarg
since Python 3.13, passing count to `re.sub()` as positional argument
has been deprecated. and when runnint `test.py` with Python 3.13, we
have following warning:

```
/home/kefu/dev/scylladb/./test.py:1477: DeprecationWarning: 'count' is passed as positional argument
  args.tests = set(re.sub(r'.* List configured unit tests\n(.*)\n', r'\1', out, 1, re.DOTALL).split("\n"))
```

see also https://github.com/python/cpython/issues/56166

in order to silence this distracting warning, let's pass
`count` using kwarg.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20859
2024-09-30 13:57:02 +03:00
Kefu Chai
947d9d5a97 scylla_coredump_setup: fix typos in comment
these typos were identified by the codespell workflow.

and fixed a syntax error along the way.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20877
2024-09-30 13:29:34 +03:00
Aleksandra Martyniuk
efc7ad8547 node_ops: fix task_manager_module::get_nodes()
Currently, node ops virtual task gathers its children from all nodes contained
in a sum of service::topology::normal_nodes and service::topology::transition_nodes.
The maps may contain nodes that are down but weren't removed yet. So, if a user
requests the status of a node ops virtual task, the task's attempt to retrieve
its children list may fail with seastar::rpc::closed_error.

Filter out the tasks that are down in node_ops::task_manager_module::get_nodes.

Fixes: #20843.

Closes scylladb/scylladb#20856
2024-09-30 12:32:23 +03:00
Pavel Emelyanov
423b5a3ba7 Merge 'directories: cleanups to silence clang-tidy false alarms' from Kefu Chai
clang-tidy warns:

```
Warning: /__w/scylladb/scylladb/utils/directories.cc:132:52: warning: 'path' used after it was moved [bugprone-use-after-move]
  132 |         bool can_access = co_await file_accessible(path.string(), access_flags::read | access_flags::write | access_flags::execute);
      |                                                    ^
/__w/scylladb/scylladb/utils/directories.cc:121:28: note: move occurred here
  121 |         verification_error(std::move(path), "File not owned by current euid: {}. Owner is: {}", geteuid(), sd.uid);
      |                            ^
```

because we pass `std::move(path)` to `verification_error()`, and "then" use this variable again in this same function.
this is a false alarm, but we could make it very clear to convince this tool that it's safe to do so.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#20875

* github.com:scylladb/scylladb:
  directories: mark verification_error() with [[noreturn]]
  directories: pass const ref of path to verification_error()
2024-09-30 12:02:39 +03:00
Kamil Braun
322efb54c2 Merge 'raft_group0_client: place on a #include diet' from Avi Kivity
Reduce compile time and unnecessary compilations by reducing #include load.

Minor refactoring, no backport.

Closes scylladb/scylladb#20864

* github.com:scylladb/scylladb:
  raft_group0_client: uninclude "raft_group0_registry.hh"
  raft_group_registry: extract raft_timeout
  raft_group0_client: uninclude "mutation/mutation.hh"
  raft_group0_client: uninclude "db/system_keyspace.hh"
  db: system_keyspace: extract auth_version_t into its own header
2024-09-30 10:43:44 +02:00
Kefu Chai
faec71e666 directories: mark verification_error() with [[noreturn]]
this helps the compiler or static analyzers do make the right decision.
for instance, clang-tidy thinks a parameter like `std::move(path)`
could be reused after being moved away. with this attribute, this tool
should be able to tell that this never happens.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-30 12:07:15 +08:00
Kefu Chai
0ef72475fc directories: pass const ref of path to verification_error()
before this change, we pass a `path` to `verification_error()` by
moving away from the original `path`. this works fine in the sense
that it is correct and does not incur potential performance issues.

but clang-tidy considers it a used-after-move, because it cannot tell
`verification_error()` does not return at all, and believes that `path`
could be accessed again after being moved away. so it warns like:

```
Warning: /__w/scylladb/scylladb/utils/directories.cc:132:52: warning: 'path' used after it was moved [bugprone-use-after-move]
  132 |         bool can_access = co_await file_accessible(path.string(), access_flags::read | access_flags::write | access_flags::execute);
      |                                                    ^
/__w/scylladb/scylladb/utils/directories.cc:121:28: note: move occurred here
  121 |         verification_error(std::move(path), "File not owned by current euid: {}. Owner is: {}", geteuid(), sd.uid);
      |                            ^
```

in this change, instead of passing `fs::path` to `verification_error()`,
we pass a `const fs::path&` to this function. because
`verification_error()` is not coroutine, neither does it not pass `path` to
another continuation to be scheduled. so it's perfectly fine to pass
`path` to it.

this change address the false alarms from clang-tidy.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-30 12:07:15 +08:00
Nadav Har'El
64c0540d02 cql-pytest: test a few small materialized views syntax issue
While documenting materialized view in a new document (Refs #16569)
I encountered a few questions and this patch contains tests that
clarify their answer - and can later guarantee that the answer doesn't
unintentionally change in the future. The questions that these tests
answer are:

1. It is not allowed to filter a view on a static column (a comment
   on the test explains why).

2. We already tested that it's not allowed to SELECT a static column into
   a view. Here we add the check that "SELECT *" is also not allowed if
   a static column exists in the base table.

3. We check that CREATE MATERIALIZED VIEW ... WITH COMMENT='..' works.

4. We check that CREATE MATERIALIZED VIEW ... WITH COMPACT STORAGE is
   forbidden.

5. We check that CREATE MATERIALIZED VIEW ... WITH garbage=.. fails
   with a clean InvalidRequest.

All these tests pass on both Scylla and Cassandra.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20873
2024-09-29 21:34:24 +03:00
Nadav Har'El
b008dabee5 test/cql-pytest: fix support for Cassandra 3
One of the design goals of the test/cql-pytest frameworks was to be able
to run these tests against Cassandra. Preferably, we should be able to
run most of the tests against any popular version of Cassandra, including
Cassandra 3. This is admittingly a very old version, but was still maintained
until just a year ago, it's the version that Scylla is most compatible with,
and we can still be curious about how it worked.

Until recently cql-pytest indeed worked on Cassandra 3, but it broke on some
change related to tablet detection that cause our most basic fixture -
"text_keyspace" - to use the Cassandra 4 feature of "auto expand".
This is trivial to fix - we should just use the this_dc fixture that we already
had exactly for this purpose.

Fixes #20781

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20782
2024-09-29 19:36:33 +03:00
Benny Halevy
946f21bbd3 cql-pytest: test_virtual_tables: add test_snapshots_multiple_keyspaces
Test snapshots listing in system.snapshots
using multiple keyspaces and multiple snpashots.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-29 14:36:18 +03:00
Benny Halevy
906de3444b virtual_tables: snapshots: include all snapshots
Use database::get_snapshot_details to get the details
of all snapshots on disk, in particular those of
deleted tables.

Add test_snapshots_dropped_table to test listing
of snapshots of a deleted table.
And harden the existing test cases to use a unique
snapshot tag and to delete it when the test ends.

Fixes scylladb/scylladb#18313

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-29 14:16:11 +03:00
Botond Dénes
a4c41755de Update seastar submodule
* ./seastar 69f88e2f...3c9c2696 (14):
  > core/reactor: don't check AIO block count when they are not needed
  > build: do not print the default value of --c++-standard in help output
  > json_formatter: Add tests for formatter::write
  > Add APIs to get group details and to change ownership of file.
  > scripts/perftune.py: improve a dry-run printout
  > build: drop the workaround for a GCC bug
  > cmake: Depend on libbsd if DPDK depends on it
  > http: clarify the ownership in the router's doxygen comment
  > build: check for P2582R1 support
  > python: introduce a python formatting CI check
  > addr2line: reformat with black
  > scripts: add pyproject.toml
  > json_formatter: Make formatter::write work for std::pair
  > README.md: use the github homepage of Ceph for Crimson

Closes scylladb/scylladb#20836
2024-09-29 13:47:40 +03:00
Avi Kivity
5a470b2bfb Merge 'scylla_raid_setup: configure SELinux file context' from Takuya ASADA
On RHEL9, systemd-coredump fails to coredump on /var/lib/scylla/coredump because the service only have write acess with systemd_coredump_var_lib_t. To make it writable, we need to add file context rule for /var/lib/scylla/coredump, and run restorecon on /var/lib/scylla.

Fixes #19325

Closes scylladb/scylladb#20528

* github.com:scylladb/scylladb:
  scylla_raid_setup: configure SELinux file context
  scylla_coredump_setup: fix SELinux configuration for RHEL9
2024-09-29 12:53:00 +03:00
Avi Kivity
884297ae2e raft_group0_client: uninclude "raft_group0_registry.hh"
Reduce unnecessary recompilations.
2024-09-28 17:25:11 +03:00
Avi Kivity
67cdd0d389 raft_group_registry: extract raft_timeout
It is a vocabulary term that shouldn't need the registry to be visible.
Extract it to a new header.
2024-09-28 17:25:03 +03:00
Avi Kivity
93afc77307 raft_group0_client: uninclude "mutation/mutation.hh"
Lighten the dependency load. Some constructors and destructors
are uninlined to avoid the header depending on the mutation class.
2024-09-28 16:31:53 +03:00
Avi Kivity
5d68efe0bd raft_group0_client: uninclude "db/system_keyspace.hh"
It doesn't need it apart from a forward declaration.

Files that lost necessary includes are adjusted, and some users
of auth_version_t are redirected to the definition outside system_keyspace.
2024-09-28 16:31:53 +03:00
Avi Kivity
df3ee94467 db: system_keyspace: extract auth_version_t into its own header
Users of auth_version_t shouldn't need to include the heavyweight
system_keyspace.hh.
2024-09-28 16:31:50 +03:00
Pavel Emelyanov
c17d353718 Revert "[script/pull_github_pr.sh] Check Gating status before merging"
This reverts commit fac682df7e.

Again, this patch broke maintainer workflows, it needs even more care.
2024-09-27 19:12:18 +03:00
Benny Halevy
23d6b996b8 test/pylib: scylla_cluster: set endpoint_snitch in scylla conf
When `property_file` is provided, we generate a
`cassandra-rackdc.properties` file, but to actually use it,
`endpoint_snitch` must be set to `GossipingPropertyFileSnitch`.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#20730
2024-09-27 16:46:54 +03:00
David Garcia
4900e4b1ac docs: update theme 1.8.1
chore: update README

Closes scylladb/scylladb#20832
2024-09-27 14:35:39 +02:00
Laszlo Ersek
153279dbfa test/boost/bptree_test: fix the CMake build
Commit 4cf4b7d4ef ("test: Move B+tree compactiont test from unit to
boost", 2024-09-24) introduced the first SEASTAR_THREAD_TEST_CASE to
"test/boost/bptree_test.cc" (alongside the prior BOOST_AUTO_TEST_CASEs),
but missed changing the KIND of the test from BOOST to SEASTAR. Therefore
we get a linker failure:

> : && /usr/bin/clang++ -O2 -Xlinker --build-id=sha1 --ld-path=ld.lld
> -dynamic-linker=/.../lib64/ld-linux-x86-64.so.2
> test/boost/CMakeFiles/bptree_test.dir/Dev/bptree_test.cc.o -o
> test/boost/Dev/bptree_test -L$srcdir/idl/absl::headers
> -Wl,-rpath,$srcdir/idl/absl::headers test/lib/Dev/libtest-lib.a
> seastar/Dev/libseastar.a /usr/lib64/libxxhash.so
> /usr/lib64/libboost_unit_test_framework.so.1.83.0  utils/Dev/libutils.a
> -Xlinker --push-state -Xlinker --whole-archive auth/Dev/libscylla_auth.a
> -Xlinker --pop-state  /usr/lib64/libcrypt.so cdc/Dev/libcdc.a
> compaction/Dev/libcompaction.a mutation_writer/Dev/libmutation_writer.a
> -Xlinker --push-state -Xlinker --whole-archive  dht/Dev/libscylla_dht.a
> -Xlinker --pop-state types/Dev/libtypes.a  index/Dev/libindex.a -Xlinker
> --push-state -Xlinker --whole-archive locator/Dev/libscylla_locator.a
> -Xlinker --pop-state message/Dev/libmessage.a  gms/Dev/libgms.a
> sstables/Dev/libsstables.a readers/Dev/libreaders.a
> schema/Dev/libschema.a  -Xlinker --push-state -Xlinker --whole-archive
> tracing/Dev/libscylla_tracing.a  -Xlinker --pop-state
> Dev/libscylla-main.a  -Xlinker --push-state -Xlinker --whole-archive
> Dev/libscylla-zstd.a  -Xlinker --pop-state /usr/lib64/libzstd.so
> abseil/absl/strings/Dev/libabsl_cord.a
> abseil/absl/strings/Dev/libabsl_cordz_info.a
> abseil/absl/strings/Dev/libabsl_cord_internal.a
> abseil/absl/strings/Dev/libabsl_cordz_functions.a
> abseil/absl/strings/Dev/libabsl_cordz_handle.a
> abseil/absl/crc/Dev/libabsl_crc_cord_state.a
> abseil/absl/crc/Dev/libabsl_crc32c.a
> abseil/absl/crc/Dev/libabsl_crc_internal.a
> abseil/absl/crc/Dev/libabsl_crc_cpu_detect.a
> abseil/absl/strings/Dev/libabsl_str_format_internal.a /usr/lib64/libz.so
> service/Dev/libservice.a  node_ops/Dev/libnode_ops.a
> service/Dev/libservice.a  node_ops/Dev/libnode_ops.a  -lsystemd
> raft/Dev/libraft.a  repair/Dev/librepair.a  streaming/Dev/libstreaming.a
> replica/Dev/libreplica.a  db/Dev/libdb.a  mutation/Dev/libmutation.a
> data_dictionary/Dev/libdata_dictionary.a  cql3/Dev/libcql3.a
> transport/Dev/libtransport.a  cql3/Dev/libcql3.a
> transport/Dev/libtransport.a  lang/Dev/liblang.a
> /usr/lib64/liblua-5.4.so  -lm  /usr/lib64/libsnappy.so.1.1.10
> abseil/absl/container/Dev/libabsl_raw_hash_set.a
> abseil/absl/hash/Dev/libabsl_hash.a  abseil/absl/hash/Dev/libabsl_city.a
> abseil/absl/types/Dev/libabsl_bad_variant_access.a
> abseil/absl/hash/Dev/libabsl_low_level_hash.a
> abseil/absl/types/Dev/libabsl_bad_optional_access.a
> abseil/absl/container/Dev/libabsl_hashtablez_sampler.a
> abseil/absl/profiling/Dev/libabsl_exponential_biased.a
> abseil/absl/synchronization/Dev/libabsl_synchronization.a
> abseil/absl/debugging/Dev/libabsl_stacktrace.a
> abseil/absl/synchronization/Dev/libabsl_graphcycles_internal.a
> abseil/absl/synchronization/Dev/libabsl_kernel_timeout_internal.a
> abseil/absl/debugging/Dev/libabsl_symbolize.a
> abseil/absl/debugging/Dev/libabsl_debugging_internal.a
> abseil/absl/base/Dev/libabsl_malloc_internal.a
> abseil/absl/debugging/Dev/libabsl_demangle_internal.a
> abseil/absl/time/Dev/libabsl_time.a
> abseil/absl/strings/Dev/libabsl_strings.a
> abseil/absl/strings/Dev/libabsl_strings_internal.a
> abseil/absl/strings/Dev/libabsl_string_view.a
> abseil/absl/base/Dev/libabsl_throw_delegate.a
> abseil/absl/numeric/Dev/libabsl_int128.a
> abseil/absl/base/Dev/libabsl_base.a
> abseil/absl/base/Dev/libabsl_raw_logging_internal.a
> abseil/absl/base/Dev/libabsl_log_severity.a
> abseil/absl/base/Dev/libabsl_spinlock_wait.a  -lrt
> abseil/absl/time/Dev/libabsl_civil_time.a
> abseil/absl/time/Dev/libabsl_time_zone.a rust/Dev/libwasmtime_bindings.a
> rust/librust_combined.a utils/Dev/libutils.a  seastar/Dev/libseastar.a
> /usr/lib64/libboost_program_options.so  /usr/lib64/libboost_thread.so
> /usr/lib64/libboost_chrono.so  /usr/lib64/libboost_atomic.so
> /usr/lib64/libcares.so  /usr/lib64/libfmt.so.10.2.1 /usr/lib64/liblz4.so
> /usr/lib64/libgnutls.so  -latomic /usr/lib64/libsctp.so
> /usr/lib64/libprotobuf.so /usr/lib64/libyaml-cpp.so
> /usr/lib64/libhwloc.so  /usr/lib64/libnuma.so /usr/lib64/libxxhash.so
> /usr/lib64/libcryptopp.so /usr/lib64/libdeflate.so
> /usr/lib64/libboost_regex.so.1.83.0 /usr/lib64/libicui18n.so
> /usr/lib64/libicuuc.so  -ldl && :
> ld.lld: error: undefined symbol: main
> >>> referenced by
> /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o:(_start)
>
> ld.lld: error: undefined symbol:
> seastar::testing::seastar_test::seastar_test(char const*, char const*,
> int, boost::unit_test::decorator::collector_t&)
> ooo referenced by bptree_test.cc
> >>>
> test/boost/CMakeFiles/bptree_test.dir/Dev/bptree_test.cc.o:(_GLOBAL__sub_I_bptree_test.cc)
> clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Fix the KIND now.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>
2024-09-27 12:21:17 +02:00
Laszlo Ersek
5fa87cb1c6 test/boost/auth_test: fix the CMake build
Commit 78ab1ee8b7 ("test: Add tests for `CREATE ROLE WITH SALTED HASH`",
2024-09-20) made test/boost/auth_test dependent on cql3, but didn't encode
the dependency in "CMakeLists.txt":

> FAILED:
> test/boost/CMakeFiles/auth_test.dir/RelWithDebInfo/auth_test.cc.o
> /usr/bin/clang++ -DBOOST_ALL_DYN_LINK -DFMT_SHARED
> -DSCYLLA_BUILD_MODE=release -DSEASTAR_API_LEVEL=7
> -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT
> -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SSTRING
> -DSEASTAR_TESTING_MAIN -DXXH_PRIVATE_API
> -DCMAKE_INTDIR=\"RelWithDebInfo\" -I$srcdir -I$srcdir/build/gen
> -I$srcdir/seastar/include -I$srcdir/build/seastar/gen/include
> -I$srcdir/build/seastar/gen/src -isystem $srcdir/abseil -isystem
> $srcdir/build/rust -ffunction-sections -fdata-sections -O3 -g -gz
> -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra
> -Wno-error=deprecated-declarations -Wimplicit-fallthrough
> -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags
> -Wno-missing-field-initializers -Wno-overloaded-virtual
> -Wno-unsupported-friend -Wno-enum-constexpr-conversion
> -Wno-unused-parameter -ffile-prefix-map=$srcdir/build=. -march=westmere
> -Xclang -fexperimental-assignment-tracking=disabled -mllvm
> -inline-threshold=2500 -fno-slp-vectorize -Werror=unused-result -MD -MT
> test/boost/CMakeFiles/auth_test.dir/RelWithDebInfo/auth_test.cc.o -MF
> test/boost/CMakeFiles/auth_test.dir/RelWithDebInfo/auth_test.cc.o.d -o
> test/boost/CMakeFiles/auth_test.dir/RelWithDebInfo/auth_test.cc.o -c
> $srcdir/test/boost/auth_test.cc
> $srcdir/test/boost/auth_test.cc:22:10: fatal error: 'cql3/CqlParser.hpp'
> file not found
>    22 | #include "cql3/CqlParser.hpp"
>       |          ^~~~~~~~~~~~~~~~~~~~
> 1 error generated.

State the dependency now.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>
2024-09-27 11:38:03 +02:00
Tomasz Grabiec
b5ae7da9d2 sstables: bsearch_clustered_cursor: Add trace-level logging 2024-09-27 01:25:15 +02:00
Tomasz Grabiec
8e54ecd38e sstables: bsearch_clustered_cursor: Move definitions out of line
In order to later use the formatter for the inner class
promoted_index_block, which is defined out of line after
cached_promoted_index class definition.
2024-09-27 01:25:15 +02:00
Tomasz Grabiec
0279ac5faa test, sstables: Verify parsing stability when allocating section is retried 2024-09-27 01:25:15 +02:00
Tomasz Grabiec
c09fa0cb98 test, sstables: Verify parsing stability when buffers cross page boundary 2024-09-27 01:25:15 +02:00
Tomasz Grabiec
7670ee701a sstables: bsearch_clustered_cursor: Switch parsers to work with page_view
This fixes a use-after-free bug when parsing clustering key across
pages.

Clustering key index lookup is based on the index file page cache. We
do a binary search within the index, which involves parsing index
blocks touched by the algorithm. Index file pages are 4 KB chunks
which are stored in LSA.

To parse the first key of the block, we reuse clustering_parser, which
is also used when parsing the data file. The parser is stateful and
accepts consecutive chunks as temporary_buffers. The parser is
supposed to keep its state across chunks.

In b1b5bda, the parser was changed to keep shared fragments of the
buffer passed to the parser in its internal state (across pages)
rather than copy the fragments into a new buffer. This is problematic
when buffers come from page cache because LSA buffers may be moved
around or evicted. So the temporary_buffer which is a view on the LSA
buffer is valid only around the duration of a single consume() call to
the parser.

If the blob which is parsed (e.g. variable-length clustering key
component) spans pages, the fragments stored in the parser may be
invalidated before the component is fully parsed. As a result, the
parsed clustering key may have incorrect component values. This never
causes parsing errors because the "length" field is always parsed from
the current buffer, which is valid, and component parsing will end at
the right place in the next (valid) buffer.

The problematic path for clustering_key parsing is the one which calls
primitive_consumer::read_bytes(), which is called for example for text
components. Fixed-size components are not parsed like this, they store
the intermediate state by copying data.

This may cause incorrect clustering keys to be parsed when doing
binary search in the index, diverting the search to an incorrect
block.

The solution is to use page_view instead of temporary_buffer, which
can be safely shared via share() and stored across allocating
section. The page_view maintains its hold to the LSA buffer even
across allocating sections.

Fixes #20766
2024-09-27 01:25:15 +02:00
Tomasz Grabiec
c15145b71d cached_file: Adapt page_view to ContiguousSharedBuffer 2024-09-27 01:25:15 +02:00
Tomasz Grabiec
29498a97ae cached_file: Change meaning of page_view::_size to be relative to _offset rather than page start
Will be easier to implement ContiguousSharedBuffer API as the buffer
size will be equal to _size.
2024-09-27 01:25:15 +02:00
Tomasz Grabiec
c0fa49bab5 sstables, utils: Allow parsers to work with different buffer types
Currently, parsers work with temporary_buffer<char>. This is unsafe
when invoked by bsearch_clustered_cursor, which reuses some of the
parsers, and passes temporary_buffer<char> which is a view onto LSA
buffer which comes from the index file page cache. This view is stable
only around consume(). If parsing requires more than one page, it will
continue with a different input buffer. The old buffer will be
invalid, and it's unsafe for the parser to store and access
it. Unfortunetly, the temporary_buffer API allows sharing the buffer
via the share() method, which shares the underlying memory area. This
is not correct when the underlying is managed by LSA, because storage
may move. Parser uses this sharing when parsing blobs, e.g. clustering
key components. When parsing resumes in the next page, parser will try
to access the stored shared buffers pointing to the previous page,
which may result in use-after-free on the memory area.

In prearation for fixing the problem, parametrize parsers to work with
different kinds of buffers. This will allow us to instantiate them
with a buffer kind which supports sharing of LSA buffers properly in a
safe way.

It's not purely mechanical work. Some parts of the parsing state
machine still works with temporary_buffer<char>, and allocate buffers
internally, when reading into linearized destination buffer. They used
to store this destination in _read_bytes vector, same field which is
used to store the shared buffers. Now it's not possible, since shared
buffer type may be different than temporary_buffer<char>. So those
paths were changed to use a new field: _read_bytes_buf.
2024-09-27 01:24:54 +02:00
Tomasz Grabiec
93bfaf4282 sstables: promoted_index_block_parser: Make reset() always bring parser to initial state
When reset() is done due to allocating section retry, it can be
theoretically in an arbitrary point. So we should not assume that it
finished parsing and state was reset by previous parsing. We should
reset all the fields.
2024-09-27 01:23:43 +02:00
Tomasz Grabiec
ac823b1050 sstables: bsearch_clustered_cursor: Switch read_block_offset() to use the read() method
To unify logic which handles allocating section retry, and thus
improve safety.
2024-09-27 01:22:35 +02:00
Nadav Har'El
9af43dcd06 Merge 'Move collections stress tests from unit/ to boost/' from Pavel Emelyanov
Collection stress tests include testing of B- B+- and radix trees, and those tests live in unit/ suite. There are also small corner-case tests for those collections in boost/ suite. There's an attempt to get rid of unit suite in favor of boost one, and this PR moves the collections stress testing from unit suite into their boost counterparts.

refs: scylladb/qa-tasks#1655

Closes scylladb/scylladb#20475

* github.com:scylladb/scylladb:
  test: Move other collection-testing headers from unit to boost
  test: Move stress-collecton header from unit to boost
  test: Move B+tree compactiont test from unit to boost
  test: Move radix tree compactiont test from unit to boost
  test: Move B-tree compactiont test from unit to boost
  test: Move radix tree stress test from unit to boost
  test: Move B-tree stress test from unit to boost
  test: Move b+tree stress test from unit to boost
  test: Add bool in_thread argument to stress_collection function
2024-09-26 18:11:23 +03:00
Botond Dénes
9fe64b5d70 Merge 'Remove datadir string from table::config' from Pavel Emelyanov
The datadir keeps path to directory where local sstables can be. The very same information is now kept in table's storage options (#20542). This set fixes the remaining places that still use table::config::datadir and table::dir() and removes the datadir field.

Closes scylladb/scylladb#20675

* github.com:scylladb/scylladb:
  treewide: Remove table::config::datadir
  distributed_loader: Print storage options, not datadir
  data_dictionary: Add formatter for storage_options
  test: Construct table_for_tests with table storage options
  test: Generalize pair of make_table_for_tests helpers
  tests: Add helper to get snapshot directory from storage options
  table: snapshot_exists: Get directory from storage options
  table: snapshot_on_all_shards: Get directory from storage options
2024-09-26 15:26:45 +03:00
Kamil Braun
9224e48d6b Merge 'Populate raft address map from gossiper on raft configuration change' from Gleb Natapov
For each new node added to the raft config populate its ID to IP mapping
in raft address map from the gossiper. The mapping may have expired if a
node is added to the raft configuration long after it first appears in
the gossiper.

Fixes scylladb/scylladb#20600

Backport to all supported versions since the bug may cause bootstrapping failure.

Closes scylladb/scylladb#20601

* github.com:scylladb/scylladb:
  test: extend existing test to check that a joining node can map addresses of all pre-existing nodes during join
  group0: make sure that address map has an entry for each new node in the raft configuration
2024-09-26 12:41:25 +02:00
Tomasz Grabiec
8aca93b3ec sstables: bsearch_clustered_cursor: Fix parsing when allocating section is retried
Parser's state was not reset when allocating section was retried.

This doesn't cause problems in practice, because reserves are enough
to cover allocation demands of parsing clustering keys, which are at
most 64K in size. But it's still potentially unsafe and needs fixing.
2024-09-26 12:34:41 +02:00
Laszlo Ersek
ed91d35171 sstables: coroutinize sstable::load()
Best viewed with "git show -b -W".

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>

Closes scylladb/scylladb#20822
2024-09-26 13:26:22 +03:00
Lakshmi Narayanan Sreethar
7beea03196 build: cmake: link cql3 library to the service library
After commit d16ea0af, compiling the server using cmake fails with the
following error :

```
FAILED: service/CMakeFiles/service.dir/Dev/qos/service_level_controller.cc.o
...
/home/Scylla/scylladb/cql3/util.hh:21:10: fatal error: 'cql3/CqlParser.hpp' file not found
   21 | #include "cql3/CqlParser.hpp"
      |          ^~~~~~~~~~~~~~~~~~~~
1 error generated.
```

Fix it by linking the cql3 to the service library.

Closes scylladb/scylladb#20805
2024-09-26 09:17:30 +03:00
Yaron Kaikov
fac682df7e [script/pull_github_pr.sh] Check Gating status before merging
Maintainers use scripts/pull_github_pr.sh from scylladb.git when merging PRs and before pushing to the next. We want to prevent merges from piling up on top of unstable builds. This change will check Gating's current status and notify the maintainers

Related to scylladb/scylla-pkg#3644

Closes scylladb/scylladb#20742
2024-09-26 08:44:06 +03:00
Nadav Har'El
7715abfc56 Merge 'Alternator store ProvisionedThroughput' from Amnon Heiman
When users create a table using the Alternator API, they can decide if the billing is PROVISIONED of PAY_PER_REQUEST.
If the billing is set to PROVISIONED, they need to set the ProvisionedThroughput ReadCapacityUnits (RCU) and WriteCapacityUnits (WCU).

This series adds support for getting and setting the ProvisionedThroughput. The values will be stored as table extension tags.
Following how TTL is stored within the Alternator, we will use ```system:rcu_attribute``` and ```system:wcu_attribute``` for the labels.

The series adds a test that sets ProvisionedThroughput and validates that it gets the value back. It was tested with both Alternator and AWS.

This series is part of the effort to monitor, limit, and bill Alternator operations.

New code, no need to backport.

Closes scylladb/scylladb#20056

* github.com:scylladb/scylladb:
  docs/alternator/compatibility.md: explain the consumed capacity provisioned
  Add test/alternator/test_provisioned_throughput.py
  test/alternator/util.py: Allow override BillingMode
  alternator/executor.cc: Store ProvisionedThroughput
2024-09-26 01:23:17 +03:00
Avi Kivity
357168114b cql3: statement_restrictions: use the evaluator to calculate token for constrained global index query
A global index has a primary key of the form

   (indexed_column, token, partition_key_column..., clustering_key_column...)

The primary key columns are used to point at the base table row, and
the token (computed as token(partition_key_column...) is used to maintain
sort order.

The query planner has an optimization: if the partition key is fully
constrained to a unique value, then we compute the token from the partition
key and use that to seek directly into the clustering row range for
that base table partition. If the clustering key is also partially
constrained, it is used to refine the index clustering key.

Currently, this optimization is implemented as a hack: the partition key
is extracted from the prepared statement + query options in
get_global_index_token_clustering_ranges(), then used to calculate
the token, which is then substituted in the expression passed to
get_single_column_clustering_bounds() (the expression is shared across
all running queries, so this is quite dangerous).

We simplify the whole thing:

 - Let prepare_index_global() recognize that if the partition key is not
   fully constrained, then there is no way that we'll be able to compute
   the token (as it needs all partition key columns). Since the token
   is the first clustering key column of the index table, we can truncate
   it to length zero and bail out.

 - Otherwise, the partition key is fully constrained. We refactor the
   predicate (pk1 = :a AND pk2 = :b) to (pk1, pk2) := (:a, :b). We then
   pass expressions representing the partition key to the token function,
   ending up with token(:a, :b). We then substitute this expression into
   (*_idx_tbl_ck_prefix)[0], which computes the first clustering key
   column for the index table.

 - Remove the runtime component in get_global_index_clustering_ranges().
   Note this include the early return if the partition key wasn't fully
   constrained (though the comment only mentions over-constraining), and
   the token computation, which is now done by evaluate().

Closes scylladb/scylladb#20733
2024-09-25 22:48:16 +03:00
Yaron Kaikov
d164fd45bc install-dependencies.sh: update node_exporter to 1.8.2
Update node_exporter to 1.8.2

Fixes: #18493

Closes scylladb/scylladb#20254

[avi: regenerate frozen toolchain, with new clang in

  https://devpkg.scylladb.com/clang/clang-18.1.8-Fedora-40-aarch64.tar.gz
  https://devpkg.scylladb.com/clang/clang-18.1.8-Fedora-40-x86_64.tar.gz

new clang regenerated due to new packaging format (f6fe4d9e73) and
some other minor changes.]
2024-09-25 18:42:25 +03:00
Gleb Natapov
9e4cd32096 test: extend existing test to check that a joining node can map addresses of all pre-existing nodes during join 2024-09-25 17:10:09 +03:00
Kamil Braun
7d8f1d251a Merge 'Mark node as being replaced earlier' from Gleb Natapov
Before 17f4a151ce the node was marked as
been replaced in join_group0 state, before it actually joins the group0,
so by the time it actually joins and starts transferring snapshot/log no
traffic is sent to it. The commit changed this to mark the node as
being replaced after the snapshot/log is already transferred so we can
get the traffic to the node while it sill did not caught up with a
leader and this may causes problems since the state is not complete.
Mark the node as being replaced earlier, but still add the new node to
the topology later as the commit above intended.

Fixes: scylladb/scylladb#20629

Need to be backported since this is a regression

Closes scylladb/scylladb#20743

* github.com:scylladb/scylladb:
  test: amend test_replace_reuse_ip test to check that there is no stale writes after snapshot transfer starts
  topology coordinator:: mark node as being replaced earlier
  topology coordinator: do metadata barrier before calling finish_accepting_node() during replace
2024-09-25 15:46:12 +02:00
Kamil Braun
09c68c0731 service: raft: fix rpc error message
What it called "leader" is actually the destination of the RPC.

Trivial fix, should be backported to all affected versions.

Closes scylladb/scylladb#20789
2024-09-25 15:46:37 +03:00
Kefu Chai
d5b348460f config: do not provide default value for set_value() and friends
before this change, `config_file::set_value()` and
`config_file::set_value_on_all_shards()` provide default value for
`config_source`. but the default value is never used -- we alway
specify the `source_source` when calling `set_value_on_all_shards()`.

so in hope to improve the readability, the default value is removed.
so, for example, one can figure out when `config_source::Internal` is
used with less efforts. despite that `config_file::set_value()` is not
used in the tree. for the sake of completeness, its default value is
also dropped.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20728
2024-09-25 15:45:42 +03:00
Anna Stuchlik
8145109120 doc: add OS support for version 6.2
This commit adds the OS support for version 6.2.
In addition, it removes support for 6.0, as the policy is only to include
information for the supported versions, i.e., the two latest versions.

Fixes https://github.com/scylladb/scylladb/issues/20804

Closes scylladb/scylladb#20806
2024-09-25 15:39:23 +03:00
Pavel Emelyanov
ae76481444 Merge 'treewide: add "table" parameter to "backup" API ' from Kefu Chai
with this parameter, "backup" API can backup the given table, this
enables it to be a drop-in replacement of existing rclone API used by
scylla manager.

Fixes https://github.com/scylladb/scylladb/issues/20636

---

this change is a part of the efforts to bring the native backup/restore to scylla, no need to backprt.

Closes scylladb/scylladb#20661

* github.com:scylladb/scylladb:
  backup_task: fix the indent
  treewide: add "table" parameter to "backup" API
2024-09-25 10:53:38 +03:00
Takuya ASADA
f6fe4d9e73 toolchain: fix broken INSTALL_FROM mode
We found that --clang-build-mode INSTALL_FROM tries to rebuild clang
even we use an archive of prebuilt image.
Seems like it is because ninja detected changes on standard library
headers, which updated when we build new frozen toolchain container
image.

To avoid such unnecessary rebuild, we should stop archive whole clang
build directory, we should archive install image instead.
To do so, we can use
"DESTDIR=<sysroot dir> ninja install-distribution-stripped", and archive
sysroot dir as clang archive.

Fixes #20421

Closes scylladb/scylladb#20422
2024-09-25 10:48:56 +03:00
Anna Stuchlik
da8047a834 doc: add an intro to the Features page
This commit modifies the Features page in the following way:

- It adds a short introduction and descriptions to each listed feature.
- It hides the ToC (required to control and modify the information on the page,
  e.g., to add descriptions, have full control over what is displayed, etc.)
- Removes the info about Enterprise features (following the request not to include
  Enterprise info in the OSS docs)

Fixes https://github.com/scylladb/scylladb/issues/20617
Blocks https://github.com/scylladb/scylla-enterprise/pull/4711

Closes scylladb/scylladb#20635
2024-09-25 08:50:21 +03:00
Aleksandra Martyniuk
3195ebd04e node_ops: make node_ops tasks type more human-friendly
Currently, node ops tasks type is retrieved from topology_request
without any change. Use respective node operation name instead.

Closes scylladb/scylladb#20671
2024-09-25 08:49:34 +03:00
Kamil Braun
69b4769418 test: fix topology_custom/test_raft_recovery_stuck flakiness
The test performs consecutive schema changes in RECOVERY mode. The
second change relies on the first. However the driver might route the
changes to different servers and we don't have group 0 to guarantee
linearizability. We must rely on the first change coordinator to push
the schema mutations to other servers before returning, but that only
happens when it sees other servers as alive when doing the schema
change. It wasn't guaranteed in the test. Fix this.

Fixes scylladb/scylladb#20791

Should be backported to all branches containing this test to reduce
flakiness.

Closes scylladb/scylladb#20792
2024-09-25 08:45:37 +03:00
Kefu Chai
54858b8242 backup_task: fix the indent
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-25 09:11:26 +08:00
Kefu Chai
d663b6c13b treewide: add "table" parameter to "backup" API
with this parameter, "backup" API can backup the given table, this
enables it to be a drop-in replacement of existing rclone API used by
scylla manager.

in this change:

* api/storage_service: add "table" parameter to "backup" API.
* snapshot_ctl: compose the full path of the snapshot directory in
  `snapshot_ctl::start_backup`. since we have all the information
  for composing the snapshot directory, and what the `backup_task_impl`
  class is interested is but the snapshot directory, we just pass
  the path to it instead the individual components of the directory.
* backup_task_impl: instead of scan the whole keyspace recursively,
  only scan the specified snapshot directory.

Fixes scylladb/scylladb#20636
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-25 09:11:26 +08:00
Avi Kivity
d16ea0afd6 Merge 'cql3: Extend DESC SCHEMA by auth and service levels' from Dawid Mędrek
Auth has been managed via Raft since Scylla 6.0. Restoring data
following the usual procedure (1) is error-prone and so a safer
method must have been designed and implemented. That's what
happens in this PR.

We want to extend `DESC SCHEMA` by auth and service levels
to provide a safe way to backup and restore those two components.
To realize that, we change the meaning of `DESC SCHEMA WITH INTERNALS`
and add a new "tier": `DESC SCHEMA WITH INTERNALS AND PASSWORDS`.

* `DESC SCHEMA` -- no change, i.e. the statement describes the current
  schema items such as keyspaces, tables, views, UDTs, etc.
* `DESC SCHEMA WITH INTERNALS` -- does the same as the previous tier
  and also describes auth and service levels. No information about
  passwords is returned.
* `DESC SCHEMA WITH INTERNALS AND PASSWORDS` -- does the same
  as the previous tier and also includes information about the salted
  hashes corresponding to the passwords of roles.

To restore existing roles, we extend the `CREATE ROLE` statement
by allowing to use the option `WITH SALTED HASH = '[...]'`.

---

Implementation strategy:

* Add missing things/adjust existing ones that will be used later.
* Implement creating a role with salted hash.
* Add tests for creating a role with salted hash.
* Prepare for implementing describe functionality of auth and service levels.
* Implement describe functionality for elements of auth and service levels.
* Extend the grammar.
* Add tests for describe auth and service levels.
* Add/update documentation.

---

(1): https://opensource.docs.scylladb.com/stable/operating-scylla/procedures/backup-restore/restore.html
In case the link stops working, restoring a schema was realised
by managing raw files on disk.

Fixes scylladb/scylladb#18750
Fixes scylladb/scylladb#18751
Fixes scylladb/scylladb#20711

Closes scylladb/scylladb#20168

* github.com:scylladb/scylladb:
  docs: Update user documentation for backup and restore
  docs/dev: Add documentation for DESC SCHEMA
  test: Add tests for describing auth and service levels
  cql3/functions/user_function: Remove newline character before and after UDF body
  cql3: Implement DESCRIBE SCHEMA WITH INTERNALS AND PASSWORDS
  auth: Implement describing auth
  auth/authenticator: Add member functions for querying password hash
  service/qos/service_level_controller: Describe service levels
  data_dictionary: Remove keyspace_element.hh
  treewide: Start using new overloads of describe
  treewide: Fix indentation in describe functions
  treewide: Return create statement optionally in describe functions
  treewide: Add new describe overloads to implementations of data_dictionary::keyspace_element
  treewide: Start using schema::ks_name() instead of schema::keyspace_name()
  cql3: Refactor `description`
  cql3: Move description to dedicated files
  test: Add tests for `CREATE ROLE WITH SALTED HASH`
  cql3/statements: Restrict CREATE ROLE WITH SALTED HASH
  auth: Allow for creating roles with SALTED HASH
  types: Introduce a function `cql3_type_name_without_frozen()`
  cql3/util: Accept std::string_view rather than const sstring&
2024-09-24 21:44:32 +03:00
Tomasz Grabiec
bca8258150 Merge 'tablet: Fix single-sstable split when attaching new unsplit sstables' from Raphael "Raph" Carvalho
To fix a race between split and repair here c1de4859d8, a new sstable
  generated during streaming can be split before being attached to the sstable
  set. That's to prevent an unsplit sstable from reaching the set after the
  tablet map is resized.

  So we can think this split is an extension of the sstable writer. A failure
  during split means the new sstable won't be added. Also, the duration of split
  is also adding to the time erm is held. For example, repair writer will only
  release its erm once the split sstable is added into the set.

  This single-sstable split is going through run_custom_job(), which serializes
  with other maintenance tasks. That was a terrible decision, since the split may
  have to wait for ongoing maintenance task to finish, which means holding erm
  for longer. Additionally, if split monitor decides to run split on the entire
  compaction group, it can cause single-sstable split to be aborted since the
  former wants to select all sstables, propagating a failure to the streaming
  writer.
  That results in new sstable being leaked and may cause problems on restart,
  since the underlying tablet may have moved elsewhere or multiple splits may
  have happened. We have some fragility today in cleaning up leaked sstables on
  streaming failure, but this single-sstable split made it worse since the
  failure can happen during normal operation, when there's e.g. no I/O error.

  It makes sense to kill run_custom_job() usage, since the single-sstable split
  is offline and an extension of sstable writing, therefore it makes no sense to
  serialize with maintenance tasks. It must also inherit the sched group of the
  process writing the new sstable. The inheritance happens today, but is fragile.

  Fixes #20626.

Closes scylladb/scylladb#20737

* github.com:scylladb/scylladb:
  tablet: Fix single-sstable split when attaching new unsplit sstables
  replica: Fix tablet split execute after restart
2024-09-24 19:46:11 +02:00
Abhinav
36d68ec955 raft topology: add error for removal of non-normal nodes
In the current scenario, We check if a node being removed is normal
on the node initiating the removenode request. However, we don't have a
similar check on the topology coordinator. The node being removed could be
normal when we initiate the request, but it doesn't have to be normal when
the topology coordinator starts handling the request.
For example, the topology coordinator could have removed this node while handling
another removenode request that was added to the request queue earlier.

This commit intends to fix this issue by adding more checks in the enqueuing phase
and return errors for duplicate requests for node removal.

This PR fixes a bug. Hence we need to backport it.

Fixes: scylladb/scylladb#20271

Closes scylladb/scylladb#20500
2024-09-24 16:11:19 +02:00
Botond Dénes
24ac408a08 Revert "[script/pull_github_pr.sh] Check Gating status before merging"
This reverts commit ec0bb42b45.

This patch broke maintainer workflows, it needs more work before it can
land.
2024-09-24 16:53:02 +03:00
Artsiom Mishuta
c07306582b test.py: deselect remove_data_dir_of_dead_node event
Deselect remove_data_dir_of_dead_node event from test_random_failures
due to issue scylladb/scylladb#20751

Closes scylladb/scylladb#20790
2024-09-24 14:49:00 +02:00
Dawid Mędrek
1ef51be1d7 docs: Update user documentation for backup and restore
We update the relevant articles addressing backing-up
and restoring the schema by specifying that the user
performing it must be a superuser. We also update
the required version of cqlsh.

Additionally, we add an article covering the fundamental
information on `DESCRIBE SCHEMA`.
2024-09-24 14:21:15 +02:00
Dawid Mędrek
5e1d7f109a docs/dev: Add documentation for DESC SCHEMA
We add documentation for developers addressing
`DESCRIBE SCHEMA`. It covers the following aspects
of it:

* motivation,
* synopsis of the solution,
* implementation of the solution,

as well as a few subsections explaining the details:

* restoring process and its side effects,
* restoring roles with passwords,
* list of statements generated by `DESC SCHEMA`
  with examples,
* implementation details.
2024-09-24 14:18:01 +02:00
Dawid Mędrek
d42f1604ad test: Add tests for describing auth and service levels
We add tests verifying the following features work correctly:

* describing auth: roles, role grants, granting permissions on
  resources,
* describing service levels: creating them and attaching to roles.
2024-09-24 14:18:01 +02:00
Dawid Mędrek
10d13f541b cql3/functions/user_function: Remove newline character before and after UDF body
We remove newline characters that are printed before and after
a UDF's body. This way, we want to keep the create statement
as close to what was actually provided as possible. Although
there should be no semantic differences with or without the
newline characters, it's a lot more convenient in testing when
they're not present.

Fixes scylladb/scylladb#20711
2024-09-24 14:18:01 +02:00
Dawid Mędrek
be851cef10 cql3: Implement DESCRIBE SCHEMA WITH INTERNALS AND PASSWORDS
When executing `DESC SCHEMA WITH INTERNALS`, Scylla now also returns
statements that can be used to recreate service levels and restore
the state of auth. That encompasses granting roles and permissions
as well as attaching service levels to roles.

If the additional parameter `WITH PASSWORDS` is provided,
the statements corresponding to recreating roles in the system
will also contain the stored salted hashes.
2024-09-24 14:18:01 +02:00
Dawid Mędrek
2a27d4b4d6 auth: Implement describing auth
We introduce a function `describe_auth()` in `auth::service`
responsible for producing a sequence of descriptions whose
corresponding CQL statement can be used to restore the state
of auth.
2024-09-24 14:17:58 +02:00
Nadav Har'El
b70ab7bd64 test/boost: add README.md
Add a README.md in test/boost, giving a short introduction to what this
directory is and what kind of tests it contains, and how to run individual
tests.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20550
2024-09-24 15:16:55 +03:00
Pavel Emelyanov
39dc340424 test: Move other collection-testing headers from unit to boost
Simple and straightforward.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
f0d60c2b4d test: Move stress-collecton header from unit to boost
Now all its users are in boost suite. Once moved, the
stress_collection() function no longer runs in seastar thread, and the
in_thread argument is removed while the function is moved.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
4cf4b7d4ef test: Move B+tree compactiont test from unit to boost
This time the boost test needs to stop being pure-boost test, since
bptree compaction test case needs to run in seastar thread. Other
collection tests are already such, not bptree_test joins the party.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
d1f727669c test: Move radix tree compactiont test from unit to boost
No surprises here, just move the code and hard-code default args.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
bdcf965318 test: Move B-tree compactiont test from unit to boost
This test must run in seastar thread, so put it in seastar-thread test
case, fortunately btree test allows that. Just like its stress peer,
this test also has two invocations from suite, so make it two distinct
test cases as well.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
328b5b71d7 test: Move radix tree stress test from unit to boost
Just move the code. Test "scale" is also taken from default unit test
arguments.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:13 +03:00
Pavel Emelyanov
023cc99514 test: Move B-tree stress test from unit to boost
This also moves the code, but takes into account the stress test had two
invovations with suite options -- small and large. Inherit both with two
distinct test cases.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:42:12 +03:00
Pavel Emelyanov
72cb835c1e test: Move b+tree stress test from unit to boost
Just move the code. And hard-code the "scale" (i.e. -- number of keys
and iterations) from default arguments of the unit test.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:31:33 +03:00
Pavel Emelyanov
f0526bf6a4 test: Add bool in_thread argument to stress_collection function
This code is going to be shared between seastar thread and boost tests,
temporarily. So not to yield in pure boost test, add the switch. It will
be removed really soon.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-24 13:31:33 +03:00
Tomasz Grabiec
bd6eeb4730 Merge 'Separate schema merging logic' from Marcin Maliszkiewicz
This patch doesn't yet change how schema merging works but it prepares the ground for it by simplifying the code and separating merging logic into its own unit.

It consists of:
- minor cleanups of unused code
- moving code into separate file
- simplifying merge_keyspaces code

More detailed explanation in per commit messages.

Relates scylladb/scylladb#19153

Closes scylladb/scylladb#19687

* github.com:scylladb/scylladb:
  db: schema_applier: simplify merge_keyspaces function
  db: schema_applier: remove unnecessary read in merge_keyspaces
  db: schema_tables: move scylla specific code into create keyspace function
  db: move schema merging code into a separate unit
  db: schema_tables: export some schema management functions
  replica: remove unused table_selector forward declaration
  db: remove unused flush arg from do_merge_schema func
  db: remove unused read_arg_values function
2024-09-24 11:43:06 +02:00
Michał Jadwiszczak
d7945eea2a docs/dev/service_levels: replace unspecified workload type with NULL
`unspecified` workload type is an internal value and it's not exposed to
user via CQL.
Default value for workload type from user's perspective is `NULL`.

Fixes scylladb/scylladb#20780
2024-09-24 11:43:29 +03:00
Yaron Kaikov
ec0bb42b45 [script/pull_github_pr.sh] Check Gating status before merging
Maintainers use scripts/pull_github_pr.sh from scylladb.git when merging PRs and before pushing to the next. We want to prevent merges from piling up on top of unstable builds. This change will check Gating's current status and notify the maintainers

Related to https://github.com/scylladb/scylla-pkg/issues/3644

Closes scylladb/scylladb#20742
2024-09-24 08:39:47 +03:00
Pavel Emelyanov
9fd8eba3ec proxy: Don't keep truncate timeout as optional argument
Because it is never such -- the only caller of truncate_blocking()
always knows the timeout it want this method to use.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20620
2024-09-24 08:25:54 +03:00
Pavel Emelyanov
d64529f370 Merge 'sstables/sstables.hh: Remove unused forward declarations' from Nikos Dragazis
Code cleanup, no backport needed.

Closes scylladb/scylladb#20767

* github.com:scylladb/scylladb:
  sstables: Remove forward declaration for random_access_reader
  sstables: Remove forward declaration for metadata_collector
  sstables: Remove forward declaration for sstables_manager
  sstables: Remove forward declaration for sstable_writer_v2
  sstables: Remove forward declaration for key
2024-09-24 07:44:56 +03:00
Andrei Chekun
da2397005b test.py: Remount cgroup before changing files ownership
Change order of functions: firstly remount, then change ownership for
cgroup. It was not failing before because with privileged mode, it will
mount cgroups as RW, but it's better to have this check if behavior will
change.

Closes scylladb/scylladb#20676
2024-09-24 07:27:24 +03:00
Kefu Chai
657ea95f4c main: coroutinize read_config()
for better readability.

read_config() is not on the critical path, so the performance
degradation caused by C++20 couroutine is neglectable.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20694
2024-09-24 06:30:34 +03:00
Gleb Natapov
1213f02a5a test: skip test_lwt_semaphore::test_cas_semaphore in aarch64 debug mode
The test configures write timeout to much smaller value to make the test
run faster since for some writes sleep is inserted to hit the timeout,
but it makes aarch64 debug flaky since timeout happens when it should
not because of a natural slowness.

Fixes scylladb/scylladb#20515

Closes scylladb/scylladb#20744
2024-09-23 20:46:55 +02:00
Avi Kivity
5c329e3db0 Merge 'Put sstables::test class on a diet' from Pavel Emelyanov
This one is aimed at giving tests the ability to call private methods of class sstable. Some of the wrappers in the test class wrap public methods and can be removed.

Closes scylladb/scylladb#20614

* github.com:scylladb/scylladb:
  test: Remove sstables::test::binary_search()
  test: Remove sstables::test::move_summary()
  test: Remove sstables::test::read_toc()
  test: Remove sstables::test::get_summary()
  test: Remove sstables::test::get_statistics()
  test: Remove sstables::test::data_read()
2024-09-23 21:40:40 +03:00
Yaniv Michael Kaul
26f2cbdfe2 optimized_clang.sh: compile with -march
Add for both x86_64 compilation flags for clang, to get it compile with newer arch x86_64-v3 for x86 and ARM 8.2 level for aarch64.

Tested to compile fine with both clang 18.1.6 and 18.1.8.
Signed-off-by: Yaniv Kaul <yaniv.kaul@scylladb.com>

Closes scylladb/scylladb#20682
2024-09-23 17:40:20 +03:00
Paweł Zakrzewski
16dd58fb0d cql3: respect the user-defined page size in aggregate queries
This change allows the user to fully set the page size for the query.
There's still an internal hard-limit of 1MB anyway, so there's no need
to limit it to our default value (because using a larger page size might
be a query optimization sometimes)

Fixes #20612

Closes scylladb/scylladb#20692
2024-09-23 16:31:21 +03:00
Botond Dénes
64ed3f80c7 Merge 'Coroutinize sstable_directory::remove_unshared_sstables()' from Pavel Emelyanov
This one is pretty simple

```
    return do_with(std::move(data), [] {
        toss_data(data);
        return remove(std::move(data));
    });
```

it doesn't really need to do_with() since "toss_data" is non-preemptive. Still, convert it into

```
    toss_data(data);
    co_await remove(std::move(data));
```

Closes scylladb/scylladb#20479

* github.com:scylladb/scylladb:
  sstables: Restore indentation after previous patch
  sstables: Coroutinize remove_unshared_sstables()
2024-09-23 16:15:46 +03:00
Kefu Chai
1aa030a8cd docs: explain precedence of configure options
to explain for instance which setting takes effect if both
command line options and `scylla.yaml` configures the same parameter.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20696
2024-09-23 16:12:44 +03:00
Yaniv Michael Kaul
85c0bb7ff4 optimized_clang.sh: add missing symbolic links to clang (for ccache)
The removal of clang removes the symblic links ccache uses to mask itself as clang/clang++
Manually add them back, so ccache can work.

Signed-off-by: Yaniv Kaul <yaniv.kaul@scylladb.com>
Fixes: https://github.com/scylladb/scylladb/issues/20490

Closes scylladb/scylladb#20491
2024-09-23 15:55:22 +03:00
Nikos Dragazis
1e4b67dd8a sstables: Remove forward declaration for random_access_reader
The sstables header contains a forward declaration for
`random_access_reader`. This was introduced in 75dc7b799e for no
obvious reason.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-09-23 15:28:43 +03:00
Nikos Dragazis
83ccd5bcca sstables: Remove forward declaration for metadata_collector
The sstables header contains a forward declaration for
`metadata_collector`. This was introduced in 2d6608bb88 for the return
value of the `sstable_writer::get_metadata_collector()`. This function
was later removed in 9e7144f719 but the forward declaration was left
behind.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-09-23 15:28:43 +03:00
Nikos Dragazis
90aff33cb0 sstables: Remove forward declaration for sstables_manager
This is a duplicate.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-09-23 15:28:43 +03:00
Nikos Dragazis
4efca437c8 sstables: Remove forward declaration for sstable_writer_v2
The sstables header contains a forward declaration for
`sstable_writer_v2`. This was introduced in fed5b73147 but never used.
It is probably a leftover from a previous revision of the patchset.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-09-23 15:28:43 +03:00
Nikos Dragazis
fda98ba9f6 sstables: Remove forward declaration for key
The sstables header contains a forward declaration for `key`.
This was introduced in 198f55dc5c for a reference parameter in
`binary_search()`.

The function was eventually moved to a different header in 4ed7e529db
but the forward declaration was left behind.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2024-09-23 15:28:26 +03:00
Piotr Dulikowski
d1c7e2effa configure.py: deduplicate --out-final-name arg added in build.ninja
Every time the ninja buildfile decides it needs to be updates, it calls
the configure.py script with roughly the same set of flags. However, the
--out-final-name flag is improperly handled and, on each reconfigure,
one more --out-final-name flag is appended to the rebuild command. This
is harmless because each instance of the flag will specify the same
parameter, but slightly annoying because it bloats the generated file
and the duplicated flags show up in ninja's output when reconfigure
runs.

Fix the problem by stripping the --out-final-name flags from the set of
the flags passed to the configure.py before forwarding them to the
reconfigure rule.

Closes scylladb/scylladb#20731
2024-09-23 15:05:13 +03:00
Dawid Mędrek
90ce86930a auth/authenticator: Add member functions for querying password hash
We add new member functions to the interface of `auth::authenticator`
responsible for querying the password hash corresponding to a given
role. One method indicates whether a given authenticator uses
password hashes, while the other queries them or throws an exception
password hashes are not used.

The rationale for extending the interface of authenticator is
to be able to access salted hashes from other parts of auth.
We will need them in an upcoming commit responsible for describing
auth.
2024-09-23 13:55:52 +02:00
Dawid Mędrek
6517ca8920 service/qos/service_level_controller: Describe service levels
We implement a member function responsible for producing
instances of `cql3::description` that can be used to
restore service levels.
2024-09-23 13:55:49 +02:00
Kefu Chai
40f2d4c988 build: cmake: drop scylla-jmx from the build
in 3cd2a61736, we dropped scylla-jmx
from the build. but didn't update the CMake building system accordingly,
this broke the CMake build, as the dependencies pointing to jmx cannot
be found or fulfilled.

in this change, we remove all references to jmx in the CMake build.

Signed-off-by: Laszlo Ersek <laszlo.ersek@scylladb.com>

Closes scylladb/scylladb#20736
2024-09-23 14:20:42 +03:00
Marcin Maliszkiewicz
2df8eefd67 db: schema_applier: simplify merge_keyspaces function
- removes uneccesary temporary sets/vectors
- removes auto&&
- moves return value instead of copying
- instead adds diff references to keep readability
- create and alter logic is almost the same, now it's visible better
2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
7225538845 db: schema_applier: remove unnecessary read in merge_keyspaces
read_schema_partition_for_keyspace() is already called for every
changing keyspace by get_schema_complete_view() and stored in _after
field so we can reuse this data.
2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
f49822f78d db: schema_tables: move scylla specific code into create keyspace function
Since extract_scylla_specific_keyspace_info() was always coupled
with create_keyspace_from_schema_partition() there is no value
in separating them. By moving first into the latter we:
- reduce number of exported functions
- simplify arguments of create_keyspace_from_schema_partition
- simplify caller's code
2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
9792d720c9 db: move schema merging code into a separate unit
It's mostly self containted and it's easier to
maintain reasonably sized files. Also splitting
better shows boundaries between schema and
schema merging code.
2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
208050f190 db: schema_tables: export some schema management functions
In subseqent commits schema merging code will be separated from
db/schema_tables.cc but code which manages schema will remain intact.
So those two translation units will share some amount of code.

It's similar case as with replica/database.cc which creates schema
on startup, it calls functions from db/schema_tables.cc.

Struct qualified_name got moved to header as it's used as
read_table_mutations() argument.
2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
258ffbd126 replica: remove unused table_selector forward declaration 2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
4630864b58 db: remove unused flush arg from do_merge_schema func 2024-09-23 12:01:36 +02:00
Marcin Maliszkiewicz
4cce9c8b5a db: remove unused read_arg_values function 2024-09-23 12:01:36 +02:00
Nadav Har'El
6496eab5ee Merge 'Rename Alternator batch item count metrics' from Amnon Heiman
This PR addresses multiple issues with alternator batch metrics:

1. Rename the metrics to scylla_alternator_batch_item_count with op=BatchGetItem/BatchWriteItem
2. The batch size calculation was wrong and didn't count all items in the batch.
3. Add a test to validate that the metrics values increase by the correct value (not just increase). This also requires an addition to the testing to validate ops of different metrics and an exact value change.

Needs backporting to allow the monitoring to use the correct metrics names.

Fixes #20571

Closes scylladb/scylladb#20646

* github.com:scylladb/scylladb:
  alternator:test_metrics test metrics for batch item count
  alternator:test_metrics Add validating the increased value
  alternator: Fix item counting in batch operations
  Alterntor rename batch item count metrics
2024-09-23 10:13:07 +03:00
Kefu Chai
2014d1c0cb cql3: drop workaround for castas_fctn_simple()
now that e13a584ab7
has been merged, and our toolchain is based on the fedora 40 on 20240710, which should include this
change.

so let's drop the workaround from 51d09e6a

Refs #18508
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20750
2024-09-22 19:59:10 +03:00
Kefu Chai
fdc8773278 test/scylla_gdb: get table::_schema raw pointer with lw_shared_ptr
This commit addresses an issue where accessing the raw pointer of the
schema instance within `table::_schema` using `table.schema._p` was
unreliable.

before this change, `_p` was of type `lw_shared_ptr_counter_base*`, a
type-erased smart pointer, preventing direct casting to the underlying
schema pointer. but we still cast it to `schema*` anyway. this led to
a gdb.MemoryError when dereferencing the deduced pointer:
but the type of `_p` is `lw_shared_ptr_counter_base*`, which is a
type erased smart pointer, and it cannot be casted directly to the
under pointer pointing to a `schema` instance. this results in:

```
Traceback (most recent call last):
  File "/home/avi/scylla/test/scylla_gdb/../../scylla-gdb.py", line 5554, in invoke
    self.print_key_type(seastar_lw_shared_ptr(schema['_clustering_key_type']).get().dereference(), 'clustering')
  File "/home/avi/scylla/test/scylla_gdb/../../scylla-gdb.py", line 5533, in print_key_type
    key_type = seastar_shared_ptr(key_type).get().dereference()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gdb.MemoryError: Cannot access memory at address 0x4000079656b0078
```

when we are dereferencing the raw pointer deduced this way.

in this change,

* we use the wrapper of `seastar_lw_shared_ptr` to safely obtain the
  raw pointer.
* reenable this test previously disabled by 3d781c4f

tested using
```console
$ SCYLLA=/home/kefu/dev/scylladb/master/build/release/scylla \
  test/scylla_gdb/run -o junit_suite_name=scylla_gdb test_misc.py::test_schema
```

on an up-to-date fedora 40 installation.

Refs 3d781c4f
Fixes scylladb/scylladb#20741
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20746
2024-09-22 18:30:16 +03:00
Avi Kivity
657848dcbb cql3: statement_restrictions, expr: move restrictions-related expression utilities out of expression.cc
Move all of the blatantly restriction-related expression utilities
to statement_restrictions.cc.

Some are so blatant as to include the word "restriction" in their name.
Others are just so specialized that they cannot be used for anything else.

The motivation is that further refactoring will be simplified if it can
happen within the same module, as there will not be a need to prove
it has no effect elsewhere.

Most of the declarations are made non-public (in .cc file) to limit
proliferation. A few are needed for tests or in select_statement.cc
and so are kept public.

Other than that, the only changes are namespace qualifications and
removal of a now-duplicate definition ("inclusive").

Closes scylladb/scylladb#20732
2024-09-22 11:00:51 +03:00
Avi Kivity
3d781c4fc8 Update frozen toolchain
* tools/java e505a6d3bb...5b0e274f12 (1):
  > Merge 'build.xml: install and use java-11 when building' from Kefu Chai

Updates to clang 18.1.8 + LLVM patch to match Fedora 40.

New optimized clang build generated and stored in

    https://devpkg.scylladb.com/clang/clang-18.1.8-x86_64.tar.gz
    https://devpkg.scylladb.com/clang/clang-18.1.8-aarch64.tar.gz

Due to the loss of the jmx submodule, we no longer install java-11-openjdk.
We add it in install-dependencies.sh here to compensate, pending a better
solution.

tools/java submodule updated to remove build failure where Java 8
was selected instead of Java 11.

The scylla_gdb test suite was disabled due to a regression in gdb 15,
which is brought in by the toolchain update [1].

[1] https://github.com/scylladb/scylladb/issues/20741.
2024-09-21 20:07:28 +03:00
Raphael S. Carvalho
38ce2c605d tablet: Fix single-sstable split when attaching new unsplit sstables
To fix a race between split and repair here c1de4859d8, a new sstable
generated during streaming can be split before being attached to the sstable
set. That's to prevent an unsplit sstable from reaching the set after the
tablet map is resized.

So we can think this split is an extension of the sstable writer. A failure
during split means the new sstable won't be added. Also, the duration of split
is also adding to the time erm is held. For example, repair writer will only
release its erm once the split sstable is added into the set.

This single-sstable split is going through run_custom_job(), which serializes
with other maintenance tasks. That was a terrible decision, since the split may
have to wait for ongoing maintenance task to finish, which means holding erm
for longer. Additionally, if split monitor decides to run split on the entire
compaction group, it can cause single-sstable split to be aborted since the
former wants to select all sstables, propagating a failure to the streaming
writer.
That results in new sstable being leaked and may cause problems on restart,
since the underlying tablet may have moved elsewhere or multiple splits may
have happened. We have some fragility today in cleaning up leaked sstables on
streaming failure, but this single-sstable split made it worse since the
failure can happen during normal operation, when there's e.g. no I/O error.

It makes sense to kill run_custom_job() usage, since the single-sstable split
is offline and an extension of sstable writing, therefore it makes no sense to
serialize with maintenance tasks. It must also inherit the sched group of the
process writing the new sstable. The inheritance happens today, but is fragile.

Fixes #20626.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2024-09-20 23:03:01 -03:00
Raphael S. Carvalho
999f1f1318 replica: Fix tablet split execute after restart
let's assume there are 2 nodes, n1, n2. n1 is the coordinator.

1) n1 emits split
2) n1 and n2 complete split work
3) n1 becomes aware all replicas are ready for split
4) n2 restarts, but places split sstable into main group[1]
5) n1 executes split
6) n2 handles split completion, but see the main group is not empty

[1]: During split, main group should only contain unsplit sstables.
If all sstables are split, main must be empty.

This is a result of replica not setting storage group to split mode on restart
(using tablet map) and therefore sstables are incorrectly placed on main group.

The fix is about looking at tablet map and setting group to split mode before
sstables are populated into it.

Refs #20626.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2024-09-20 22:28:09 -03:00
Avi Kivity
cd861bc788 row_cache: coroutinize do_update()
do_with() makes the change a no-brainer, and besides, it's called once
per huge update.

Closes scylladb/scylladb#20735
2024-09-21 00:07:02 +02:00
Botond Dénes
488a372fdc tool/scylla-nodetool: status: reorder endpoint calls to match old nodetool
Old nodetool requested `/storage_service/tokens_endpoing` first, then
`/storage_service/host_id`, while the native nodetool did it in reverse
order. Most of the time this is inconsequential but there is an edge
case when a node's IP address is changed. This reversing of the order
results in unexpected behavior for tests, causing noise via flaky
tests.
Match the order of the old nodetool so that the native nodetool exhibits
the behavior expected by tests (and users too probably).

Fixes: scylladb/scylladb#18693

Closes scylladb/scylladb#20615
2024-09-20 15:07:16 +02:00
Dawid Mędrek
b357307406 data_dictionary: Remove keyspace_element.hh
The interface is not used anywhere anymore, so we can
remove it safely. It has been replaced by custom
functions for each keyspace element and `cql3::description`.
2024-09-20 14:24:54 +02:00
Dawid Mędrek
7b4f9c806c treewide: Start using new overloads of describe
We continue removing `data_dictionary::keyspace_element`.
In this commit, we start using the overloads returning
`cql3::description` in places where the methods specified
by `data_dictionary::keyspace_element` were used.
2024-09-20 14:24:54 +02:00
Dawid Mędrek
df94e92b06 treewide: Fix indentation in describe functions
After modifying new functions for generating `cql3::description`,
we fix indentation in them in this commit.
2024-09-20 14:24:54 +02:00
Dawid Mędrek
86722e4cea treewide: Return create statement optionally in describe functions
We add a new parameter in functions used to generate instances
of `cql3::description` for types related to situations where we
might not need a create statement. An example of such a scenario
could be `DESCRIBE TYPES`.
2024-09-20 14:24:54 +02:00
Dawid Mędrek
0702e93e32 treewide: Add new describe overloads to implementations of data_dictionary::keyspace_element
We're removing `data_dictionary::keyspace_element`.
Before we can do that, we need to substitute the existing
methods used for describing keyspace elements with their
new versions returning `cql3::description`.
That's what happens in this commit.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
39cf106151 treewide: Start using schema::ks_name() instead of schema::keyspace_name()
We're going to remove the interface `data_dictionary::keyspace_element`.
As `schema::keyspace_name()` is an implementation of one of the methods
specified by that interface, we replace its uses by `schema::ks_name()`.
`schema::keyspace_name()` was an alias for it, so no semantic change
has occured.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
1844c71f9a cql3: Refactor description
In these changes, we describe the purpose of the type
and make it reusable for other parts of the code.
That includes ditching the existing constructors,
leaving the formatting of its fields to the user
of the interface.

The removed constructors have been replaced by
free functions so that existing code can still
use them the way it did before.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
05d6794e65 cql3: Move description to dedicated files
We move the declaration of `description` to dedicated files
to be able to create instances of it from other parts of
the code.

`describe_statement.cc` has been functioning as an
intermediary between objects that can be described
and the end user. It will still perform that duty,
but we want to let other modules be able to generate
descriptions on their own, without having to share
an additional layer of abstraction in form of types
inheriting from `data_dictionary::keyspace_element`.
Those types may not perform any other function than
that and thus may be redundant.

Adjusting `description` to its new purpose will happen
in an upcoming commit.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
78ab1ee8b7 test: Add tests for CREATE ROLE WITH SALTED HASH 2024-09-20 14:24:53 +02:00
Dawid Mędrek
47a5469280 cql3/statements: Restrict CREATE ROLE WITH SALTED HASH
We start requiring that the user issuing `CREATE ROLE
WITH SALTED HASH` be a superuser. The rationale for
that is the statement directly modifies a system
tables, circumventing the hashing algorithm.

Additionally, we correct a possible existing problem.
`_options.is_superuser` in `create_role_statement`
may be an empty optional, so dereferencing it
without a prior check could lead to undefined
behavior in the future.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
206fdf2848 auth: Allow for creating roles with SALTED HASH
We introduce a way to create a role with explictly
provided salted hash.

The algorithm for creating a role with a password works
like this:

1. The user issues a statement `CREATE ROLE <role> WITH
   PASSWORD = '<password>' <...>`.
2. Scylla produces a hash based on the value of
   `<password>`.
3. Scylla puts the produced hash in `system.roles`,
   in the column `salted_hash`.

The newly introduced way to create a role is based
on a new form of the create statement:
`CREATE ROLE <role> WITH SALTED HASH = '<salted_hash>`

The difference in the algorithm used for processing
this statement is that we insert `<salted_hash>`
into `system.roles` directly, without hashing it.

The rationale for introducing this new statement is that
we want to be able to restore roles. The original password
isn't stored anywhere in the database (as intended),
so we need to rely on the column `salted_hash`.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
35a92d189e types: Introduce a function cql3_type_name_without_frozen()
The introduced function returns the actual name
of the type represented by `abstract_type`.
It circumvents name processing like wrapping a type
within `frozen<>` or using Cassandra's syntax.

We add the function to be able to describe UDFs
in the upcoming commits that require that their
arguments not be `frozen<>`.

We also test the implementation.
2024-09-20 14:24:53 +02:00
Dawid Mędrek
202d866892 cql3/util: Accept std::string_view rather than const sstring& 2024-09-20 14:24:53 +02:00
Avi Kivity
61d19e4464 Update tools/java submodule
* tools/java 0b4accdd5e...e505a6d3bb (1):
  > [C-S] Make it use DCAwareRoundRobinPolicy unless rack is provided
2024-09-20 14:49:21 +03:00
Pavel Emelyanov
b45891acd7 sstables: storage: Don't keep base directory in base class
This reverts commit 44bd183187 and
moves the base directory back on filesystem_storage. The mentioned
commit says

>     so we can use the base (table) directory for
>    e.g. pending_delete logs, in the next patch.

but "next patch" doesn't use it outside of the filesystem-storage
anyway.

This field doesn't make sense for S3 backend. Its "location" is not
location, but a key in the system.sstables, which should rather be
schema ID, not /var/lib/.../keyspace/table-uuid string.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20642
2024-09-20 11:51:04 +03:00
Andrei Chekun
bd9a73c39b Add .idea folder to .gitignore
.idea directory used by JetBrains IDE's to store data about project
config

Closes scylladb/scylladb#20718
2024-09-20 11:49:41 +03:00
Tomasz Grabiec
8e047e8fff gdb: Add std::set wrapper
Allows accessing std::set fields from gdb, e.g.:

(gdb) python for e in std_set(_promoted_index._blocks): print(e)

Closes scylladb/scylladb#20650
2024-09-20 08:24:15 +03:00
Anna Stuchlik
5da7894f70 doc: move the install-jmx instructions to a common folder
This commit moves the install-jmx.rst file from the install-scylla folder
to the installation-common folder.

All the references to the moved document are updated.

This is a follow-up to https://github.com/scylladb/scylladb/pull/17969/

Closes scylladb/scylladb#20712
2024-09-20 00:36:32 +03:00
Nadav Har'El
3499c407f7 test: avoid silly "no_mode.1" labels when running tests outside test.py
For the benefit of running test.py inside CI, we recently added to
test/cql-pytest and test/alternator the knowledge of which "Scylla mode"
(--mode) and "run number" is running (--run_id), although these concepts
are alien to these two test frameworks (remember that those test frameworks
can also run tests against unknown versions of Scylla or even our competitors'
implementations).

One unfortunate result of this change is that now if you run a test by
using pytest directly (or test/*/run) instead of test.py, for example:

    $ cd test/alternator
    $ pytest --aws test_item.py::test_basic_string_put_and_get

The test's success or failure reports the ugly name

    test_item.py::test_basic_string_put_and_get.no_mode.1

This unnecessary "no_mode.1" come from the the default values for --mode
and --run_id, respectively. But there is no reason for these silly
defaults. In this patch we change these defaults to None, and when they
are None, they aren't tacked onto the test's name.

This patch shouldn't affect running tests through test.py, because
test.py always sets the --mode and --run_id options, and doesn't leave
them as the default.

Fixes #20512

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

Closes scylladb/scylladb#20513
2024-09-20 00:36:32 +03:00
Avi Kivity
b015c85d31 Merge 'gms: inet_address: drop unused raw_addr method and modernize comperators' from Benny Halevy
Drop the unused `gms::inet_address::raw_addr` method
and modernize operator== and operator< as class methods

* Cleanup only, no backport needed

Closes scylladb/scylladb#20681

* github.com:scylladb/scylladb:
  gms: inet_address: modernize comparison operators
  gms: inet_address: drop unused raw_addr method
2024-09-20 00:36:32 +03:00
Piotr Dulikowski
7e7701d436 Merge 'cql3/statements/select_statement: SELECT ... USING SERVICE LEVEL' from Michał Jadwiszczak
Allow to specify service level used in select statement `SELECT ... USING SERVICE LEVEL sl_name`.
In OSS, this only affects statement's timeout.

In case both service level and timeout are specified `SELECT ... USING SERVICE LEVEL sl_name AND TIMEOUT 1h`, the timeout has higher priority as statement's timeout.

Fixes scylladb/scylladb#18471

Closes scylladb/scylladb#20523

* github.com:scylladb/scylladb:
  test/cql-pytest: add test for `SELECT ... USING SERVICE LEVEL`
  cql3/Cql.g: extend grammar to allow `SELECT ... USING SERVICE LEVEL`
  cql3/statements/select_statement: use service level timeout
  cql3/attributes: add service level name field
  qos/service_level_controller: add method to check if service level exists in cache
2024-09-19 18:19:23 +02:00
Pavel Emelyanov
bd720dd2da Merge 'cql3: statement_restrictions: adapt to functional style' from Avi Kivity
The statement_restrictions class started life in the object-oriented style - an
object that interacts with its environment via mutators and is observed via
observers.

This is however not suitable for its objective: to analyze the WHERE clause,
select a query plan, and partition the WHERE clause atoms to the various
parts demanded by the query plan (read_command and filters). Furthermore,
the object oriented style makes it hard to work with as you can only call some
observers after the related mutators were called.

Fix this by transforming the code info a more functional style: we call
a function that returns an immutable statement_restrictions object that
can only be observed. This makes it easier to further change in the future,
as changes will not have to consider interaction with the environment.

No backport as this is a refactoring

Closes scylladb/scylladb#20672

* github.com:scylladb/scylladb:
  cql3: statement_restrictions: use functional style
  cql3: statement_restrictions: calculate the index only once
  cql3: statement_restrictions: make it a const object
2024-09-19 18:18:28 +03:00
Kefu Chai
8cc9d783a0 sstables/sstable_directory: document components_lister::process()
for better maintainability.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20693
2024-09-19 18:11:31 +03:00
Kefu Chai
7985aa97b1 main, test: use seastar::handle_signal() instead
use `seastar::handle_signal()` instead of `reactor::handle_signal()`.

in a recent change in seastar (c3e826ad1197f2610138f3bcfaeb0b458f8fb799),
the later was marked as deprecated in favor of the former, so let's
use the recommended API.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20695
2024-09-19 18:10:07 +03:00
Kefu Chai
1fd1698a90 test: btree: use BOOST_DATA_TEST_CASE() when appropriate
instead grouping tests with different parameters, let's parameterize
them using `BOOST_DATA_TEST_CASE()`, simpler this way. and the tests
can be more structured.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20697
2024-09-19 18:09:05 +03:00
Avi Kivity
6f7c2ce0aa Merge 'cql_server::connection: Process rebounce message in case of multiple shard migrations' from Sergey Zolotukhin
During a query execution, the query can be re-bounced to another shard if the requested data is located there. Previous implementation assumed that the shard cannot be changed after first re-bounce, however with the introduction of Tablets, data could be migrated to another shard after the query was already re-bounced, causing a failure of the query execution. To avoid this issue, the query is re-bounced as needed until it is executed on the correct shard.

Fixes #15465

Closes scylladb/scylladb#20493

* github.com:scylladb/scylladb:
  cql_server: Add a test for multiple query msg rebounces.
  cql_server::connection: process: rebounce msg if needed
  cql_server::connection: process: co-routinize connection::process_on_shard
  cql_server: connection: process: fixup indentation
  cql_server: connection: process_on_shard: drop permit parameter
  transport: server: pass bounce_to_shard as foreign shared ptr
  cql_server: connection: process: add template concept for process_fn
  cql_server: move process_fn_return_type to class definition
2024-09-19 17:27:55 +03:00
Gleb Natapov
1b4c255ffd test: amend test_replace_reuse_ip test to check that there is no stale writes after snapshot transfer starts 2024-09-19 15:24:59 +03:00
Gleb Natapov
c0939d86f9 topology coordinator:: mark node as being replaced earlier
Before 17f4a151ce the node was marked as
been replaced in join_group0 state, before it actually joins the group0,
so by the time it actually joins and starts transferring snapshot/log no
traffic is sent to it. The commit changed this to mark the node as
being replaced after the snapshot/log is already transferred so we can
get the traffic to the node while it sill did not caught up with a
leader and this may causes problems since the state is not complete.
Mark the node as being replaced earlier, but still add the new node to
the topology later as the commit above intended.
2024-09-19 15:23:48 +03:00
Gleb Natapov
644e7a2012 topology coordinator: do metadata barrier before calling finish_accepting_node() during replace
During replace with the same IP a node may get queries that were intended
for the node it was replacing since the new node declares itself UP
before it advertises that it is a replacement. But after the node
starts replacing procedure the old node is marked as "being replaced"
and queries no longer sent there. It is important to do so before the
new node start to get raft snapshot since the snapshot application is
not atomic and queries that run parallel with it may see partial state
and fail in weird ways. Queries that are sent before that will fail
because schema is empty, so they will not find any tables in the first
place. The is pre-existing and not addressed by this patch.
2024-09-19 15:00:27 +03:00
Benny Halevy
574a08ed96 storage_service: rebuild: warn about tablets-enabled keyspaces
Until we automatically support rebuild for tablets-enabled
keyspaces, warn the user about them.

The reason this is not an error, is that after
increasing RF in a new datacenter, the current procedure
is to run `nodetool rebuild` on all nodes in that dc
to rebuild the new vnode replicas.
This is not required for tablets, since the additional
replicas are rebuilt automatically as part of ALTER KS.

However, `nodetool rebuild` is also run after local
data loss (e.g. due to corruption and removal of sstables).
In this case, rebuild is not supported for tablets-enabled
keyspaces, as tablet replicas that had lost data may have
already been migrated to other nodes, and rebuilding the
requested node will not know about it.
It is advised to repair all nodes in the datacenter instead.

Refs scylladb/scylladb#17575

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#20375
2024-09-19 14:25:46 +03:00
Pavel Emelyanov
8487f2fd93 treewide: Remove table::config::datadir
It's write-only now, all the places than wanted to know where table's
storage is, already use storage_options.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
350f64c38b distributed_loader: Print storage options, not datadir
When populating keyspace on boot the dist. loader prints a debugging
message with ks:cf names, state and the directory from where it picks
sstables. The last one is not extremely correct, as loading sstables
from S3 happens from a bucket, not directory. So it's better to print
the storage options, not the datadir string.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
b2fcfdcaa9 data_dictionary: Add formatter for storage_options
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
5046cfab4b test: Construct table_for_tests with table storage options
The only place that constructs table_for_tests is make_table_for_tests
helper. It can and should prepare the correct storage options, because
that's the last place where the target directory is still known.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
eaad4f348b test: Generalize pair of make_table_for_tests helpers
They only differ in a way they get target directory from -- one via
argument, andother from test_env. Respectively, the latter can call the
former.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
d9ef9bdd3b tests: Add helper to get snapshot directory from storage options
There's a bunch of tests that check the contents of snapshot directory
after creating one. Add a helper for those that gets this directory via
storage options, not table config.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:39 +03:00
Pavel Emelyanov
a734fd5c9c table: snapshot_exists: Get directory from storage options
Similarly to snapshot_on_all_shards, the way snapshot directory is
evaluated is changed to rely on storage options. Two ... assumptions are
that when asking for non-local snapshot existance or for a snapshot of a
virtual table, it's correct to return false instead of throwing.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:06:09 +03:00
Pavel Emelyanov
24589cf00c table: snapshot_on_all_shards: Get directory from storage options
There are several things that are changed here

- The target directory for snapshot is evaluated using table directory
  taken from its storage options, not from config

- If the storage options are not "local", the snapshot_on_all_shards is
  failed early, it's impossible to snapshot sstables anyway

- If the storage is not configured for the obtained local options,
  snapshotting is skilled, because it's a virtual table that's probably
  not supposed to have snapshots

- The late failure to snapshot non-local sstables is converted into
  internal error, as this functionality cannot be executed as per
  previous change

- The target path is created using fs::path operator/ overload, not by
  concatenating strings (it's minor change)

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-19 13:05:16 +03:00
Anna Stuchlik
cdc69b4e06 doc: enable publishing docs for branch-6.2
This commit enables publishing documentation from branch-6.2. The docs will be published as UNSTABLE (the warning about version 6.1 being unstable will be displayed).

Fixes https://github.com/scylladb/scylladb/issues/20643

No backport is required.

Closes scylladb/scylladb#20647
2024-09-19 09:39:58 +03:00
Anna Stuchlik
400a14eefa doc: update the unified installer instructions
This commit updates the unified installer instructions to avoid specifying a given version.
At the moment, we're technically unable to use variables in URLs, so we need to update
the page each release.

Fixes https://github.com/scylladb/scylladb/issues/20677

Closes scylladb/scylladb#20680
2024-09-19 09:28:44 +03:00
Anna Stuchlik
aa0c95c95c doc: fix a broken link
This commit fixes a link to the Manager by adding a missing underscore
to the external link.

Closes scylladb/scylladb#20656
2024-09-19 09:20:20 +03:00
Calle Wilund
60f8a9f39d database: Also forced new schema commitlog segment on user initiated memtable flush
Refs #20686
Refs #15607

In #15060 we added forced new commitlog segment on user initated flush,
mainly so that tests can verify tombstone gc and other compaction related
things, without having to wait for "organic" segment deletion.
Schema commitlog was not included, mainly because we did not have tests
featuring compaction checks of schema related tables, but also because
it was assumed to be lower general througput.
There is however no real reason to not include it, and it will make some
testing much quicker and more predictable.

Closes scylladb/scylladb#20691
2024-09-19 09:00:33 +03:00
Benny Halevy
5ccdf1cf1c gms: inet_address: modernize comparison operators
Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-18 17:07:51 +03:00
Benny Halevy
38540d89a1 gms: inet_address: drop unused raw_addr method
Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-18 14:21:18 +03:00
Kefu Chai
b0696bd842 test: btree: use BOOST_DATA_TEST_CASE to structure parameterized tests
for better readability. and for more structured tests.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20516
2024-09-18 14:16:28 +03:00
Pavel Emelyanov
eb22c2a8c8 Merge 'reader_concurrency_semaphore: improve the diagnostics dump' from Botond Dénes
* Also dump diagnostics when a read times out while active (not queued).
* Add the "Trigger permit" line, containing the details of the permit which caused the diagnostics dump (by e.g. timing out).
* Add the "Identified bottleneck(s)" line, containing the identified bottlenecks which lead to permits being queued. This line is missing if no such bottleneck can be identified.
* Document the new features, as well as the stat dump, which was added some time ago.

Example of the new dump format:
```
INFO  2024-09-12 08:09:48,046 [shard  0:main] reader_concurrency_semaphore - Semaphore reader_concurrency_semaphore_dump_reader_diganostics with 8/10 count and 106192275/32768 memory resources: timed out, dumping permit diagnostics:
Trigger permit: count=0, memory=0, table=ks.tbl0, operation=mutation-query, state=waiting_for_admission
Identified bottleneck(s): memory

permits count   memory  table/operation/state
3       2       26M     *.*/push-view-updates-2/active
3       2       16M     ks.tbl1/push-view-updates-1/active
1       1       15M     ks.tbl2/push-view-updates-1/active
1       0       13M     ks.tbl1/multishard-mutation-query/active
1       0       12M     ks.tbl0/push-view-updates-1/active
1       1       10M     ks.tbl3/push-view-updates-2/active
1       1       6060K   ks.tbl3/multishard-mutation-query/active
2       1       1930K   ks.tbl0/push-view-updates-2/active
1       0       1216K   ks.tbl0/multishard-mutation-query/active
6       0       0B      ks.tbl1/shard-reader/waiting_for_admission
3       0       0B      *.*/data-query/waiting_for_admission
9       0       0B      ks.tbl0/mutation-query/waiting_for_admission
2       0       0B      ks.tbl2/shard-reader/waiting_for_admission
4       0       0B      ks.tbl0/shard-reader/waiting_for_admission
9       0       0B      ks.tbl0/data-query/waiting_for_admission
7       0       0B      ks.tbl3/mutation-query/waiting_for_admission
5       0       0B      ks.tbl1/mutation-query/waiting_for_admission
2       0       0B      ks.tbl2/mutation-query/waiting_for_admission
8       0       0B      ks.tbl1/data-query/waiting_for_admission
1       0       0B      *.*/mutation-query/waiting_for_admission
26      0       0B      permits omitted for brevity

96      8       101M    total

Stats:
permit_based_evictions: 0
time_based_evictions: 0
inactive_reads: 0
total_successful_reads: 0
total_failed_reads: 0
total_reads_shed_due_to_overload: 0
total_reads_killed_due_to_kill_limit: 0
reads_admitted: 1
reads_enqueued_for_admission: 82
reads_enqueued_for_memory: 0
reads_admitted_immediately: 1
reads_queued_because_ready_list: 0
reads_queued_because_need_cpu_permits: 82
reads_queued_because_memory_resources: 0
reads_queued_because_count_resources: 0
reads_queued_with_eviction: 0
total_permits: 97
current_permits: 96
need_cpu_permits: 0
awaits_permits: 0
disk_reads: 0
sstables_read: 0
```

Fixes: https://github.com/scylladb/scylladb/issues/19535

Improvement, no backport needed.

Closes scylladb/scylladb#20545

* github.com:scylladb/scylladb:
  docs/dev/reader-concurrency-semaphore.md: update the documentation on diagnostics dumps
  test/boost/reader_concurrency_semaphore_test: test the new diagnostics functionality
  reader_concurrency_semaphore: add bottleneck self-diagnosis to diagnosis dump
  reader_concurrency_semaphore: include trigger permit in diagnostic dump
  reader_concurrency_semaphore: propagate permit to do_dump_reader_permit_diagnostics()
  reader_concurrency_semaphore: use consistent exception type for timeout
  reader_concurrency_semaphore: dump diagnostics when non-waiting reader times out
2024-09-18 14:06:05 +03:00
Botond Dénes
1efda557b1 replica/table: query_mutations(): enter the table's async gate
So the table is not dropped while the query is ongoing.
query() already does this but using old-fashioned enter()+leave(),
convert it to use the new RAII helper.

Closes scylladb/scylladb#20583
2024-09-18 14:03:22 +03:00
Pavel Emelyanov
2f4f0eb060 Merge 'Alternator: a few RBAC fixes' from Nadav Har'El
The main goal of this PR is to fix a bug (#20619) in the alternator_enforce_authorization=false setting - which didn't do its job (i.e, _don't_ check permissions) when authorization is configured in CQL but not wanted in Alternator.

The series also a few smaller bugs in the code that were discovered while debugging the main issue:
1. A potential use-after-free (that didn't seem to hit us in practice) is fixed.
2. A confusing error message (that was also reported in #20619) is improved.
3. Make the alternator_enforce_authorization live-updatable. There was no reason why it shouldn't be, and as this series needs to make this flag available to more code, let's just do it properly and assume the flag is live-updatable.

Because the RBAC feature has not been backported to any open-source branches, neither should these fixes. But if some private branch received a backport of the RBAC feature, it should get these fixes too.

Fixes #20619.

Closes scylladb/scylladb#20640

* github.com:scylladb/scylladb:
  alternator: make alternator_enforce_authorization live-updateable
  alternator: fix alternator_enforce_authorization=false
  alternator: improve error message when unauthenticated
  alternator: avoid use-after-free in RBAC
2024-09-18 14:02:09 +03:00
Kefu Chai
cb1670b79b Update seastar submodule
* seastar ec5da7a6...69f88e2f (38):
  > build: s/Sanitizers_COMPILER_OPTIONS/Sanitizers_COMPILE_OPTIONS
  > test: Update httpd test with request/reply body writing sugar
  > http: Add sugar to request and response body writers
  > utils: Add util::write_to_stream() helper
  > seastar-addr2line: adjust llvm termination regex
  > README.md: add Crimson project
  > rpc: conditionally use fmt::runtime() based on SEASTAR_LOGGER_COMPILE_TIME_FMT
  > build: check the combination of Sanitizers
  > tls: clear session ticket before releasing
  > print: remove dead code
  > doc/lambda-coroutine-fiasco: reword for better readability
  > rpc: fix compilation error caused by fmt::runtime()
  > tutorial: explain the use case of rethrow_exception and coroutine::exception
  > reactor: print more informative error when io_submit fails
  > README.md: note GitHub discussions
  > prometheus: `fmt::print` to stringstream directly
  > doc: add document for testing with seastar
  > seastar/testing: only include used headers
  > test: Add abortable http client test cases
  > http/client: Add abortable make_request() API method
  > http/client: Abort established connections
  > http/client: Handle abort source in pool wait
  > http/client: Add abort source to factory::make() method
  > http/client: Pass abort_source here and there
  > http/client: Idnentation fix after previous patch
  > http/client: Merge some continuations explicitly
  > signal: add seastar signal api
  > httpd: remove unused prometheus structs
  > print: use fmtlib's fmt::format_string in format()
  > rpc: do not use seastar::format() in rpc logger
  > treewide: s/format/seastar::format/
  > prometheus: sanitize label value for text protocol
  > tests: unit test prometheus wire format
  > io-tester: Introduce batches to rate-based submission
  > io-tester: Generalize issueing request and collecting its result
  > io-tester: Cancel intent once
  > io-tester: Dont carry rps/parallelism variables over lambdas
  > io-tester: Simplify in-flight management

The breaking changes in the seastar submodule necessitate corresponding
modifications in our code. These changes must be implemented together in
a single commit to maintain consistency. So that each commit is buildable.

following changes are included in addition to seastar submodule update:
* instead of passing a `const char*` for the format string, pass a
  templated `fmt::format_string<...>`, this depends on the
  `seastar::format()` change in seastar.
* explicitly call `fmt::runtime()` if the format string is not a
  consteval expression. this depends on the `seastar::format()` change
  in seastar. as `seastar::format()` does not accept a plain
  `const char*` which is not constexpr anymore.
* pass abort_source to `dns_connection_factory::make()`. this depends on
  the change in seastar, which added a `abort_source*` argument to
  the pure virtual member function of `connection_factory::make()`.
* call call {fmt,seastar}::format() explicitly. this is a follow up of
  3e84d43f, which takes care of all places where we should call
  `fmt::format()` and `seastar::format()` explicitly to disambiguate the
  `format()` call. but more `format()` call made their way into the source
   tree after 3e84d43f. so we need fix them as well.
* include used header in tests

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Update seastar submodule

 Please enter the commit message for your changes. Lines starting

Closes scylladb/scylladb#20649
2024-09-18 13:59:22 +03:00
Gleb Natapov
bddaf498df group0: make sure that address map has an entry for each new node in the raft configuration
ID->IP mapping is added to the raft address map when the mapping first
appears in the gossiper, but it is added as expiring entry. It becomes
non expiring when a node is added to raft configuration. But when a node
joins those two events may be distant in time (since the node's request
may sit in the topology coordinator queue for a while) and mappings may
expire already from the map. This patch makes sure to transfer the
mapping from the gossiper for a node that is added to the raft
configuration instead of assuming that the mapping is already there.
2024-09-18 13:42:38 +03:00
Amnon Heiman
8dec292698 alternator:test_metrics test metrics for batch item count
This patch adds tests for the batch operations item count.

The tests validate that the metrics tracking the number of items
processed in a batch increase by the correct amount.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-18 11:31:06 +03:00
Amnon Heiman
4d57a43815 alternator:test_metrics Add validating the increased value
The `check_increases_operation` now allows override the checked metric.

Additionally, a custom validation value can now be passed, which make it
possible to validate the amount by which a value has changed, rather
than just validating that the value increased.

The default behavior of validating that values have increased remains
unchanged, ensuring backward compatibility.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-18 11:31:06 +03:00
Amnon Heiman
905408f764 alternator: Fix item counting in batch operations
This patch fixes the logic for counting items in batch operations.
Previously, the item count in requests was inaccurate, it count the
number of tabels in get_item and the request_items in write_items.

The new logic correctly counts each individual item in `BatchGetItem`
and `BatchWriteItem` requests.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-18 11:30:59 +03:00
Amnon Heiman
515857a4a9 Alterntor rename batch item count metrics
This patch renames metrics tracking the total number of items in a batch
to `scylla_alternator_batch_item_count`.  It uses the existing `op` label to
differentiate between `BatchGetItem` and `BatchWriteItem` operations.

Ensures better clarity and distinction for batch operations in monitoring.

This an example of how it looks like:
 # HELP scylla_alternator_batch_item_count The total number of items processed across all batches
 # TYPE scylla_alternator_batch_item_count counter
 scylla_alternator_batch_item_count{op="BatchGetItem",shard="0"} 4
 scylla_alternator_batch_item_count{op="BatchWriteItem",shard="0"} 4
2024-09-18 11:20:07 +03:00
Anna Mikhlin
0c7ca284ad mergify: add support for branch-6.2
branch-6.2 is already available, adding support for it in mergify to
allow backport to this new branch.
in addition, since branch 5.4 reached EOL - removing it

Closes scylladb/scylladb#20669
2024-09-18 08:30:41 +03:00
Ernest Zaslavsky
924325fd25 treewide: add "prefix" parameter to backup API
Allow the caller to pass the prefix when performing backup and restore

Fixes scylladb/scylladb#20335

Closes scylladb/scylladb#20413
2024-09-18 08:25:00 +03:00
Calle Wilund
b789361091 commitlog: Fix assertion in oversized_alloc
Fixes #20633

Cannot assert on actual request_controller when releasing permit, as the
release, if we have waiters in queue, will subtract some units to hand to them.
Instead assert on permit size + waiter status (and if zero, also controller value)

* v2 - use SCYLLA_ASSERT

Closes scylladb/scylladb#20654
2024-09-18 08:22:28 +03:00
Avi Kivity
57ab5ce313 repair: row_level: simplify repair_put_row_diff_with_rpc_stream_process_op()
repair_put_row_diff_with_rpc_stream_process_op() always returns
stop_iteration::no (or throws). Moreover, the return value is ignored
by its only caller. Simplify by returning a plain future<>.

Closes scylladb/scylladb#20610
2024-09-18 08:17:09 +03:00
Botond Dénes
d72fcb11f5 Merge 'Add new GDB commands to dump sstable index file from memory and print promoted index ' from Tomasz Grabiec
Closes scylladb/scylladb#20648

* github.com:scylladb/scylladb:
  gdb: Introduce "scylla sstable-dump-cached-index" command
  gdb: Introduce "scylla sstable-promoted-index" command
  gdb: Fix range printer for singular ranges
2024-09-18 08:13:04 +03:00
Nadav Har'El
24fb92c8ba Merge 'cql3: simplify runtime component of selection filtering' from Avi Kivity
Most of the analysis of the WHERE clause is done in statement_restrictions. It determines
what parts to use for the primary or secondary index, and what parts to use for filtering.

The difficult part is that it has a very wide interface. After construction, the user must pick
the correct bits from many public functions. There are subtle interactions between them
that are hard to untangle.

This series simplifies the interface as it is used for selection filtering. In the end, only
two public functions are used, both returning expressions: one for the partition-level
filtering, one for the clustering row level filtering.

In the end, the WHERE clause is factored into three parts:
 - one part goes into the read_command of the primary or secondary index
 - another part (that references only partition key columns and static key columns) is used to filter entire partitions
 - another part (that currently references only clustering key columns and regular columns, but one day may reference other columns) is used to filter clustering rows

Refactoring, no backport.

Closes scylladb/scylladb#20487

* github.com:scylladb/scylladb:
  cql3: statement_restrictions: drop accessors for single-column key restrictions
  cql3: selection: adjust indentation
  cql3: selection: delete empty loop
  cql3: statement_restrictions, selection: fold multi-column restrictions into row-level filter
  cql3: statement_restrictions, selection: merge clustering key filter and regular columns filter
  cql3: statement_restrictions, selection: merge partition key filter and static columns filter
  cql3: selection: filter regular and static rows as a single expression each
  cql3: statement_restrictions: collect regular column and static column filters into single expressions
  cql3: selection: filter clustering key as a single expression
  cql3: statement_restrictions: expose filter for clustering key
  cql3: selection: filter partition key as a single expression
  cql3: statement_restrictions: expose filter for partition key
  cql3: statement_restrictions: remove relations used for indexing from filtering
  cql3: statement_restrictions: bail out of find_idx if !_uses_secondary_index
  cql3: statement_restrictions, modification_statement: pass correct value of check_indexes
  cql3: statement_restrictions: correct mismatched clustering/partition restrictions references
  cql3: statement_restrictions: precalculate get_column_defs_for_filtering()
  cql3: selection: do_filter(): push static/regular row glue to higher level
2024-09-17 22:58:24 +03:00
Piotr Dulikowski
cc5c3aaae7 Merge 'message/messaging_service: guard adding maintenance tenant under cluster feature' from Michał Jadwiszczak
In https://github.com/scylladb/scylladb/pull/18729, we introduced a new statement tenant `$maintenance`, but the change wasn't protected by any cluster feature.
This wasn't a problem for OSS, since unknown isolation cookie just uses default scheduling group. However, in enterprise that leads to creating a service level on not-upgraded nodes, which may end up in an error if user create maximum number of service levels.

This patch adds a cluster feature to guard adding the new tenant. It's done in the way to handle two upgrade scenarios:
- version without `$maintenance` tenant -> version with `$maintenance` tenant guarded by a feature
- version with `$maintenance` tenant but not guarded by a feature -> version with `$maintenance` tenant guarded by a feature

The PR adds `enabled` flag to statement tenants.
This way, when the tenant is disabled, it cannot be used to create a connection, but it can be used to accept an incoming connection.
The `$maintenance` tenant is added to the config as disabled and it gets enabled once the corresponding feature is enabled.

Fixes scylladb/scylladb#20070
Refs scylladb/scylla-enterprise#4403

Closes scylladb/scylladb#19802

* github.com:scylladb/scylladb:
  message/messaging_service: guard adding maintenance tenant under cluster feature
  message/messaging_service: add feature_service dependency
  message/messaging_service: add `enabled` flag to statement tenants
2024-09-17 18:24:34 +02:00
Avi Kivity
1663fbe717 cql3: statement_restrictions: use functional style
Instead of a constructor, use a new function
analyze_statement_restrictions() as the entry point. It returns an
immutable statement_restrictions object.

This opens the door to returning a variant, with each arm of the variant
corresponding to a different query plan.
2024-09-17 17:13:27 +03:00
Avi Kivity
3169b8e0ec cql3: statement_restrictions: calculate the index only once
find_idx() is called several times. Rename it do_find_idx(), call it
just once, store the results, and make find_idx() return the stored
results.

This simplifies control flow and reduces the risk that successive
calls of find_idx return different results.
2024-09-17 17:03:31 +03:00
Avi Kivity
d5c8083b76 cql3: statement_restrictions: make it a const object
Make validate_secondary_index_selections() const (it trivially is),
and call prepare_indexed_local() / prepared_indexed_global() at the
end of the constructor.

By making statement_restrictions a const object, reasoning about it
can be local (looking at the source file) rather than global (looking
at all the interactions of the class with its environment. In fact,
we might make it a function one day.

Since prepare_indexed_global()/prepare_indexed_local() only mutate
_idx_tbl_ck_prefix, which isn't mutated by the rest of the code, the
transformation is safe.

The corresponding code is removed from select_statement. The removal
isn't complete since it still uses some computation, but later
deduplication is left for another day.
2024-09-17 17:03:27 +03:00
Sergey Zolotukhin
68740f57c2 cql_server: Add a test for multiple query msg rebounces.
The test emulates several LWT(Lightweight Transaction) query rebounces. Currently, the code
that processes queries does not expect that a query may be rebounced more than once.
It was impossible with the VNodes, but with intruduction of the Tablets, data can be moved
between shards by the balancer thus a query can be rebounced to different shards multiple times.
2024-09-17 15:19:56 +02:00
Benny Halevy
65430b9e1b cql_server::connection: process: rebounce msg if needed
Rebounce the msg to another shard if needed,
e.g. in the case of tablet migration.

An example for that, as given by Tomasz Grabiec:
> Bouncing happens when executing LWT statement in
> modification_statement::execute_with_condition by returning a
> special result message kind. The code assumes that after
> jumping to the shard from the bounce request, the result
> message is the regular one and not yet another bounce.
> There is no problem with vnodes, because shards don't change.
> With tablets, they can change at run time on migration.

Fixes scylladb/scylladb#15465

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-17 15:09:43 +02:00
Sergey Zolotukhin
f674f522aa cql_server::connection: process: co-routinize connection::process_on_shard
`cql_server::connection::process_on_shard` is made a co-routine to
make sure captured objects' lifetime is managed by the source shard,
avoiding error prone inter-shard objects transfers.
2024-09-17 14:54:42 +02:00
Nadav Har'El
17deaae463 alternator: make alternator_enforce_authorization live-updateable
For no good reason, the "alternator_enforce_authorization" flag (which
chooses whether to enable authentication and authorization checks in
Alternator) was not live-updatable, so make it so.

Both "server" and "executor" objects use this configuration flag, the
former is fixed in this patch (to hold a live-updatable reference
instead of a copy of a boolean), the latter was already prepared for
this change and already held a live-updatable reference.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-09-17 15:51:16 +03:00
Nadav Har'El
00793059e1 alternator: fix alternator_enforce_authorization=false
When the configuration has alternator_enforce_authorization=false,
Alternator should not do authentication (check which user signed each
request) nor authorization (check if that user has permissions to do
each operation).

Our implementation forgot to disable the authorization checks when
it's configured to false. The (incorrect) assumption was that when
alternator_enforce_authorization is configured to false, the CQL
'authenticator' and 'authorizer' configuration is also disabled -
so the authorization checks will be no-ops. But we can't assume
that: Users are free to configure 'authenticator' and 'authorizer'
for use in CQL, and then set alternator_enforce_authorization=false
just for Alternator.

So this patch adds a new test for this case - when we have
authenticator=PasswordAuthenticator, authorizer=CassandraAuthorizer
but alternator_enforce_authorization=false, and fixes it to work
correctly.

The heart of the fix is trivial: the `verify_*_permission()` functions
just need to check the alternator_enforce_authorization and return
immediately when false. The bigger part of this change is to get the
alternator_enforce_authorization into the "executor" object and then
to pass it into the verify calls.

Although alternator_enforce_authorization is not YET live updatable,
this code is prepared for the future that it may become live
updatable, so the executor object saves not the boolean value of
this flag, but a live-updatable reference to it.

Fixes #20619

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-09-17 15:50:00 +03:00
Nadav Har'El
76af7c0389 alternator: improve error message when unauthenticated
When access-control checks report permission denied, we want to report
the name of the authenticated role (the role signing the request) which
didn't have the permission. When authentication was disabled, and there
is no authenticated role, we printed the fake name "anonymous", but this
can confuse users (it confused me!) to think there's an actual role
named "anonymous". So let's change that string to "<anonymous>" with
angle brackets - it makes it more obvious that this isn't a real role,
but actually an anonymous request.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2024-09-17 15:44:29 +03:00
Tomasz Grabiec
e70ce4d6ed gdb: Introduce "scylla sstable-dump-cached-index" command 2024-09-17 14:41:18 +02:00
Tomasz Grabiec
9f0eed263d gdb: Introduce "scylla sstable-promoted-index" command 2024-09-17 14:41:13 +02:00
Nadav Har'El
3543bf14e9 alternator: avoid use-after-free in RBAC
While auditing the code, I noticed that the current Alternator access
control checks have code like:

```
    return client_state.check_has_permission(auth::command_desc(
            permission_to_check,
            auth::make_data_resource(schema->ks_name(), schema->cf_name()))).then(
```

There's a problem here - it turns out that, unfortunately, command_desc
holds a reference to the "resource" object - not a copy. So the temporary
object returned by make_data_resource may be freed and then used...
Curiously, we've not seen a bug caused by this in practice (not even in
debug build mode), but better safe than sorry, so this patch changes the
code in one of two ways:

1. Code using coroutines can keep the "resource" as a variable on the
   stack.
2. Code using continuations needs to hold the "resource" with do_with(),
   but since this already incurs the cost of an extra allocation
   (even in the successful case), might as well just switch to using
   coroutines and have less ugly code.

This patch does not change any functionality, and all the tests seem to
work before and after it the same.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>

hello
2024-09-17 15:41:09 +03:00
Tomasz Grabiec
2c463ead59 gdb: Fix range printer for singular ranges
Before, it printed [x, +inf) instead of {x}
2024-09-17 14:30:28 +02:00
Andrei Chekun
bbb6c3c2ff test.py: Add resource consumption metrics
This PR adds the possibility to gather resource consumption metrics. The collected metrics can be used to compare performance before and after specific changes aimed at increasing performance. Currently, this functionality works only in manual mode, and this is just raw data. Later on, these metrics can be used in Jupyter notebook to analyze and visualize how the resources are used and can provide the insight on how to improve it. This PR is a first insight after gathering these metrics.

Add the possibility to gather resource consumption for the test.py execution. SQLite DB will be created with different performance metrics that will allow comparing the resource consumption between changes.
The DB will be in the tmp directory that by default set to testlog. Across the runs, the DB will not be deleted, so each new run will just add information to the existing DB.
Parameter --get-metrics was added to switch on or off the metrics gathering. By default, it's switched on.

Closes: scylladb/qa-tasks#1666

Closes: scylladb/qa-tasks#1707

Closes scylladb/scylladb#19881
2024-09-17 15:22:34 +03:00
Benny Halevy
39ce358d82 time_window_compaction_strategy: get_reshaping_job: restrict sort of multi_window vector to its size
Currently the function calls boost::partial_sort with a middle
iterator that might be out of bound and cause undefined behavior.

Check the vector size, and do a partial sort only if its longer
than `max_sstables`, otherwise sort the whole vector.

Fixes scylladb/scylladb#20608

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>

Closes scylladb/scylladb#20609
2024-09-17 15:05:37 +03:00
Tomasz Grabiec
adf99402c5 Merge 'readers/flat_mutation_reader_v2: call set_close_required() from consume*()' from Botond Dénes
The `consume*()` variants just forward the call to the `_impl` method with the same name. The latter, being a member of `::impl`, will bypass the top level `fill_buffer()`, etc. methods and thus will never call `set_close_required()`. Do this in the top-level `consume*()` methods instead, to ensure a reader, on which only `consume*()` is called, and then is destroyed, will complain as it should (and abort).
Only one place was found in core code, which didn't close the reader: `split_mutation() in `mutation/mutation.cc` and this reader is the "from-mutation" one which has no real close routine. All other places were in tests. All this is to say, there were no real bugs uncovered by this PR.

Fixes #16520

Improvement, no backport required.

Closes scylladb/scylladb#16522

* github.com:scylladb/scylladb:
  readers/flat_mutation_reader_v2: call set_close_required() from consume*()
  test/boost/sstable_compaction_test: close reader after use
  test/boost/repair_test: close reader after use
  mutation/mutation: split_mutation(): close reader after use
2024-09-17 13:21:34 +02:00
Anna Mikhlin
66c0814c33 Update ScyllaDB version to: 6.3.0-dev 2024-09-17 13:43:04 +03:00
Botond Dénes
6250ff18eb Merge 'sstable: s/crawling_sstable_mutation_reader/sstable_full_scan_reader' from Kefu Chai
"crawling" is a little bit obscure in this context. so let's rename this class to reflect the fact that this reader only reads the entire content of the sstable.

both crawling reader for kl and mx formats are renamed. also, in order to be consistent, all "crawling reader" in variable names are updated as well.

---

it's a cleanup, hence no need to backport.

Closes scylladb/scylladb#20599

* github.com:scylladb/scylladb:
  sstable: s/crawling_sstable_mutation_reader/sstable_full_scan_reader
  sstable/mx/reader: add comment for mx_crawling_sstable_mutation_reader
2024-09-17 11:55:08 +03:00
Pavel Emelyanov
ebfa73e004 s3/client: Don't move file from write_body's lambda
Requests sent by S3 are retriable, so when request.write_body() is
called, it should keep everything intact in case http client will call
it again.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>

Closes scylladb/scylladb#20579
2024-09-17 09:48:09 +03:00
Tzach Livyatan
cb864b11d8 Update client-node-encryption: OpsnSSL is FIPS *enabled*
Closes scylladb/scylladb#19705
2024-09-17 09:47:07 +03:00
Botond Dénes
f32e67cb9e Merge 'Make sstables without on-disk path' from Pavel Emelyanov
New sstables for a table are created by the table::make_sstable() method. The method then calls sstables_manager::make_sstable() and passes there a path to component files which, in turn, sits on table::config. Since some time ago having an on-disk path for an sstable had become optional, as sstables could be put on S3 storage without local paths involved. In that case the aforementioned "path" is ~~ab~~used as a key in the system.sstables registry, that references a record with information used to retrieve URLs of sstables' objects.

This PR removes the "path" argument from sstables_manager::make_sstable() and its sstable_sdirectory peer. The details of sstables' location are moved onto storage_options and depend on storage type. For now in both storage types this location is still the good-old $datadir/$keyspace/$table-$uuid string. S3 storage needs to be patched more to use more elegant "location" value.

Eventually the `table::config::{datadir|all_datadirs}` will be removed, this PR is the step towards it.

closes: #12707

Closes scylladb/scylladb#20542

* github.com:scylladb/scylladb:
  table: Use storage options to clean the storage
  sstables/storage: Re-use ocally generated vector of paths
  sstables/storage: Visit options once to initialize storage
  sstables_manager: Return table storage options when initalizing storage
  sstables/storage: Fix indentation after previous patch
  table: Move datadirs initialization parallelism to storage level
  sstables/storage: Split the visitor's overloaded functor
  restore: Don't use table_dir to construct sstable_directory
  sstable_directory: Remove table_dir field
  sstable_directory: Use options details in lister
  sstables_manager: Remove table_dir from make_sstable()
  sstables: Remove table_dir from sstable constructor
  sstables/storage: Remove sstring dir from make_storage()
  sstables/storage: Use options to construct
  tests: Properly initialize storage options with "dir"
  distributed_loader: Create S3 options with prefix for restore
  storage_options: Add special-purpose local options maker
  storage_options: Keep local path / s3 prefix onboard
  table: Get another options when initializing storage
2024-09-17 09:41:21 +03:00
Kefu Chai
df7f332a58 sstable: s/crawling_sstable_mutation_reader/sstable_full_scan_reader
"crawling" is a little bit obscure in this context. so let's rename this
class to reflect the fact that this reader only reads the entire content
of the sstable.

both crawling reader for kl and mx formats are renamed. also, in order
to be consistent, all "crawling reader" in variable names are updated
as well.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-17 10:39:37 +08:00
Kefu Chai
c1ed2f0ea4 sstable/mx/reader: add comment for mx_crawling_sstable_mutation_reader
to explain its typical usage.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
2024-09-17 10:39:25 +08:00
Michał Jadwiszczak
b4b91ca364 message/messaging_service: guard adding maintenance tenant under cluster feature
Set `enabled` flag for `$maintenance` tenant to false and
enable it when `MAINTENANCE_TENANT` feature is enabled.
2024-09-16 15:34:36 +02:00
Michał Jadwiszczak
71a03ef6b0 message/messaging_service: add feature_service dependency 2024-09-16 15:33:40 +02:00
Michał Jadwiszczak
d44844241d message/messaging_service: add enabled flag to statement tenants
Adding a new tenant needs to be done under cluster feature protection.
However it wasn't the case for adding `$maintenance` statement tenant
and to fix it we need to support an upgrade from node which doesn't
know about maintenance tenant at all and from one which uses it without
any cluster feature protection.

This commit adds `enabled` flag to statement tenants.
This way, when the tenant is disabled, it cannot be used to create
a connection, but it can be used to accept an incoming connection.
2024-09-16 15:31:04 +02:00
Michał Jadwiszczak
de7acbad8b test/cql-pytest: add test for SELECT ... USING SERVICE LEVEL 2024-09-16 14:31:43 +02:00
Michał Jadwiszczak
8255c61f5f cql3/Cql.g: extend grammar to allow SELECT ... USING SERVICE LEVEL 2024-09-16 14:31:32 +02:00
Michał Jadwiszczak
af6dc78025 cql3/statements/select_statement: use service level timeout
Use service level timeout in selecte statement when specified.
`USING TIMEOUT` have higher priority in timeout definition.
2024-09-16 13:48:48 +02:00
Michał Jadwiszczak
2e545c915b cql3/attributes: add service level name field
In next patches, we will allow to do `SELECT ... USING SERVICE LEVEL
sl_name`. To do it, we need to extend `cql3::attributes` with service
level name.
2024-09-16 13:48:43 +02:00
Michał Jadwiszczak
b9b326c2bb qos/service_level_controller: add method to check if service level exists in cache
There is `service_level_controller::get_service_level()` method,
which searches for service level in the controller cache and returns
default service level if SL with given name doesn't exist.

Added method allows to check whether a service level exists in the
controller cache.
2024-09-16 12:41:15 +02:00
Pavel Emelyanov
bf5021e735 test: Remove sstables::test::binary_search()
That's the most mysterious wrapper in this set as it doesn't need
sstable itself at all, it just duplicates the existing non-class
function out there.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:51:35 +03:00
Pavel Emelyanov
309d315af7 test: Remove sstables::test::move_summary()
This one is a bit tricky, as it needs to modify the sstables's summary.
However, the sstables::test::_summary() one returns mutable reference
and the only caller can use it.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:50:48 +03:00
Pavel Emelyanov
deec952111 test: Remove sstables::test::read_toc()
The sstable::read_toc() is public method, use it directly.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:50:19 +03:00
Pavel Emelyanov
25cd8ccdd8 test: Remove sstables::test::get_summary()
Same as previous patch -- callers can come with const reference to
summary, so they can live with existing public sstable::get_summary().

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:49:39 +03:00
Pavel Emelyanov
f714ac9b48 test: Remove sstables::test::get_statistics()
Just call the public sstable::get_statistics(). The callers would get
const reference on it, but they don't need more than that.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:48:43 +03:00
Pavel Emelyanov
53afa583e8 test: Remove sstables::test::data_read()
The wrapper just changes the order of arguments for a public method.
Drop it, and call the wrapee directly.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-16 12:47:59 +03:00
Avi Kivity
e4cab3a5e9 cql3: statement_restrictions: drop accessors for single-column key restrictions
No longer used.
2024-09-16 12:15:14 +03:00
Avi Kivity
626acf416e cql3: selection: adjust indentation 2024-09-16 12:15:14 +03:00
Avi Kivity
c443d922ea cql3: selection: delete empty loop
Our refactoring left a loop with no body, delete it.
2024-09-16 12:15:14 +03:00
Avi Kivity
56e8a4c931 cql3: statement_restrictions, selection: fold multi-column restrictions into row-level filter
When filtering, we apply single-column and multi-column filters separately.

This is completely unnecessary. Find the multi-column filters during prepare
time and append them to the row-level filter.

This slightly changes the original: in the original, if we had a multi-column
filter, we applied all of the restrictions. But hopefully if we check
for multi-column filters, that's what we need.
2024-09-16 12:15:14 +03:00
Avi Kivity
a6d81806c0 cql3: statement_restrictions, selection: merge clustering key filter and regular columns filter
The two filters are used in the same way: check the filter, return false if
it matches.

Unify the two filters into a clustering_row_level_filter.

Since one of the two filters wasn't std::optional, we take the liberty
of making the combined filter non-optional.
2024-09-16 12:15:03 +03:00
Avi Kivity
2933a2f118 cql3: statement_restrictions, selection: merge partition key filter and static columns filter
The two filters are used in the same way: check the filter, set a boolean
flag if it matches, return false. The two boolean flags are in turn checked
in the same way.

Unify the two filters into a partition_level_filter.

Since one of the two filters wasn't std::optional, we take the liberty
of making the combined filter non-optional.
2024-09-16 12:10:49 +03:00
Avi Kivity
807153a9ed cql3: selection: filter regular and static rows as a single expression each
Instead of filtering regular and static columns column by column, call
is_satisfied_by() for an expression containing all the static columns
predicates, and one for all the regular column.

We cannot have one expression, since the code sets
_current_static_row_does_not_match only for static columns.

Note the fix for #20485 is now implicit, since the evaluation machinery
will treat missing regular columns as NULL.
2024-09-15 14:33:57 +03:00
Avi Kivity
3c71096479 cql3: statement_restrictions: collect regular column and static column filters into single expressions
Similar to previous work with clustering and partition key, expose
static and reglar column filters as single expressions.

Since we don't currently expose a boolean for whether those filters
exist, we expose them now as non-optionals. In any case evaluating
an empty conjunction is plenty fast.
2024-09-15 14:33:57 +03:00
Avi Kivity
ec2898afe9 cql3: selection: filter clustering key as a single expression
Instead of filtering the clustering key column by column, call
is_satisfied_by() for an expression containing all the clustering key
predicates.

The check for clustering_key.empty() is removed; the evaluation machinery
is able to handle partial clustering keys. In fact if we add IS NULL,
we have to evaluate as an empty clustering key should match.
2024-09-15 14:33:57 +03:00
Avi Kivity
318d653d80 cql3: statement_restrictions: expose filter for clustering key
cql3::selection performs filtering by consulting
ck_restrictions_need_filtering() and
get_single_column_clustering_key_restrictions() (which is a map of column
definition to expressions). Make them available in one
nice package as an optional<expression>. When the optional is engaged,
filtering is needed, and the expression in the equivalent of all of the
map.
2024-09-15 14:33:57 +03:00
Avi Kivity
0bd2f12922 cql3: selection: filter partition key as a single expression
Instead of filtering the partition key column by column, call
is_satisfied_by() for an expression containing all the partition key
predicates.
2024-09-15 14:33:56 +03:00
Avi Kivity
21cb91077f cql3: statement_restrictions: expose filter for partition key
cql3::selection performs filtering by consulting
pk_restrictions_need_filtering() and
get_single_column_partition_key_restrictions() (which is a map of column
definition to expressions). Make them available in one
nice package as an optional<expression>. When the optional is engaged,
filtering is needed, and the expression in the equivalent of all of the
map.
2024-09-15 14:33:56 +03:00
Avi Kivity
a453221314 cql3: statement_restrictions: remove relations used for indexing from filtering
statement_restrictions does not name columns that were used for a secondary
index for selection for filtering, since accessing the index "pre-filters"
these columns.

However, it keeps the relations that contain these columns. This makes
it impossible (besides unnecessary) to evaluate the relations, as the
columns they reference aren't selected.

The reason this works now is that
result_set_builder::restrictions_filter::do_filter() iterates on selected
columns, matching them to relations, then execute the matched relation.
A relation that references an unselected column is invisible to do_filter().

We wish to filter using complete expressions, rather than fragments, so as
a first step remove these unnecessary and unusable relations while we
choose which columns are necessary for filtering.

calculate_column_defs_for_filtering is renamed to remind us of the extra
work done.
2024-09-15 14:33:56 +03:00
Avi Kivity
ba8c2014bf cql3: statement_restrictions: bail out of find_idx if !_uses_secondary_index
The condition seems trivial, but wasn't implemented, without ill effects
so far.

With the following patches, calculate_column_defs_for_filtering() becomes
confused as it selects an indexing code path even when !_uses_secondary_index,
triggered by the reproducer of #10300.
2024-09-15 14:33:56 +03:00
Avi Kivity
65ba19323c cql3: statement_restrictions, modification_statement: pass correct value of check_indexes
Our UPDATE/INSERT/DELETE statements require a full primary/partition key
and therefore never use indexes; fix the check_index parameter passed from
modification_statement.

So far the bug is benign as we did not take any action on the value.

Make the parameter non-default to avoid such confusion in the future.
2024-09-15 14:33:56 +03:00
Avi Kivity
71ea3200ba cql3: statement_restrictions: correct mismatched clustering/partition restrictions references
The second loop of calculate_column_defs_for_filtering() finds clustering
keys that are used for filtering, minus and clustering keys that happen
to be used for secondary indexing.

However, to check whether the clustering key is used for secondary indexing,
it looks up in _single_column_partition_key_restrictions, which contains
partition key restrictions.

The end result is that we select a column which ends the partition key
for the secondary index, and so is unnecessary. We do a little more work,
but the bug is benign. Nevertheless, fix it, as it interferes with following
work.
2024-09-15 14:33:56 +03:00
Avi Kivity
33db14e7d5 cql3: statement_restrictions: precalculate get_column_defs_for_filtering()
get_column_defs_for_filtering() names all the columns that are required
for filtering. While doing that, it skips over columns that are participate
in indexing (primary or secondary), since the index "pre-filters" the
query.

We wish to make use of this skipping. As a first step, call the calculation
from the constructor, so we have control over when it is executed.
2024-09-15 14:33:56 +03:00
Avi Kivity
251ad4fcd0 cql3: selection: do_filter(): push static/regular row glue to higher level
Currently, for each column we call get_non_pk_values() to transform
the way we get the information (query::result_row_view) to the way
the expression evaluation machinery wants it (vector<managed_bytes_opt>).

Call it just once outside the loop.
2024-09-15 14:33:56 +03:00
Pavel Emelyanov
f850681b14 table: Use storage options to clean the storage
Like it was done for table::init_storage(), patch the
table::destroy_storage() not to mess with datadir path and rely on
storage options only.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
3aea7bebb7 sstables/storage: Re-use ocally generated vector of paths
A cleanup after prefious patch -- in order to create storage options for
table the local initialization code can re-use the vector of paths that
it hag generated in the same call to create table directory layout.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
7c34724509 sstables/storage: Visit options once to initialize storage
The init_table_storage() method now does it twice -- one time to
initialize the storage, another one to create new options for table.
Both can be merged, thus making table storage options initialization
better encapsulated for local/s3 cases.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
311fb906be sstables_manager: Return table storage options when initalizing storage
Now the table::init_storage() calls sstables manager two times -- first,
to get storage options, second, to initialize the storage with obtained
options. Merge two calls into one.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
918ec00c1d sstables/storage: Fix indentation after previous patch
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
f1e4367439 table: Move datadirs initialization parallelism to storage level
The table::init_table_storage() calls sstables_manager's storage
initialization for each of the datadirs found on config. That's not
great, it's sstables manager (and its storage) that know if table needs
to mess with datadirs or not. This patch moves the loop to storage.cc.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
b6b3a477c5 sstables/storage: Split the visitor's overloaded functor
The main goal is to have init_table_storage() overload for local options
as standalone function. This makes next patching simpler.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
30c8d89f97 restore: Don't use table_dir to construct sstable_directory
Continuation of the previous patch patching the special-purpose sstable
directory constructor that's used by restore-from-s3-backup code.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
af14408052 sstable_directory: Remove table_dir field
It's no longer needed -- both, lister and making sstable, work with
having storage options at hand.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
f403728aa4 sstable_directory: Use options details in lister
This class is very similar to sstables::storage one -- it also needs
path or s3 prefix to construct. Now when this information is stored on
storage_options, it's better to stick to it, not to the argument.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
36863d4ad0 sstables_manager: Remove table_dir from make_sstable()
It used to be passed to sstable constructor, but now it doesn't need
this argument.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
0764eca553 sstables: Remove table_dir from sstable constructor
It used to be passed to storage constructor, now storage works with
options only and this argument is no longer needed.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
d79ae1f02b sstables/storage: Remove sstring dir from make_storage()
Now the directory/s3 prefix is propagated via storage options.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
65a19df8ef sstables/storage: Use options to construct
All callers of make_sstable are now patched to provide correct storage
options with path/prefix set. The make_storage() helper can switch to
using it. Respectively, it's good to make sure that the storage is
created with table options that have path/prefix.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
4425cf54c6 tests: Properly initialize storage options with "dir"
Most of the tests work with local storage options. Some support S3
options as well. Whatever it is, when creating an sstable, tests need to
put proper "dir" on the options, this patch does so.

In fact, storage options for tests are created together with the
test-env, and ideally this is the place where dir should be assigned on
it. However, there are still places that explicitly specify path they
want to see sstables at, for those the new temporary options should be
constructed.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:49:50 +03:00
Pavel Emelyanov
33bc9e7112 distributed_loader: Create S3 options with prefix for restore
Restore-from-backup code wants to collect sstables from remote S3. For
that it constructs S3 options, and now it needs to put prefix on it as
well.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:32:39 +03:00
Pavel Emelyanov
56111a50cd storage_options: Add special-purpose local options maker
Lost of code (in tools and tests) explicitly deal with local sstables
and need to create options for it. Currently default-constructing
options generates local ones, but without the directory path. Add a
helper that creates local options with path and patch callers.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:32:39 +03:00
Pavel Emelyanov
95e60cde9f storage_options: Keep local path / s3 prefix onboard
Now when tables keep their own copy of storage options, it's possible
for each table to add table-specific information on it. Namely -- path
for local storage and prefix for S3 one (in fact, it's not a "prefix",
but a key in sstables registry, but fixing it is beyond the scope of
this set).

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:32:32 +03:00
Pavel Emelyanov
14976fda73 table: Get another options when initializing storage
Right now the table's storage_options life starts in cql, and shortly
after the lw-shared-pointer to options is put on keyspace metadata.
Later, when the table is created the pointer from keyspace is copied on
the table via its contructor.

Next patches will extend the options pointed to by a table, and the
extension is going to be different for different tables. For that, each
table needs to have its private options and this patch prepares for
that.

For now table directly calls sstables/storage code to get the options
from, but it's temporary, soon the options will be created via sstables
manager together with initialising the storage itself.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-13 16:32:32 +03:00
Botond Dénes
cb30271d29 readers/flat_mutation_reader_v2: call set_close_required() from consume*()
The `consume*()` variants just forward the call to the `_impl` method
with the same name. The latter, being a member of `::impl`, will bypass
the top level `fill_buffer()`, etc. methods and thus will never call
`set_close_required()`. Do this in the top-level `consume*()` methods
instead, to ensure a reader, on which only `consume*()` is called, and
then is destroyed, will complain as it should (and abort).

operator()() was also missing `set_close_required()`, fix that too.
2024-09-13 06:52:26 -04:00
Botond Dénes
fbed280cd5 test/boost/sstable_compaction_test: close reader after use 2024-09-13 06:52:26 -04:00
Botond Dénes
116b044fec test/boost/repair_test: close reader after use 2024-09-13 06:52:26 -04:00
Botond Dénes
1a11f9cf95 mutation/mutation: split_mutation(): close reader after use 2024-09-13 06:52:26 -04:00
Takuya ASADA
0ac450de05 scylla_raid_setup: configure SELinux file context
On RHEL9, systemd-coredump fails to coredump on /var/lib/scylla/coredump
because the service only have write acess with systemd_coredump_var_lib_t.
To make it writable, we need to add file context rule for
/var/lib/scylla/coredump, and run restorecon on /var/lib/scylla.

Fixes #20573
2024-09-13 04:31:52 +09:00
Takuya ASADA
56c971373c scylla_coredump_setup: fix SELinux configuration for RHEL9
Seems like specific version of systemd pacakge on RHEL9 has a bug on
SELinux configuration, it introduced "systemd-container-coredump" module
to provide rule for systemd-coredump, but not enabled by default.
We have to manually load it, otherwise it causes permission error.

Fixes #19325
2024-09-13 04:31:16 +09:00
Botond Dénes
f834ad81e0 docs/dev/reader-concurrency-semaphore.md: update the documentation on diagnostics dumps
The part of the document which explains diagnostics dumps was due for an
update. It was missing an explanation on the dumped stats and it
also needs to explain the "Problematic permit" and "Identified
bottleneck(s)".
2024-09-12 08:31:25 -04:00
Botond Dénes
fdff4beb1f test/boost/reader_concurrency_semaphore_test: test the new diagnostics functionality
Adjust the test reader_concurrency_semaphore_dump_reader_diganostics to
also cover the new diagnostics functionality. The test is not a
correctness test -- the output has to be inspected by a human. But it is
good enough to make sure the code paths do not have any memory errors.
2024-09-12 08:31:25 -04:00
Botond Dénes
40b6616d3d reader_concurrency_semaphore: add bottleneck self-diagnosis to diagnosis dump
There are a few typical cases of bottlenecks, which can be easily
identified when dumping the semaphore diagnostics. Identify and print
these to fast-track investigations.
2024-09-12 08:31:25 -04:00
Botond Dénes
7d2b931619 reader_concurrency_semaphore: include trigger permit in diagnostic dump
In the previous patch, we provided an opportunity for callers to provide
a trigger permit, when calling `maybe_dump_reader_permit_diagnostics()`.
If the caller provided the trigger permit, include its details in the
dump, allowing the identification of the table and code-path of the
permit which triggered the dump.
2024-09-12 08:30:50 -04:00
Benny Halevy
0b93409b44 cql_server: connection: process: fixup indentation
Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-12 11:32:17 +02:00
Benny Halevy
71052dca6a cql_server: connection: process_on_shard: drop permit parameter
It is currently unused in `process_on_shard`, which
generates an empty service_permit.

The next patch may call process_on_shard in a loop,
so it can't simply move the permit to the callee
and better hold on to it until processing completes.

`cql_server::connection::process` was turned into
a coroutine in this patch to hold on to the permit parameter
in a simple way. This is a preliminary step to changing
`if (bounce_msg)` to `while (bounce_msg)` that will allow
rebouncing the message in case it moved yet again when
yielding in `process_on_shard`.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-12 11:32:17 +02:00
Benny Halevy
eb7fbdbed2 transport: server: pass bounce_to_shard as foreign shared ptr
So it can safely passed between shards, as will be needed
in the following patch that handles a (re)bounce_to_shard result
from process_fn that's called by `process_on_shard` on the
`move_to_shard`.

With that in mind, pass the `bounce_to_shard` payload
to `process_on_shard` rather than the foreign shared ptr
since the latter grabs what it needs from it on entry
and the shared_ptr can be released on the calling shard.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-12 11:32:15 +02:00
Benny Halevy
0df6f55379 cql_server: connection: process: add template concept for process_fn
Quoting Avi Kivity:
> Out of scope: we should consider detemplating this.

As a follow-up we should consider that and pass
a function object as process_fn, just make sure
there are no drawbacks.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-12 10:26:13 +02:00
Benny Halevy
150dce5de0 cql_server: move process_fn_return_type to class definition
So it can be used for a template concept in the next patch.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
2024-09-12 10:26:13 +02:00
Botond Dénes
c044904f07 reader_concurrency_semaphore: propagate permit to do_dump_reader_permit_diagnostics()
Will be used in the next patch.
2024-09-12 00:51:56 -04:00
Botond Dénes
67565a5eee reader_concurrency_semaphore: use consistent exception type for timeout
When a read times out, we use different exception types for the permit's
future (if the permit is waiting), or the permit's abort exception _ex
(which is used to abort ongoing reads). This patch changes both to use
named_semaphore_timed_out, which is the more verbose of the two.
2024-09-12 00:51:03 -04:00
Botond Dénes
036d27dc1b reader_concurrency_semaphore: dump diagnostics when non-waiting reader times out
Currently the semaphore only dumps diagnostics when a waiting reader
times out. The diagnostics are also useful when a non-waiting reader
(which is in the process of reading) times out, so also dump diagnostics
in this case.
Change the code to use a switch statement, so future addition of states
don't miss updating this logic.
2024-09-12 00:51:03 -04:00
Amnon Heiman
46792bd04f docs/alternator/compatibility.md: explain the consumed capacity provisioned
This patch change the alternator documentation to express that the
provisoned units are stored and return but Alternator ignores them.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-10 17:28:31 -04:00
Amnon Heiman
3726c20564 Add test/alternator/test_provisioned_throughput.py
The test_provisioned_throughput.py test ProvisionedThroughput support.
The first test, check that ProvisionedThroughput can be set and get when
using describe table.

The second test check that missing read or write will throw an
exception.

The third test check that when using billing PAY_PER_REQUEST it returns
zero for the read and write units.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-10 17:27:19 -04:00
Amnon Heiman
9b5f29b6bc test/alternator/util.py: Allow override BillingMode
This patch adds the ability to override the BillingMode. If a
BillingMode is provided to the create_test_table function, it will
override the default BillingMode.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-10 17:06:47 -04:00
Amnon Heiman
c76347032d alternator/executor.cc: Store ProvisionedThroughput
This patch adds the ability to store and retrieve the
ProvisionedThroughput in a table.

The information is stored in the table tags. We use the TTL convention
used in alternator, and the tags will be: system:provisioned_rcu and
system:provisioned_wcu.

verify_billing_mode function now return a struct with the billing mode
information.

The code of describe_table now check if the provision tags exists and
return the RCU and WCU accordingly.

Signed-off-by: Amnon Heiman <amnon@scylladb.com>
2024-09-10 17:06:40 -04:00
Pavel Emelyanov
103c68b419 sstables: Restore indentation after previous patch
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-06 18:24:56 +03:00
Pavel Emelyanov
c47c0f1cd6 sstables: Coroutinize remove_unshared_sstables()
Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2024-09-06 18:24:40 +03:00
1024 changed files with 24418 additions and 10395 deletions

View File

@@ -1,7 +1,7 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignAfterOpenBracket: DontAlign
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
@@ -42,9 +42,9 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
@@ -52,8 +52,8 @@ AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: false
BinPackParameters: false
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
@@ -89,7 +89,7 @@ ColumnLimit: 160
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
@@ -103,22 +103,6 @@ ForEachMacros:
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
@@ -148,7 +132,7 @@ MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PackConstructorInitializers: NextLine
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
@@ -171,9 +155,9 @@ RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortIncludes: Never
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SortUsingDeclarations: Never
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true

5
.github/CODEOWNERS vendored
View File

@@ -91,7 +91,7 @@ test/boost/mutation_reader_test.cc @denesb
test/boost/querier_cache_test.cc @denesb
# PYTEST-BASED CQL TESTS
test/cql-pytest/* @nyh
test/cqlpy/* @nyh
# RAFT
raft/* @kbr-scylla @gleb-cloudius @kostja
@@ -99,3 +99,6 @@ test/raft/* @kbr-scylla @gleb-cloudius @kostja
# HEAT-WEIGHTED LOAD BALANCING
db/heat_load_balance.* @nyh @gleb-cloudius
# Tools
tools/* @denesb

View File

@@ -1,15 +0,0 @@
This is Scylla's bug tracker, to be used for reporting bugs only.
If you have a question about Scylla, and not a bug, please ask it in
our mailing-list at scylladb-dev@googlegroups.com or in our slack channel.
- [] I have read the disclaimer above, and I am reporting a suspected malfunction in Scylla.
*Installation details*
Scylla version (or git commit hash):
Cluster size:
OS (RHEL/CentOS/Ubuntu/AWS AMI):
*Hardware details (for performance issues)* Delete if unneeded
Platform (physical/VM/cloud instance type/docker):
Hardware: sockets= cores= hyperthreading= memory=
Disks: (SSD/HDD, count)

86
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,86 @@
name: "Report a bug"
description: "File a bug report."
title: "[Bug]: "
type: "bug"
labels: bug
body:
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: "This is Scylla's bug tracker, to be used for reporting bugs only.
If you have a question about Scylla, and not a bug, please ask it in
our forum at https://forum.scylladb.com/ or in our slack channel https://slack.scylladb.com/ "
options:
- label: I have read the disclaimer above and am reporting a suspected malfunction in Scylla.
required: true
- type: input
id: product-version
attributes:
label: product version
description: Scylla version (or git commit hash)
placeholder: ex. scylla-6.1.1
validations:
required: true
- type: input
id: cluster-size
attributes:
label: Cluster Size
validations:
required: true
- type: input
id: os
attributes:
label: OS
placeholder: RHEL/CentOS/Ubuntu/AWS AMI
validations:
required: true
- type: textarea
id: additional-data
attributes:
label: Additional Environmental Data
#description:
placeholder: Add additional data
value: "Platform (physical/VM/cloud instance type/docker):\n
Hardware: sockets= cores= hyperthreading= memory=\n
Disks: (SSD/HDD, count)"
validations:
required: false
- type: textarea
id: reproducer-steps
attributes:
label: Reproduction Steps
placeholder: Describe how to reproduce the problem
value: "The steps to reproduce the problem are:"
validations:
required: true
- type: textarea
id: the-problem
attributes:
label: What is the problem?
placeholder: Describe the problem you found
value: "The problem is that"
validations:
required: true
- type: textarea
id: what-happened
attributes:
label: Expected behavior?
placeholder: Describe what should have happened
value: "I expected that "
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell

9
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/docs"
schedule:
interval: "daily"
allow:
- dependency-name: "sphinx-scylladb-theme"
- dependency-name: "sphinx-multiversion-scylla"

50
.github/mergify.yml vendored
View File

@@ -15,6 +15,31 @@ pull_request_rules:
- closed
actions:
delete_head_branch:
- name: Automate backport pull request 6.2
conditions:
- or:
- closed
- merged
- or:
- base=master
- base=next
- label=backport/6.2 # The PR must have this label to trigger the backport
- label=promoted-to-master
actions:
copy:
title: "[Backport 6.2] {{ title }}"
body: |
{{ body }}
{% for c in commits %}
(cherry picked from commit {{ c.sha }})
{% endfor %}
Refs #{{number}}
branches:
- branch-6.2
assignees:
- "{{ author }}"
- name: Automate backport pull request 6.1
conditions:
- or:
@@ -40,31 +65,6 @@ pull_request_rules:
- branch-6.1
assignees:
- "{{ author }}"
- name: Automate backport pull request 5.4
conditions:
- or:
- closed
- merged
- or:
- base=master
- base=next
- label=backport/5.4 # The PR must have this label to trigger the backport
- label=promoted-to-master
actions:
copy:
title: "[Backport 5.4] {{ title }}"
body: |
{{ body }}
{% for c in commits %}
(cherry picked from commit {{ c.sha }})
{% endfor %}
Refs #{{number}}
branches:
- branch-5.4
assignees:
- "{{ author }}"
- name: Automate backport pull request 6.0
conditions:
- or:

181
.github/scripts/auto-backport.py vendored Executable file
View File

@@ -0,0 +1,181 @@
#!/usr/bin/env python3
import argparse
import os
import re
import sys
import tempfile
import logging
from github import Github, GithubException
from git import Repo, GitCommandError
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
try:
github_token = os.environ["GITHUB_TOKEN"]
except KeyError:
print("Please set the 'GITHUB_TOKEN' environment variable")
sys.exit(1)
def is_pull_request():
return '--pull-request' in sys.argv[1:]
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--repo', type=str, required=True, help='Github repository name')
parser.add_argument('--base-branch', type=str, default='refs/heads/master', help='Base branch')
parser.add_argument('--commits', default=None, type=str, help='Range of promoted commits.')
parser.add_argument('--pull-request', type=int, help='Pull request number to be backported')
parser.add_argument('--head-commit', type=str, required=is_pull_request(), help='The HEAD of target branch after the pull request specified by --pull-request is merged')
return parser.parse_args()
def create_pull_request(repo, new_branch_name, base_branch_name, pr, backport_pr_title, commits, is_draft=False):
pr_body = f'{pr.body}\n\n'
for commit in commits:
pr_body += f'- (cherry picked from commit {commit})\n\n'
pr_body += f'Parent PR: #{pr.number}'
try:
backport_pr = repo.create_pull(
title=backport_pr_title,
body=pr_body,
head=f'scylladbbot:{new_branch_name}',
base=base_branch_name,
draft=is_draft
)
logging.info(f"Pull request created: {backport_pr.html_url}")
backport_pr.add_to_assignees(pr.user)
logging.info(f"Assigned PR to original author: {pr.user}")
return backport_pr
except GithubException as e:
if 'A pull request already exists' in str(e):
logging.warning(f'A pull request already exists for {pr.user}:{new_branch_name}')
else:
logging.error(f'Failed to create PR: {e}')
def get_pr_commits(repo, pr, stable_branch, start_commit=None):
commits = []
if pr.merged:
merge_commit = repo.get_commit(pr.merge_commit_sha)
if len(merge_commit.parents) > 1: # Check if this merge commit includes multiple commits
commits.append(pr.merge_commit_sha)
else:
if start_commit:
promoted_commits = repo.compare(start_commit, stable_branch).commits
else:
promoted_commits = repo.get_commits(sha=stable_branch)
for commit in pr.get_commits():
for promoted_commit in promoted_commits:
commit_title = commit.commit.message.splitlines()[0]
# In Scylla-pkg and scylla-dtest, for example,
# we don't create a merge commit for a PR with multiple commits,
# according to the GitHub API, the last commit will be the merge commit,
# which is not what we need when backporting (we need all the commits).
# So here, we are validating the correct SHA for each commit so we can cherry-pick
if promoted_commit.commit.message.startswith(commit_title):
commits.append(promoted_commit.sha)
elif pr.state == 'closed':
events = pr.get_issue_events()
for event in events:
if event.event == 'closed':
commits.append(event.commit_id)
return commits
def create_pr_comment_and_remove_label(pr, comment_body):
labels = pr.get_labels()
pattern = re.compile(r"backport/\d+\.\d+$")
for label in labels:
if pattern.match(label.name):
print(f"Removing label: {label.name}")
comment_body += f'- {label.name}\n'
pr.remove_from_labels(label)
pr.create_issue_comment(comment_body)
def backport(repo, pr, version, commits, backport_base_branch):
new_branch_name = f'backport/{pr.number}/to-{version}'
backport_pr_title = f'[Backport {version}] {pr.title}'
repo_url = f'https://scylladbbot:{github_token}@github.com/{repo.full_name}.git'
fork_repo = f'https://scylladbbot:{github_token}@github.com/scylladbbot/{repo.name}.git'
with (tempfile.TemporaryDirectory() as local_repo_path):
try:
repo_local = Repo.clone_from(repo_url, local_repo_path, branch=backport_base_branch)
repo_local.git.checkout(b=new_branch_name)
is_draft = False
for commit in commits:
try:
repo_local.git.cherry_pick(commit, '-m1', '-x')
except GitCommandError as e:
logging.warning(f'Cherry-pick conflict on commit {commit}: {e}')
is_draft = True
repo_local.git.add(A=True)
repo_local.git.cherry_pick('--continue')
if not repo.private and not repo.has_in_collaborators(pr.user.login):
repo.add_to_collaborators(pr.user.login, permission="push")
comment = f':warning: @{pr.user.login} you have been added as collaborator to scylladbbot fork '
comment += f'Please check your inbox and approve the invitation, once it is done, please add the backport labels again'
create_pr_comment_and_remove_label(pr, comment)
return
repo_local.git.push(fork_repo, new_branch_name, force=True)
create_pull_request(repo, new_branch_name, backport_base_branch, pr, backport_pr_title, commits,
is_draft=is_draft)
except GitCommandError as e:
logging.warning(f"GitCommandError: {e}")
def main():
args = parse_args()
base_branch = args.base_branch.split('/')[2]
promoted_label = 'promoted-to-master'
repo_name = args.repo
if 'scylla-enterprise' in args.repo:
promoted_label = 'promoted-to-enterprise'
stable_branch = base_branch
backport_branch = 'branch-'
backport_label_pattern = re.compile(r'backport/\d+\.\d+$')
g = Github(github_token)
repo = g.get_repo(repo_name)
closed_prs = []
start_commit = None
if args.commits:
start_commit, end_commit = args.commits.split('..')
commits = repo.compare(start_commit, end_commit).commits
for commit in commits:
match = re.search(rf"Closes .*#([0-9]+)", commit.commit.message, re.IGNORECASE)
if match:
pr_number = int(match.group(1))
pr = repo.get_pull(pr_number)
closed_prs.append(pr)
if args.pull_request:
start_commit = args.head_commit
pr = repo.get_pull(args.pull_request)
closed_prs = [pr]
for pr in closed_prs:
labels = [label.name for label in pr.labels]
backport_labels = [label for label in labels if backport_label_pattern.match(label)]
if promoted_label not in labels:
print(f'no {promoted_label} label: {pr.number}')
continue
if not backport_labels:
print(f'no backport label: {pr.number}')
continue
commits = get_pr_commits(repo, pr, stable_branch, start_commit)
logging.info(f"Found PR #{pr.number} with commit {commits} and the following labels: {backport_labels}")
for backport_label in backport_labels:
version = backport_label.replace('backport/', '')
backport_base_branch = backport_label.replace('backport/', backport_branch)
backport(repo, pr, version, commits, backport_base_branch)
if __name__ == "__main__":
main()

View File

@@ -16,13 +16,8 @@ def parser():
parser = argparse.ArgumentParser()
parser.add_argument('--repository', type=str, required=True,
help='Github repository name (e.g., scylladb/scylladb)')
parser.add_argument('--commit_before_merge', type=str, required=True, help='Git commit ID to start labeling from ('
'newest commit).')
parser.add_argument('--commit_after_merge', type=str, required=True,
help='Git commit ID to end labeling at (oldest '
'commit, exclusive).')
parser.add_argument('--update_issue', type=bool, default=False, help='Set True to update issues when backport was '
'done')
parser.add_argument('--commits', type=str, required=True, help='Range of promoted commits.')
parser.add_argument('--label', type=str, default='promoted-to-master', help='Label to use')
parser.add_argument('--ref', type=str, required=True, help='PR target branch')
return parser.parse_args()
@@ -53,12 +48,14 @@ def main():
target_branch = re.search(r'branch-(\d+\.\d+)', args.ref)
g = Github(github_token)
repo = g.get_repo(args.repository, lazy=False)
commits = repo.compare(head=args.commit_after_merge, base=args.commit_before_merge)
start_commit, end_commit = args.commits.split('..')
commits = repo.compare(start_commit, end_commit).commits
processed_prs = set()
# Print commit information
for commit in commits.commits:
for commit in commits:
print(f'Commit sha is: {commit.sha}')
match = pr_pattern.search(commit.commit.message)
pr_last_line = commit.commit.message.splitlines()[-1]
match = pr_pattern.search(pr_last_line)
if match:
pr_number = int(match.group(1))
if pr_number in processed_prs:
@@ -66,13 +63,13 @@ def main():
if target_branch:
pr = repo.get_pull(pr_number)
branch_name = target_branch[1]
refs_pr = re.findall(r'Refs (?:#|https.*?)(\d+)', pr.body)
refs_pr = re.findall(r'Parent PR: (?:#|https.*?)(\d+)', pr.body)
if refs_pr:
print(f'branch-{target_branch.group(1)}, pr number is: {pr_number}')
# 1. change the backport label of the parent PR to note that
# we've merge the corresponding backport PR
# we've merged the corresponding backport PR
# 2. close the backport PR and leave a comment on it to note
# that it has been merged with a certain git commit,
# that it has been merged with a certain git commit.
ref_pr_number = refs_pr[0]
mark_backport_done(repo, ref_pr_number, branch_name)
comment = f'Closed via {commit.sha}'

View File

@@ -5,9 +5,10 @@ on:
branches:
- master
- branch-*.*
env:
DEFAULT_BRANCH: 'master'
- enterprise
pull_request_target:
types: [labeled]
branches: [master, next, enterprise]
jobs:
check-commit:
@@ -20,17 +21,51 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Set Default Branch
id: set_branch
run: |
if [[ "${{ github.repository }}" == *enterprise* ]]; then
echo "DEFAULT_BRANCH=enterprise" >> $GITHUB_ENV
else
echo "DEFAULT_BRANCH=master" >> $GITHUB_ENV
fi
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
ref: ${{ env.DEFAULT_BRANCH }}
token: ${{ secrets.AUTO_BACKPORT_TOKEN }}
fetch-depth: 0 # Fetch all history for all tags and branches
- name: Set up Git identity
run: |
git config --global user.name "GitHub Action"
git config --global user.email "action@github.com"
git config --global merge.conflictstyle diff3
- name: Install dependencies
run: sudo apt-get install -y python3-github
run: sudo apt-get install -y python3-github python3-git
- name: Run python script
if: github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python .github/scripts/label_promoted_commits.py --commit_before_merge ${{ github.event.before }} --commit_after_merge ${{ github.event.after }} --repository ${{ github.repository }} --ref ${{ github.ref }}
GITHUB_TOKEN: ${{ secrets.AUTO_BACKPORT_TOKEN }}
run: python .github/scripts/label_promoted_commits.py --commits ${{ github.event.before }}..${{ github.sha }} --repository ${{ github.repository }} --ref ${{ github.ref }}
- name: Run auto-backport.py when promotion completed
if: github.event_name == 'push' && github.ref == 'refs/heads/${{ env.DEFAULT_BRANCH }}'
env:
GITHUB_TOKEN: ${{ secrets.AUTO_BACKPORT_TOKEN }}
run: python .github/scripts/auto-backport.py --repo ${{ github.repository }} --base-branch ${{ github.ref }} --commits ${{ github.event.before }}..${{ github.sha }}
- name: Check if label starts with 'backport/' and contains digits
id: check_label
run: |
label_name="${{ github.event.label.name }}"
if [[ "$label_name" =~ ^backport/[0-9]+\.[0-9]+$ ]]; then
echo "Label matches backport/X.X pattern."
echo "backport_label=true" >> $GITHUB_OUTPUT
else
echo "Label does not match the required pattern."
echo "backport_label=false" >> $GITHUB_OUTPUT
fi
- name: Run auto-backport.py when label was added
if: github.event_name == 'pull_request_target' && steps.check_label.outputs.backport_label == 'true' && (github.event.pull_request.state == 'closed' && github.event.pull_request.merged == true)
env:
GITHUB_TOKEN: ${{ secrets.AUTO_BACKPORT_TOKEN }}
run: python .github/scripts/auto-backport.py --repo ${{ github.repository }} --base-branch ${{ github.ref }} --pull-request ${{ github.event.pull_request.number }} --head-commit ${{ github.event.pull_request.base.sha }}

View File

@@ -10,6 +10,9 @@ on:
- 'docs/**'
- '.github/**'
workflow_dispatch:
issue_comment:
types:
- created
env:
BUILD_TYPE: RelWithDebInfo
@@ -25,6 +28,7 @@ concurrency:
jobs:
read-toolchain:
if: github.event_name == 'pull_request' || (github.event.issue.pull_request && startsWith(github.event.comment.body, '/clang-tidy'))
uses: ./.github/workflows/read-toolchain.yaml
clang-tidy:
name: Run clang-tidy

View File

@@ -0,0 +1,45 @@
name: Notify PR Authors of Conflicts
on:
schedule:
- cron: '0 10 * * 1,4' # Runs every Monday and Thursday at 10:00am
workflow_dispatch: # Manual trigger for testing
jobs:
notify_conflict_prs:
runs-on: ubuntu-latest
steps:
- name: Notify PR Authors of Conflicts
uses: actions/github-script@v7
with:
script: |
const prs = await github.paginate(github.rest.pulls.list, {
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
per_page: 100
});
const branchPrefix = 'branch-';
const threeDaysAgo = new Date();
const conflictLabel = 'conflicts';
threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
for (const pr of prs) {
if (!pr.base.ref.startsWith(branchPrefix)) continue;
const hasConflictLabel = pr.labels.some(label => label.name === conflictLabel);
if (!hasConflictLabel) continue;
const updatedDate = new Date(pr.updated_at);
if (updatedDate >= threeDaysAgo) continue;
if (pr.assignee === null) continue;
const assignee = pr.assignee;
if (assignee) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: `@${assignee}, this PR has been open with conflicts. Please resolve the conflicts so we can merge it.`,
});
console.log(`Notified @${assignee} for PR #${pr.number}`);
}
}
console.log(`Total PRs checked: ${prs.length}`);

View File

@@ -9,7 +9,9 @@ env:
BUILD_TYPE: RelWithDebInfo
BUILD_DIR: build
CLEANER_OUTPUT_PATH: build/clang-include-cleaner.log
CLEANER_DIRS: test/unit exceptions alternator api auth cdc compaction
# the "idl" subdirectory does not contain C++ source code. the .hh files in it are
# supposed to be processed by idl-compiler.py, so we don't check them using the cleaner
CLEANER_DIRS: test/unit exceptions alternator api auth cdc compaction db dht gms index lang
permissions: {}

1
.gitignore vendored
View File

@@ -34,3 +34,4 @@ compile_commands.json
.mypy_cache
.envrc
clang_build
.idea/

View File

@@ -23,7 +23,8 @@ if(DEFINED CMAKE_BUILD_TYPE)
endif(DEFINED CMAKE_BUILD_TYPE)
include(mode.common)
if(CMAKE_CONFIGURATION_TYPES)
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
include(mode.${config})
list(APPEND scylla_build_modes ${scylla_build_mode_${config}})
@@ -47,16 +48,58 @@ set(CMAKE_CXX_EXTENSIONS ON CACHE INTERNAL "")
set(CMAKE_CXX_SCAN_FOR_MODULES OFF CACHE INTERNAL "")
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(Seastar_TESTING ON CACHE BOOL "" FORCE)
set(Seastar_API_LEVEL 7 CACHE STRING "" FORCE)
set(Seastar_DEPRECATED_OSTREAM_FORMATTERS OFF CACHE BOOL "" FORCE)
set(Seastar_APPS ON CACHE BOOL "" FORCE)
set(Seastar_EXCLUDE_APPS_FROM_ALL ON CACHE BOOL "" FORCE)
set(Seastar_EXCLUDE_TESTS_FROM_ALL ON CACHE BOOL "" FORCE)
set(Seastar_IO_URING OFF CACHE BOOL "" FORCE)
set(Seastar_SCHEDULING_GROUPS_COUNT 16 CACHE STRING "" FORCE)
set(Seastar_UNUSED_RESULT_ERROR ON CACHE BOOL "" FORCE)
add_subdirectory(seastar)
if(is_multi_config)
find_package(Seastar)
# this is atypical compared to standard ExternalProject usage:
# - Seastar's build system should already be configured at this point.
# - We maintain separate project variants for each configuration type.
#
# Benefits of this approach:
# - Allows the parent project to consume the compile options exposed by
# .pc file. as the compile options vary from one config to another.
# - Allows application of config-specific settings
# - Enables building Seastar within the parent project's build system
# - Facilitates linking of artifacts with the external project target,
# establishing proper dependencies between them
include(ExternalProject)
ExternalProject_Add(Seastar
SOURCE_DIR "${PROJECT_SOURCE_DIR}/seastar"
BINARY_DIR "${CMAKE_BINARY_DIR}/$<CONFIG>/seastar"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR>
--target seastar
--target seastar_testing
--target seastar_perf_testing
--target app_iotune
BUILD_ALWAYS ON
BUILD_BYPRODUCTS
<BINARY_DIR>/libseastar.$<IF:$<CONFIG:Debug,Dev>,so,a>
<BINARY_DIR>/libseastar_testing.$<IF:$<CONFIG:Debug,Dev>,so,a>
<BINARY_DIR>/libseastar_perf_testing.$<IF:$<CONFIG:Debug,Dev>,so,a>
<BINARY_DIR>/apps/iotune/iotune
<BINARY_DIR>/gen/include/seastar/http/chunk_parsers.hh
<BINARY_DIR>/gen/include/seastar/http/request_parser.hh
<BINARY_DIR>/gen/include/seastar/http/response_parser.hh
INSTALL_COMMAND "")
add_dependencies(Seastar::seastar Seastar)
add_dependencies(Seastar::seastar_testing Seastar)
else()
set(Seastar_TESTING ON CACHE BOOL "" FORCE)
set(Seastar_API_LEVEL 7 CACHE STRING "" FORCE)
set(Seastar_DEPRECATED_OSTREAM_FORMATTERS OFF CACHE BOOL "" FORCE)
set(Seastar_APPS ON CACHE BOOL "" FORCE)
set(Seastar_EXCLUDE_APPS_FROM_ALL ON CACHE BOOL "" FORCE)
set(Seastar_EXCLUDE_TESTS_FROM_ALL ON CACHE BOOL "" FORCE)
set(Seastar_IO_URING OFF CACHE BOOL "" FORCE)
set(Seastar_SCHEDULING_GROUPS_COUNT 16 CACHE STRING "" FORCE)
set(Seastar_UNUSED_RESULT_ERROR ON CACHE BOOL "" FORCE)
add_subdirectory(seastar)
target_compile_definitions (seastar
PRIVATE
SEASTAR_NO_EXCEPTION_HACK)
endif()
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
find_package(Sanitizers QUIET)
@@ -101,6 +144,7 @@ find_package(libxcrypt REQUIRED)
find_package(Snappy REQUIRED)
find_package(RapidJSON REQUIRED)
find_package(xxHash REQUIRED)
find_package(yaml-cpp REQUIRED)
find_package(zstd REQUIRED)
set(scylla_gen_build_dir "${CMAKE_BINARY_DIR}/gen")
@@ -196,6 +240,10 @@ include(check_headers)
check_headers(check-headers scylla-main
GLOB ${CMAKE_CURRENT_SOURCE_DIR}/*.hh)
option(Scylla_DIST
"Build dist targets"
ON)
add_custom_target(compiler-training)
add_subdirectory(api)
@@ -274,8 +322,9 @@ target_link_libraries(scylla PRIVATE
utils)
target_link_libraries(scylla PRIVATE
seastar
Seastar::seastar
absl::headers
yaml-cpp::yaml-cpp
Boost::program_options)
target_include_directories(scylla PRIVATE
@@ -287,4 +336,6 @@ add_custom_target(maybe-scylla
add_dependencies(compiler-training
maybe-scylla)
add_subdirectory(dist)
if(Scylla_DIST)
add_subdirectory(dist)
endif()

View File

@@ -78,7 +78,7 @@ fi
# Default scylla product/version tags
PRODUCT=scylla
VERSION=6.2.0-dev
VERSION=6.3.0-dev
if test -f version
then
@@ -104,7 +104,7 @@ else
fi
if [ -f "$OUTPUT_DIR/SCYLLA-RELEASE-FILE" ]; then
GIT_COMMIT_FILE=$(cat "$OUTPUT_DIR/SCYLLA-RELEASE-FILE" |cut -d . -f 3)
GIT_COMMIT_FILE=$(cat "$OUTPUT_DIR/SCYLLA-RELEASE-FILE" | rev | cut -d . -f 1 | rev)
if [ "$GIT_COMMIT" = "$GIT_COMMIT_FILE" ]; then
exit 0
fi

View File

@@ -8,7 +8,7 @@
#include "alternator/error.hh"
#include "auth/common.hh"
#include "log.hh"
#include "utils/log.hh"
#include <string>
#include <string_view>
#include "bytes.hh"

View File

@@ -15,8 +15,6 @@
#include "utils/base64.hh"
#include "utils/rjson.hh"
#include <stdexcept>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/algorithm/cxx11/any_of.hpp>
#include "utils/overloaded_functor.hh"
#include "expressions.hh"
@@ -743,9 +741,9 @@ bool verify_condition_expression(
};
switch (list.op) {
case '&':
return boost::algorithm::all_of(list.conditions, verify_condition);
return std::ranges::all_of(list.conditions, verify_condition);
case '|':
return boost::algorithm::any_of(list.conditions, verify_condition);
return std::ranges::any_of(list.conditions, verify_condition);
default:
// Shouldn't happen unless we have a bug in the parser
throw std::logic_error("bad operator in condition_list");

View File

@@ -130,10 +130,10 @@ future<> controller::start_server() {
std::throw_with_nested(std::runtime_error("Failed to set up Alternator TLS credentials"));
}
}
bool alternator_enforce_authorization = _config.alternator_enforce_authorization();
_server.invoke_on_all(
[this, addr, alternator_port, alternator_https_port, creds = std::move(creds), alternator_enforce_authorization] (server& server) mutable {
return server.init(addr, alternator_port, alternator_https_port, creds, alternator_enforce_authorization,
[this, addr, alternator_port, alternator_https_port, creds = std::move(creds)] (server& server) mutable {
return server.init(addr, alternator_port, alternator_https_port, creds,
_config.alternator_enforce_authorization,
&_memory_limiter.local().get_semaphore(),
_config.max_concurrent_requests_per_shard);
}).handle_exception([this, addr, alternator_port, alternator_https_port] (std::exception_ptr ep) {

View File

@@ -10,10 +10,11 @@
#include <seastar/core/sleep.hh>
#include "alternator/executor.hh"
#include "auth/permission.hh"
#include "auth/resource.hh"
#include "cdc/log.hh"
#include "auth/service.hh"
#include "db/config.hh"
#include "log.hh"
#include "utils/log.hh"
#include "schema/schema_builder.hh"
#include "exceptions/exceptions.hh"
#include "service/client_state.hh"
@@ -36,7 +37,6 @@
#include "utils/assert.hh"
#include "utils/overloaded_functor.hh"
#include <seastar/json/json_elements.hh>
#include <boost/algorithm/cxx11/any_of.hpp>
#include "collection_mutation.hh"
#include "schema/schema.hh"
#include "db/tags/extension.hh"
@@ -44,10 +44,10 @@
#include "replica/database.hh"
#include "alternator/rmw_operation.hh"
#include <seastar/core/coroutine.hh>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm/find_end.hpp>
#include <unordered_set>
#include "service/storage_proxy.hh"
#include "gms/feature_service.hh"
#include "gms/gossiper.hh"
#include "utils/error_injection.hh"
#include "db/schema_tables.hh"
@@ -58,6 +58,10 @@ using namespace std::chrono_literals;
logging::logger elogger("alternator-executor");
namespace alternator {
// We write the provisioned read and write capacity on a table using the
// tags RCU_TAG_KEY and WCU_TAG_KEY.
static const sstring RCU_TAG_KEY("system:provisioned_rcu");
static const sstring WCU_TAG_KEY("system:provisioned_wcu");
enum class table_status {
active = 0,
@@ -80,7 +84,7 @@ static sstring_view table_status_to_sstring(table_status tbl_status) {
return "UNKNOWN";
}
static lw_shared_ptr<keyspace_metadata> create_keyspace_metadata(std::string_view keyspace_name, service::storage_proxy& sp, gms::gossiper& gossiper, api::timestamp_type, const std::map<sstring, sstring>& tags_map);
static lw_shared_ptr<keyspace_metadata> create_keyspace_metadata(std::string_view keyspace_name, service::storage_proxy& sp, gms::gossiper& gossiper, api::timestamp_type, const std::map<sstring, sstring>& tags_map, const gms::feature_service& feat);
static map_type attrs_type() {
static thread_local auto t = map_type_impl::get_instance(utf8_type, bytes_type, true);
@@ -136,6 +140,25 @@ std::string json_string::to_json() const {
return _value;
}
executor::executor(gms::gossiper& gossiper,
service::storage_proxy& proxy,
service::migration_manager& mm,
db::system_distributed_keyspace& sdks,
cdc::metadata& cdc_metadata,
smp_service_group ssg,
utils::updateable_value<uint32_t> default_timeout_in_ms)
: _gossiper(gossiper),
_proxy(proxy),
_mm(mm),
_sdks(sdks),
_cdc_metadata(cdc_metadata),
_enforce_authorization(_proxy.data_dictionary().get_config().alternator_enforce_authorization()),
_ssg(ssg)
{
s_default_timeout_in_ms = std::move(default_timeout_in_ms);
}
void executor::supplement_table_info(rjson::value& descr, const schema& schema, service::storage_proxy& sp) {
rjson::add(descr, "CreationDateTime", rjson::value(std::chrono::duration_cast<std::chrono::seconds>(gc_clock::now().time_since_epoch()).count()));
rjson::add(descr, "TableStatus", "ACTIVE");
@@ -446,6 +469,8 @@ static rjson::value generate_arn_for_index(const schema& schema, std::string_vie
static rjson::value fill_table_description(schema_ptr schema, table_status tbl_status, service::storage_proxy const& proxy)
{
rjson::value table_description = rjson::empty_object();
auto tags_ptr = db::get_tags_of_table(schema);
rjson::add(table_description, "TableName", rjson::from_string(schema->cf_name()));
// FIXME: take the tables creation time, not the current time!
size_t creation_date_seconds = std::chrono::duration_cast<std::chrono::seconds>(gc_clock::now().time_since_epoch()).count();
@@ -458,16 +483,35 @@ static rjson::value fill_table_description(schema_ptr schema, table_status tbl_s
rjson::add(table_description, "TableStatus", rjson::from_string(table_status_to_sstring(tbl_status)));
rjson::add(table_description, "TableArn", generate_arn_for_table(*schema));
rjson::add(table_description, "TableId", rjson::from_string(schema->id().to_sstring()));
// FIXME: Instead of hardcoding, we should take into account which mode was chosen
// when the table was created. But, Spark jobs expect something to be returned
// and PAY_PER_REQUEST seems closer to reality than PROVISIONED.
rjson::add(table_description, "BillingModeSummary", rjson::empty_object());
rjson::add(table_description["BillingModeSummary"], "BillingMode", "PAY_PER_REQUEST");
rjson::add(table_description["BillingModeSummary"], "LastUpdateToPayPerRequestDateTime", rjson::value(creation_date_seconds));
// In PAY_PER_REQUEST billing mode, provisioned capacity should return 0
int rcu = 0;
int wcu = 0;
bool is_pay_per_request = true;
if (tags_ptr) {
auto rcu_tag = tags_ptr->find(RCU_TAG_KEY);
auto wcu_tag = tags_ptr->find(WCU_TAG_KEY);
if (rcu_tag != tags_ptr->end() && wcu_tag != tags_ptr->end()) {
try {
rcu = std::stoi(rcu_tag->second);
wcu = std::stoi(wcu_tag->second);
is_pay_per_request = false;
} catch (...) {
rcu = 0;
wcu = 0;
}
}
}
if (is_pay_per_request) {
rjson::add(table_description["BillingModeSummary"], "BillingMode", "PAY_PER_REQUEST");
} else {
rjson::add(table_description["BillingModeSummary"], "BillingMode", "PROVISIONED");
}
rjson::add(table_description, "ProvisionedThroughput", rjson::empty_object());
rjson::add(table_description["ProvisionedThroughput"], "ReadCapacityUnits", 0);
rjson::add(table_description["ProvisionedThroughput"], "WriteCapacityUnits", 0);
rjson::add(table_description["ProvisionedThroughput"], "ReadCapacityUnits", rcu);
rjson::add(table_description["ProvisionedThroughput"], "WriteCapacityUnits", wcu);
rjson::add(table_description["ProvisionedThroughput"], "NumberOfDecreasesToday", 0);
@@ -555,47 +599,44 @@ future<executor::request_return_type> executor::describe_table(client_state& cli
// SELECT, DROP, etc.) on the given table. When permission is denied an
// appropriate user-readable api_error::access_denied is thrown.
future<> verify_permission(
bool enforce_authorization,
const service::client_state& client_state,
const schema_ptr& schema,
auth::permission permission_to_check) {
// Using exceptions for errors makes this function faster in the success
// path (when the operation is allowed). Using a continuation instead of
// co_await makes it faster (no allocation) in the happy path where
// permissions are cached and check_has_permissions() doesn't yield.
return client_state.check_has_permission(auth::command_desc(
permission_to_check,
auth::make_data_resource(schema->ks_name(), schema->cf_name()))).then(
[permission_to_check, &schema, &client_state] (bool allowed) {
if (!allowed) {
sstring username = "anonymous";
if (client_state.user() && client_state.user()->name) {
username = client_state.user()->name.value();
}
throw api_error::access_denied(format(
"{} access on table {}.{} is denied to role {}",
auth::permissions::to_string(permission_to_check),
schema->ks_name(), schema->cf_name(), username));
}
});
if (!enforce_authorization) {
co_return;
}
auto resource = auth::make_data_resource(schema->ks_name(), schema->cf_name());
if (!co_await client_state.check_has_permission(auth::command_desc(permission_to_check, resource))) {
sstring username = "<anonymous>";
if (client_state.user() && client_state.user()->name) {
username = client_state.user()->name.value();
}
// Using exceptions for errors makes this function faster in the
// success path (when the operation is allowed).
throw api_error::access_denied(format(
"{} access on table {}.{} is denied to role {}",
auth::permissions::to_string(permission_to_check),
schema->ks_name(), schema->cf_name(), username));
}
}
// Similar to verify_permission() above, but just for CREATE operations.
// Those do not operate on any specific table, so require permissions on
// ALL KEYSPACES instead of any specific table.
future<> verify_create_permission(const service::client_state& client_state) {
return client_state.check_has_permission(auth::command_desc(
auth::permission::CREATE,
auth::resource(auth::resource_kind::data))).then(
[&client_state] (bool allowed) {
if (!allowed) {
sstring username = "anonymous";
if (client_state.user() && client_state.user()->name) {
username = client_state.user()->name.value();
}
throw api_error::access_denied(format(
"CREATE access on ALL KEYSPACES is denied to role {}", username));
}
});
future<> verify_create_permission(bool enforce_authorization, const service::client_state& client_state) {
if (!enforce_authorization) {
co_return;
}
auto resource = auth::resource(auth::resource_kind::data);
if (!co_await client_state.check_has_permission(auth::command_desc(auth::permission::CREATE, resource))) {
sstring username = "<anonymous>";
if (client_state.user() && client_state.user()->name) {
username = client_state.user()->name.value();
}
throw api_error::access_denied(format(
"CREATE access on ALL KEYSPACES is denied to role {}", username));
}
}
future<executor::request_return_type> executor::delete_table(client_state& client_state, tracing::trace_state_ptr trace_state, service_permit permit, rjson::value request) {
@@ -613,7 +654,7 @@ future<executor::request_return_type> executor::delete_table(client_state& clien
schema_ptr schema = get_table(_proxy, request);
rjson::value table_description = fill_table_description(schema, table_status::deleting, _proxy);
co_await verify_permission(client_state, schema, auth::permission::DROP);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::DROP);
co_await _mm.container().invoke_on(0, [&, cs = client_state.move_to_other_shard()] (service::migration_manager& mm) -> future<> {
// FIXME: the following needs to be in a loop. If mm.announce() below
// fails, we need to retry the whole thing.
@@ -643,11 +684,11 @@ future<executor::request_return_type> executor::delete_table(client_state& clien
// to the group0_batch and back to the pair :-(
service::group0_batch mc(std::move(group0_guard));
mc.add_mutations(std::move(m));
co_await auth::revoke_all(*cs.get().get_auth_service(),
auth::make_data_resource(schema->ks_name(), schema->cf_name()), mc);
auto resource = auth::make_data_resource(schema->ks_name(), schema->cf_name());
co_await auth::revoke_all(*cs.get().get_auth_service(), resource, mc);
for (const view_ptr& v : tbl->views()) {
co_await auth::revoke_all(*cs.get().get_auth_service(),
auth::make_data_resource(v->ks_name(), v->cf_name()), mc);
resource = auth::make_data_resource(v->ks_name(), v->cf_name());
co_await auth::revoke_all(*cs.get().get_auth_service(), resource, mc);
}
std::tie(m, group0_guard) = co_await std::move(mc).extract();
@@ -907,7 +948,7 @@ future<executor::request_return_type> executor::tag_resource(client_state& clien
if (tags->Size() < 1) {
co_return api_error::validation("The number of tags must be at least 1") ;
}
co_await verify_permission(client_state, schema, auth::permission::ALTER);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::ALTER);
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [tags](std::map<sstring, sstring>& tags_map) {
update_tags_map(*tags, tags_map, update_tags_action::add_tags);
});
@@ -927,7 +968,7 @@ future<executor::request_return_type> executor::untag_resource(client_state& cli
}
schema_ptr schema = get_table_from_arn(_proxy, rjson::to_string_view(*arn));
co_await verify_permission(client_state, schema, auth::permission::ALTER);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::ALTER);
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [tags](std::map<sstring, sstring>& tags_map) {
update_tags_map(*tags, tags_map, update_tags_action::delete_tags);
});
@@ -957,8 +998,14 @@ future<executor::request_return_type> executor::list_tags_of_resource(client_sta
return make_ready_future<executor::request_return_type>(make_jsonable(std::move(ret)));
}
static void verify_billing_mode(const rjson::value& request) {
// Alternator does not yet support billing or throughput limitations, but
struct billing_mode_type {
bool provisioned = false;
int rcu;
int wcu;
};
static billing_mode_type verify_billing_mode(const rjson::value& request) {
// Alternator does not yet support billing or throughput limitations, but
// let's verify that BillingMode is at least legal.
std::string billing_mode = get_string_attribute(request, "BillingMode", "PROVISIONED");
if (billing_mode == "PAY_PER_REQUEST") {
@@ -966,12 +1013,24 @@ static void verify_billing_mode(const rjson::value& request) {
throw api_error::validation("When BillingMode=PAY_PER_REQUEST, ProvisionedThroughput cannot be specified.");
}
} else if (billing_mode == "PROVISIONED") {
if (!rjson::find(request, "ProvisionedThroughput")) {
const rjson::value *provisioned_throughput = rjson::find(request, "ProvisionedThroughput");
if (!provisioned_throughput) {
throw api_error::validation("When BillingMode=PROVISIONED, ProvisionedThroughput must be specified.");
}
const rjson::value& throughput = *provisioned_throughput;
auto rcu = get_int_attribute(throughput, "ReadCapacityUnits");
auto wcu = get_int_attribute(throughput, "WriteCapacityUnits");
if (!rcu.has_value()) {
throw api_error::validation("provisionedThroughput.readCapacityUnits is missing, when BillingMode=PROVISIONED, ProvisionedThroughput must be specified.");
}
if (!wcu.has_value()) {
throw api_error::validation("provisionedThroughput.writeCapacityUnits is missing, when BillingMode=PROVISIONED, ProvisionedThroughput must be specified.");
}
return billing_mode_type{true, *rcu, *wcu};
} else {
throw api_error::validation("Unknown BillingMode={}. Must be PAY_PER_REQUEST or PROVISIONED.");
}
return billing_mode_type();
}
// Validate that a AttributeDefinitions parameter in CreateTable is valid, and
@@ -1010,7 +1069,7 @@ static std::unordered_set<std::string> validate_attribute_definitions(const rjso
return seen_attribute_names;
}
static future<executor::request_return_type> create_table_on_shard0(service::client_state&& client_state, tracing::trace_state_ptr trace_state, rjson::value request, service::storage_proxy& sp, service::migration_manager& mm, gms::gossiper& gossiper) {
static future<executor::request_return_type> create_table_on_shard0(service::client_state&& client_state, tracing::trace_state_ptr trace_state, rjson::value request, service::storage_proxy& sp, service::migration_manager& mm, gms::gossiper& gossiper, bool enforce_authorization) {
SCYLLA_ASSERT(this_shard_id() == 0);
// We begin by parsing and validating the content of the CreateTable
@@ -1044,7 +1103,7 @@ static future<executor::request_return_type> create_table_on_shard0(service::cli
}
builder.with_column(bytes(executor::ATTRS_COLUMN_NAME), attrs_type(), column_kind::regular_column);
verify_billing_mode(request);
billing_mode_type bm = verify_billing_mode(request);
schema_ptr partial_schema = builder.build();
@@ -1170,7 +1229,7 @@ static future<executor::request_return_type> create_table_on_shard0(service::cli
}
if (!unused_attribute_definitions.empty()) {
co_return api_error::validation(format(
co_return api_error::validation(fmt::format(
"AttributeDefinitions defines spurious attributes not used by any KeySchema: {}",
unused_attribute_definitions));
}
@@ -1202,9 +1261,13 @@ static future<executor::request_return_type> create_table_on_shard0(service::cli
if (tags && tags->IsArray()) {
update_tags_map(*tags, tags_map, update_tags_action::add_tags);
}
if (bm.provisioned) {
tags_map[RCU_TAG_KEY] = std::to_string(bm.rcu);
tags_map[WCU_TAG_KEY] = std::to_string(bm.wcu);
}
builder.add_extension(db::tags_extension::NAME, ::make_shared<db::tags_extension>(tags_map));
co_await verify_create_permission(client_state);
co_await verify_create_permission(enforce_authorization, client_state);
schema_ptr schema = builder.build();
for (auto& view_builder : view_builders) {
@@ -1225,7 +1288,7 @@ static future<executor::request_return_type> create_table_on_shard0(service::cli
auto group0_guard = co_await mm.start_group0_operation();
auto ts = group0_guard.write_timestamp();
std::vector<mutation> schema_mutations;
auto ksm = create_keyspace_metadata(keyspace_name, sp, gossiper, ts, tags_map);
auto ksm = create_keyspace_metadata(keyspace_name, sp, gossiper, ts, tags_map, sp.features());
// Alternator Streams doesn't yet work when the table uses tablets (#16317)
if (stream_specification && stream_specification->IsObject()) {
auto stream_enabled = rjson::find(*stream_specification, "StreamEnabled");
@@ -1274,13 +1337,15 @@ static future<executor::request_return_type> create_table_on_shard0(service::cli
// between the pair to the group0_batch and back to the pair :-(
service::group0_batch mc(std::move(group0_guard));
mc.add_mutations(std::move(schema_mutations));
co_await auth::grant_applicable_permissions(
*client_state.get_auth_service(), *client_state.user(),
auth::make_data_resource(schema->ks_name(), schema->cf_name()), mc);
for (const schema_builder& view_builder : view_builders) {
if (client_state.user()) {
auto resource = auth::make_data_resource(schema->ks_name(), schema->cf_name());
co_await auth::grant_applicable_permissions(
*client_state.get_auth_service(), *client_state.user(),
auth::make_data_resource(view_builder.ks_name(), view_builder.cf_name()), mc);
*client_state.get_auth_service(), *client_state.user(), resource, mc);
for (const schema_builder& view_builder : view_builders) {
resource = auth::make_data_resource(view_builder.ks_name(), view_builder.cf_name());
co_await auth::grant_applicable_permissions(
*client_state.get_auth_service(), *client_state.user(), resource, mc);
}
}
std::tie(schema_mutations, group0_guard) = co_await std::move(mc).extract();
@@ -1297,9 +1362,9 @@ future<executor::request_return_type> executor::create_table(client_state& clien
_stats.api_operations.create_table++;
elogger.trace("Creating table {}", request);
co_return co_await _mm.container().invoke_on(0, [&, tr = tracing::global_trace_state_ptr(trace_state), request = std::move(request), &sp = _proxy.container(), &g = _gossiper.container(), client_state_other_shard = client_state.move_to_other_shard()]
co_return co_await _mm.container().invoke_on(0, [&, tr = tracing::global_trace_state_ptr(trace_state), request = std::move(request), &sp = _proxy.container(), &g = _gossiper.container(), client_state_other_shard = client_state.move_to_other_shard(), enforce_authorization = bool(_enforce_authorization)]
(service::migration_manager& mm) mutable -> future<executor::request_return_type> {
co_return co_await create_table_on_shard0(client_state_other_shard.get(), tr, std::move(request), sp.local(), mm, g.local());
co_return co_await create_table_on_shard0(client_state_other_shard.get(), tr, std::move(request), sp.local(), mm, g.local(), enforce_authorization);
});
}
@@ -1324,7 +1389,7 @@ future<executor::request_return_type> executor::update_table(client_state& clien
verify_billing_mode(request);
}
co_return co_await _mm.container().invoke_on(0, [&p = _proxy.container(), request = std::move(request), gt = tracing::global_trace_state_ptr(std::move(trace_state)), client_state_other_shard = client_state.move_to_other_shard()]
co_return co_await _mm.container().invoke_on(0, [&p = _proxy.container(), request = std::move(request), gt = tracing::global_trace_state_ptr(std::move(trace_state)), enforce_authorization = bool(_enforce_authorization), client_state_other_shard = client_state.move_to_other_shard()]
(service::migration_manager& mm) mutable -> future<executor::request_return_type> {
// FIXME: the following needs to be in a loop. If mm.announce() below
// fails, we need to retry the whole thing.
@@ -1355,7 +1420,7 @@ future<executor::request_return_type> executor::update_table(client_state& clien
}
auto schema = builder.build();
co_await verify_permission(client_state_other_shard.get(), schema, auth::permission::ALTER);
co_await verify_permission(enforce_authorization, client_state_other_shard.get(), schema, auth::permission::ALTER);
auto m = co_await service::prepare_column_family_update_announcement(p.local(), schema, std::vector<view_ptr>(), group0_guard.write_timestamp());
co_await mm.announce(std::move(m), std::move(group0_guard), format("alternator-executor: update {} table", tab->cf_name()));
@@ -1601,8 +1666,9 @@ static lw_shared_ptr<query::read_command> previous_item_read_command(service::st
// FIXME: We pretend to take a selection (all callers currently give us a
// wildcard selection...) but here we read the entire item anyway. We
// should take the column list from selection instead of building it here.
auto regular_columns = boost::copy_range<query::column_id_vector>(
schema->regular_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto regular_columns =
schema->regular_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
auto partition_slice = query::partition_slice(std::move(bounds), {}, std::move(regular_columns), selection->get_query_options());
return ::make_lw_shared<query::read_command>(schema->id(), schema->version(), partition_slice, proxy.get_max_result_size(partition_slice),
query::tombstone_limit(proxy.get_tombstone_limit()));
@@ -1914,7 +1980,7 @@ future<executor::request_return_type> executor::put_item(client_state& client_st
tracing::add_table_name(trace_state, op->schema()->ks_name(), op->schema()->cf_name());
const bool needs_read_before_write = op->needs_read_before_write();
co_await verify_permission(client_state, op->schema(), auth::permission::MODIFY);
co_await verify_permission(_enforce_authorization, client_state, op->schema(), auth::permission::MODIFY);
if (auto shard = op->shard_for_execute(needs_read_before_write); shard) {
_stats.api_operations.put_item--; // uncount on this shard, will be counted in other shard
@@ -2006,7 +2072,7 @@ future<executor::request_return_type> executor::delete_item(client_state& client
tracing::add_table_name(trace_state, op->schema()->ks_name(), op->schema()->cf_name());
const bool needs_read_before_write = op->needs_read_before_write();
co_await verify_permission(client_state, op->schema(), auth::permission::MODIFY);
co_await verify_permission(_enforce_authorization, client_state, op->schema(), auth::permission::MODIFY);
if (auto shard = op->shard_for_execute(needs_read_before_write); shard) {
_stats.api_operations.delete_item--; // uncount on this shard, will be counted in other shard
@@ -2125,7 +2191,7 @@ static future<> do_batch_write(service::storage_proxy& proxy,
// likely that a batch will contain both tables which always demand LWT and ones
// that don't - it's fragile to split a batch into multiple storage proxy requests though.
// Hence, the decision is conservative - if any table enforces LWT,the whole batch will use it.
const bool needs_lwt = boost::algorithm::any_of(mutation_builders | boost::adaptors::map_keys, [] (const schema_ptr& schema) {
const bool needs_lwt = std::ranges::any_of(mutation_builders | std::views::keys, [] (const schema_ptr& schema) {
return rmw_operation::get_write_isolation_for_schema(schema) == rmw_operation::write_isolation::LWT_ALWAYS;
});
if (!needs_lwt) {
@@ -2195,7 +2261,6 @@ future<executor::request_return_type> executor::batch_write_item(client_state& c
mutation_builders.reserve(request_items.MemberCount());
uint batch_size = 0;
for (auto it = request_items.MemberBegin(); it != request_items.MemberEnd(); ++it) {
batch_size++;
schema_ptr schema = get_table_from_batch_request(_proxy, it);
tracing::add_table_name(trace_state, schema->ks_name(), schema->cf_name());
std::unordered_set<primary_key, primary_key_hash, primary_key_equal> used_keys(
@@ -2216,6 +2281,7 @@ future<executor::request_return_type> executor::batch_write_item(client_state& c
co_return api_error::validation("Provided list of item keys contains duplicates");
}
used_keys.insert(std::move(mut_key));
batch_size++;
} else if (r_name == "DeleteRequest") {
const rjson::value& key = (r->value)["Key"];
mutation_builders.emplace_back(schema, put_or_delete_item(
@@ -2226,6 +2292,7 @@ future<executor::request_return_type> executor::batch_write_item(client_state& c
co_return api_error::validation("Provided list of item keys contains duplicates");
}
used_keys.insert(std::move(mut_key));
batch_size++;
} else {
co_return api_error::validation(fmt::format("Unknown BatchWriteItem request type: {}", r_name));
}
@@ -2233,7 +2300,7 @@ future<executor::request_return_type> executor::batch_write_item(client_state& c
}
for (const auto& b : mutation_builders) {
co_await verify_permission(client_state, b.first, auth::permission::MODIFY);
co_await verify_permission(_enforce_authorization, client_state, b.first, auth::permission::MODIFY);
}
_stats.api_operations.batch_write_item_batch_total += batch_size;
@@ -2642,7 +2709,7 @@ static bool check_needs_read_before_write(const parsed::value& v) {
return false;
},
[&] (const parsed::value::function_call& f) -> bool {
return boost::algorithm::any_of(f._parameters, [&] (const parsed::value& param) {
return std::ranges::any_of(f._parameters, [&] (const parsed::value& param) {
return check_needs_read_before_write(param);
});
},
@@ -2653,7 +2720,7 @@ static bool check_needs_read_before_write(const parsed::value& v) {
}
static bool check_needs_read_before_write(const attribute_path_map<parsed::update_expression::action>& update_expression) {
return boost::algorithm::any_of(update_expression, [](const auto& p) {
return std::ranges::any_of(update_expression, [](const auto& p) {
if (!p.second.has_value()) {
// If the action is not on the top-level attribute, we need to
// read the old item: we change only a part of the top-level
@@ -3281,7 +3348,7 @@ future<executor::request_return_type> executor::update_item(client_state& client
tracing::add_table_name(trace_state, op->schema()->ks_name(), op->schema()->cf_name());
const bool needs_read_before_write = op->needs_read_before_write();
co_await verify_permission(client_state, op->schema(), auth::permission::MODIFY);
co_await verify_permission(_enforce_authorization, client_state, op->schema(), auth::permission::MODIFY);
if (auto shard = op->shard_for_execute(needs_read_before_write); shard) {
_stats.api_operations.update_item--; // uncount on this shard, will be counted in other shard
@@ -3367,8 +3434,9 @@ future<executor::request_return_type> executor::get_item(client_state& client_st
check_key(query_key, schema);
//TODO(sarna): It would be better to fetch only some attributes of the map, not all
auto regular_columns = boost::copy_range<query::column_id_vector>(
schema->regular_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto regular_columns =
schema->regular_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
auto selection = cql3::selection::selection::wildcard(schema);
@@ -3380,7 +3448,7 @@ future<executor::request_return_type> executor::get_item(client_state& client_st
auto attrs_to_get = calculate_attrs_to_get(request, used_attribute_names);
const rjson::value* expression_attribute_names = rjson::find(request, "ExpressionAttributeNames");
verify_all_are_used(expression_attribute_names, used_attribute_names, "ExpressionAttributeNames", "GetItem");
co_await verify_permission(client_state, schema, auth::permission::SELECT);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::SELECT);
co_return co_await _proxy.query(schema, std::move(command), std::move(partition_ranges), cl,
service::storage_proxy::coordinator_query_options(executor::default_timeout(), std::move(permit), client_state, trace_state)).then(
[this, schema, partition_slice = std::move(partition_slice), selection = std::move(selection), attrs_to_get = std::move(attrs_to_get), start_time = std::move(start_time)] (service::storage_proxy::coordinator_query_result qr) mutable {
@@ -3483,7 +3551,7 @@ future<executor::request_return_type> executor::batch_get_item(client_state& cli
}
};
std::vector<table_requests> requests;
uint batch_size = 0;
for (auto it = request_items.MemberBegin(); it != request_items.MemberEnd(); ++it) {
table_requests rs(get_table_from_batch_request(_proxy, it));
tracing::add_table_name(trace_state, sstring(executor::KEYSPACE_NAME_PREFIX) + rs.schema->cf_name(), rs.schema->cf_name());
@@ -3497,14 +3565,15 @@ future<executor::request_return_type> executor::batch_get_item(client_state& cli
rs.add(key);
check_key(key, rs.schema);
}
batch_size += rs.requests.size();
requests.emplace_back(std::move(rs));
}
for (const table_requests& tr : requests) {
co_await verify_permission(client_state, tr.schema, auth::permission::SELECT);
co_await verify_permission(_enforce_authorization, client_state, tr.schema, auth::permission::SELECT);
}
_stats.api_operations.batch_get_item_batch_total += requests.size();
_stats.api_operations.batch_get_item_batch_total += batch_size;
// If we got here, all "requests" are valid, so let's start the
// requests for the different partitions all in parallel.
std::vector<future<std::vector<rjson::value>>> response_futures;
@@ -3521,8 +3590,9 @@ future<executor::request_return_type> executor::batch_get_item(client_state& cli
bounds.push_back(query::clustering_range::make_singular(ck.first));
}
}
auto regular_columns = boost::copy_range<query::column_id_vector>(
rs.schema->regular_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto regular_columns =
rs.schema->regular_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
auto selection = cql3::selection::selection::wildcard(rs.schema);
auto partition_slice = query::partition_slice(std::move(bounds), {}, std::move(regular_columns), selection->get_query_options());
auto command = ::make_lw_shared<query::read_command>(rs.schema->id(), rs.schema->version(), partition_slice, _proxy.get_max_result_size(partition_slice),
@@ -3916,7 +3986,8 @@ static future<executor::request_return_type> do_query(service::storage_proxy& pr
service::client_state& client_state,
cql3::cql_stats& cql_stats,
tracing::trace_state_ptr trace_state,
service_permit permit) {
service_permit permit,
bool enforce_authorization) {
lw_shared_ptr<service::pager::paging_state> old_paging_state = nullptr;
tracing::trace(trace_state, "Performing a database query");
@@ -3943,12 +4014,14 @@ static future<executor::request_return_type> do_query(service::storage_proxy& pr
old_paging_state = make_lw_shared<service::pager::paging_state>(pk, pos, query::max_partitions, query_id::create_null_id(), service::pager::paging_state::replicas_per_token_range{}, std::nullopt, 0);
}
co_await verify_permission(client_state, table_schema, auth::permission::SELECT);
co_await verify_permission(enforce_authorization, client_state, table_schema, auth::permission::SELECT);
auto regular_columns = boost::copy_range<query::column_id_vector>(
table_schema->regular_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto static_columns = boost::copy_range<query::column_id_vector>(
table_schema->static_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto regular_columns =
table_schema->regular_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
auto static_columns =
table_schema->static_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
auto selection = cql3::selection::selection::wildcard(table_schema);
query::partition_slice::option_set opts = selection->get_query_options();
opts.add(custom_opts);
@@ -4087,7 +4160,7 @@ future<executor::request_return_type> executor::scan(client_state& client_state,
verify_all_are_used(expression_attribute_values, used_attribute_values, "ExpressionAttributeValues", "Scan");
return do_query(_proxy, schema, exclusive_start_key, std::move(partition_ranges), std::move(ck_bounds), std::move(attrs_to_get), limit, cl,
std::move(filter), query::partition_slice::option_set(), client_state, _stats.cql_stats, trace_state, std::move(permit));
std::move(filter), query::partition_slice::option_set(), client_state, _stats.cql_stats, trace_state, std::move(permit), _enforce_authorization);
}
static dht::partition_range calculate_pk_bound(schema_ptr schema, const column_definition& pk_cdef, const rjson::value& comp_definition, const rjson::value& attrs) {
@@ -4567,7 +4640,7 @@ future<executor::request_return_type> executor::query(client_state& client_state
query::partition_slice::option_set opts;
opts.set_if<query::partition_slice::option::reversed>(!forward);
return do_query(_proxy, schema, exclusive_start_key, std::move(partition_ranges), std::move(ck_bounds), std::move(attrs_to_get), limit, cl,
std::move(filter), opts, client_state, _stats.cql_stats, std::move(trace_state), std::move(permit));
std::move(filter), opts, client_state, _stats.cql_stats, std::move(trace_state), std::move(permit), _enforce_authorization);
}
future<executor::request_return_type> executor::list_tables(client_state& client_state, service_permit permit, rjson::value request) {
@@ -4697,7 +4770,7 @@ future<executor::request_return_type> executor::describe_continuous_backups(clie
// of nodes in the cluster: A cluster with 3 or more live nodes, gets RF=3.
// A smaller cluster (presumably, a test only), gets RF=1. The user may
// manually create the keyspace to override this predefined behavior.
static lw_shared_ptr<keyspace_metadata> create_keyspace_metadata(std::string_view keyspace_name, service::storage_proxy& sp, gms::gossiper& gossiper, api::timestamp_type ts, const std::map<sstring, sstring>& tags_map) {
static lw_shared_ptr<keyspace_metadata> create_keyspace_metadata(std::string_view keyspace_name, service::storage_proxy& sp, gms::gossiper& gossiper, api::timestamp_type ts, const std::map<sstring, sstring>& tags_map, const gms::feature_service& feat) {
int endpoint_count = gossiper.num_endpoints();
int rf = 3;
if (endpoint_count < rf) {
@@ -4723,7 +4796,7 @@ static lw_shared_ptr<keyspace_metadata> create_keyspace_metadata(std::string_vie
// used by default on new Alternator tables. Change this initialization
// to 0 enable tablets by default, with automatic number of tablets.
std::optional<unsigned> initial_tablets;
if (sp.get_db().local().get_config().enable_tablets()) {
if (feat.tablets) {
auto it = tags_map.find(INITIAL_TABLETS_TAG_KEY);
if (it != tags_map.end()) {
// Tag set. If it's a valid number, use it. If not - e.g., it's

View File

@@ -23,6 +23,8 @@
#include "utils/rjson.hh"
#include "utils/updateable_value.hh"
#include "tracing/trace_state.hh"
namespace db {
class system_distributed_keyspace;
}
@@ -50,6 +52,8 @@ class gossiper;
}
class schema_builder;
namespace alternator {
class rmw_operation;
@@ -158,6 +162,7 @@ class executor : public peering_sharded_service<executor> {
service::migration_manager& _mm;
db::system_distributed_keyspace& _sdks;
cdc::metadata& _cdc_metadata;
utils::updateable_value<bool> _enforce_authorization;
// An smp_service_group to be used for limiting the concurrency when
// forwarding Alternator request between shards - if necessary for LWT.
smp_service_group _ssg;
@@ -176,10 +181,7 @@ public:
db::system_distributed_keyspace& sdks,
cdc::metadata& cdc_metadata,
smp_service_group ssg,
utils::updateable_value<uint32_t> default_timeout_in_ms)
: _gossiper(gossiper), _proxy(proxy), _mm(mm), _sdks(sdks), _cdc_metadata(cdc_metadata), _ssg(ssg) {
s_default_timeout_in_ms = std::move(default_timeout_in_ms);
}
utils::updateable_value<uint32_t> default_timeout_in_ms);
future<request_return_type> create_table(client_state& client_state, tracing::trace_state_ptr trace_state, service_permit permit, rjson::value request);
future<request_return_type> describe_table(client_state& client_state, tracing::trace_state_ptr trace_state, service_permit permit, rjson::value request);
@@ -265,6 +267,6 @@ bool is_big(const rjson::value& val, int big_size = 100'000);
// Check CQL's Role-Based Access Control (RBAC) permission (MODIFY,
// SELECT, DROP, etc.) on the given table. When permission is denied an
// appropriate user-readable api_error::access_denied is thrown.
future<> verify_permission(const service::client_state&, const schema_ptr&, auth::permission);
future<> verify_permission(bool enforce_authorization, const service::client_state&, const schema_ptr&, auth::permission);
}

View File

@@ -20,9 +20,6 @@
#include <seastar/core/print.hh>
#include <seastar/util/log.hh>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <functional>
#include <unordered_map>

View File

@@ -12,6 +12,8 @@
#include "service/paxos/cas_request.hh"
#include "utils/rjson.hh"
#include "executor.hh"
#include "tracing/trace_state.hh"
#include "keys.hh"
namespace alternator {

View File

@@ -8,7 +8,7 @@
#include "utils/base64.hh"
#include "utils/rjson.hh"
#include "log.hh"
#include "utils/log.hh"
#include "serialization.hh"
#include "error.hh"
#include "concrete_types.hh"

View File

@@ -7,7 +7,8 @@
*/
#include "alternator/server.hh"
#include "log.hh"
#include "gms/application_state.hh"
#include "utils/log.hh"
#include <fmt/ranges.h>
#include <seastar/http/function_handlers.hh>
#include <seastar/http/short_streams.hh>
@@ -211,9 +212,28 @@ protected:
// using _gossiper().get_live_members(). But getting
// just the list of live nodes in this DC needs more elaborate code:
auto& topology = _proxy.get_token_metadata_ptr()->get_topology();
sstring local_dc = topology.get_datacenter();
std::unordered_set<gms::inet_address> local_dc_nodes = topology.get_datacenter_endpoints().at(local_dc);
// /localnodes lists nodes in a single DC. By default the DC of this
// server is used, but it can be overridden by a "dc" query option.
// If the DC does not exist, we return an empty list - not an error.
sstring query_dc = req->get_query_param("dc");
sstring local_dc = query_dc.empty() ? topology.get_datacenter() : query_dc;
std::unordered_set<gms::inet_address> local_dc_nodes;
const auto& endpoints = topology.get_datacenter_endpoints();
auto dc_it = endpoints.find(local_dc);
if (dc_it != endpoints.end()) {
local_dc_nodes = dc_it->second;
}
// By default, /localnodes lists the nodes of all racks in the given
// DC, unless a single rack is selected by the "rack" query option.
// If the rack does not exist, we return an empty list - not an error.
sstring query_rack = req->get_query_param("rack");
for (auto& ip : local_dc_nodes) {
if (!query_rack.empty()) {
auto rack = _gossiper.get_application_state_value(ip, gms::application_state::RACK);
if (rack != query_rack) {
continue;
}
}
// Note that it's not enough for the node to be is_alive() - a
// node joining the cluster is also "alive" but not responsive to
// requests. We need the node to be in normal state. See #19694.
@@ -556,9 +576,9 @@ server::server(executor& exec, service::storage_proxy& proxy, gms::gossiper& gos
}
future<> server::init(net::inet_address addr, std::optional<uint16_t> port, std::optional<uint16_t> https_port, std::optional<tls::credentials_builder> creds,
bool enforce_authorization, semaphore* memory_limiter, utils::updateable_value<uint32_t> max_concurrent_requests) {
utils::updateable_value<bool> enforce_authorization, semaphore* memory_limiter, utils::updateable_value<uint32_t> max_concurrent_requests) {
_memory_limiter = memory_limiter;
_enforce_authorization = enforce_authorization;
_enforce_authorization = std::move(enforce_authorization);
_max_concurrent_requests = std::move(max_concurrent_requests);
if (!port && !https_port) {
return make_exception_future<>(std::runtime_error("Either regular port or TLS port"

View File

@@ -39,7 +39,7 @@ class server {
qos::service_level_controller& _sl_controller;
key_cache _key_cache;
bool _enforce_authorization;
utils::updateable_value<bool> _enforce_authorization;
utils::small_vector<std::reference_wrapper<seastar::httpd::http_server>, 2> _enabled_servers;
gate _pending_requests;
// In some places we will need a CQL updateable_timeout_config object even
@@ -76,7 +76,7 @@ public:
server(executor& executor, service::storage_proxy& proxy, gms::gossiper& gossiper, auth::service& service, qos::service_level_controller& sl_controller);
future<> init(net::inet_address addr, std::optional<uint16_t> port, std::optional<uint16_t> https_port, std::optional<tls::credentials_builder> creds,
bool enforce_authorization, semaphore* memory_limiter, utils::updateable_value<uint32_t> max_concurrent_requests);
utils::updateable_value<bool> enforce_authorization, semaphore* memory_limiter, utils::updateable_value<uint32_t> max_concurrent_requests);
future<> stop();
private:
void set_routes(seastar::httpd::routes& r);

View File

@@ -29,8 +29,6 @@ stats::stats() : api_operations{} {
seastar::metrics::description("Latency summary of an operation via Alternator API"), [this]{return to_metrics_summary(api_operations.name.summary());})(op(CamelCaseName)).set_skip_when_empty(),
OPERATION(batch_get_item, "BatchGetItem")
OPERATION(batch_write_item, "BatchWriteItem")
OPERATION(batch_get_item_batch_total, "BatchGetItemSize")
OPERATION(batch_write_item_batch_total, "BatchWriteItemSize")
OPERATION(create_backup, "CreateBackup")
OPERATION(create_global_table, "CreateGlobalTable")
OPERATION(create_table, "CreateTable")
@@ -98,6 +96,10 @@ stats::stats() : api_operations{} {
seastar::metrics::description("number of rows read and matched during filtering operations")),
seastar::metrics::make_total_operations("filtered_rows_dropped_total", [this] { return cql_stats.filtered_rows_read_total - cql_stats.filtered_rows_matched_total; },
seastar::metrics::description("number of rows read and dropped during filtering operations")),
seastar::metrics::make_counter("batch_item_count", seastar::metrics::description("The total number of items processed across all batches"),{op("BatchWriteItem")},
api_operations.batch_write_item_batch_total).set_skip_when_empty(),
seastar::metrics::make_counter("batch_item_count", seastar::metrics::description("The total number of items processed across all batches"),{op("BatchGetItem")},
api_operations.batch_get_item_batch_total).set_skip_when_empty(),
});
}

View File

@@ -824,7 +824,7 @@ future<executor::request_return_type> executor::get_records(client_state& client
tracing::add_table_name(trace_state, schema->ks_name(), schema->cf_name());
co_await verify_permission(client_state, schema, auth::permission::SELECT);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::SELECT);
db::consistency_level cl = db::consistency_level::LOCAL_QUORUM;
partition_key pk = iter.shard.id.to_partition_key(*schema);
@@ -844,19 +844,21 @@ future<executor::request_return_type> executor::get_records(client_state& client
static const bytes op_column_name = cdc::log_meta_column_name_bytes("operation");
static const bytes eor_column_name = cdc::log_meta_column_name_bytes("end_of_batch");
std::optional<attrs_to_get> key_names = boost::copy_range<attrs_to_get>(
boost::range::join(std::move(base->partition_key_columns()), std::move(base->clustering_key_columns()))
| boost::adaptors::transformed([&] (const column_definition& cdef) {
std::optional<attrs_to_get> key_names =
base->primary_key_columns()
| std::views::transform([&] (const column_definition& cdef) {
return std::make_pair<std::string, attrs_to_get_node>(cdef.name_as_text(), {}); })
);
| std::ranges::to<attrs_to_get>()
;
// Include all base table columns as values (in case pre or post is enabled).
// This will include attributes not stored in the frozen map column
std::optional<attrs_to_get> attr_names = boost::copy_range<attrs_to_get>(base->regular_columns()
std::optional<attrs_to_get> attr_names = base->regular_columns()
// this will include the :attrs column, which we will also force evaluating.
// But not having this set empty forces out any cdc columns from actual result
| boost::adaptors::transformed([] (const column_definition& cdef) {
| std::views::transform([] (const column_definition& cdef) {
return std::make_pair<std::string, attrs_to_get_node>(cdef.name_as_text(), {}); })
);
| std::ranges::to<attrs_to_get>()
;
std::vector<const column_definition*> columns;
columns.reserve(schema->all_columns().size());
@@ -867,10 +869,11 @@ future<executor::request_return_type> executor::get_records(client_state& client
std::transform(pks.begin(), pks.end(), std::back_inserter(columns), [](auto& c) { return &c; });
std::transform(cks.begin(), cks.end(), std::back_inserter(columns), [](auto& c) { return &c; });
auto regular_columns = boost::copy_range<query::column_id_vector>(schema->regular_columns()
| boost::adaptors::filtered([](const column_definition& cdef) { return cdef.name() == op_column_name || cdef.name() == eor_column_name || !cdc::is_cdc_metacolumn_name(cdef.name_as_text()); })
| boost::adaptors::transformed([&] (const column_definition& cdef) { columns.emplace_back(&cdef); return cdef.id; })
);
auto regular_columns = schema->regular_columns()
| std::views::filter([](const column_definition& cdef) { return cdef.name() == op_column_name || cdef.name() == eor_column_name || !cdc::is_cdc_metacolumn_name(cdef.name_as_text()); })
| std::views::transform([&] (const column_definition& cdef) { columns.emplace_back(&cdef); return cdef.id; })
| std::ranges::to<query::column_id_vector>()
;
stream_view_type type = cdc_options_to_steam_view_type(base->cdc_options());

View File

@@ -23,7 +23,7 @@
#include "gms/inet_address.hh"
#include "inet_address_vectors.hh"
#include "locator/abstract_replication_strategy.hh"
#include "log.hh"
#include "utils/log.hh"
#include "gc_clock.hh"
#include "replica/database.hh"
#include "service/client_state.hh"
@@ -99,7 +99,7 @@ future<executor::request_return_type> executor::update_time_to_live(client_state
}
sstring attribute_name(v->GetString(), v->GetStringLength());
co_await verify_permission(client_state, schema, auth::permission::ALTER);
co_await verify_permission(_enforce_authorization, client_state, schema, auth::permission::ALTER);
co_await db::modify_tags(_mm, schema->ks_name(), schema->cf_name(), [&](std::map<sstring, sstring>& tags_map) {
if (enabled) {
if (tags_map.contains(TTL_TAG_KEY)) {
@@ -521,8 +521,9 @@ struct scan_ranges_context {
// be good if we can read only the single item of the map - it
// should be possible (and a must for issue #7751!).
lw_shared_ptr<service::pager::paging_state> paging_state = nullptr;
auto regular_columns = boost::copy_range<query::column_id_vector>(
s->regular_columns() | boost::adaptors::transformed([] (const column_definition& cdef) { return cdef.id; }));
auto regular_columns =
s->regular_columns() | std::views::transform([] (const column_definition& cdef) { return cdef.id; })
| std::ranges::to<query::column_id_vector>();
selection = cql3::selection::selection::wildcard(s);
query::partition_slice::option_set opts = selection->get_query_options();
opts.set<query::partition_slice::option::allow_short_read>();

View File

@@ -1,4 +1,29 @@
# Generate C++ sources from Swagger definitions
function(generate_swagger)
set(one_value_args TARGET VAR IN_FILE OUT_DIR)
cmake_parse_arguments(args "" "${one_value_args}" "" ${ARGN})
get_filename_component(in_file_name ${args_IN_FILE} NAME)
set(generator ${PROJECT_SOURCE_DIR}/seastar/scripts/seastar-json2code.py)
set(header_out ${args_OUT_DIR}/${in_file_name}.hh)
set(source_out ${args_OUT_DIR}/${in_file_name}.cc)
add_custom_command(
DEPENDS
${args_IN_FILE}
${generator}
OUTPUT ${header_out} ${source_out}
COMMAND ${CMAKE_COMMAND} -E make_directory ${args_OUT_DIR}
COMMAND ${generator} --create-cc -f ${args_IN_FILE} -o ${header_out})
add_custom_target(${args_TARGET}
DEPENDS
${header_out}
${source_out})
set(${args_VAR} ${header_out} ${source_out} PARENT_SCOPE)
endfunction()
set(swagger_files
api-doc/authorization_cache.json
api-doc/cache_service.json
@@ -29,7 +54,7 @@ set(swagger_files
foreach(f ${swagger_files})
get_filename_component(fname "${f}" NAME_WE)
get_filename_component(dir "${f}" DIRECTORY)
seastar_generate_swagger(
generate_swagger(
TARGET scylla_swagger_gen_${fname}
VAR scylla_swagger_gen_${fname}_files
IN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${f}"
@@ -37,7 +62,7 @@ foreach(f ${swagger_files})
list(APPEND swagger_gen_files "${scylla_swagger_gen_${fname}_files}")
endforeach()
add_library(api)
add_library(api STATIC)
target_sources(api
PRIVATE
api.cc

View File

@@ -94,6 +94,38 @@
]
}
]
},
{
"path":"/raft/trigger_stepdown/",
"operations":[
{
"method":"POST",
"summary":"Triggers stepdown of a leader for given Raft group or group0 if not provided (returns an error if the node is not a leader)",
"type":"string",
"nickname":"trigger_stepdown",
"produces":[
"application/json"
],
"parameters":[
{
"name":"group_id",
"description":"The ID of the group which leader should stepdown",
"required":false,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"name":"timeout",
"description":"Timeout in seconds after which the endpoint returns a failure. If not provided, 60s is used.",
"required":false,
"allowMultiple":false,
"type":"long",
"paramType":"query"
}
]
}
]
}
]
}

View File

@@ -782,6 +782,14 @@
"type":"string",
"paramType":"query"
},
{
"name":"prefix",
"description":"The prefix of the objects for the backuped sstables",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"name":"keyspace",
"description":"Name of a keyspace to copy sstables from",
@@ -790,6 +798,14 @@
"type":"string",
"paramType":"query"
},
{
"name":"table",
"description":"Name of a table to copy sstables from",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"name":"snapshot",
"description":"Name of a snapshot to copy sstables from",
@@ -831,13 +847,25 @@
"paramType":"query"
},
{
"name":"snapshot",
"description":"Name of a snapshot to copy SSTables from",
"name":"prefix",
"description":"The prefix of the object keys for the backuped SSTables",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"in": "body",
"name": "sstables",
"description": "The list of the object keys of the TOC component of the SSTables to be restored",
"required":true,
"schema" :{
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name":"keyspace",
"description":"Name of a keyspace to copy SSTables to",
@@ -849,7 +877,7 @@
{
"name":"table",
"description":"Name of a table to copy SSTables to",
"required":false,
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"query"

View File

@@ -135,6 +135,14 @@ future<> unset_load_meter(http_context& ctx) {
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_load_meter(ctx, r); });
}
future<> set_format_selector(http_context& ctx, db::sstables_format_selector& sel) {
return ctx.http_server.set_routes([&ctx, &sel] (routes& r) { set_format_selector(ctx, r, sel); });
}
future<> unset_format_selector(http_context& ctx) {
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_format_selector(ctx, r); });
}
future<> set_server_sstables_loader(http_context& ctx, sharded<sstables_loader>& sst_loader) {
return ctx.http_server.set_routes([&ctx, &sst_loader] (routes& r) { set_sstables_loader(ctx, r, sst_loader); });
}
@@ -274,16 +282,16 @@ future<> unset_hinted_handoff(http_context& ctx) {
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_hinted_handoff(ctx, r); });
}
future<> set_server_compaction_manager(http_context& ctx) {
auto rb = std::make_shared < api_registry_builder > (ctx.api_doc);
return ctx.http_server.set_routes([rb, &ctx](routes& r) {
rb->register_function(r, "compaction_manager",
"The Compaction manager API");
set_compaction_manager(ctx, r);
future<> set_server_compaction_manager(http_context& ctx, sharded<compaction_manager>& cm) {
return register_api(ctx, "compaction_manager", "The Compaction manager API", [&cm] (http_context& ctx, routes& r) {
set_compaction_manager(ctx, r, cm);
});
}
future<> unset_server_compaction_manager(http_context& ctx) {
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_compaction_manager(ctx, r); });
}
future<> set_server_done(http_context& ctx) {
auto rb = std::make_shared < api_registry_builder > (ctx.api_doc);
@@ -291,15 +299,22 @@ future<> set_server_done(http_context& ctx) {
rb->register_function(r, "lsa", "Log-structured allocator API");
set_lsa(ctx, r);
rb->register_function(r, "commitlog",
"The commit log API");
set_commitlog(ctx,r);
rb->register_function(r, "collectd",
"The collectd API");
set_collectd(ctx, r);
});
}
future<> set_server_commitlog(http_context& ctx, sharded<replica::database>& db) {
return register_api(ctx, "commitlog", "The commit log API", [&db] (http_context& ctx, routes& r) {
set_commitlog(ctx, r, db);
});
}
future<> unset_server_commitlog(http_context& ctx) {
return ctx.http_server.set_routes([&ctx] (routes& r) { unset_commitlog(ctx, r); });
}
future<> set_server_task_manager(http_context& ctx, sharded<tasks::task_manager>& tm, lw_shared_ptr<db::config> cfg) {
auto rb = std::make_shared < api_registry_builder > (ctx.api_doc);

View File

@@ -17,6 +17,8 @@
using request = http::request;
using reply = http::reply;
class compaction_manager;
namespace service {
class load_meter;
@@ -49,6 +51,7 @@ namespace cql_transport { class controller; }
namespace db {
class snapshot_ctl;
class config;
class sstables_format_selector;
namespace view {
class view_builder;
}
@@ -120,7 +123,8 @@ future<> set_hinted_handoff(http_context& ctx, sharded<service::storage_proxy>&
future<> unset_hinted_handoff(http_context& ctx);
future<> set_server_cache(http_context& ctx);
future<> unset_server_cache(http_context& ctx);
future<> set_server_compaction_manager(http_context& ctx);
future<> set_server_compaction_manager(http_context& ctx, sharded<compaction_manager>& cm);
future<> unset_server_compaction_manager(http_context& ctx);
future<> set_server_done(http_context& ctx);
future<> set_server_task_manager(http_context& ctx, sharded<tasks::task_manager>& tm, lw_shared_ptr<db::config> cfg);
future<> unset_server_task_manager(http_context& ctx);
@@ -132,7 +136,11 @@ future<> set_server_raft(http_context&, sharded<service::raft_group_registry>&);
future<> unset_server_raft(http_context&);
future<> set_load_meter(http_context& ctx, service::load_meter& lm);
future<> unset_load_meter(http_context& ctx);
future<> set_format_selector(http_context& ctx, db::sstables_format_selector& sel);
future<> unset_format_selector(http_context& ctx);
future<> set_server_cql_server_test(http_context& ctx, cql_transport::controller& ctl);
future<> unset_server_cql_server_test(http_context& ctx);
future<> set_server_commitlog(http_context& ctx, sharded<replica::database>&);
future<> unset_server_commitlog(http_context& ctx);
}

View File

@@ -11,6 +11,7 @@
#include <seastar/core/scollectd.hh>
#include <seastar/core/scollectd_api.hh>
#include <boost/range/irange.hpp>
#include <ranges>
#include <regex>
#include "api/api_init.hh"
@@ -61,7 +62,7 @@ void set_collectd(http_context& ctx, routes& r) {
return do_with(std::vector<cd::collectd_value>(), [id] (auto& vec) {
vec.resize(smp::count);
return parallel_for_each(boost::irange(0u, smp::count), [&vec, id] (auto cpu) {
return parallel_for_each(std::views::iota(0u, smp::count), [&vec, id] (auto cpu) {
return smp::submit_to(cpu, [id = *id] {
return scollectd::get_collectd_value(id);
}).then([&vec, cpu] (auto res) {

View File

@@ -24,6 +24,8 @@
#include "compaction/compaction_manager.hh"
#include "unimplemented.hh"
#include <boost/range/algorithm/copy.hpp>
extern logging::logger apilog;
namespace api {
@@ -61,14 +63,6 @@ table_id get_uuid(const sstring& name, const replica::database& db) {
return get_uuid(ks, cf, db);
}
future<> foreach_column_family(http_context& ctx, const sstring& name, std::function<void(replica::column_family&)> f) {
auto uuid = get_uuid(name, ctx.db.local());
return ctx.db.invoke_on_all([f, uuid](replica::database& db) {
f(db.find_column_family(uuid));
});
}
future<json::json_return_type> get_cf_stats(http_context& ctx, const sstring& name,
int64_t replica::column_family_stats::*f) {
return map_reduce_cf(ctx, name, int64_t(0), [f](const replica::column_family& cf) {
@@ -83,7 +77,7 @@ future<json::json_return_type> get_cf_stats(http_context& ctx,
}, std::plus<int64_t>());
}
static future<json::json_return_type> set_tables(http_context& ctx, const sstring& keyspace, std::vector<sstring> tables, std::function<future<>(replica::table&)> set) {
static future<json::json_return_type> for_tables_on_all_shards(http_context& ctx, const sstring& keyspace, std::vector<sstring> tables, std::function<future<>(replica::table&)> set) {
if (tables.empty()) {
tables = map_keys(ctx.db.local().find_keyspace(keyspace).metadata().get()->cf_meta_data());
}
@@ -123,7 +117,7 @@ static future<json::json_return_type> set_tables_autocompaction(http_context& ct
return ctx.db.invoke_on(0, [&ctx, keyspace, tables = std::move(tables), enabled] (replica::database& db) {
auto g = autocompaction_toggle_guard(db);
return set_tables(ctx, keyspace, tables, [enabled] (replica::table& cf) {
return for_tables_on_all_shards(ctx, keyspace, tables, [enabled] (replica::table& cf) {
if (enabled) {
cf.enable_auto_compaction();
} else {
@@ -136,7 +130,7 @@ static future<json::json_return_type> set_tables_autocompaction(http_context& ct
static future<json::json_return_type> set_tables_tombstone_gc(http_context& ctx, const sstring &keyspace, std::vector<sstring> tables, bool enabled) {
apilog.info("set_tables_tombstone_gc: enabled={} keyspace={} tables={}", enabled, keyspace, tables);
return set_tables(ctx, keyspace, std::move(tables), [enabled] (replica::table& t) {
return for_tables_on_all_shards(ctx, keyspace, std::move(tables), [enabled] (replica::table& t) {
t.set_tombstone_gc_enabled(enabled);
return make_ready_future<>();
});
@@ -1056,12 +1050,12 @@ void set_column_family(http_context& ctx, routes& r, sharded<db::system_keyspace
});
cf::set_compaction_strategy_class.set(r, [&ctx](std::unique_ptr<http::request> req) {
auto [ks, cf] = parse_fully_qualified_cf_name(req->get_path_param("name"));
sstring strategy = req->get_query_param("class_name");
apilog.info("column_family/set_compaction_strategy_class: name={} strategy={}", req->get_path_param("name"), strategy);
return foreach_column_family(ctx, req->get_path_param("name"), [strategy](replica::column_family& cf) {
return for_tables_on_all_shards(ctx, ks, {std::move(cf)}, [strategy] (replica::table& cf) {
cf.set_compaction_strategy(sstables::compaction_strategy::type(strategy));
}).then([] {
return make_ready_future<json::json_return_type>(json_void());
return make_ready_future<>();
});
});

View File

@@ -23,8 +23,6 @@ void set_column_family(http_context& ctx, httpd::routes& r, sharded<db::system_k
void unset_column_family(http_context& ctx, httpd::routes& r);
table_id get_uuid(const sstring& name, const replica::database& db);
future<> foreach_column_family(http_context& ctx, const sstring& name, std::function<void(replica::column_family&)> f);
template<class Mapper, class I, class Reducer>
future<I> map_reduce_cf_raw(http_context& ctx, const sstring& name, I init,

View File

@@ -9,18 +9,20 @@
#include "commitlog.hh"
#include "db/commitlog/commitlog.hh"
#include "api/api-doc/commitlog.json.hh"
#include "api/api-doc/storage_service.json.hh"
#include "api/api_init.hh"
#include "replica/database.hh"
#include <vector>
namespace api {
using namespace seastar::httpd;
namespace ss = httpd::storage_service_json;
template<typename T>
static auto acquire_cl_metric(http_context& ctx, std::function<T (const db::commitlog*)> func) {
static auto acquire_cl_metric(sharded<replica::database>& db, std::function<T (const db::commitlog*)> func) {
typedef T ret_type;
return ctx.db.map_reduce0([func = std::move(func)](replica::database& db) {
return db.map_reduce0([func = std::move(func)](replica::database& db) {
if (db.commitlog() == nullptr) {
return make_ready_future<ret_type>();
}
@@ -30,11 +32,11 @@ static auto acquire_cl_metric(http_context& ctx, std::function<T (const db::comm
});
}
void set_commitlog(http_context& ctx, routes& r) {
void set_commitlog(http_context& ctx, routes& r, sharded<replica::database>& db) {
httpd::commitlog_json::get_active_segment_names.set(r,
[&ctx](std::unique_ptr<request> req) {
[&db](std::unique_ptr<request> req) {
auto res = make_shared<std::vector<sstring>>();
return ctx.db.map_reduce([res](std::vector<sstring> names) {
return db.map_reduce([res](std::vector<sstring> names) {
res->insert(res->end(), names.begin(), names.end());
}, [](replica::database& db) {
if (db.commitlog() == nullptr) {
@@ -52,20 +54,35 @@ void set_commitlog(http_context& ctx, routes& r) {
return res;
});
httpd::commitlog_json::get_completed_tasks.set(r, [&ctx](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(ctx, std::bind(&db::commitlog::get_completed_tasks, std::placeholders::_1));
httpd::commitlog_json::get_completed_tasks.set(r, [&db](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(db, std::bind(&db::commitlog::get_completed_tasks, std::placeholders::_1));
});
httpd::commitlog_json::get_pending_tasks.set(r, [&ctx](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(ctx, std::bind(&db::commitlog::get_pending_tasks, std::placeholders::_1));
httpd::commitlog_json::get_pending_tasks.set(r, [&db](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(db, std::bind(&db::commitlog::get_pending_tasks, std::placeholders::_1));
});
httpd::commitlog_json::get_total_commit_log_size.set(r, [&ctx](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(ctx, std::bind(&db::commitlog::get_total_size, std::placeholders::_1));
httpd::commitlog_json::get_total_commit_log_size.set(r, [&db](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(db, std::bind(&db::commitlog::get_total_size, std::placeholders::_1));
});
httpd::commitlog_json::get_max_disk_size.set(r, [&ctx](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(ctx, std::bind(&db::commitlog::disk_limit, std::placeholders::_1));
httpd::commitlog_json::get_max_disk_size.set(r, [&db](std::unique_ptr<request> req) {
return acquire_cl_metric<uint64_t>(db, std::bind(&db::commitlog::disk_limit, std::placeholders::_1));
});
ss::get_commitlog.set(r, [&db](const_req req) {
return db.local().commitlog()->active_config().commit_log_location;
});
}
void unset_commitlog(http_context& ctx, routes& r) {
httpd::commitlog_json::get_active_segment_names.unset(r);
httpd::commitlog_json::get_archiving_segment_names.unset(r);
httpd::commitlog_json::get_completed_tasks.unset(r);
httpd::commitlog_json::get_pending_tasks.unset(r);
httpd::commitlog_json::get_total_commit_log_size.unset(r);
httpd::commitlog_json::get_max_disk_size.unset(r);
ss::get_commitlog.unset(r);
}
}

View File

@@ -8,12 +8,17 @@
#pragma once
#include <seastar/core/sharded.hh>
namespace seastar::httpd {
class routes;
}
namespace replica { class database; }
namespace api {
struct http_context;
void set_commitlog(http_context& ctx, seastar::httpd::routes& r);
void set_commitlog(http_context& ctx, seastar::httpd::routes& r, seastar::sharded<replica::database>&);
void unset_commitlog(http_context& ctx, seastar::httpd::routes& r);
}

View File

@@ -13,6 +13,7 @@
#include "compaction/compaction_manager.hh"
#include "api/api.hh"
#include "api/api-doc/compaction_manager.json.hh"
#include "api/api-doc/storage_service.json.hh"
#include "db/system_keyspace.hh"
#include "column_family.hh"
#include "unimplemented.hh"
@@ -23,13 +24,14 @@
namespace api {
namespace cm = httpd::compaction_manager_json;
namespace ss = httpd::storage_service_json;
using namespace json;
using namespace seastar::httpd;
static future<json::json_return_type> get_cm_stats(http_context& ctx,
static future<json::json_return_type> get_cm_stats(sharded<compaction_manager>& cm,
int64_t compaction_manager::stats::*f) {
return ctx.db.map_reduce0([f](replica::database& db) {
return db.get_compaction_manager().get_stats().*f;
return cm.map_reduce0([f](compaction_manager& cm) {
return cm.get_stats().*f;
}, int64_t(0), std::plus<int64_t>()).then([](const int64_t& res) {
return make_ready_future<json::json_return_type>(res);
});
@@ -44,11 +46,10 @@ static std::unordered_map<std::pair<sstring, sstring>, uint64_t, utils::tuple_ha
return std::move(a);
}
void set_compaction_manager(http_context& ctx, routes& r) {
cm::get_compactions.set(r, [&ctx] (std::unique_ptr<http::request> req) {
return ctx.db.map_reduce0([](replica::database& db) {
void set_compaction_manager(http_context& ctx, routes& r, sharded<compaction_manager>& cm) {
cm::get_compactions.set(r, [&cm] (std::unique_ptr<http::request> req) {
return cm.map_reduce0([](compaction_manager& cm) {
std::vector<cm::summary> summaries;
const compaction_manager& cm = db.get_compaction_manager();
for (const auto& c : cm.get_compactions()) {
cm::summary s;
@@ -100,10 +101,9 @@ void set_compaction_manager(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
cm::stop_compaction.set(r, [&ctx] (std::unique_ptr<http::request> req) {
cm::stop_compaction.set(r, [&cm] (std::unique_ptr<http::request> req) {
auto type = req->get_query_param("type");
return ctx.db.invoke_on_all([type] (replica::database& db) {
auto& cm = db.get_compaction_manager();
return cm.invoke_on_all([type] (compaction_manager& cm) {
return cm.stop_compaction(type);
}).then([] {
return make_ready_future<json::json_return_type>(json_void());
@@ -135,8 +135,8 @@ void set_compaction_manager(http_context& ctx, routes& r) {
}, std::plus<int64_t>());
});
cm::get_completed_tasks.set(r, [&ctx] (std::unique_ptr<http::request> req) {
return get_cm_stats(ctx, &compaction_manager::stats::completed_tasks);
cm::get_completed_tasks.set(r, [&cm] (std::unique_ptr<http::request> req) {
return get_cm_stats(cm, &compaction_manager::stats::completed_tasks);
});
cm::get_total_compactions_completed.set(r, [] (std::unique_ptr<http::request> req) {
@@ -153,14 +153,14 @@ void set_compaction_manager(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(0);
});
cm::get_compaction_history.set(r, [&ctx] (std::unique_ptr<http::request> req) {
std::function<future<>(output_stream<char>&&)> f = [&ctx] (output_stream<char>&& out) -> future<> {
cm::get_compaction_history.set(r, [&cm] (std::unique_ptr<http::request> req) {
std::function<future<>(output_stream<char>&&)> f = [&cm] (output_stream<char>&& out) -> future<> {
auto s = std::move(out);
bool first = true;
std::exception_ptr ex;
try {
co_await s.write("[");
co_await ctx.db.local().get_compaction_manager().get_compaction_history([&s, &first](const db::compaction_history_entry& entry) mutable -> future<> {
co_await cm.local().get_compaction_history([&s, &first](const db::compaction_history_entry& entry) mutable -> future<> {
cm::history h;
h.id = fmt::to_string(entry.id);
h.ks = std::move(entry.ks);
@@ -168,7 +168,9 @@ void set_compaction_manager(http_context& ctx, routes& r) {
h.compacted_at = entry.compacted_at;
h.bytes_in = entry.bytes_in;
h.bytes_out = entry.bytes_out;
for (auto it : entry.rows_merged) {
std::map<int32_t, int64_t> items(entry.rows_merged.begin(), entry.rows_merged.end());
for (auto it : items) {
httpd::compaction_manager_json::row_merged e;
e.key = it.first;
e.value = it.second;
@@ -201,6 +203,34 @@ void set_compaction_manager(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(res);
});
ss::get_compaction_throughput_mb_per_sec.set(r, [&cm](std::unique_ptr<http::request> req) {
int value = cm.local().throughput_mbs();
return make_ready_future<json::json_return_type>(value);
});
ss::set_compaction_throughput_mb_per_sec.set(r, [](std::unique_ptr<http::request> req) {
//TBD
unimplemented();
auto value = req->get_query_param("value");
return make_ready_future<json::json_return_type>(json_void());
});
}
void unset_compaction_manager(http_context& ctx, routes& r) {
cm::get_compactions.unset(r);
cm::get_pending_tasks_by_table.unset(r);
cm::force_user_defined_compaction.unset(r);
cm::stop_compaction.unset(r);
cm::stop_keyspace_compaction.unset(r);
cm::get_pending_tasks.unset(r);
cm::get_completed_tasks.unset(r);
cm::get_total_compactions_completed.unset(r);
cm::get_bytes_compacted.unset(r);
cm::get_compaction_history.unset(r);
cm::get_compaction_info.unset(r);
ss::get_compaction_throughput_mb_per_sec.unset(r);
ss::set_compaction_throughput_mb_per_sec.unset(r);
}
}

View File

@@ -7,13 +7,17 @@
*/
#pragma once
#include <seastar/core/sharded.hh>
namespace seastar::httpd {
class routes;
}
class compaction_manager;
namespace api {
struct http_context;
void set_compaction_manager(http_context& ctx, seastar::httpd::routes& r);
void set_compaction_manager(http_context& ctx, seastar::httpd::routes& r, seastar::sharded<compaction_manager>& cm);
void unset_compaction_manager(http_context& ctx, seastar::httpd::routes& r);
}

View File

@@ -9,7 +9,6 @@
#ifndef SCYLLA_BUILD_MODE_RELEASE
#include <seastar/core/coroutine.hh>
#include <boost/range/algorithm/transform.hpp>
#include "api/api-doc/cql_server_test.json.hh"
#include "cql_server_test.hh"
@@ -50,7 +49,7 @@ void set_cql_server_test(http_context& ctx, seastar::httpd::routes& r, cql_trans
auto sl_params = co_await ctl.get_connections_service_level_params();
std::vector<connection_sl_params> result;
boost::transform(std::move(sl_params), std::back_inserter(result), [] (const cql_transport::connection_service_level_params& params) {
std::ranges::transform(std::move(sl_params), std::back_inserter(result), [] (const cql_transport::connection_service_level_params& params) {
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(params.timeout_config.read_timeout).count();
return connection_sl_params(
std::move(params.role_name),

View File

@@ -11,7 +11,7 @@
#include <seastar/http/exception.hh>
#include "utils/logalloc.hh"
#include "log.hh"
#include "utils/log.hh"
namespace api {
using namespace seastar::httpd;

View File

@@ -11,7 +11,8 @@
#include "api/api-doc/raft.json.hh"
#include "service/raft/raft_group_registry.hh"
#include "log.hh"
#include "service/raft/raft_address_map.hh"
#include "utils/log.hh"
using namespace seastar::httpd;
@@ -102,8 +103,8 @@ void set_raft(http_context&, httpd::routes& r, sharded<service::raft_group_regis
if (!req->query_parameters.contains("group_id")) {
// Read barrier on group 0 by default
co_await raft_gr.invoke_on(0, [timeout] (service::raft_group_registry& raft_gr) {
return raft_gr.group0_with_timeouts().read_barrier(nullptr, timeout);
co_await raft_gr.invoke_on(0, [timeout] (service::raft_group_registry& raft_gr) -> future<> {
co_await raft_gr.group0_with_timeouts().read_barrier(nullptr, timeout);
});
co_return json_void{};
}
@@ -111,18 +112,52 @@ void set_raft(http_context&, httpd::routes& r, sharded<service::raft_group_regis
raft::group_id gid{utils::UUID{req->get_query_param("group_id")}};
std::atomic<bool> found_srv{false};
co_await raft_gr.invoke_on_all([gid, timeout, &found_srv] (service::raft_group_registry& raft_gr) {
co_await raft_gr.invoke_on_all([gid, timeout, &found_srv] (service::raft_group_registry& raft_gr) -> future<> {
if (!raft_gr.find_server(gid)) {
return make_ready_future<>();
co_return;
}
found_srv = true;
return raft_gr.get_server_with_timeouts(gid).read_barrier(nullptr, timeout);
co_await raft_gr.get_server_with_timeouts(gid).read_barrier(nullptr, timeout);
});
if (!found_srv) {
throw bad_param_exception{fmt::format("Server for group ID {} not found", gid)};
}
co_return json_void{};
});
r::trigger_stepdown.set(r, [&raft_gr] (std::unique_ptr<http::request> req) -> future<json_return_type> {
auto timeout = get_request_timeout(*req);
auto dur = timeout.value ? *timeout.value - lowres_clock::now() : std::chrono::seconds(60);
const auto stepdown_timeout_ticks = dur / service::raft_tick_interval;
auto timeout_dur = raft::logical_clock::duration(stepdown_timeout_ticks);
if (!req->query_parameters.contains("group_id")) {
// Stepdown on group 0 by default
co_await raft_gr.invoke_on(0, [timeout_dur] (service::raft_group_registry& raft_gr) {
apilog.info("Triggering stepdown for group0");
return raft_gr.group0().stepdown(timeout_dur);
});
co_return json_void{};
}
raft::group_id gid{utils::UUID{req->get_path_param("group_id")}};
std::atomic<bool> found_srv{false};
co_await raft_gr.invoke_on_all([gid, timeout_dur, &found_srv] (service::raft_group_registry& raft_gr) -> future<> {
auto* srv = raft_gr.find_server(gid);
if (!srv) {
co_return;
}
found_srv = true;
apilog.info("Triggering stepdown for group {}", gid);
co_await srv->stepdown(timeout_dur);
});
if (!found_srv) {
throw std::runtime_error{fmt::format("Server for group ID {} not found", gid)};
}
co_return json_void{};
});
}
@@ -131,6 +166,7 @@ void unset_raft(http_context&, httpd::routes& r) {
r::trigger_snapshot.unset(r);
r::get_leader_host.unset(r);
r::read_barrier.unset(r);
r::trigger_stepdown.unset(r);
}
}

View File

@@ -30,7 +30,6 @@
#include "service/raft/raft_group0_client.hh"
#include "service/storage_service.hh"
#include "service/load_meter.hh"
#include "db/commitlog/commitlog.hh"
#include "gms/gossiper.hh"
#include "db/system_keyspace.hh"
#include <seastar/http/exception.hh>
@@ -40,7 +39,7 @@
#include "repair/row_level.hh"
#include "locator/snitch_base.hh"
#include "column_family.hh"
#include "log.hh"
#include "utils/log.hh"
#include "release.hh"
#include "compaction/compaction_manager.hh"
#include "compaction/task_manager_module.hh"
@@ -54,6 +53,7 @@
#include "locator/abstract_replication_strategy.hh"
#include "sstables_loader.hh"
#include "db/view/view_builder.hh"
#include "utils/rjson.hh"
#include "utils/user_provided_param.hh"
using namespace seastar::httpd;
@@ -496,13 +496,18 @@ void set_sstables_loader(http_context& ctx, routes& r, sharded<sstables_loader>&
auto keyspace = req->get_query_param("keyspace");
auto table = req->get_query_param("table");
auto bucket = req->get_query_param("bucket");
auto snapshot_name = req->get_query_param("snapshot");
if (table.empty()) {
// TODO: If missing, should restore all tables
throw httpd::bad_param_exception("The table name must be specified");
}
auto prefix = req->get_query_param("prefix");
auto task_id = co_await sst_loader.local().download_new_sstables(keyspace, table, endpoint, bucket, snapshot_name);
// TODO: the http_server backing the API does not use content streaming
// should use it for better performance
rjson::value parsed = rjson::parse(req->content);
if (!parsed.IsArray()) {
throw httpd::bad_param_exception("malformatted sstables in body");
}
auto sstables = parsed.GetArray() |
std::views::transform([] (const auto& s) { return sstring(rjson::to_string_view(s)); }) |
std::ranges::to<std::vector>();
auto task_id = co_await sst_loader.local().download_new_sstables(keyspace, table, prefix, std::move(sstables), endpoint, bucket);
co_return json::json_return_type(fmt::to_string(task_id));
});
@@ -538,10 +543,6 @@ static future<json::json_return_type> describe_ring_as_json_for_table(const shar
}
void set_storage_service(http_context& ctx, routes& r, sharded<service::storage_service>& ss, service::raft_group0_client& group0_client) {
ss::get_commitlog.set(r, [&ctx](const_req req) {
return ctx.db.local().commitlog()->active_config().commit_log_location;
});
ss::get_token_endpoint.set(r, [&ctx, &ss] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
const auto keyspace_name = req->get_query_param("keyspace");
const auto table_name = req->get_query_param("cf");
@@ -898,7 +899,8 @@ void set_storage_service(http_context& ctx, routes& r, sharded<service::storage_
auto host_id = validate_host_id(req->get_query_param("host_id"));
std::vector<sstring> ignore_nodes_strs = utils::split_comma_separated_list(req->get_query_param("ignore_nodes"));
apilog.info("remove_node: host_id={} ignore_nodes={}", host_id, ignore_nodes_strs);
auto ignore_nodes = std::list<locator::host_id_or_endpoint>();
locator::host_id_or_endpoint_list ignore_nodes;
ignore_nodes.reserve(ignore_nodes_strs.size());
for (const sstring& n : ignore_nodes_strs) {
try {
auto hoep = locator::host_id_or_endpoint(n);
@@ -1061,18 +1063,6 @@ void set_storage_service(http_context& ctx, routes& r, sharded<service::storage_
return make_ready_future<json::json_return_type>(0);
});
ss::get_compaction_throughput_mb_per_sec.set(r, [&ctx](std::unique_ptr<http::request> req) {
int value = ctx.db.local().get_compaction_manager().throughput_mbs();
return make_ready_future<json::json_return_type>(value);
});
ss::set_compaction_throughput_mb_per_sec.set(r, [](std::unique_ptr<http::request> req) {
//TBD
unimplemented();
auto value = req->get_query_param("value");
return make_ready_future<json::json_return_type>(json_void());
});
ss::is_incremental_backups_enabled.set(r, [&ctx](std::unique_ptr<http::request> req) {
// If this is issued in parallel with an ongoing change, we may see values not agreeing.
// Reissuing is asking for trouble, so we will just return true upon seeing any true value.
@@ -1571,7 +1561,6 @@ void set_storage_service(http_context& ctx, routes& r, sharded<service::storage_
}
void unset_storage_service(http_context& ctx, routes& r) {
ss::get_commitlog.unset(r);
ss::get_token_endpoint.unset(r);
ss::toppartitions_generic.unset(r);
ss::get_release_version.unset(r);
@@ -1614,8 +1603,6 @@ void unset_storage_service(http_context& ctx, routes& r) {
ss::is_joined.unset(r);
ss::set_stream_throughput_mb_per_sec.unset(r);
ss::get_stream_throughput_mb_per_sec.unset(r);
ss::get_compaction_throughput_mb_per_sec.unset(r);
ss::set_compaction_throughput_mb_per_sec.unset(r);
ss::is_incremental_backups_enabled.unset(r);
ss::set_incremental_backups_enabled.unset(r);
ss::rebuild.unset(r);
@@ -1795,7 +1782,9 @@ void set_snapshot(http_context& ctx, routes& r, sharded<db::snapshot_ctl>& snap_
ss::start_backup.set(r, [&snap_ctl] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
auto endpoint = req->get_query_param("endpoint");
auto keyspace = req->get_query_param("keyspace");
auto table = req->get_query_param("table");
auto bucket = req->get_query_param("bucket");
auto prefix = req->get_query_param("prefix");
auto snapshot_name = req->get_query_param("snapshot");
if (snapshot_name.empty()) {
// TODO: If missing, snapshot should be taken by scylla, then removed
@@ -1803,7 +1792,7 @@ void set_snapshot(http_context& ctx, routes& r, sharded<db::snapshot_ctl>& snap_
}
auto& ctl = snap_ctl.local();
auto task_id = co_await ctl.start_backup(std::move(endpoint), std::move(bucket), std::move(keyspace), std::move(snapshot_name));
auto task_id = co_await ctl.start_backup(std::move(endpoint), std::move(bucket), std::move(prefix), std::move(keyspace), std::move(table), std::move(snapshot_name));
co_return json::json_return_type(fmt::to_string(task_id));
});

View File

@@ -12,6 +12,7 @@
#include <seastar/json/json_elements.hh>
#include "api/api_init.hh"
#include "db/data_listeners.hh"
#include "compaction/compaction_descriptor.hh"
namespace cql_transport { class controller; }
namespace db {

View File

@@ -10,7 +10,7 @@
#include "api/api-doc/system.json.hh"
#include "api/api-doc/metrics.json.hh"
#include "replica/database.hh"
#include "sstables/sstables_manager.hh"
#include "db/sstables-format-selector.hh"
#include <rapidjson/document.h>
#include <seastar/core/reactor.hh>
@@ -20,7 +20,7 @@
#include <seastar/util/short_streams.hh>
#include <seastar/http/short_streams.hh>
#include "log.hh"
#include "utils/log.hh"
extern logging::logger apilog;
@@ -183,11 +183,18 @@ void set_system(http_context& ctx, routes& r) {
apilog.info("Profile dumped to {}", profile_dest);
return make_ready_future<json::json_return_type>(json::json_return_type(json::json_void()));
}) ;
}
hs::get_highest_supported_sstable_version.set(r, [&ctx] (const_req req) {
auto& table = ctx.db.local().find_column_family("system", "local");
return seastar::to_sstring(table.get_sstables_manager().get_highest_supported_format());
void set_format_selector(http_context& ctx, routes& r, db::sstables_format_selector& sel) {
hs::get_highest_supported_sstable_version.set(r, [&sel] (std::unique_ptr<request> req) {
return smp::submit_to(0, [&sel] {
return make_ready_future<json::json_return_type>(seastar::to_sstring(sel.selected_format()));
});
});
}
void unset_format_selector(http_context& ctx, routes& r) {
hs::get_highest_supported_sstable_version.unset(r);
}
}

View File

@@ -12,9 +12,14 @@ namespace seastar::httpd {
class routes;
}
namespace db { class sstables_format_selector; }
namespace api {
struct http_context;
void set_system(http_context& ctx, seastar::httpd::routes& r);
void set_format_selector(http_context& ctx, seastar::httpd::routes& r, db::sstables_format_selector& sel);
void unset_format_selector(http_context& ctx, seastar::httpd::routes& r);
}

View File

@@ -18,7 +18,6 @@
#include "utils/overloaded_functor.hh"
#include <utility>
#include <boost/range/adaptors.hpp>
namespace api {
@@ -34,7 +33,7 @@ tm::task_status make_status(tasks::task_status status) {
::gmtime_r(&start_time, &st);
std::vector<tm::task_identity> tis{status.children.size()};
boost::transform(status.children, tis.begin(), [] (const auto& child) {
std::ranges::transform(status.children, tis.begin(), [] (const auto& child) {
tm::task_identity ident;
ident.task_id = child.task_id.to_sstring();
ident.node = fmt::format("{}", child.node);
@@ -80,7 +79,7 @@ tm::task_stats make_stats(tasks::task_stats stats) {
void set_task_manager(http_context& ctx, routes& r, sharded<tasks::task_manager>& tm, db::config& cfg) {
tm::get_modules.set(r, [&tm] (std::unique_ptr<http::request> req) -> future<json::json_return_type> {
std::vector<std::string> v = boost::copy_range<std::vector<std::string>>(tm.local().get_modules() | boost::adaptors::map_keys);
std::vector<std::string> v = tm.local().get_modules() | std::views::keys | std::ranges::to<std::vector>();
co_return v;
});

View File

@@ -16,6 +16,7 @@
#include "compaction/task_manager_module.hh"
#include "service/storage_service.hh"
#include "tasks/task_manager.hh"
#include "replica/database.hh"
using namespace seastar::httpd;

View File

@@ -71,7 +71,7 @@ void set_token_metadata(http_context& ctx, routes& r, sharded<locator::shared_to
ss::get_host_id_map.set(r, [&tm](const_req req) {
std::vector<ss::mapper> res;
return map_to_key_value(tm.local().get()->get_endpoint_to_host_id_map_for_reading(), res);
return map_to_key_value(tm.local().get()->get_endpoint_to_host_id_map(), res);
});
static auto host_or_broadcast = [&tm](const_req req) {

View File

@@ -12,6 +12,7 @@
#include <stdexcept>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <seastar/core/print.hh>
#include <seastar/core/sstring.hh>
@@ -22,6 +23,7 @@ namespace auth {
enum class authentication_option {
password,
hashed_password,
options
};
@@ -35,6 +37,8 @@ struct fmt::formatter<auth::authentication_option> : fmt::formatter<string_view>
switch (a) {
case password:
return formatter<string_view>::format("PASSWORD", ctx);
case hashed_password:
return formatter<string_view>::format("HASHED PASSWORD", ctx);
case options:
return formatter<string_view>::format("OPTIONS", ctx);
}
@@ -48,13 +52,22 @@ using authentication_option_set = std::unordered_set<authentication_option>;
using custom_options = std::unordered_map<sstring, sstring>;
struct password_option {
sstring password;
};
/// Used exclusively for restoring roles.
struct hashed_password_option {
sstring hashed_password;
};
struct authentication_options final {
std::optional<sstring> password;
std::optional<std::variant<password_option, hashed_password_option>> credentials;
std::optional<custom_options> options;
};
inline bool any_authentication_options(const authentication_options& aos) noexcept {
return aos.password || aos.options;
return aos.options || aos.credentials;
}
class unsupported_authentication_option : public std::invalid_argument {

View File

@@ -43,6 +43,11 @@ struct certificate_info {
using session_dn_func = std::function<future<std::optional<certificate_info>>()>;
class unsupported_authentication_operation : public std::invalid_argument {
public:
using std::invalid_argument::invalid_argument;
};
///
/// Abstract client for authenticating role identity.
///
@@ -129,6 +134,19 @@ public:
///
virtual future<custom_options> query_custom_options(std::string_view role_name) const = 0;
virtual bool uses_password_hashes() const {
return false;
}
///
/// Query the password hash corresponding to a given role.
///
/// If the authenticator doesn't use password hashes, throws an `unsupported_authentication_operation` exception.
///
virtual future<std::optional<sstring>> get_password_hash(std::string_view role_name) const {
return make_exception_future<std::optional<sstring>>(unsupported_authentication_operation("get_password_hash is not implemented"));
}
///
/// System resources used internally as part of the implementation. These are made inaccessible to users.
///

View File

@@ -9,7 +9,7 @@
#include "auth/certificate_authenticator.hh"
#include <regex>
#include <boost/regex.hpp>
#include <fmt/ranges.h>
#include "utils/class_registrator.hh"
@@ -76,7 +76,7 @@ auth::certificate_authenticator::certificate_authenticator(cql3::query_processor
continue;
} catch (std::out_of_range&) {
// just fallthrough
} catch (std::regex_error&) {
} catch (boost::regex_error&) {
std::throw_with_nested(std::invalid_argument(fmt::format("Invalid query expression: {}", map.at(cfg_query_attr))));
}
}

View File

@@ -10,6 +10,7 @@
#pragma once
#include "auth/authenticator.hh"
#include <boost/regex_fwd.hpp> // IWYU pragma: keep
namespace cql3 {

View File

@@ -25,6 +25,7 @@
#include "service/raft/group0_state_machine.hh"
#include "timeout_config.hh"
#include "utils/error_injection.hh"
#include "db/system_keyspace.hh"
namespace auth {
@@ -40,7 +41,7 @@ constinit const std::string_view AUTH_PACKAGE_NAME("org.apache.cassandra.auth.")
static logging::logger auth_log("auth");
bool legacy_mode(cql3::query_processor& qp) {
return qp.auth_version < db::system_keyspace::auth_version_t::v2;
return qp.auth_version < db::auth_version_t::v2;
}
std::string_view get_auth_ks_name(cql3::query_processor& qp) {

View File

@@ -27,7 +27,7 @@ extern "C" {
#include "cql3/query_processor.hh"
#include "cql3/untyped_result_set.hh"
#include "exceptions/exceptions.hh"
#include "log.hh"
#include "utils/log.hh"
#include "utils/class_registrator.hh"
namespace auth {

View File

@@ -11,6 +11,7 @@
#include <seastar/core/future.hh>
#include <stdexcept>
#include <string_view>
#include "cql3/description.hh"
#include "utils/class_registrator.hh"
namespace auth {
@@ -43,6 +44,10 @@ future<> maintenance_socket_role_manager::stop() {
return make_ready_future<>();
}
future<> maintenance_socket_role_manager::ensure_superuser_is_created() {
return make_ready_future<>();
}
template<typename T = void>
future<T> operation_not_supported_exception(std::string_view operation) {
return make_exception_future<T>(
@@ -109,4 +114,8 @@ future<> maintenance_socket_role_manager::remove_attribute(std::string_view role
return operation_not_supported_exception("REMOVE ATTRIBUTE");
}
future<std::vector<cql3::description>> maintenance_socket_role_manager::describe_role_grants() {
return operation_not_supported_exception<std::vector<cql3::description>>("DESCRIBE SCHEMA WITH INTERNALS");
}
} // namespace auth

View File

@@ -39,6 +39,8 @@ public:
virtual future<> stop() override;
virtual future<> ensure_superuser_is_created() override;
virtual future<> create(std::string_view role_name, const role_config&, ::service::group0_batch&) override;
virtual future<> drop(std::string_view role_name, ::service::group0_batch& mc) override;
@@ -68,6 +70,8 @@ public:
virtual future<> set_attribute(std::string_view role_name, std::string_view attribute_name, std::string_view attribute_value, ::service::group0_batch& mc) override;
virtual future<> remove_attribute(std::string_view role_name, std::string_view attribute_name, ::service::group0_batch& mc) override;
virtual future<std::vector<cql3::description>> describe_role_grants() override;
};
}

View File

@@ -14,16 +14,17 @@
#include <string_view>
#include <optional>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <seastar/core/seastar.hh>
#include <seastar/core/sleep.hh>
#include <variant>
#include "auth/authenticated_user.hh"
#include "auth/authentication_options.hh"
#include "auth/common.hh"
#include "auth/passwords.hh"
#include "auth/roles-metadata.hh"
#include "cql3/untyped_result_set.hh"
#include "log.hh"
#include "utils/log.hh"
#include "service/migration_manager.hh"
#include "utils/class_registrator.hh"
#include "replica/database.hh"
@@ -199,7 +200,7 @@ bool password_authenticator::require_authentication() const {
}
authentication_option_set password_authenticator::supported_options() const {
return authentication_option_set{authentication_option::password};
return authentication_option_set{authentication_option::password, authentication_option::hashed_password};
}
authentication_option_set password_authenticator::alterable_options() const {
@@ -218,28 +219,8 @@ future<authenticated_user> password_authenticator::authenticate(
const sstring username = credentials.at(USERNAME_KEY);
const sstring password = credentials.at(PASSWORD_KEY);
// Here was a thread local, explicit cache of prepared statement. In normal execution this is
// fine, but since we in testing set up and tear down system over and over, we'd start using
// obsolete prepared statements pretty quickly.
// Rely on query processing caching statements instead, and lets assume
// that a map lookup string->statement is not gonna kill us much.
const sstring query = seastar::format("SELECT {} FROM {}.{} WHERE {} = ?",
SALTED_HASH,
get_auth_ks_name(_qp),
meta::roles_table::name,
meta::roles_table::role_col_name);
try {
const auto res = co_await _qp.execute_internal(
query,
consistency_for_user(username),
internal_distributed_query_state(),
{username},
cql3::query_processor::cache_internal::yes);
auto salted_hash = std::optional<sstring>();
if (!res->empty()) {
salted_hash = res->one().get_opt<sstring>(SALTED_HASH);
}
const std::optional<sstring> salted_hash = co_await get_password_hash(username);
if (!salted_hash || !passwords::check(password, *salted_hash)) {
throw exceptions::authentication_exception("Username and/or password are incorrect");
}
@@ -258,28 +239,45 @@ future<authenticated_user> password_authenticator::authenticate(
}
future<> password_authenticator::create(std::string_view role_name, const authentication_options& options, ::service::group0_batch& mc) {
if (!options.password) {
// When creating a role with the usual `CREATE ROLE` statement, turns the underlying `PASSWORD`
// into the corresponding hash.
// When creating a role with `CREATE ROLE WITH HASHED PASSWORD`, simply extracts the `HASHED PASSWORD`.
auto maybe_hash = options.credentials.transform([&] (const auto& creds) -> sstring {
return std::visit(make_visitor(
[&] (const password_option& opt) {
return passwords::hash(opt.password, rng_for_salt);
},
[] (const hashed_password_option& opt) {
return opt.hashed_password;
}
), creds);
});
// Neither `PASSWORD`, nor `HASHED PASSWORD` has been specified.
if (!maybe_hash) {
co_return;
}
const auto query = update_row_query();
if (legacy_mode(_qp)) {
co_await _qp.execute_internal(
query,
consistency_for_user(role_name),
internal_distributed_query_state(),
{passwords::hash(*options.password, rng_for_salt), sstring(role_name)},
{std::move(*maybe_hash), sstring(role_name)},
cql3::query_processor::cache_internal::no).discard_result();
} else {
co_await collect_mutations(_qp, mc, query,
{passwords::hash(*options.password, rng_for_salt), sstring(role_name)});
co_await collect_mutations(_qp, mc, query, {std::move(*maybe_hash), sstring(role_name)});
}
}
future<> password_authenticator::alter(std::string_view role_name, const authentication_options& options, ::service::group0_batch& mc) {
if (!options.password) {
if (!options.credentials) {
co_return;
}
const auto password = std::get<password_option>(*options.credentials).password;
const sstring query = seastar::format("UPDATE {}.{} SET {} = ? WHERE {} = ?",
get_auth_ks_name(_qp),
meta::roles_table::name,
@@ -290,11 +288,11 @@ future<> password_authenticator::alter(std::string_view role_name, const authent
query,
consistency_for_user(role_name),
internal_distributed_query_state(),
{passwords::hash(*options.password, rng_for_salt), sstring(role_name)},
{passwords::hash(password, rng_for_salt), sstring(role_name)},
cql3::query_processor::cache_internal::no).discard_result();
} else {
co_await collect_mutations(_qp, mc, query,
{passwords::hash(*options.password, rng_for_salt), sstring(role_name)});
{passwords::hash(password, rng_for_salt), sstring(role_name)});
}
}
@@ -319,6 +317,36 @@ future<custom_options> password_authenticator::query_custom_options(std::string_
return make_ready_future<custom_options>();
}
bool password_authenticator::uses_password_hashes() const {
return true;
}
future<std::optional<sstring>> password_authenticator::get_password_hash(std::string_view role_name) const {
// Here was a thread local, explicit cache of prepared statement. In normal execution this is
// fine, but since we in testing set up and tear down system over and over, we'd start using
// obsolete prepared statements pretty quickly.
// Rely on query processing caching statements instead, and lets assume
// that a map lookup string->statement is not gonna kill us much.
const sstring query = seastar::format("SELECT {} FROM {}.{} WHERE {} = ?",
SALTED_HASH,
get_auth_ks_name(_qp),
meta::roles_table::name,
meta::roles_table::role_col_name);
const auto res = co_await _qp.execute_internal(
query,
consistency_for_user(role_name),
internal_distributed_query_state(),
{role_name},
cql3::query_processor::cache_internal::yes);
if (res->empty()) {
co_return std::nullopt;
}
co_return res->one().get_opt<sstring>(SALTED_HASH);
}
const resource_set& password_authenticator::protected_resources() const {
static const resource_set resources({make_data_resource(meta::legacy::AUTH_KS, meta::roles_table::name)});
return resources;

View File

@@ -72,6 +72,10 @@ public:
virtual future<custom_options> query_custom_options(std::string_view role_name) const override;
virtual bool uses_password_hashes() const override;
virtual future<std::optional<sstring>> get_password_hash(std::string_view role_name) const override;
virtual const resource_set& protected_resources() const override;
virtual ::shared_ptr<sasl_challenge> new_sasl_challenge() const override;

View File

@@ -17,7 +17,7 @@
#include "auth/permission.hh"
#include "auth/resource.hh"
#include "auth/role_or_anonymous.hh"
#include "log.hh"
#include "utils/log.hh"
#include "utils/hash.hh"
#include "utils/loading_cache.hh"

View File

@@ -23,7 +23,7 @@
#include "cql3/functions/user_function.hh"
#include "cql3/util.hh"
#include "db/marshal/type_parser.hh"
#include "log.hh"
#include "utils/log.hh"
namespace auth {

View File

@@ -18,6 +18,7 @@
#include <seastar/core/sstring.hh>
#include "auth/resource.hh"
#include "cql3/description.hh"
#include "seastarx.hh"
#include "exceptions/exceptions.hh"
#include "service/raft/raft_group0_client.hh"
@@ -106,6 +107,13 @@ public:
virtual future<> stop() = 0;
///
/// Ensure that superuser role exists.
///
/// \returns a future once it is ensured that the superuser role exists.
///
virtual future<> ensure_superuser_is_created() = 0;
///
/// \returns an exceptional future with \ref role_already_exists for a role that has previously been created.
///
@@ -195,5 +203,8 @@ public:
/// \note: This is a no-op if the role does not have the named attribute set.
///
virtual future<> remove_attribute(std::string_view role_name, std::string_view attribute_name, ::service::group0_batch& mc) = 0;
/// Produces descriptions that can be used to restore the role grants.
virtual future<std::vector<cql3::description>> describe_role_grants() = 0;
};
}

View File

@@ -8,7 +8,6 @@
#include "auth/roles-metadata.hh"
#include <boost/algorithm/cxx11/any_of.hpp>
#include <seastar/core/print.hh>
#include <seastar/core/shared_ptr.hh>
#include <seastar/core/sstring.hh>
@@ -79,7 +78,7 @@ future<bool> any_nondefault_role_row_satisfies(
}
static const sstring col_name = sstring(meta::roles_table::role_col_name);
co_return boost::algorithm::any_of(*results, [&](const cql3::untyped_result_set_row& row) {
co_return std::ranges::any_of(*results, [&](const cql3::untyped_result_set_row& row) {
auto superuser = rolename ? std::string_view(*rolename) : meta::DEFAULT_SUPERUSER_NAME;
const bool is_nondefault = row.get_as<sstring>(col_name) != superuser;
return is_nondefault && p(row);

View File

@@ -18,7 +18,7 @@
#include <seastar/core/sstring.hh>
#include "auth/authenticated_user.hh"
#include "bytes.hh"
#include "bytes_fwd.hh"
#include "seastarx.hh"
namespace auth {

View File

@@ -8,6 +8,8 @@
#include <exception>
#include <seastar/core/coroutine.hh>
#include "auth/authentication_options.hh"
#include "auth/authorizer.hh"
#include "auth/resource.hh"
#include "auth/service.hh"
@@ -25,14 +27,17 @@
#include "auth/role_or_anonymous.hh"
#include "cql3/functions/functions.hh"
#include "cql3/query_processor.hh"
#include "cql3/description.hh"
#include "cql3/untyped_result_set.hh"
#include "cql3/util.hh"
#include "db/config.hh"
#include "db/consistency_level_type.hh"
#include "db/functions/function_name.hh"
#include "log.hh"
#include "utils/log.hh"
#include "schema/schema_fwd.hh"
#include <seastar/core/future.hh>
#include <seastar/coroutine/parallel_for_each.hh>
#include <variant>
#include "service/migration_manager.hh"
#include "service/raft/raft_group0_client.hh"
#include "timestamp.hh"
@@ -257,6 +262,10 @@ future<> service::stop() {
});
}
future<> service::ensure_superuser_is_created() {
return _role_manager->ensure_superuser_is_created();
}
void service::update_cache_config() {
auto db = _qp.db();
@@ -322,8 +331,11 @@ static void validate_authentication_options_are_supported(
}
};
if (options.password) {
check(authentication_option::password);
if (options.credentials) {
std::visit(make_visitor(
[&] (const password_option&) { check(authentication_option::password); },
[&] (const hashed_password_option&) { check(authentication_option::hashed_password); }
), *options.credentials);
}
if (options.options) {
@@ -418,6 +430,223 @@ future<bool> service::exists(const resource& r) const {
return make_ready_future<bool>(false);
}
future<std::vector<cql3::description>> service::describe_roles(bool with_hashed_passwords) {
std::vector<cql3::description> result{};
const auto roles = co_await _role_manager->query_all();
result.reserve(roles.size());
const bool authenticator_uses_password_hashes = _authenticator->uses_password_hashes();
auto produce_create_statement = [with_hashed_passwords] (const sstring& formatted_role_name,
const std::optional<sstring>& maybe_hashed_password, bool can_login, bool is_superuser) {
// Even after applying formatting to a role, `formatted_role_name` can only equal `meta::DEFAULT_SUPER_NAME`
// if the original identifier was equal to it.
const sstring role_part = formatted_role_name == meta::DEFAULT_SUPERUSER_NAME
? seastar::format("IF NOT EXISTS {}", formatted_role_name)
: formatted_role_name;
const sstring with_hashed_password_part = with_hashed_passwords && maybe_hashed_password
// `K_PASSWORD` in Scylla's CQL grammar requires that passwords be quoted
// with single quotation marks.
? seastar::format("WITH HASHED PASSWORD = {} AND", cql3::util::single_quote(*maybe_hashed_password))
: "WITH";
return seastar::format("CREATE ROLE {} {} LOGIN = {} AND SUPERUSER = {};",
role_part, with_hashed_password_part, can_login, is_superuser);
};
for (const auto& role : roles) {
const sstring formatted_role_name = cql3::util::maybe_quote(role);
std::optional<sstring> maybe_hashed_password;
if (authenticator_uses_password_hashes) {
maybe_hashed_password = co_await _authenticator->get_password_hash(role);
}
const bool can_login = co_await _role_manager->can_login(role);
const bool is_superuser = co_await _role_manager->is_superuser(role);
result.push_back(cql3::description {
// Roles do not belong to any keyspace.
.keyspace = std::nullopt,
.type = "role",
.name = role,
.create_statement = produce_create_statement(formatted_role_name, maybe_hashed_password, can_login, is_superuser)
});
}
std::ranges::sort(result, std::less<>{}, std::mem_fn(&cql3::description::name));
co_return result;
}
// The function doesn't assume anything about `role`.
static sstring describe_data_resource(const permission& perm, const resource& r, std::string_view role) {
const auto permission = permissions::to_string(perm);
const auto formatted_role = cql3::util::maybe_quote(role);
const auto view = data_resource_view(r);
const auto maybe_ks = view.keyspace();
const auto maybe_cf = view.table();
// The documentation says:
//
// Both keyspace and table names consist of only alphanumeric characters, cannot be empty,
// and are limited in size to 48 characters (that limit exists mostly to avoid filenames,
// which may include the keyspace and table name, to go over the limits of certain file systems).
// By default, keyspace and table names are case insensitive (myTable is equivalent to mytable),
// but case sensitivity can be forced by using double-quotes ("myTable" is different from mytable).
//
// That's why we wrap identifiers with quotation marks below.
if (!maybe_ks) {
return seastar::format("GRANT {} ON ALL KEYSPACES TO {};", permission, formatted_role);
}
const auto ks = cql3::util::maybe_quote(*maybe_ks);
if (!maybe_cf) {
return seastar::format("GRANT {} ON KEYSPACE {} TO {};", permission, ks, formatted_role);
}
const auto cf = cql3::util::maybe_quote(*maybe_cf);
return seastar::format("GRANT {} ON {}.{} TO {};", permission, ks, cf, formatted_role);
}
// The function doesn't assume anything about `role`.
static sstring describe_role_resource(const permission& perm, const resource& r, std::string_view role) {
const auto permission = permissions::to_string(perm);
const auto formatted_role = cql3::util::maybe_quote(role);
const auto view = role_resource_view(r);
const auto maybe_target_role = view.role();
if (!maybe_target_role) {
return seastar::format("GRANT {} ON ALL ROLES TO {};", permission, formatted_role);
}
return seastar::format("GRANT {} ON ROLE {} TO {};", permission, cql3::util::maybe_quote(*maybe_target_role), formatted_role);
}
// The function doesn't assume anything about `role`.
static sstring describe_udf_resource(const permission& perm, const resource& r, std::string_view role) {
const auto permission = permissions::to_string(perm);
const auto formatted_role = cql3::util::maybe_quote(role);
const auto view = functions_resource_view(r);
const auto maybe_ks = view.keyspace();
const auto maybe_fun_sig = view.function_signature();
const auto maybe_fun_name = view.function_name();
const auto maybe_fun_args = view.function_args();
// The documentation says:
//
// Both keyspace and table names consist of only alphanumeric characters, cannot be empty,
// and are limited in size to 48 characters (that limit exists mostly to avoid filenames,
// which may include the keyspace and table name, to go over the limits of certain file systems).
// By default, keyspace and table names are case insensitive (myTable is equivalent to mytable),
// but case sensitivity can be forced by using double-quotes ("myTable" is different from mytable).
//
// That's why we wrap identifiers with quotation marks below.
if (!maybe_ks) {
return seastar::format("GRANT {} ON ALL FUNCTIONS TO {};", permission, formatted_role);
}
const auto ks = cql3::util::maybe_quote(*maybe_ks);
if (!maybe_fun_sig && !maybe_fun_name) {
return seastar::format("GRANT {} ON ALL FUNCTIONS IN KEYSPACE {} TO {};", permission, ks, formatted_role);
}
if (maybe_fun_name) {
SCYLLA_ASSERT(maybe_fun_args);
const auto fun_name = cql3::util::maybe_quote(*maybe_fun_name);
const auto fun_args_range = *maybe_fun_args | std::views::transform([] (const auto& fun_arg) {
return cql3::util::maybe_quote(fun_arg);
});
return seastar::format("GRANT {} ON FUNCTION {}.{}({}) TO {};",
permission, ks, fun_name, fmt::join(fun_args_range, ", "), formatted_role);
}
SCYLLA_ASSERT(maybe_fun_sig);
auto [fun_name, fun_args] = decode_signature(*maybe_fun_sig);
fun_name = cql3::util::maybe_quote(fun_name);
// We don't call `cql3::util::maybe_quote` later because `cql3_type_name_without_frozen` already guarantees
// that the type will be wrapped within double quotation marks if it's necessary.
auto parsed_fun_args = fun_args | std::views::transform([] (const data_type& dt) {
return dt->without_reversed().cql3_type_name_without_frozen();
});
return seastar::format("GRANT {} ON FUNCTION {}.{}({}) TO {};",
permission, ks, fun_name, fmt::join(parsed_fun_args, ", "), formatted_role);
}
// The function doesn't assume anything about `role`.
static sstring describe_resource_kind(const permission& perm, const resource& r, std::string_view role) {
switch (r.kind()) {
case resource_kind::data:
return describe_data_resource(perm, r, role);
case resource_kind::role:
return describe_role_resource(perm, r, role);
case resource_kind::service_level:
on_internal_error(log, "Granting permissions for service levels is not supported");
case resource_kind::functions:
return describe_udf_resource(perm, r, role);
}
}
future<std::vector<cql3::description>> service::describe_permissions() const {
std::vector<cql3::description> result{};
const auto permission_list = co_await std::invoke([&] -> future<std::vector<permission_details>> {
try {
co_return co_await _authorizer->list_all();
} catch (const unsupported_authorization_operation&) {
// If Scylla uses AllowAllAuthorizer, permissions do not exist and the corresponding authorizer
// will throw an exception when trying to access them.
co_return std::vector<permission_details>{};
}
});
for (const auto& permissions : permission_list) {
for (const auto& permission : permissions.permissions) {
result.push_back(cql3::description {
// Permission grants do not belong to any keyspace.
.keyspace = std::nullopt,
.type = "grant_permission",
.name = permissions.role_name,
.create_statement = describe_resource_kind(permission, permissions.resource, permissions.role_name)
});
}
co_await coroutine::maybe_yield();
}
std::ranges::sort(result, std::less<>{}, [] (const cql3::description& desc) noexcept {
return std::make_tuple(std::ref(desc.name), std::ref(*desc.create_statement));
});
co_return result;
}
future<std::vector<cql3::description>> service::describe_auth(bool with_hashed_passwords) {
auto role_descs = co_await describe_roles(with_hashed_passwords);
auto role_grant_descs = co_await _role_manager->describe_role_grants();
auto permission_descs = co_await describe_permissions();
auto join_vectors = [] (std::vector<cql3::description>& v1, std::vector<cql3::description>&& v2) {
v1.insert(v1.end(), std::make_move_iterator(v2.begin()), std::make_move_iterator(v2.end()));
};
join_vectors(role_descs, std::move(role_grant_descs));
join_vectors(role_descs, std::move(permission_descs));
co_return role_descs;
}
//
// Free functions.
//

View File

@@ -23,6 +23,7 @@
#include "auth/permissions_cache.hh"
#include "auth/role_manager.hh"
#include "auth/common.hh"
#include "cql3/description.hh"
#include "seastarx.hh"
#include "service/raft/raft_group0_client.hh"
#include "utils/observable.hh"
@@ -131,6 +132,8 @@ public:
future<> stop();
future<> ensure_superuser_is_created();
void update_cache_config();
void reset_authorization_cache();
@@ -174,6 +177,12 @@ public:
future<bool> exists(const resource&) const;
///
/// Produces descriptions that can be used to restore the state of auth. That encompasses
/// roles, role grants, and permission grants.
///
future<std::vector<cql3::description>> describe_auth(bool with_hashed_passwords);
authenticator& underlying_authenticator() const {
return *_authenticator;
}
@@ -197,6 +206,9 @@ public:
private:
future<> create_legacy_keyspace_if_missing(::service::migration_manager& mm) const;
future<bool> has_superuser(std::string_view role_name, const role_set& roles) const;
future<std::vector<cql3::description>> describe_roles(bool with_hashed_passwords);
future<std::vector<cql3::description>> describe_permissions() const;
};
future<bool> has_superuser(const service&, const authenticated_user&);

View File

@@ -24,10 +24,12 @@
#include "auth/role_manager.hh"
#include "auth/roles-metadata.hh"
#include "cql3/query_processor.hh"
#include "cql3/description.hh"
#include "cql3/untyped_result_set.hh"
#include "cql3/util.hh"
#include "db/consistency_level_type.hh"
#include "exceptions/exceptions.hh"
#include "log.hh"
#include "utils/log.hh"
#include "seastar/core/loop.hh"
#include "seastar/coroutine/maybe_yield.hh"
#include "service/raft/raft_group0_client.hh"
@@ -241,35 +243,39 @@ future<> standard_role_manager::migrate_legacy_metadata() {
}
future<> standard_role_manager::start() {
return once_among_shards([this] {
return futurize_invoke([this] () {
if (legacy_mode(_qp)) {
return create_legacy_metadata_tables_if_missing();
}
return make_ready_future<>();
}).then([this] {
_stopped = auth::do_after_system_ready(_as, [this] {
return seastar::async([this] {
if (legacy_mode(_qp)) {
_migration_manager.wait_for_schema_agreement(_qp.db().real_database(), db::timeout_clock::time_point::max(), &_as).get();
return once_among_shards([this] () -> future<> {
if (legacy_mode(_qp)) {
co_await create_legacy_metadata_tables_if_missing();
}
if (any_nondefault_role_row_satisfies(_qp, &has_can_login).get()) {
if (legacy_metadata_exists()) {
log.warn("Ignoring legacy user metadata since nondefault roles already exist.");
}
auto handler = [this] () -> future<> {
const bool legacy = legacy_mode(_qp);
if (legacy) {
if (!_superuser_created_promise.available()) {
_superuser_created_promise.set_value();
}
co_await _migration_manager.wait_for_schema_agreement(_qp.db().real_database(), db::timeout_clock::time_point::max(), &_as);
return;
}
if (legacy_metadata_exists()) {
migrate_legacy_metadata().get();
return;
}
if (co_await any_nondefault_role_row_satisfies(_qp, &has_can_login)) {
if (legacy_metadata_exists()) {
log.warn("Ignoring legacy user metadata since nondefault roles already exist.");
}
create_default_role_if_missing().get();
});
});
});
co_return;
}
if (legacy_metadata_exists()) {
co_await migrate_legacy_metadata();
co_return;
}
}
co_await create_default_role_if_missing();
if (!legacy) {
_superuser_created_promise.set_value();
}
};
_stopped = auth::do_after_system_ready(_as, handler);
co_return;
});
}
@@ -278,6 +284,11 @@ future<> standard_role_manager::stop() {
return _stopped.handle_exception_type([] (const sleep_aborted&) { }).handle_exception_type([](const abort_requested_exception&) {});;
}
future<> standard_role_manager::ensure_superuser_is_created() {
SCYLLA_ASSERT(this_shard_id() == 0);
return _superuser_created_promise.get_shared_future();
}
future<> standard_role_manager::create_or_replace(std::string_view role_name, const role_config& c, ::service::group0_batch& mc) {
const sstring query = seastar::format("INSERT INTO {}.{} ({}, is_superuser, can_login) VALUES (?, ?, ?)",
get_auth_ks_name(_qp),
@@ -701,4 +712,33 @@ future<> standard_role_manager::remove_attribute(std::string_view role_name, std
{sstring(role_name), sstring(attribute_name)});
}
}
future<std::vector<cql3::description>> standard_role_manager::describe_role_grants() {
std::vector<cql3::description> result{};
const auto grants = co_await query_all_directly_granted();
result.reserve(grants.size());
for (const auto& [grantee_role, granted_role] : grants) {
const auto formatted_grantee = cql3::util::maybe_quote(grantee_role);
const auto formatted_granted = cql3::util::maybe_quote(granted_role);
result.push_back(cql3::description {
// Role grants do not belong to any keyspace.
.keyspace = std::nullopt,
.type = "grant_role",
.name = granted_role,
.create_statement = seastar::format("GRANT {} TO {};", formatted_granted, formatted_grantee)
});
co_await coroutine::maybe_yield();
}
std::ranges::sort(result, std::less<>{}, [] (const cql3::description& desc) noexcept {
return std::make_tuple(std::ref(desc.name), std::ref(*desc.create_statement));
});
co_return result;
}
} // namespace auth

View File

@@ -15,8 +15,10 @@
#include <seastar/core/abort_source.hh>
#include <seastar/core/future.hh>
#include <seastar/core/shared_future.hh>
#include <seastar/core/sstring.hh>
#include "cql3/description.hh"
#include "seastarx.hh"
#include "service/raft/raft_group0_client.hh"
@@ -37,6 +39,7 @@ class standard_role_manager final : public role_manager {
future<> _stopped;
abort_source _as;
std::string _superuser;
shared_promise<> _superuser_created_promise;
public:
standard_role_manager(cql3::query_processor&, ::service::raft_group0_client&, ::service::migration_manager&);
@@ -49,6 +52,8 @@ public:
virtual future<> stop() override;
virtual future<> ensure_superuser_is_created() override;
virtual future<> create(std::string_view role_name, const role_config&, ::service::group0_batch&) override;
virtual future<> drop(std::string_view role_name, ::service::group0_batch& mc) override;
@@ -79,6 +84,8 @@ public:
virtual future<> remove_attribute(std::string_view role_name, std::string_view attribute_name, ::service::group0_batch& mc) override;
virtual future<std::vector<cql3::description>> describe_role_grants() override;
private:
enum class membership_change { add, remove };
@@ -97,4 +104,4 @@ private:
future<> modify_membership(std::string_view role_name, std::string_view grantee_name, membership_change, ::service::group0_batch& mc);
};
}
} // namespace auth

View File

@@ -103,6 +103,14 @@ public:
return _authenticator->query_custom_options(role_name);
}
virtual bool uses_password_hashes() const override {
return _authenticator->uses_password_hashes();
}
virtual future<std::optional<sstring>> get_password_hash(std::string_view role_name) const override {
return _authenticator->get_password_hash(role_name);
}
virtual const resource_set& protected_resources() const override {
return _authenticator->protected_resources();
}

View File

@@ -7,6 +7,7 @@
*/
#include "bytes.hh"
#include <fmt/ostream.h>
#include <seastar/core/print.hh>
static inline int8_t hex_to_int(unsigned char c) {

View File

@@ -16,13 +16,10 @@
#include <iosfwd>
#include <functional>
#include <compare>
#include "bytes_fwd.hh"
#include "utils/mutable_view.hh"
#include "utils/simple_hashers.hh"
using bytes = basic_sstring<int8_t, uint32_t, 31, false>;
using bytes_view = std::basic_string_view<int8_t>;
using bytes_mutable_view = basic_mutable_view<bytes_view::value_type>;
using bytes_opt = std::optional<bytes>;
using sstring_view = std::string_view;
inline bytes to_bytes(bytes&& b) {

20
bytes_fwd.hh Normal file
View File

@@ -0,0 +1,20 @@
/*
* Copyright (C) 2024-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <seastar/core/sstring.hh>
#include "utils/mutable_view.hh"
using namespace seastar;
using bytes = basic_sstring<int8_t, uint32_t, 31, false>;
using bytes_view = std::basic_string_view<int8_t>;
using bytes_mutable_view = basic_mutable_view<bytes_view::value_type>;
using bytes_opt = std::optional<bytes>;

View File

@@ -8,8 +8,6 @@
#pragma once
#include <boost/range/iterator_range.hpp>
#include "bytes.hh"
#include "utils/assert.hh"
#include "utils/managed_bytes.hh"
@@ -17,6 +15,51 @@
#include <seastar/core/loop.hh>
#include <bit>
#include <concepts>
#include <ranges>
class bytes_ostream_fragment_iterator {
public:
using iterator_category = std::input_iterator_tag;
using iterator_concept = std::input_iterator_tag;
using value_type = bytes_view;
using difference_type = std::ptrdiff_t;
using pointer = bytes_view*;
using reference = bytes_view&;
public:
using chunk = multi_chunk_blob_storage;
struct implementation {
chunk* current_chunk;
};
private:
chunk* _current = nullptr;
public:
bytes_ostream_fragment_iterator() = default;
bytes_ostream_fragment_iterator(chunk* current) : _current(current) {}
bytes_ostream_fragment_iterator(const bytes_ostream_fragment_iterator&) = default;
bytes_ostream_fragment_iterator& operator=(const bytes_ostream_fragment_iterator&) = default;
bytes_view operator*() const {
return { _current->data, _current->frag_size };
}
bytes_view operator->() const {
return *(*this);
}
bytes_ostream_fragment_iterator& operator++() {
_current = _current->next;
return *this;
}
bytes_ostream_fragment_iterator operator++(int) {
bytes_ostream_fragment_iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(const bytes_ostream_fragment_iterator&) const = default;
implementation extract_implementation() const {
return implementation {
.current_chunk = _current,
};
}
};
/**
* Utility for writing data into a buffer when its final size is not known up front.
@@ -46,46 +89,7 @@ private:
size_type _size;
size_type _initial_chunk_size = default_chunk_size;
public:
class fragment_iterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = bytes_view;
using difference_type = std::ptrdiff_t;
using pointer = bytes_view*;
using reference = bytes_view&;
struct implementation {
chunk* current_chunk;
};
private:
chunk* _current = nullptr;
public:
fragment_iterator() = default;
fragment_iterator(chunk* current) : _current(current) {}
fragment_iterator(const fragment_iterator&) = default;
fragment_iterator& operator=(const fragment_iterator&) = default;
bytes_view operator*() const {
return { _current->data, _current->frag_size };
}
bytes_view operator->() const {
return *(*this);
}
fragment_iterator& operator++() {
_current = _current->next;
return *this;
}
fragment_iterator operator++(int) {
fragment_iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(const fragment_iterator&) const = default;
implementation extract_implementation() const {
return implementation {
.current_chunk = _current,
};
}
};
using fragment_iterator = bytes_ostream_fragment_iterator;
using const_iterator = fragment_iterator;
class output_iterator {
@@ -358,7 +362,7 @@ public:
output_iterator write_begin() { return output_iterator(*this); }
boost::iterator_range<fragment_iterator> fragments() const {
std::ranges::subrange<fragment_iterator> fragments() const {
return { begin(), end() };
}

View File

@@ -76,7 +76,7 @@ public:
};
template<typename T>
static inline
inline
size_t cartesian_product_size(const std::vector<std::vector<T>>& vec_of_vecs) {
size_t r = 1;
for (auto&& vec : vec_of_vecs) {
@@ -86,7 +86,7 @@ size_t cartesian_product_size(const std::vector<std::vector<T>>& vec_of_vecs) {
}
template<typename T>
static inline
inline
bool cartesian_product_is_empty(const std::vector<std::vector<T>>& vec_of_vecs) {
for (auto&& vec : vec_of_vecs) {
if (vec.empty()) {
@@ -97,7 +97,7 @@ bool cartesian_product_is_empty(const std::vector<std::vector<T>>& vec_of_vecs)
}
template<typename T>
static inline
inline
cartesian_product<T> make_cartesian_product(const std::vector<std::vector<T>>& vec_of_vecs) {
return cartesian_product<T>(vec_of_vecs);
}

View File

@@ -11,7 +11,7 @@
#include <seastar/core/sstring.hh>
#include "bytes.hh"
#include "bytes_fwd.hh"
#include "cdc/cdc_options.hh"
#include "schema/schema.hh"
#include "serializer_impl.hh"
@@ -34,7 +34,7 @@ public:
return ser::serialize_to_buffer<bytes>(_cdc_options.to_map());
}
static std::map<sstring, sstring> deserialize(const bytes_view& buffer) {
return ser::deserialize_from_buffer(buffer, boost::type<std::map<sstring, sstring>>());
return ser::deserialize_from_buffer(buffer, std::type_identity<std::map<sstring, sstring>>());
}
const options& get_options() const {
return _cdc_options;

View File

@@ -6,7 +6,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <boost/type.hpp>
#include <type_traits>
#include <random>
#include <unordered_set>
#include <algorithm>

View File

@@ -18,7 +18,7 @@
#include "utils/xx_hasher.hh"
#include "db/timeout_clock.hh"
#include "log.hh"
#include "utils/log.hh"
extern logging::logger cell_locker_log;

View File

@@ -16,13 +16,13 @@
extern std::atomic<int64_t> clocks_offset;
template<typename Duration>
static inline void forward_jump_clocks(Duration delta)
inline void forward_jump_clocks(Duration delta)
{
auto d = std::chrono::duration_cast<std::chrono::seconds>(delta).count();
clocks_offset.fetch_add(d, std::memory_order_relaxed);
}
static inline std::chrono::seconds get_clocks_offset()
inline std::chrono::seconds get_clocks_offset()
{
auto off = clocks_offset.load(std::memory_order_relaxed);
return std::chrono::seconds(off);

115
cmake/FindSeastar.cmake Normal file
View File

@@ -0,0 +1,115 @@
#
# Copyright 2024-present ScyllaDB
#
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
find_package(PkgConfig QUIET REQUIRED)
set(saved_pkg_config_path "$ENV{PKG_CONFIG_PATH}")
foreach(config ${CMAKE_CONFIGURATION_TYPES})
# this path should be consistent with the path used by configure.py, which configures
# seastar's building system for each enabled build mode / configuration type
set(binary_dir "${CMAKE_BINARY_DIR}/${config}/seastar")
set(ENV{PKG_CONFIG_PATH} "${saved_pkg_config_path}:${CMAKE_BINARY_DIR}/${config}/seastar")
pkg_search_module(seastar-${config}
REQUIRED QUIET
NO_CMAKE_PATH
IMPORTED_TARGET GLOBAL
seastar)
find_path(seastar_INCLUDE_DIR
NAMES seastar/core/seastar.hh
HINTS
${seastar-${config}_INCLUDE_DIRS})
pkg_search_module(seastar_testing-${config}
REQUIRED QUIET
NO_CMAKE_PATH
IMPORTED_TARGET GLOBAL
seastar-testing)
find_path(seastar_testing_INCLUDE_DIR
NAMES seastar/testing/seastar_test.hh
HINTS
${seastar_testing-${config}_INCLUDE_DIRS})
mark_as_advanced(
seastar_INCLUDE_DIR
seastar_testing_INCLUDE_DIR)
endforeach(config ${CMAKE_CONFIGURATION_TYPES})
set(ENV{PKG_CONFIG_PATH} "${saved_pkg_config_path}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Seastar
REQUIRED_VARS
seastar_INCLUDE_DIR
seastar_testing_INCLUDE_DIR)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
# this directory is created when building Seastar, but we create it manually.
# otherwise CMake would complain when configuring targets which link against the
# "Seastar::seastar" library. it is imported library. and CMake assures that
# all INTERFACE_INCLUDE_DIRECTORIES of an imported library should exist.
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${config}/seastar/gen/include)
endforeach()
foreach(component "seastar" "seastar_testing" "seastar_perf_testing")
if(NOT TARGET Seastar::${component})
add_library(Seastar::${component} UNKNOWN IMPORTED)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
set_property(TARGET Seastar::${component} APPEND
PROPERTY
IMPORTED_CONFIGURATIONS ${config})
string (TOUPPER ${config} CONFIG)
if(config MATCHES "Debug|Dev")
set_property(TARGET Seastar::${component}
PROPERTY
IMPORTED_LOCATION_${CONFIG} "${CMAKE_BINARY_DIR}/${config}/seastar/lib${component}.so")
set(prefix ${component}-${config})
else()
set_property(TARGET Seastar::${component}
PROPERTY
IMPORTED_LOCATION_${CONFIG} "${CMAKE_BINARY_DIR}/${config}/seastar/lib${component}.a")
set(prefix ${component}-${config}_STATIC)
endif()
# these two libraries provide .pc, so set the properties retrieved with
# pkg-config.
if(component MATCHES "^(seastar|seastar_testing)$")
set_property(TARGET Seastar::${component} APPEND
PROPERTY
INTERFACE_INCLUDE_DIRECTORIES $<$<CONFIG:${config}>:${${prefix}_INCLUDE_DIRS}>)
set_property(TARGET Seastar::${component} APPEND
PROPERTY
INTERFACE_LINK_LIBRARIES $<$<CONFIG:${config}>:${${prefix}_LINK_LIBRARIES}>)
set_property(TARGET Seastar::${component} APPEND
PROPERTY
INTERFACE_LINK_OPTIONS $<$<CONFIG:${config}>:${${prefix}_LDFLAGS}>)
set_property(TARGET Seastar::${component} APPEND
PROPERTY
INTERFACE_COMPILE_OPTIONS $<$<CONFIG:${config}>:${${prefix}_CFLAGS_OTHER}>)
endif()
endforeach()
# seastar_perf_testing does not provide its .pc, so let's just hardwire its
# properties
if(component STREQUAL "seastar_perf_testing")
set_target_properties(Seastar::seastar_perf_testing PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Seastar_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES Seastar::seastar)
endif()
endif()
endforeach()
if(NOT TARGET Seastar::iotune)
add_executable(Seastar::iotune IMPORTED)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
set_property(TARGET Seastar::iotune APPEND
PROPERTY
IMPORTED_CONFIGURATIONS ${config})
string (TOUPPER ${config} CONFIG)
set_property(TARGET Seastar::iotune
PROPERTY
IMPORTED_LOCATION_${CONFIG} ${CMAKE_BINARY_DIR}/${config}/seastar/apps/iotune/iotune)
endforeach()
endif()

View File

@@ -22,7 +22,7 @@ function (check_headers check_headers_target target)
file(GLOB_RECURSE sources
LIST_DIRECTORIES false
RELATIVE ${CMAKE_SOURCE_DIR}
"${parsed_args_RECURSIVE}")
"${parsed_args_GLOB_RECURSE}")
else()
message(FATAL_ERROR "Please specify GLOB or GLOB_RECURSE.")
endif()
@@ -35,7 +35,6 @@ function (check_headers check_headers_target target)
foreach(fn ${sources})
get_filename_component(file_dir ${fn} DIRECTORY)
list(APPEND includes "${CMAKE_SOURCE_DIR}/${file_dir}")
set(src_dir "${CMAKE_BINARY_DIR}/check-headers/${file_dir}")
file(MAKE_DIRECTORY "${src_dir}")
get_filename_component(file_name ${fn} NAME)
@@ -44,10 +43,7 @@ function (check_headers check_headers_target target)
add_custom_command(
OUTPUT ${src}
DEPENDS ${CMAKE_SOURCE_DIR}/${fn}
# silence "-Wpragma-once-outside-header"
COMMAND sed
-e "s/^#pragma once//"
"${fn}" > "${src}"
COMMAND ${CMAKE_COMMAND} -E echo "#include \"${fn}\"" > "${src}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
VERBATIM)
list(APPEND srcs "${src}")

View File

@@ -9,6 +9,7 @@
#pragma once
#include "bytes.hh"
#include <memory>
class schema;
class partition_key;

View File

@@ -17,9 +17,7 @@
#include <algorithm>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/join.hpp>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/algorithm/string/join.hpp>
#include <seastar/core/future-util.hh>
@@ -226,20 +224,15 @@ static api::timestamp_type get_max_purgeable_timestamp(const table_state& table_
}
static std::vector<shared_sstable> get_uncompacting_sstables(const table_state& table_s, std::vector<shared_sstable> sstables) {
auto all_sstables = boost::copy_range<std::vector<shared_sstable>>(*table_s.main_sstable_set().all());
auto sstable_set = table_s.sstable_set_for_tombstone_gc();
auto all_sstables = boost::copy_range<std::vector<shared_sstable>>(*sstable_set->all());
auto& compacted_undeleted = table_s.compacted_undeleted_sstables();
all_sstables.insert(all_sstables.end(), compacted_undeleted.begin(), compacted_undeleted.end());
boost::sort(all_sstables, [] (const shared_sstable& x, const shared_sstable& y) {
return x->generation() < y->generation();
});
std::sort(sstables.begin(), sstables.end(), [] (const shared_sstable& x, const shared_sstable& y) {
return x->generation() < y->generation();
});
std::ranges::sort(all_sstables, std::ranges::less(), std::mem_fn(&sstable::generation));
std::ranges::sort(sstables, std::ranges::less(), std::mem_fn(&sstable::generation));
std::vector<shared_sstable> not_compacted_sstables;
boost::set_difference(all_sstables, sstables,
std::back_inserter(not_compacted_sstables), [] (const shared_sstable& x, const shared_sstable& y) {
return x->generation() < y->generation();
});
std::ranges::set_difference(all_sstables, sstables, std::back_inserter(not_compacted_sstables),
std::ranges::less(), std::mem_fn(&sstable::generation), std::mem_fn(&sstable::generation));
return not_compacted_sstables;
}
@@ -445,7 +438,7 @@ struct compaction_read_monitor_generator final : public read_monitor_generator {
: _table_s(table_s), _use_backlog_tracker(use_backlog_tracker) {}
uint64_t compacted() const {
return boost::accumulate(_generated_monitors | boost::adaptors::map_values | boost::adaptors::transformed([](auto& monitor) { return monitor.compacted(); }), uint64_t(0));
return std::ranges::fold_left(_generated_monitors | std::views::values | std::views::transform([](auto& monitor) { return monitor.compacted(); }), uint64_t(0), std::plus());
}
void remove_exhausted_sstables(const std::vector<sstables::shared_sstable>& exhausted_sstables) {
@@ -508,6 +501,7 @@ protected:
uint64_t _estimated_partitions = 0;
double _estimated_droppable_tombstone_ratio = 0;
uint64_t _bloom_filter_checks = 0;
combined_reader_statistics _reader_statistics;
db::replay_position _rp;
encoding_stats_collector _stats_collector;
const bool _can_split_large_partition = false;
@@ -730,9 +724,9 @@ private:
const query::partition_slice& slice,
tracing::trace_state_ptr,
streamed_mutation::forwarding fwd,
mutation_reader::forwarding) const = 0;
mutation_reader::forwarding) = 0;
mutation_reader setup_sstable_reader() const {
mutation_reader setup_sstable_reader() {
if (!_owned_ranges_checker) {
return make_sstable_reader(_schema,
_permit,
@@ -904,6 +898,7 @@ protected:
.start_size = _start_size,
.end_size = _end_size,
.bloom_filter_checks = _bloom_filter_checks,
.reader_statistics = std::move(_reader_statistics),
},
};
@@ -1155,7 +1150,7 @@ public:
const query::partition_slice& slice,
tracing::trace_state_ptr trace,
streamed_mutation::forwarding sm_fwd,
mutation_reader::forwarding mr_fwd) const override {
mutation_reader::forwarding mr_fwd) override {
return _compacting->make_local_shard_sstable_reader(std::move(s),
std::move(permit),
range,
@@ -1163,7 +1158,9 @@ public:
std::move(trace),
sm_fwd,
mr_fwd,
unwrap_monitor_generator());
unwrap_monitor_generator(),
default_sstable_predicate(),
&_reader_statistics);
}
std::string_view report_start_desc() const override {
@@ -1302,7 +1299,7 @@ public:
const query::partition_slice& slice,
tracing::trace_state_ptr trace,
streamed_mutation::forwarding sm_fwd,
mutation_reader::forwarding mr_fwd) const override {
mutation_reader::forwarding mr_fwd) override {
return _compacting->make_local_shard_sstable_reader(std::move(s),
std::move(permit),
range,
@@ -1606,7 +1603,7 @@ private:
std::string _scrub_start_description;
mutable std::string _scrub_finish_description;
uint64_t _bucket_count = 0;
mutable uint64_t _validation_errors = 0;
uint64_t _validation_errors = 0;
public:
scrub_compaction(table_state& table_s, compaction_descriptor descriptor, compaction_data& cdata, compaction_type_options::scrub options, compaction_progress_monitor& progress_monitor)
@@ -1633,12 +1630,12 @@ public:
const query::partition_slice& slice,
tracing::trace_state_ptr trace,
streamed_mutation::forwarding sm_fwd,
mutation_reader::forwarding mr_fwd) const override {
mutation_reader::forwarding mr_fwd) override {
if (!range.is_full()) {
on_internal_error(clogger, fmt::format("Scrub compaction in mode {} expected full partition range, but got {} instead", _options.operation_mode, range));
}
auto crawling_reader = _compacting->make_crawling_reader(std::move(s), std::move(permit), nullptr, unwrap_monitor_generator());
return make_mutation_reader<reader>(std::move(crawling_reader), _options.operation_mode, _validation_errors);
auto full_scan_reader = _compacting->make_full_scan_reader(std::move(s), std::move(permit), nullptr, unwrap_monitor_generator());
return make_mutation_reader<reader>(std::move(full_scan_reader), _options.operation_mode, _validation_errors);
}
uint64_t partitions_per_sstable() const override {
@@ -1720,7 +1717,7 @@ public:
_estimation_per_shard[s].estimated_partitions += std::max(uint64_t(1), uint64_t(ceil(double(estimated_partitions) / shards.size())));
}
}
for (auto i : boost::irange(0u, smp::count)) {
for (auto i : std::views::iota(0u, smp::count)) {
_run_identifiers[i] = run_id::create_random_id();
}
}
@@ -1734,7 +1731,7 @@ public:
const query::partition_slice& slice,
tracing::trace_state_ptr trace,
streamed_mutation::forwarding sm_fwd,
mutation_reader::forwarding mr_fwd) const override {
mutation_reader::forwarding mr_fwd) override {
return _compacting->make_range_sstable_reader(std::move(s),
std::move(permit),
range,
@@ -1939,7 +1936,7 @@ get_fully_expired_sstables(const table_state& table_s, const std::vector<sstable
// Get ancestors from sstable which is empty after restart. It works for this purpose because
// we only need to check that a sstable compacted *in this instance* hasn't an ancestor undeleted.
// Not getting it from sstable metadata because mc format hasn't it available.
return boost::algorithm::any_of(candidate->compaction_ancestors(), [&compacted_undeleted_gens] (const generation_type& gen) {
return std::ranges::any_of(candidate->compaction_ancestors(), [&compacted_undeleted_gens] (const generation_type& gen) {
return compacted_undeleted_gens.contains(gen);
});
};

View File

@@ -9,6 +9,7 @@
#pragma once
#include "readers/combined_reader_stats.hh"
#include "sstables/shared_sstable.hh"
#include "compaction/compaction_descriptor.hh"
#include "gc_clock.hh"
@@ -77,6 +78,7 @@ struct compaction_stats {
uint64_t validation_errors = 0;
// Bloom filter checks during max purgeable calculation
uint64_t bloom_filter_checks = 0;
combined_reader_statistics reader_statistics;
compaction_stats& operator+=(const compaction_stats& r) {
ended_at = std::max(ended_at, r.ended_at);

View File

@@ -27,7 +27,6 @@
#include "utils/UUID_gen.hh"
#include "db/system_keyspace.hh"
#include <cmath>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/range/algorithm/remove_if.hpp>
static logging::logger cmlog("compaction_manager");
@@ -188,7 +187,7 @@ unsigned compaction_manager::current_compaction_fan_in_threshold() const {
return 0;
}
auto largest_fan_in = std::ranges::max(_tasks | boost::adaptors::transformed([] (auto& task) {
return task->compaction_running() ? task->compaction_data().compaction_fan_in : 0;
return task.compaction_running() ? task.compaction_data().compaction_fan_in : 0;
}));
// conservatively limit fan-in threshold to 32, such that tons of small sstables won't accumulate if
// running major on a leveled table, which can even have more than one thousand files.
@@ -388,15 +387,29 @@ future<sstables::compaction_result> compaction_task_executor::compact_sstables_a
co_return res;
}
future<sstables::sstable_set> compaction_task_executor::sstable_set_for_tombstone_gc(table_state& t) {
auto compound_set = t.sstable_set_for_tombstone_gc();
// Compound set will be linearized into a single set, since compaction might add or remove sstables
// to it for incremental compaction to work.
auto new_set = sstables::make_partitioned_sstable_set(t.schema(), false);
co_await compound_set->for_each_sstable_gently([&] (const sstables::shared_sstable& sst) {
auto inserted = new_set.insert(sst);
if (!inserted) {
on_internal_error(cmlog, format("Unable to insert SSTable {} into set used for tombstone GC", sst->get_filename()));
}
});
co_return std::move(new_set);
}
future<sstables::compaction_result> compaction_task_executor::compact_sstables(sstables::compaction_descriptor descriptor, sstables::compaction_data& cdata, on_replacement& on_replace, compaction_manager::can_purge_tombstones can_purge,
sstables::offstrategy offstrategy) {
table_state& t = *_compacting_table;
if (can_purge) {
descriptor.enable_garbage_collection(t.main_sstable_set());
descriptor.enable_garbage_collection(co_await sstable_set_for_tombstone_gc(t));
}
descriptor.creator = [&t] (shard_id dummy) {
auto sst = t.make_sstable();
return sst;
descriptor.creator = [&t] (shard_id) {
return t.make_sstable();
};
descriptor.replacer = [this, &t, &on_replace, offstrategy] (sstables::compaction_completion_desc desc) {
t.get_compaction_strategy().notify_completion(t, desc.old_sstables, desc.new_sstables);
@@ -443,13 +456,18 @@ future<> compaction_task_executor::update_history(table_state& t, const sstables
auto ended_at = std::chrono::duration_cast<std::chrono::milliseconds>(res.stats.ended_at.time_since_epoch());
if (_cm._sys_ks) {
// FIXME: add support to merged_rows. merged_rows is a histogram that
// shows how many sstables each row is merged from. This information
// cannot be accessed until we make combined_reader more generic,
// for example, by adding a reducer method.
auto sys_ks = _cm._sys_ks; // hold pointer on sys_ks
co_await utils::get_local_injector().inject("update_history_wait", utils::wait_for_message(120s));
std::unordered_map<int32_t, int64_t> rows_merged;
for (size_t id=0; id<res.stats.reader_statistics.rows_merged_histogram.size(); ++id) {
if (res.stats.reader_statistics.rows_merged_histogram[id] <= 0) {
continue;
}
rows_merged[id] = res.stats.reader_statistics.rows_merged_histogram[id];
}
co_await sys_ks->update_compaction_history(cdata.compaction_uuid, t.schema()->ks_name(), t.schema()->cf_name(),
ended_at.count(), res.stats.start_size, res.stats.end_size, std::unordered_map<int32_t, int64_t>{});
ended_at.count(), res.stats.start_size, res.stats.end_size, std::move(rows_merged));
}
}
@@ -580,9 +598,9 @@ requires (compaction_manager& cm, throw_if_stopping do_throw_if_stopping, Args&&
}
future<compaction_manager::compaction_stats_opt> compaction_manager::perform_compaction(throw_if_stopping do_throw_if_stopping, tasks::task_info parent_info, Args&&... args) {
auto task_executor = seastar::make_shared<TaskExecutor>(*this, do_throw_if_stopping, std::forward<Args>(args)...);
_tasks.push_back(task_executor);
auto unregister_task = defer([this, task_executor] {
_tasks.remove(task_executor);
_tasks.push_back(*task_executor);
auto unregister_task = defer([task_executor] {
task_executor->unlink();
task_executor->switch_state(compaction_task_executor::state::none);
});
@@ -884,10 +902,10 @@ public:
explicit strategy_control(compaction_manager& cm) noexcept : _cm(cm) {}
bool has_ongoing_compaction(table_state& table_s) const noexcept override {
return std::any_of(_cm._tasks.begin(), _cm._tasks.end(), [&s = table_s.schema()] (const shared_ptr<compaction_task_executor>& task) {
return task->compaction_running()
&& task->compacting_table()->schema()->ks_name() == s->ks_name()
&& task->compacting_table()->schema()->cf_name() == s->cf_name();
return std::any_of(_cm._tasks.begin(), _cm._tasks.end(), [&s = table_s.schema()] (const compaction_task_executor& task) {
return task.compaction_running()
&& task.compacting_table()->schema()->ks_name() == s->ks_name()
&& task.compacting_table()->schema()->cf_name() == s->cf_name();
});
}
@@ -924,8 +942,7 @@ compaction_manager::compaction_manager(config cfg, abort_source& as, tasks::task
, _update_compaction_static_shares_action([this] { return update_static_shares(static_shares()); })
, _compaction_static_shares_observer(_cfg.static_shares.observe(_update_compaction_static_shares_action.make_observer()))
, _strategy_control(std::make_unique<strategy_control>(*this))
, _tombstone_gc_state(&_repair_history_maps)
{
, _tombstone_gc_state(&_reconcile_history_maps) {
tm.register_module(_task_manager_module->get_name(), _task_manager_module);
register_metrics();
// Bandwidth throttling is node-wide, updater is needed on single shard
@@ -947,8 +964,7 @@ compaction_manager::compaction_manager(tasks::task_manager& tm)
, _update_compaction_static_shares_action([] { return make_ready_future<>(); })
, _compaction_static_shares_observer(_cfg.static_shares.observe(_update_compaction_static_shares_action.make_observer()))
, _strategy_control(std::make_unique<strategy_control>(*this))
, _tombstone_gc_state(&_repair_history_maps)
{
, _tombstone_gc_state(&_reconcile_history_maps) {
tm.register_module(_task_manager_module->get_name(), _task_manager_module);
// No metric registration because this constructor is supposed to be used only by the testing
// infrastructure.
@@ -1051,7 +1067,7 @@ void compaction_manager::postpone_compaction_for_table(table_state* t) {
_postponed.insert(t);
}
future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_executor>> tasks, sstring reason) {
future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_executor>> tasks, sstring reason) noexcept {
// To prevent compaction from being postponed while tasks are being stopped,
// let's stop all tasks before the deferring point below.
for (auto& t : tasks) {
@@ -1059,14 +1075,16 @@ future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_e
t->stop_compaction(reason);
}
co_await coroutine::parallel_for_each(tasks, [] (auto& task) -> future<> {
auto unlink_task = deferred_action([task] { task->unlink(); });
try {
co_await task->compaction_done();
} catch (sstables::compaction_stopped_exception&) {
// swallow stop exception if a given procedure decides to propagate it to the caller,
// as it happens with reshard and reshape.
} catch (...) {
// just log any other errors as the callers have nothing to do with them.
cmlog.debug("Stopping {}: task returned error: {}", *task, std::current_exception());
throw;
co_return;
}
cmlog.debug("Stopping {}: done", *task);
});
@@ -1075,9 +1093,12 @@ future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_e
future<> compaction_manager::stop_ongoing_compactions(sstring reason, table_state* t, std::optional<sstables::compaction_type> type_opt) noexcept {
try {
auto ongoing_compactions = get_compactions(t).size();
auto tasks = boost::copy_range<std::vector<shared_ptr<compaction_task_executor>>>(_tasks | boost::adaptors::filtered([t, type_opt] (auto& task) {
return (!t || task->compacting_table() == t) && (!type_opt || task->compaction_type() == *type_opt);
}));
auto tasks = _tasks
| std::views::filter([t, type_opt] (const auto& task) {
return (!t || task.compacting_table() == t) && (!type_opt || task.compaction_type() == *type_opt);
})
| std::views::transform([] (auto& task) { return task.shared_from_this(); })
| std::ranges::to<std::vector<shared_ptr<compaction_task_executor>>>();
logging::log_level level = tasks.empty() ? log_level::debug : log_level::info;
if (cmlog.is_enabled(level)) {
std::string scope = "";
@@ -1091,16 +1112,20 @@ future<> compaction_manager::stop_ongoing_compactions(sstring reason, table_stat
}
return stop_tasks(std::move(tasks), std::move(reason));
} catch (...) {
return current_exception_as_future<>();
cmlog.error("Stopping ongoing compactions failed: {}. Ignored", std::current_exception());
}
return make_ready_future();
}
future<> compaction_manager::drain() {
cmlog.info("Asked to drain");
if (*_early_abort_subscription) {
if (_state == state::enabled) {
// This is a drain request and not a shutdown request.
// Disable the state so that it can be enabled later if requested.
_state = state::disabled;
co_await stop_ongoing_compactions("drain");
}
// Stop ongoing compactions, if the request has not been sent already and wait for them to stop.
co_await stop_ongoing_compactions("drain");
cmlog.info("Drained");
}
@@ -1109,17 +1134,20 @@ future<> compaction_manager::stop() {
if (auto cm = std::exchange(_task_manager_module, nullptr)) {
co_await cm->stop();
}
if (_state != state::none) {
co_return co_await std::move(*_stop_future);
if (_stop_future) {
co_await std::exchange(*_stop_future, make_ready_future());
}
}
future<> compaction_manager::really_do_stop() {
future<> compaction_manager::really_do_stop() noexcept {
cmlog.info("Asked to stop");
// Reset the metrics registry
_metrics.clear();
co_await stop_ongoing_compactions("shutdown");
co_await coroutine::parallel_for_each(_compaction_state | boost::adaptors::map_values, [] (compaction_state& cs) -> future<> {
if (!_tasks.empty()) {
on_fatal_internal_error(cmlog, format("{} tasks still exist after being stopped", _tasks.size()));
}
co_await coroutine::parallel_for_each(_compaction_state | std::views::values, [] (compaction_state& cs) -> future<> {
if (!cs.gate.is_closed()) {
co_await cs.gate.close();
}
@@ -1226,8 +1254,7 @@ protected:
virtual future<compaction_manager::compaction_stats_opt> do_run() override {
if (!is_system_keyspace(_status.keyspace)) {
co_await utils::get_local_injector().inject("compaction_regular_compaction_task_executor_do_run",
[] (auto& handler) { return handler.wait_for_message(db::timeout_clock::now() + 10s); });
co_await utils::get_local_injector().inject("compaction_regular_compaction_task_executor_do_run", utils::wait_for_message(10s));
}
co_await coroutine::switch_to(_cm.compaction_sg());
@@ -1618,6 +1645,9 @@ public:
std::move(sstables), std::move(compacting), compaction_manager::can_purge_tombstones::yes)
, _opt(options.as<sstables::compaction_type_options::split>())
{
if (utils::get_local_injector().is_enabled("split_sstable_rewrite")) {
_do_throw_if_stopping = throw_if_stopping::yes;
}
}
static bool sstable_needs_split(const sstables::shared_sstable& sst, const sstables::compaction_type_options::split& opt) {
@@ -1633,13 +1663,12 @@ private:
bool sstable_needs_split(const sstables::shared_sstable& sst) const {
return sstable_needs_split(sst, _opt);
}
protected:
sstables::compaction_descriptor make_descriptor(const sstables::shared_sstable& sst) const override {
return make_descriptor(sst, _opt);
}
future<sstables::compaction_result> rewrite_sstable(const sstables::shared_sstable sst) override {
future<sstables::compaction_result> do_rewrite_sstable(const sstables::shared_sstable sst) {
if (sstable_needs_split(sst)) {
return rewrite_sstables_compaction_task_executor::rewrite_sstable(std::move(sst));
}
@@ -1652,6 +1681,20 @@ protected:
return sstables::compaction_result{};
});
}
future<sstables::compaction_result> rewrite_sstable(const sstables::shared_sstable sst) override {
co_await utils::get_local_injector().inject("split_sstable_rewrite", [this] (auto& handler) -> future<> {
cmlog.info("split_sstable_rewrite: waiting");
while (!handler.poll_for_message() && !_compaction_data.is_stop_requested()) {
co_await sleep(std::chrono::milliseconds(5));
}
cmlog.info("split_sstable_rewrite: released");
if (_compaction_data.is_stop_requested()) {
throw make_compaction_stopped_exception();
}
}, false);
co_return co_await do_rewrite_sstable(std::move(sst));
}
};
}
@@ -1700,9 +1743,13 @@ compaction_manager::rewrite_sstables(table_state& t, sstables::compaction_type_o
namespace compaction {
class validate_sstables_compaction_task_executor : public sstables_task_executor {
compaction_manager::quarantine_invalid_sstables _quarantine_sstables;
public:
validate_sstables_compaction_task_executor(compaction_manager& mgr, throw_if_stopping do_throw_if_stopping, table_state* t, tasks::task_id parent_id, std::vector<sstables::shared_sstable> sstables)
validate_sstables_compaction_task_executor(compaction_manager& mgr, throw_if_stopping do_throw_if_stopping,
table_state* t, tasks::task_id parent_id, std::vector<sstables::shared_sstable> sstables,
compaction_manager::quarantine_invalid_sstables quarantine_sstables)
: sstables_task_executor(mgr, do_throw_if_stopping, t, sstables::compaction_type::Scrub, "Scrub compaction in validate mode", std::move(sstables), parent_id)
, _quarantine_sstables(quarantine_sstables)
{}
protected:
@@ -1731,7 +1778,7 @@ private:
sst->get_sstable_level(),
sstables::compaction_descriptor::default_max_sstable_bytes,
sst->run_identifier(),
sstables::compaction_type_options::make_scrub(sstables::compaction_type_options::scrub::mode::validate));
sstables::compaction_type_options::make_scrub(sstables::compaction_type_options::scrub::mode::validate, _quarantine_sstables));
co_return co_await sstables::compact_sstables(std::move(desc), _compaction_data, *_compacting_table, _progress_monitor);
} catch (sstables::compaction_stopped_exception&) {
// ignore, will be handled by can_proceed()
@@ -1761,14 +1808,14 @@ static std::vector<sstables::shared_sstable> get_all_sstables(table_state& t) {
return s;
}
future<compaction_manager::compaction_stats_opt> compaction_manager::perform_sstable_scrub_validate_mode(table_state& t, tasks::task_info info) {
future<compaction_manager::compaction_stats_opt> compaction_manager::perform_sstable_scrub_validate_mode(table_state& t, tasks::task_info info, quarantine_invalid_sstables quarantine_sstables) {
auto gh = start_compaction(t);
if (!gh) {
co_return compaction_stats_opt{};
}
// All sstables must be included, even the ones being compacted, such that everything in table is validated.
auto all_sstables = get_all_sstables(t);
co_return co_await perform_compaction<validate_sstables_compaction_task_executor>(throw_if_stopping::no, info, &t, info.id, std::move(all_sstables));
co_return co_await perform_compaction<validate_sstables_compaction_task_executor>(throw_if_stopping::no, info, &t, info.id, std::move(all_sstables), quarantine_sstables);
}
namespace compaction {
@@ -1978,8 +2025,8 @@ future<> compaction_manager::perform_cleanup(owned_ranges_ptr sorted_owned_range
future<> compaction_manager::try_perform_cleanup(owned_ranges_ptr sorted_owned_ranges, table_state& t, tasks::task_info info) {
auto check_for_cleanup = [this, &t] {
return boost::algorithm::any_of(_tasks, [&t] (auto& task) {
return task->compacting_table() == &t && task->compaction_type() == sstables::compaction_type::Cleanup;
return std::ranges::any_of(_tasks, [&t] (auto& task) {
return task.compacting_table() == &t && task.compaction_type() == sstables::compaction_type::Cleanup;
});
};
if (check_for_cleanup()) {
@@ -2077,19 +2124,19 @@ compaction_manager::maybe_split_sstable(sstables::shared_sstable sst, table_stat
}
std::vector<sstables::shared_sstable> ret;
co_await run_custom_job(t, sstables::compaction_type::Split, "Split SSTable",
[&] (sstables::compaction_data& info, sstables::compaction_progress_monitor& monitor) -> future<> {
sstables::compaction_descriptor desc = split_compaction_task_executor::make_descriptor(sst, opt);
desc.creator = [&t] (shard_id _) {
return t.make_sstable();
};
desc.replacer = [&] (sstables::compaction_completion_desc d) {
std::move(d.new_sstables.begin(), d.new_sstables.end(), std::back_inserter(ret));
};
auto gate = get_compaction_state(&t).gate.hold();
sstables::compaction_progress_monitor monitor;
sstables::compaction_data info = create_compaction_data();
sstables::compaction_descriptor desc = split_compaction_task_executor::make_descriptor(sst, opt);
desc.creator = [&t] (shard_id _) {
return t.make_sstable();
};
desc.replacer = [&] (sstables::compaction_completion_desc d) {
std::move(d.new_sstables.begin(), d.new_sstables.end(), std::back_inserter(ret));
};
co_await sstables::compact_sstables(std::move(desc), info, t, monitor);
co_await sst->unlink();
}, tasks::task_info{}, throw_if_stopping::yes);
co_await sstables::compact_sstables(std::move(desc), info, t, monitor);
co_await sst->unlink();
co_return ret;
}
@@ -2098,7 +2145,7 @@ compaction_manager::maybe_split_sstable(sstables::shared_sstable sst, table_stat
future<compaction_manager::compaction_stats_opt> compaction_manager::perform_sstable_scrub(table_state& t, sstables::compaction_type_options::scrub opts, tasks::task_info info) {
auto scrub_mode = opts.operation_mode;
if (scrub_mode == sstables::compaction_type_options::scrub::mode::validate) {
return perform_sstable_scrub_validate_mode(t, info);
return perform_sstable_scrub_validate_mode(t, info, opts.quarantine_sstables);
}
owned_ranges_ptr owned_ranges_ptr = {};
sstring option_desc = fmt::format("mode: {};\nquarantine_mode: {}\n", opts.operation_mode, opts.quarantine_operation_mode);
@@ -2159,11 +2206,11 @@ future<> compaction_manager::remove(table_state& t, sstring reason) noexcept {
auto found = false;
sstring msg;
for (auto& task : _tasks) {
if (task->compacting_table() == &t) {
if (task.compacting_table() == &t) {
if (!msg.empty()) {
msg += "\n";
}
msg += format("Found {} after remove", *task.get());
msg += format("Found {} after remove", task);
found = true;
}
}
@@ -2174,30 +2221,38 @@ future<> compaction_manager::remove(table_state& t, sstring reason) noexcept {
}
const std::vector<sstables::compaction_info> compaction_manager::get_compactions(table_state* t) const {
auto to_info = [] (const shared_ptr<compaction_task_executor>& task) {
auto to_info = [] (const compaction_task_executor& task) {
sstables::compaction_info ret;
ret.compaction_uuid = task->compaction_data().compaction_uuid;
ret.type = task->compaction_type();
ret.ks_name = task->compacting_table()->schema()->ks_name();
ret.cf_name = task->compacting_table()->schema()->cf_name();
ret.total_partitions = task->compaction_data().total_partitions;
ret.total_keys_written = task->compaction_data().total_keys_written;
ret.compaction_uuid = task.compaction_data().compaction_uuid;
ret.type = task.compaction_type();
ret.ks_name = task.compacting_table()->schema()->ks_name();
ret.cf_name = task.compacting_table()->schema()->cf_name();
ret.total_partitions = task.compaction_data().total_partitions;
ret.total_keys_written = task.compaction_data().total_keys_written;
return ret;
};
using ret = std::vector<sstables::compaction_info>;
return boost::copy_range<ret>(_tasks | boost::adaptors::filtered([t] (const shared_ptr<compaction_task_executor>& task) {
return (!t || task->compacting_table() == t) && task->compaction_running();
return boost::copy_range<ret>(_tasks | boost::adaptors::filtered([t] (const compaction_task_executor& task) {
return (!t || task.compacting_table() == t) && task.compaction_running();
}) | boost::adaptors::transformed(to_info));
}
bool compaction_manager::has_table_ongoing_compaction(const table_state& t) const {
return std::any_of(_tasks.begin(), _tasks.end(), [&t] (const shared_ptr<compaction_task_executor>& task) {
return task->compacting_table() == &t && task->compaction_running();
return std::any_of(_tasks.begin(), _tasks.end(), [&t] (const compaction_task_executor& task) {
return task.compacting_table() == &t && task.compaction_running();
});
};
bool compaction_manager::compaction_disabled(table_state& t) const {
return _compaction_state.contains(&t) && _compaction_state.at(&t).compaction_disabled();
if (auto it = _compaction_state.find(&t); it != _compaction_state.end()) {
return it->second.compaction_disabled();
} else {
cmlog.debug("compaction_disabled: {}:{} not in compaction_state", t.schema()->id(), t.get_group_id());
// Compaction is not strictly disabled, but it is not enabled either.
// The callers actually care about if it's enabled or not, not about the actual state of
// compaction_state::compaction_disabled()
return true;
}
}
future<> compaction_manager::stop_compaction(sstring type, table_state* table) {
@@ -2222,8 +2277,8 @@ future<> compaction_manager::stop_compaction(sstring type, table_state* table) {
void compaction_manager::propagate_replacement(table_state& t,
const std::vector<sstables::shared_sstable>& removed, const std::vector<sstables::shared_sstable>& added) {
for (auto& task : _tasks) {
if (task->compacting_table() == &t && task->compaction_running()) {
task->compaction_data().pending_replacements.push_back({ removed, added });
if (task.compacting_table() == &t && task.compaction_running()) {
task.compaction_data().pending_replacements.push_back({ removed, added });
}
}
}

View File

@@ -8,8 +8,6 @@
#pragma once
#include <boost/icl/interval_map.hpp>
#include <seastar/core/semaphore.hh>
#include <seastar/core/sstring.hh>
#include <seastar/core/shared_ptr.hh>
@@ -23,7 +21,6 @@
#include "utils/updateable_value.hh"
#include "utils/serialized_action.hh"
#include <vector>
#include <list>
#include <functional>
#include "compaction.hh"
#include "compaction_backlog_manager.hh"
@@ -43,11 +40,6 @@ class compaction_history_entry;
namespace sstables { class test_env_compaction_manager; }
class repair_history_map {
public:
boost::icl::interval_map<dht::token, gc_clock::time_point, boost::icl::partial_absorber, std::less, boost::icl::inplace_max> map;
};
namespace compaction {
using throw_if_stopping = bool_class<struct throw_if_stopping_tag>;
@@ -94,8 +86,13 @@ public:
private:
shared_ptr<compaction::task_manager_module> _task_manager_module;
using compaction_task_executor_list_type = bi::list<
compaction_task_executor,
bi::base_hook<bi::list_base_hook<bi::link_mode<bi::auto_unlink>>>,
bi::constant_time_size<false>>;
// compaction manager may have N fibers to allow parallel compaction per shard.
std::list<shared_ptr<compaction::compaction_task_executor>> _tasks;
compaction_task_executor_list_type _tasks;
// Possible states in which the compaction manager can be found.
//
@@ -162,7 +159,7 @@ private:
class strategy_control;
std::unique_ptr<strategy_control> _strategy_control;
per_table_history_maps _repair_history_maps;
per_table_history_maps _reconcile_history_maps;
tombstone_gc_state _tombstone_gc_state;
private:
// Requires task->_compaction_state.gate to be held and task to be registered in _tasks.
@@ -179,7 +176,7 @@ private:
}
future<compaction_manager::compaction_stats_opt> perform_compaction(throw_if_stopping do_throw_if_stopping, tasks::task_info parent_info, Args&&... args);
future<> stop_tasks(std::vector<shared_ptr<compaction::compaction_task_executor>> tasks, sstring reason);
future<> stop_tasks(std::vector<shared_ptr<compaction::compaction_task_executor>> tasks, sstring reason) noexcept;
future<> update_throughput(uint32_t value_mbs);
// Return the largest fan-in of currently running compactions
@@ -228,7 +225,8 @@ private:
// similar-sized compaction.
void postpone_compaction_for_table(compaction::table_state* t);
future<compaction_stats_opt> perform_sstable_scrub_validate_mode(compaction::table_state& t, tasks::task_info info);
using quarantine_invalid_sstables = sstables::compaction_type_options::scrub::quarantine_invalid_sstables;
future<compaction_stats_opt> perform_sstable_scrub_validate_mode(compaction::table_state& t, tasks::task_info info, quarantine_invalid_sstables quarantine_sstables);
future<> update_static_shares(float shares);
using get_candidates_func = std::function<future<std::vector<sstables::shared_sstable>>()>;
@@ -245,7 +243,7 @@ private:
// Stop all fibers, without waiting. Safe to be called multiple times.
void do_stop() noexcept;
future<> really_do_stop();
future<> really_do_stop() noexcept;
// Propagate replacement of sstables to all ongoing compaction of a given table
void propagate_replacement(compaction::table_state& t, const std::vector<sstables::shared_sstable>& removed, const std::vector<sstables::shared_sstable>& added);
@@ -470,7 +468,9 @@ public:
namespace compaction {
class compaction_task_executor : public enable_shared_from_this<compaction_task_executor> {
class compaction_task_executor
: public enable_shared_from_this<compaction_task_executor>
, public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
public:
enum class state {
none, // initial and final state
@@ -594,6 +594,8 @@ private:
future<compaction_manager::compaction_stats_opt> compaction_done() noexcept {
return _compaction_done.get_future();
}
future<sstables::sstable_set> sstable_set_for_tombstone_gc(::compaction::table_state& t);
public:
bool stopping() const noexcept {
return _compaction_data.abort.abort_requested();
@@ -614,7 +616,7 @@ public:
friend future<compaction_manager::compaction_stats_opt> compaction_manager::perform_compaction(throw_if_stopping do_throw_if_stopping, tasks::task_info parent_info, Args&&... args);
friend future<compaction_manager::compaction_stats_opt> compaction_manager::perform_task(shared_ptr<compaction_task_executor> task, throw_if_stopping do_throw_if_stopping);
friend fmt::formatter<compaction_task_executor>;
friend future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_executor>> tasks, sstring reason);
friend future<> compaction_manager::stop_tasks(std::vector<shared_ptr<compaction_task_executor>> tasks, sstring reason) noexcept;
friend sstables::test_env_compaction_manager;
};

View File

@@ -23,8 +23,7 @@
#include "schema/schema.hh"
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/remove_if.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include "size_tiered_compaction_strategy.hh"
#include "leveled_compaction_strategy.hh"
#include "time_window_compaction_strategy.hh"

View File

@@ -70,6 +70,18 @@ public:
virtual uint64_t adjust_partition_estimate(const mutation_source_metadata& ms_meta, uint64_t partition_estimate, schema_ptr schema) const;
/// Creates a decorated consumer that adds processing steps before the final consumer
///
/// This factory function takes an end consumer functor and returns a new functor that
/// extends the processing pipeline. The returned functor "interposes" (inserts) additional
/// processing steps before delegating to the original end consumer. This enables building
/// layered processing pipelines where each layer can transform or filter the mutation
/// fragments before they reach their final destination.
///
/// @param end_consumer The final consumer functor that processes mutation fragments
/// @return A new functor that wraps the end consumer with additional processing capabilities
/// @note The returned functor preserves the original consumer's semantics while allowing
/// preprocessing of data
virtual reader_consumer_v2 make_interposer_consumer(const mutation_source_metadata& ms_meta, reader_consumer_v2 end_consumer) const;
virtual bool use_interposer_consumer() const {

View File

@@ -10,13 +10,13 @@
#pragma once
#include <algorithm>
#include "utils/assert.hh"
#include "sstables/sstables.hh"
#include "size_tiered_compaction_strategy.hh"
#include "interval.hh"
#include "log.hh"
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/partial_sort.hpp>
#include "utils/log.hh"
class leveled_manifest {
table_state& _table_s;
@@ -387,7 +387,7 @@ private:
candidates = get_level(0);
if (candidates.size() > MAX_COMPACTING_L0) {
// limit to only the MAX_COMPACTING_L0 oldest candidates
boost::partial_sort(candidates, candidates.begin() + MAX_COMPACTING_L0, [] (auto& i, auto& j) {
std::ranges::partial_sort(candidates, candidates.begin() + MAX_COMPACTING_L0, [] (auto& i, auto& j) {
return i->compare_by_max_timestamp(*j) < 0;
});
candidates.resize(MAX_COMPACTING_L0);
@@ -430,7 +430,7 @@ private:
const schema& s = *_schema;
// for non-L0 compactions, pick up where we left off last time
auto& sstables = get_level(level);
boost::sort(sstables, [] (auto& i, auto& j) {
std::ranges::sort(sstables, [] (auto& i, auto& j) {
return i->compare_by_first_key(*j) < 0;
});

View File

@@ -12,7 +12,7 @@
#include "cql3/statements/property_definitions.hh"
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm.hpp>
namespace sstables {

View File

@@ -10,7 +10,6 @@
#include "compaction_strategy_impl.hh"
#include "sstables/shared_sstable.hh"
#include <boost/algorithm/cxx11/any_of.hpp>
class size_tiered_backlog_tracker;
@@ -65,7 +64,7 @@ class size_tiered_compaction_strategy : public compaction_strategy_impl {
}
bool is_any_bucket_interesting(const std::vector<std::vector<sstables::shared_sstable>>& buckets, int min_threshold) const {
return boost::algorithm::any_of(buckets, [&] (const auto& bucket) {
return std::ranges::any_of(buckets, [&] (const auto& bucket) {
return this->is_bucket_interesting(bucket, min_threshold);
});
}

View File

@@ -39,6 +39,7 @@ public:
virtual bool compaction_enforce_min_threshold() const noexcept = 0;
virtual const sstables::sstable_set& main_sstable_set() const = 0;
virtual const sstables::sstable_set& maintenance_sstable_set() const = 0;
virtual lw_shared_ptr<const sstables::sstable_set> sstable_set_for_tombstone_gc() const = 0;
virtual std::unordered_set<sstables::shared_sstable> fully_expired_sstables(const std::vector<sstables::shared_sstable>& sstables, gc_clock::time_point compaction_time) const = 0;
virtual const std::vector<sstables::shared_sstable>& compacted_undeleted_sstables() const noexcept = 0;
virtual sstables::compaction_strategy& get_compaction_strategy() const noexcept = 0;

View File

@@ -378,8 +378,7 @@ future<> global_major_compaction_task_impl::run() {
}
future<> major_keyspace_compaction_task_impl::run() {
co_await utils::get_local_injector().inject("compaction_major_keyspace_compaction_task_impl_run",
[] (auto& handler) { return handler.wait_for_message(db::timeout_clock::now() + 10s); });
co_await utils::get_local_injector().inject("compaction_major_keyspace_compaction_task_impl_run", utils::wait_for_message(10s));
if (_cv) {
co_await wait_for_your_turn(*_cv, *_current_task, _status.id);

View File

@@ -16,7 +16,7 @@
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/remove_if.hpp>
#include <boost/range/algorithm/min_element.hpp>
#include <boost/range/algorithm/partial_sort.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <ranges>
@@ -296,8 +296,9 @@ time_window_compaction_strategy::get_reshaping_job(std::vector<shared_sstable> i
// When trimming, let's keep sstables with overlapping time window, so as to reduce write amplification.
// For example, if there are N sstables spanning window W, where N <= 32, then we can produce all data for W
// in a single compaction round, removing the need to later compact W to reduce its number of files.
boost::partial_sort(multi_window, multi_window.begin() + max_sstables, [](const shared_sstable &a, const shared_sstable &b) {
return a->get_stats_metadata().max_timestamp < b->get_stats_metadata().max_timestamp;
auto sort_size = std::min(max_sstables, multi_window.size());
std::ranges::partial_sort(multi_window, multi_window.begin() + sort_size, std::ranges::less(), [] (const shared_sstable &a) {
return a->get_stats_metadata().max_timestamp;
});
maybe_trim_job(multi_window, job_size, disjoint);
}
@@ -343,7 +344,6 @@ time_window_compaction_strategy::get_sstables_for_compaction(table_state& table_
auto candidates = control.candidates(table_s);
if (candidates.empty()) {
state.estimated_remaining_tasks = 0;
return compaction_descriptor();
}
@@ -421,8 +421,6 @@ time_window_compaction_strategy::get_compaction_candidates(table_state& table_s,
// Update the highest window seen, if necessary
state.highest_window_seen = std::max(state.highest_window_seen, max_timestamp);
update_estimated_compaction_by_tasks(state, buckets, table_s.min_compaction_threshold(), table_s.schema()->max_compaction_threshold());
return newest_bucket(table_s, control, std::move(buckets), table_s.min_compaction_threshold(), table_s.schema()->max_compaction_threshold(),
state.highest_window_seen);
}
@@ -430,12 +428,10 @@ time_window_compaction_strategy::get_compaction_candidates(table_state& table_s,
timestamp_type
time_window_compaction_strategy::get_window_lower_bound(std::chrono::seconds sstable_window_size, timestamp_type timestamp) {
using namespace std::chrono;
auto timestamp_in_sec = duration_cast<seconds>(microseconds(timestamp)).count();
// mask out window size from timestamp to get lower bound of its window
auto window_lower_bound_in_sec = seconds(timestamp_in_sec - (timestamp_in_sec % sstable_window_size.count()));
auto num_windows = microseconds(timestamp) / sstable_window_size;
return timestamp_type(duration_cast<microseconds>(window_lower_bound_in_sec).count());
return duration_cast<microseconds>(num_windows * sstable_window_size).count();
}
std::pair<std::map<timestamp_type, std::vector<shared_sstable>>, timestamp_type>
@@ -520,21 +516,21 @@ std::vector<shared_sstable>
time_window_compaction_strategy::trim_to_threshold(std::vector<shared_sstable> bucket, int max_threshold) {
auto n = std::min(bucket.size(), size_t(max_threshold));
// Trim the largest sstables off the end to meet the maxThreshold
boost::partial_sort(bucket, bucket.begin() + n, [] (auto& i, auto& j) {
return i->ondisk_data_size() < j->ondisk_data_size();
});
std::ranges::partial_sort(bucket, bucket.begin() + n, std::ranges::less(), std::mem_fn(&sstable::ondisk_data_size));
bucket.resize(n);
return bucket;
}
void time_window_compaction_strategy::update_estimated_compaction_by_tasks(time_window_compaction_strategy_state& state,
std::map<timestamp_type, std::vector<shared_sstable>>& tasks,
int min_threshold, int max_threshold) {
int64_t n = 0;
timestamp_type now = state.highest_window_seen;
int64_t time_window_compaction_strategy::estimated_pending_compactions(table_state& table_s) const {
auto& state = get_state(table_s);
auto min_threshold = table_s.min_compaction_threshold();
auto max_threshold = table_s.schema()->max_compaction_threshold();
auto candidate_sstables = boost::copy_range<std::vector<sstables::shared_sstable>>(*table_s.main_sstable_set().all());
auto [buckets, max_timestamp] = get_buckets(std::move(candidate_sstables), _options);
for (auto& [bucket_key, bucket] : tasks) {
switch (compaction_mode(state, bucket, bucket_key, now, min_threshold)) {
int64_t n = 0;
for (auto& [bucket_key, bucket] : buckets) {
switch (compaction_mode(state, bucket, bucket_key, max_timestamp, min_threshold)) {
case bucket_compaction_mode::size_tiered:
n += size_tiered_compaction_strategy::estimated_pending_compactions(bucket, min_threshold, max_threshold, _stcs_options);
break;
@@ -545,7 +541,7 @@ void time_window_compaction_strategy::update_estimated_compaction_by_tasks(time_
break;
}
}
state.estimated_remaining_tasks = n;
return n;
}
std::vector<compaction_descriptor>

View File

@@ -60,7 +60,6 @@ public:
};
struct time_window_compaction_strategy_state {
int64_t estimated_remaining_tasks = 0;
db_clock::time_point last_expired_check;
// As api::timestamp_type is an int64_t, a primitive type, it must be initialized here.
api::timestamp_type highest_window_seen = 0;
@@ -143,15 +142,9 @@ public:
return api::timestamp_type(std::chrono::duration_cast<std::chrono::microseconds>(options.get_sstable_window_size()).count());
}
private:
void update_estimated_compaction_by_tasks(time_window_compaction_strategy_state& state,
std::map<api::timestamp_type, std::vector<shared_sstable>>& tasks,
int min_threshold, int max_threshold);
friend class time_window_backlog_tracker;
public:
virtual int64_t estimated_pending_compactions(table_state& table_s) const override {
return get_state(table_s).estimated_remaining_tasks;
}
virtual int64_t estimated_pending_compactions(table_state& table_s) const override;
virtual compaction_strategy_type type() const override {
return compaction_strategy_type::time_window;

View File

@@ -12,8 +12,7 @@
#include <algorithm>
#include <vector>
#include <span>
#include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <ranges>
#include "utils/assert.hh"
#include "utils/serialization.hh"
#include <seastar/util/backtrace.hh>
@@ -95,10 +94,10 @@ private:
}
public:
managed_bytes serialize_single(const managed_bytes& v) const {
return serialize_value(boost::make_iterator_range(&v, 1+&v));
return serialize_value(std::ranges::subrange(&v, 1+&v));
}
managed_bytes serialize_single(const bytes& v) const {
return serialize_value(boost::make_iterator_range(&v, 1+&v));
return serialize_value(std::ranges::subrange(&v, 1+&v));
}
template<typename RangeOfSerializedComponents>
static managed_bytes serialize_value(RangeOfSerializedComponents&& values) {
@@ -112,10 +111,10 @@ public:
}
template<typename T>
static managed_bytes serialize_value(std::initializer_list<T> values) {
return serialize_value(boost::make_iterator_range(values.begin(), values.end()));
return serialize_value(std::span(values));
}
managed_bytes serialize_optionals(std::span<const bytes_opt> values) const {
return serialize_value(boost::make_iterator_range(values.begin(), values.end()) | boost::adaptors::transformed([] (const bytes_opt& bo) -> bytes_view {
return serialize_value(values | std::views::transform([] (const bytes_opt& bo) -> bytes_view {
if (!bo) {
throw std::logic_error("attempted to create key component from empty optional");
}
@@ -123,7 +122,7 @@ public:
}));
}
managed_bytes serialize_optionals(std::span<const managed_bytes_opt> values) const {
return serialize_value(boost::make_iterator_range(values.begin(), values.end()) | boost::adaptors::transformed([] (const managed_bytes_opt& bo) -> managed_bytes_view {
return serialize_value(values | std::views::transform([] (const managed_bytes_opt& bo) -> managed_bytes_view {
if (!bo) {
throw std::logic_error("attempted to create key component from empty optional");
}
@@ -146,11 +145,10 @@ public:
}
class iterator {
public:
using iterator_category = std::input_iterator_tag;
using iterator_category = std::forward_iterator_tag;
using iterator_concept = std::forward_iterator_tag;
using value_type = const managed_bytes_view;
using difference_type = std::ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
private:
managed_bytes_view _v;
managed_bytes_view _current;
@@ -187,8 +185,7 @@ public:
++(*this);
return i;
}
const value_type& operator*() const { return _current; }
const value_type* operator->() const { return &_current; }
value_type operator*() const { return _current; }
bool operator==(const iterator& i) const { return _remaining == i._remaining; }
};
static iterator begin(managed_bytes_view v) {
@@ -197,8 +194,8 @@ public:
static iterator end(managed_bytes_view v) {
return iterator(typename iterator::end_iterator_tag(), v);
}
static boost::iterator_range<iterator> components(managed_bytes_view v) {
return { begin(v), end(v) };
static std::ranges::subrange<iterator> components(managed_bytes_view v) {
return std::ranges::subrange(begin(v), end(v));
}
value_type deserialize_value(managed_bytes_view v) const {
std::vector<bytes> result;

View File

@@ -8,13 +8,12 @@
#pragma once
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <ranges>
#include <compare>
#include "compound.hh"
#include "schema/schema.hh"
#include "sstables/version.hh"
#include "log.hh"
#include "utils/log.hh"
//FIXME: de-inline methods and define this as static in a .cc file.
extern logging::logger compound_logger;
@@ -72,12 +71,12 @@ public:
iterator(const legacy_compound_view& v)
: _singular(v._type.is_singular())
, _offset(_singular ? 0 : -2)
, _i(_singular && !v._type.begin(v._packed)->size() ?
, _i(_singular && !(*v._type.begin(v._packed)).size() ?
v._type.end(v._packed) : v._type.begin(v._packed))
{ }
iterator(const legacy_compound_view& v, end_tag)
: _offset(v._type.is_singular() && !v._type.begin(v._packed)->size() ? 0 : -2)
: _offset(v._type.is_singular() && !(*v._type.begin(v._packed)).size() ? 0 : -2)
, _i(v._type.end(v._packed))
{ }
@@ -88,20 +87,22 @@ public:
iterator() {}
value_type operator*() const {
int32_t component_size = _i->size();
auto tmp = *_i;
int32_t component_size = tmp.size();
if (_offset == -2) {
return (component_size >> 8) & 0xff;
} else if (_offset == -1) {
return component_size & 0xff;
} else if (_offset < component_size) {
return (*_i)[_offset];
return tmp[_offset];
} else { // _offset == component_size
return 0; // EOC field
}
}
iterator& operator++() {
auto component_size = (int32_t) _i->size();
auto tmp = *_i;
auto component_size = (int32_t) tmp.size();
if (_offset < component_size
// When _singular, we skip the EOC byte.
&& (!_singular || _offset != (component_size - 1)))
@@ -164,7 +165,7 @@ public:
// Equivalent to std::distance(begin(), end()), but computes faster
size_t size() const {
if (_type.is_singular()) {
return _type.begin(_packed)->size();
return (*_type.begin(_packed)).size();
}
size_t s = 0;
for (auto&& component : _type.components(_packed)) {
@@ -185,7 +186,7 @@ public:
// Converts compound_type<> representation to legacy representation
// @packed is assumed to be serialized using supplied @type.
template <typename CompoundType>
static inline
inline
bytes to_legacy(CompoundType& type, managed_bytes_view packed) {
legacy_compound_view<CompoundType> lv(type, packed);
bytes legacy_form(bytes::initialized_later(), lv.size());
@@ -343,8 +344,9 @@ public:
static composite serialize_static(const schema& s, RangeOfSerializedComponents&& values) {
// FIXME: Optimize
auto b = bytes(size_t(2), bytes::value_type(0xff));
std::vector<bytes_view> sv(s.clustering_key_size());
b += composite::serialize_value(boost::range::join(sv, std::forward<RangeOfSerializedComponents>(values)), true).release_bytes();
std::vector<bytes_view> sv(s.clustering_key_size() + std::ranges::distance(values));
std::ranges::copy(values, sv.begin() + s.clustering_key_size());
b += composite::serialize_value(sv, true).release_bytes();
return composite(std::move(b));
}
@@ -439,12 +441,12 @@ public:
return iterator(iterator::end_iterator_tag());
}
boost::iterator_range<iterator> components() const & {
std::ranges::subrange<iterator> components() const & {
return { begin(), end() };
}
auto values() const & {
return components() | boost::adaptors::transformed([](auto&& c) { return c.first; });
return components() | std::views::transform(&component_view::first);
}
std::vector<component> components() const && {
@@ -457,7 +459,7 @@ public:
std::vector<bytes> values() const && {
std::vector<bytes> result;
boost::copy(components() | boost::adaptors::transformed([](auto&& c) { return to_bytes(c.first); }), std::back_inserter(result));
std::ranges::copy(components() | std::views::transform([](auto&& c) { return to_bytes(c.first); }), std::back_inserter(result));
return result;
}
@@ -582,7 +584,7 @@ public:
return composite::iterator(composite::iterator::end_iterator_tag());
}
boost::iterator_range<composite::iterator> components() const {
std::ranges::subrange<composite::iterator> components() const {
return { begin(), end() };
}
@@ -596,7 +598,7 @@ public:
}
auto values() const {
return components() | boost::adaptors::transformed([](auto&& c) { return c.first; });
return components() | std::views::transform(&composite::component_view::first);
}
size_t size() const {

View File

@@ -174,7 +174,7 @@ template <typename Func> concept CanHandleAllTypes = requires(Func f) {
template<typename Func>
requires CanHandleAllTypes<Func>
static inline visit_ret_type<Func> visit(const abstract_type& t, Func&& f) {
inline visit_ret_type<Func> visit(const abstract_type& t, Func&& f) {
switch (t.get_kind()) {
case abstract_type::kind::ascii:
return f(*static_cast<const ascii_type_impl*>(&t));

View File

@@ -21,7 +21,7 @@ from shutil import which
from typing import NamedTuple
configure_args = str.join(' ', [shlex.quote(x) for x in sys.argv[1:] if not x.startswith('--out=')])
configure_args = str.join(' ', [shlex.quote(x) for x in sys.argv[1:] if not x.startswith('--out=') and not x.startswith('--out-final-name=')])
# distribution "internationalization", converting package names.
# Fedora name is key, values is distro -> package name dict.
@@ -555,6 +555,8 @@ scylla_tests = set([
'test/boost/row_cache_test',
'test/boost/rust_test',
'test/boost/s3_test',
'test/boost/aws_errors_test',
'test/boost/aws_error_injection_test',
'test/boost/schema_change_test',
'test/boost/schema_changes_test',
'test/boost/schema_loader_test',
@@ -630,12 +632,6 @@ scylla_tests = set([
'test/unit/lsa_sync_eviction_test',
'test/unit/row_cache_alloc_stress_test',
'test/unit/row_cache_stress_test',
'test/unit/bptree_stress_test',
'test/unit/btree_stress_test',
'test/unit/bptree_compaction_test',
'test/unit/btree_compaction_test',
'test/unit/radix_tree_stress_test',
'test/unit/radix_tree_compaction_test',
'test/unit/cross_shard_barrier_test',
])
@@ -890,6 +886,7 @@ scylla_core = (['message/messaging_service.cc',
'cql3/attributes.cc',
'cql3/cf_name.cc',
'cql3/cql3_type.cc',
'cql3/description.cc',
'cql3/operation.cc',
'cql3/index_name.cc',
'cql3/keyspace_element_name.cc',
@@ -1001,6 +998,7 @@ scylla_core = (['message/messaging_service.cc',
'db/virtual_tables.cc',
'db/system_distributed_keyspace.cc',
'db/size_estimates_virtual_reader.cc',
'db/schema_applier.cc',
'db/schema_tables.cc',
'db/cql_type_parser.cc',
'db/legacy_schema_migrator.cc',
@@ -1046,7 +1044,9 @@ scylla_core = (['message/messaging_service.cc',
'utils/multiprecision_int.cc',
'utils/gz/crc_combine.cc',
'utils/gz/crc_combine_table.cc',
'utils/s3/aws_error.cc',
'utils/s3/client.cc',
'utils/s3/retry_strategy.cc',
'gms/version_generator.cc',
'gms/versioned_value.cc',
'gms/gossiper.cc',
@@ -1167,6 +1167,7 @@ scylla_core = (['message/messaging_service.cc',
'lang/wasm.cc',
'lang/wasm_alien_thread_runner.cc',
'lang/wasm_instance_cache.cc',
'service/raft/group0_state_id_handler.cc',
'service/raft/group0_state_machine.cc',
'service/raft/group0_state_machine_merger.cc',
'service/raft/raft_sys_table_storage.cc',
@@ -1399,7 +1400,6 @@ pure_boost_tests = set([
'test/boost/small_vector_test',
'test/boost/top_k_test',
'test/boost/vint_serialization_test',
'test/boost/bptree_test',
'test/boost/utf8_test',
'test/boost/string_format_test',
'test/manual/streaming_histogram_test',
@@ -1420,12 +1420,6 @@ tests_not_using_seastar_test_framework = set([
'test/unit/lsa_async_eviction_test',
'test/unit/lsa_sync_eviction_test',
'test/unit/row_cache_alloc_stress_test',
'test/unit/bptree_stress_test',
'test/unit/btree_stress_test',
'test/unit/bptree_compaction_test',
'test/unit/btree_compaction_test',
'test/unit/radix_tree_stress_test',
'test/unit/radix_tree_compaction_test',
'test/manual/sstable_scan_footprint_test',
'test/unit/cross_shard_barrier_test',
]) | pure_boost_tests
@@ -1545,8 +1539,6 @@ def get_warning_options(cxx):
'-Wno-unsupported-friend',
'-Wno-missing-field-initializers',
'-Wno-deprecated-copy',
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
'-Wno-psabi',
'-Wno-enum-constexpr-conversion',
]
@@ -1669,6 +1661,9 @@ user_ldflags = forced_ldflags + ' ' + args.user_ldflags
curdir = os.getcwd()
user_cflags = args.user_cflags + f" -ffile-prefix-map={curdir}=."
# Since gcc 13, libgcc doesn't need the exception workaround
user_cflags += ' -DSEASTAR_NO_EXCEPTION_HACK'
if args.target != '':
user_cflags += ' -march=' + args.target
@@ -1703,9 +1698,9 @@ def configure_seastar(build_dir, mode, mode_config):
'-DCMAKE_CXX_COMPILER={}'.format(args.cxx),
'-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON',
'-DCMAKE_CXX_STANDARD=23',
'-DCMAKE_CXX_EXTENSIONS=ON',
'-DSeastar_CXX_FLAGS=SHELL:{}'.format(mode_config['lib_cflags']),
'-DSeastar_LD_FLAGS={}'.format(semicolon_separated(mode_config['lib_ldflags'], seastar_cxx_ld_flags)),
'-DSeastar_CXX_DIALECT=gnu++23',
'-DSeastar_API_LEVEL=7',
'-DSeastar_DEPRECATED_OSTREAM_FORMATTERS=OFF',
'-DSeastar_UNUSED_RESULT_ERROR=ON',
@@ -1729,7 +1724,7 @@ def configure_seastar(build_dir, mode, mode_config):
seastar_cmake_args += ['-DSeastar_ALLOC_FAILURE_INJECTION=ON']
if args.seastar_debug_allocations:
seastar_cmake_args += ['-DSeastar_DEBUG_ALLOCATIONS=ON']
if modes[mode]['build_seastar_shared_libs']:
if mode_config['build_seastar_shared_libs']:
seastar_cmake_args += ['-DBUILD_SHARED_LIBS=ON']
seastar_cmd = ['cmake', '-G', 'Ninja', real_relpath(args.seastar_path, seastar_build_dir)] + seastar_cmake_args
@@ -2500,6 +2495,33 @@ class BuildType(NamedTuple):
cmake_build_type: str
def generate_compdb_for_cmake_build(source_dir, build_dir):
# Since Seastar and Scylla are configured as separate projects, their compilation
# databases need to be merged into a single database for tooling consumption.
compdb = 'compile_commands.json'
scylla_compdb_path = os.path.join(build_dir, compdb)
seastar_compdb_path = ''
# sort build types by supposed indexing speed
for build_type in ['Dev', 'Debug', 'RelWithDebInfo', 'Sanitize']:
seastar_compdb_path = os.path.join(build_dir, build_type, 'seastar', compdb)
if os.path.exists(seastar_compdb_path):
break
assert seastar_compdb_path, "Seasetar's building system is not configured yet."
# if the file exists, just overwrite it so we can keep it updated
with open(os.path.join(source_dir, compdb), 'w+b') as merged_compdb:
# "merge-compdb.py" considers all object files under the "--prefix"
# directory as relevant. Since CMake generates .o files in
# "CMakeFiles" directories, we preserve the compilation rules for
# these generated files.
prefix = ""
subprocess.run([os.path.join(source_dir, 'scripts/merge-compdb.py'),
prefix,
scylla_compdb_path,
seastar_compdb_path],
stdout=merged_compdb,
check=True)
def configure_using_cmake(args):
# all supported build modes, and if they are built by default if selected
build_modes = {'debug': BuildType(True, 'Debug'),
@@ -2522,6 +2544,7 @@ def configure_using_cmake(args):
'CMAKE_EXE_LINKER_FLAGS': semicolon_separated(args.user_ldflags),
'CMAKE_EXPORT_COMPILE_COMMANDS': 'ON',
'Scylla_CHECK_HEADERS': 'ON',
'Scylla_DIST': 'ON' if args.enable_dist in (None, True) else 'OFF',
'Scylla_TEST_TIMEOUT': args.test_timeout,
'Scylla_TEST_REPEAT': args.test_repeat,
}
@@ -2535,22 +2558,17 @@ def configure_using_cmake(args):
source_dir = os.path.realpath(os.path.dirname(__file__))
build_dir = os.path.join(source_dir, 'build')
if not args.dist_only:
for mode in selected_modes:
configure_seastar(build_dir, build_modes[mode].cmake_build_type, modes[mode])
cmake_command = ['cmake']
cmake_command += [f'-D{var}={value}' for var, value in settings.items()]
cmake_command += ['-G', 'Ninja Multi-Config',
'-B', build_dir,
'-S', source_dir]
subprocess.check_call(cmake_command, shell=False, cwd=source_dir)
compdb_source = os.path.join(source_dir, 'compile_commands.json')
compdb_target = os.path.join(build_dir, 'compile_commands.json')
try:
os.symlink(compdb_target, compdb_source)
except FileExistsError:
# if there is already a valid compile_commands.json link in the
# source root, we are done.
pass
generate_compdb_for_cmake_build(source_dir, build_dir)
if __name__ == '__main__':

View File

@@ -10,9 +10,7 @@
#include "counters.hh"
#include "mutation/mutation.hh"
#include "combine.hh"
#include "log.hh"
#include <boost/range/algorithm/sort.hpp>
#include "utils/log.hh"
logging::logger cell_locker_log("cell_locker");
@@ -30,7 +28,7 @@ auto fmt::formatter<counter_cell_view>::format(const counter_cell_view& ccv,
void counter_cell_builder::do_sort_and_remove_duplicates()
{
boost::range::sort(_shards, [] (auto& a, auto& b) { return a.id() < b.id(); });
std::ranges::sort(_shards, std::ranges::less(), std::mem_fn(&counter_shard::id));
std::vector<counter_shard> new_shards;
new_shards.reserve(_shards.size());

Some files were not shown because too many files have changed in this diff Show More