Compare commits

..

484 Commits

Author SHA1 Message Date
Takuya ASADA
91194f0ac0 dist: prevent error building ubuntu package on EC2
fixes #491

Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-11-09 12:55:46 +02:00
Takuya ASADA
aaba5a6f7c dist: add missing dist/ubuntu/changelog.in
Missing file for d2dd6b90a9

Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-11-05 11:09:49 +02:00
Takuya ASADA
eaabbba14d dist: split debug symbol to sepalate package on ubuntu
Fixes #524

Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-11-04 17:30:43 +02:00
Takuya ASADA
8ce8a0b84c dist: support ./SCYLLA-VERSION-GEN on ubuntu package
Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-11-04 17:30:36 +02:00
Tomasz Grabiec
f74cdaa184 query_processor: Use the correct client_state
Since 4641dfff24, query_state keeps a
copy of client_state, not a reference. Therefore _cl is no longer
updated by queries using _qp. Fix by using the client_state from _qp.

Fixes #525.
2015-11-04 12:44:01 +02:00
Pekka Enberg
a461a21434 release: 0.11.1 2015-11-04 08:16:15 +02:00
Pekka Enberg
9178e96cce Merge seastar upstream
* seastar 9ae6407...05b41b8 (11):
  > resource: fix system memory reservation
  > Add .gitattributes to improve 'git diff' output
  > README: remove irrelevant OSv instructions
  > Add invocation of ninja in Ubuntu section of README
  > collectd: remove incorrect license
  > rpc server: Add pending and sent messages to server
  > scripts: posix_net_conf.sh: Use a generic logic for RPS configuring
  > scripts: posix_net_conf.sh: allow passing a NIC name as a parameter
  > doc: link to the tutorial
  > tutorial: begin documenting the network API
  > slab: remove bogus uintptr_t definition
2015-11-04 08:15:55 +02:00
Asias He
32d5a81b73 ami: Improve scylla raid setup
Use all the disks except the one for rootfs for RAID0 which stores
scylla data. If only one disk is available warn the user since currently
our AMI's rootfs is not XFS.

[fedora@ip-172-31-39-189 ~]$ cat WARN.TXT
WARN: Scylla is not using XFS to store data. Performance will suffer.

Tested on AWS with 1 disk, 2 disks, 7 disk case.

(cherry picked from commit 49d6cba471)
2015-11-03 09:22:20 +02:00
Avi Kivity
35af260ca9 Update scylla-ami submodule
* dist/ami/files/scylla-ami c6ddbea...3f37184 (1):
  > Update reflector URL

(cherry picked from commit 440b403089)
2015-11-03 09:22:11 +02:00
Takuya ASADA
1d22543f59 dist: add scylla.repo to fetch scylla rpms on ami
Mistakenly didn't included on yum repository for AMI patchset, but it's needed

Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
(cherry picked from commit 8587c4d6b3)
2015-11-03 09:22:05 +02:00
Takuya ASADA
1c040898e8 dist: update packages on ec2 instance first bootup
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
(cherry picked from commit aaeccdee60)
2015-11-03 09:21:55 +02:00
Takuya ASADA
249967d62b dist: use scylla repo on ami, instead of locally built rpms
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
(cherry picked from commit 8b98fe5a1c)
2015-11-03 09:21:49 +02:00
Takuya ASADA
9d8bc9e3cc dist: move inline script to setup-ami.sh
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
(cherry picked from commit 2863b8098f)
2015-11-03 09:21:42 +02:00
Shlomi Livne
f849c4b9c2 dist: set SCYLLA_HOME used to find the configuration and property files
Signed-off-by: Shlomi Livne <shlomi@scylladb.com>
2015-11-02 08:29:43 +02:00
Shlomi Livne
0e7e68236a dist: fedora/rhel/centos copy cassandra-rackdc.properties
Signed-off-by: Shlomi Livne <shlomi@scylladb.com>
2015-11-02 08:29:39 +02:00
Shlomi Livne
94802ce842 dist: ubuntu copy cassandra-rackdc.properties
Signed-off-by: Shlomi Livne <shlomi@scylladb.com>
2015-11-02 08:29:33 +02:00
Shlomi Livne
5362765835 Update snitch registration EC2MultiRegionSnitch --> Ec2MultiRegionSnitch
Update snitch EC2MultiRegionSnitch to Ec2MultiRegionSnitch,
org.apache.cassandra.locator.EC2MultiRegionSnitch to
org.apache.cassandra.locator.Ec2MultiRegionSnitch

Signed-off-by: Shlomi Livne <shlomi@scylladb.com>
2015-11-02 08:29:27 +02:00
Shlomi Livne
f87d9ddd34 Update snitch registration EC2Snitch --> Ec2Snitch
Update EC2Snitch to Ec2Snitch, org.apache.cassandra.locator.EC2Snitch to
org.apache.cassandra.locator.Ec2Snitch

Signed-off-by: Shlomi Livne <shlomi@scylladb.com>
2015-11-02 08:29:20 +02:00
Pekka Enberg
ca6078d5eb Merge "Wire reconnectable_snitch_helper to gossiping_property_file_snitch" from Vlad
"gossiping_property_file_snitch checks its property
file (cassandra-rackdc.properties) for changes every minute and
if there were changes it re-registers the helper and initiates
re-read of the new DC and Rack values in the corresponding places.

Therefore we need the ability to unregister/register the corresponding subscriber
at the same time when a subscriber list is possibly iterated by
some other asynchronous context on the current CPU.

The current gossiper implementation assumes that subscribers list may not be
changed from the context different from the one that iterates on their list.

So, this had to be fixed.

There was also missing an update_endpoint(ep) interface in the locator::topology
class and the corresponding token_metadata::update_topology(ep) wrapper.

Also there were some bugs in the gossiping_property_file::reload_configuration()
method."
2015-10-30 16:04:07 +02:00
Pekka Enberg
4701e698b9 Merge "Fixes for dependency packages, fix upstart script" from Takuya
"Fixes #510, (part of) #493."
2015-10-30 15:42:20 +02:00
Vlad Zolotarov
6b4b983f9d locator::gossiping_property_file_snitch: implement gossiper_starting() and reload_gossiper_state()
This functions were empty and now they have the intended code:
   - Register the reconnectable_snitch_helper if "prefer_local"
     parameter was given the TRUE value.
   - Set the application INTERNAL_IP state to listen_address().

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-30 00:16:53 +02:00
Vlad Zolotarov
17294a3bc7 locator::gossiping_property_file_snitch: fix some issues in reload_configuration()
- Invoke reload_gossiper_state() and gossip_snitch_info() on CPU0 since
     gossiper is effectively running on CPU0 therefore all methods
     modifying its state should be invoked on CPU0 as well.
   - Don't invoke any method on external "distributed" objects unless their
     corresponding per-shard service object have already been initialized.
   - Update a local Node info in a storage_service::token_metadata::topology
     when reloading snitch configuration when DC and/or Rack info has changed.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-30 00:16:53 +02:00
Vlad Zolotarov
b3504f9b1f locator::token_metadata: added topology::update_endpoint(ep) and update_topology(ep)
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-30 00:16:53 +02:00
Vlad Zolotarov
a3d55ba882 locator::reconnectable_snitch_helper: remove unused constructor parameter
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-30 00:16:53 +02:00
Vlad Zolotarov
33b195760b gms::gossiper: allow the modification of _subscribers while it's being iterated
Introduce a subscribers_list class that exposes 3 methods:
  - push_back(s) - adds a new element s to the back of the list
  - remove(s) - removes an element s from the list
  - for_each(f) - invoke f on each element of the list
  - make a subscriber_list store shared_ptr to a subscriber
    to allow removing (currently it stores a naked pointer to the object).

subscribers_list allows push_back() and remove() to be called while
another thread (e.g. seastar::async()) is in the middle of for_each().

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Simplify subscribers_list::remove() method.
   - load_broadcaster: inherit from enable_shared_from_this instead
     of async_sharded_service.
2015-10-30 00:16:16 +02:00
Takuya ASADA
3bf69db90c dist: handle SIGKILL correctly on upstart, also do not respawn process
Fixes #510
2015-10-30 00:55:47 +09:00
Takuya ASADA
6aac944588 dist: fix warning when building scylla-server ubuntu package 2015-10-30 00:53:20 +09:00
Takuya ASADA
37e00d3527 dist: fix warning when building thrift ubuntu package 2015-10-30 00:52:11 +09:00
Takuya ASADA
a165d6aa01 dist: fix warning when building antlr3-c++-dev ubuntu package 2015-10-30 00:52:00 +09:00
Takuya ASADA
9eb8aa7ea3 dist: fix warning when building antlr3-tool ubuntu package 2015-10-30 00:51:42 +09:00
Avi Kivity
f7f996d473 Merge seastar upstream
* seastar 9d8913a...9ae6407 (2):
  > core/memory.cc: Declare member min_free_pages from cpu_pages struct
  > http: All http replies should have version set
2015-10-29 16:49:10 +02:00
Asias He
6259dd73b6 token: Print token using the partitioner defined method
Make nodetool ring output align with c* output.
2015-10-29 15:53:47 +02:00
Pekka Enberg
f4849000c8 cql3: Fix exception message in lists::setter_by_index::execute()
Spotted by C* unit tests.

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-29 15:36:56 +02:00
Pekka Enberg
6634f37464 cql3: Fix exception message in lists::discarder_by_index::execute()
Spotted by C* unit tests.

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-29 15:36:51 +02:00
Pekka Enberg
2344bd806d cql3: Fix grammar 'WITH WITH' bug that causes a SIGSEGV
Fix an issue where 'WITH WITH' in CREATE and ALTER KEYSPACE would bring
down the whole server.

  https://issues.apache.org/jira/browse/CASSANDRA-9565

  c939422637

Spotted by C* unit tests.

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-29 10:59:57 +01:00
Raphael S. Carvalho
6bea503f9a db: fallback to sizetiered if compaction strategy isn't supported
It may happen that the user will migrate a table to Scylla which
compaction strategy isn't supported yet, such as Data tiered.
Let's handle that by falling back to size-tiered compaction
strategy and printing a warning message.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-29 09:33:28 +02:00
Raphael S. Carvalho
c2a98807c7 compaction_manager: fix remove
remove() is the function used to remove every reference to a cf from
the compaction manager. This function works by removing cf from the
queue, and waiting for possible ongoing compaction on cf.
However, a cf may be re-queued by compaction manager task if there
is pending compaction by the end of compaction.

If cf is still referenced by the time remove() returns, we could end
up with an use-after-free. To fix that, a task shouldn't re-queue a
cf if it was asked to stop. The stat pending_tasks was also not
being updated when a cf was removed from the task queue.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-28 17:35:26 +02:00
Gleb Natapov
ac5f92db70 storage_proxy: clean up local_dc checking
The only place local_dc is checked during mutation sending is in
send_to_live_endpoints(), but current code pass it there throw several
function call layers. Simplify the code by getting local_dc when it is
used directly.
2015-10-28 16:10:18 +02:00
Pekka Enberg
f78deffdc8 release: prepare for 0.11
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-28 14:49:59 +02:00
Paweł Dziepak
6e5916161c test/cql_test_env: merge client state after executing query
Since 4641dfff24 "service: Copy client
state to query state" after executing a query client state needs to be
merged back. If that's not done client_state::_last_timestamp_micros
won't be advanced properly and mutations originating from the same
source may have exactly the same timestamp.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-28 14:31:11 +02:00
Avi Kivity
4d23712c9c Merge "Fix gossip test" from Asias 2015-10-28 12:59:19 +02:00
Asias He
25c898fe9c gossip: Enable too more log prints for debug 2015-10-28 16:13:57 +08:00
Asias He
e0e8e9a1ed tests: Remove redundant debug info for gossip
The debug info is printed in logger already. Avoid to print it twice.
2015-10-28 16:13:57 +08:00
Asias He
01ee5d002a failure_detector: Remove debug print in operator<< 2015-10-28 16:13:57 +08:00
Asias He
f205ae30c3 tests: Fix gossip
- scylla/seastar/core/sharded.hh:439: Service& seastar::sharded<Service>::local()
  [with Service = locator::snitch_ptr]: Assertion `local_is_initialized()' failed.
- ./utils/fb_utilities.hh:74: static const inet_address utils::fb_utilities::get_broadcast_address():
  Assertion `broadcast_address()' failed.
2015-10-28 16:13:57 +08:00
Takuya ASADA
5aab69e72f dist: do not remove build/ dir when scylla-server ubuntu package building
Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-10-27 18:23:09 +02:00
Avi Kivity
7f88db8625 Merge "storage_service and gossip update" from Asias 2015-10-27 18:14:43 +02:00
Lucas Meneghel Rodrigues
a9a33d5a99 test.py: PEP8 Fixes
Fix some PEP8 problems found in the tester code:

 * Wrong spacing around operators
 * Lines between class and function definitions
 * Fixed some of the larger than 80 column statements
 * Removed an unused import

Signed-off-by: Lucas Meneghel Rodrigues <lmr@scylladb.com>
2015-10-27 17:54:54 +02:00
Tomasz Grabiec
491eae58a4 Merge branch 'gleb/read-repair' from seastar-dev.git
From Gleb:

Now that we can calculate mutation diffs do so on digest mismatch and send
them out.
2015-10-27 16:36:05 +01:00
Asias He
7e6e90dc52 storage_service: Serialize decommission
Prevent two operations happen simultaneously.
2015-10-27 21:48:38 +08:00
Asias He
4b75815306 storage_service: Introduce run_with_write_api_lock helper
It is useful to run code on cpu zero with the api lock.
2015-10-27 21:48:38 +08:00
Asias He
62228726a3 storage_service: Introduce a rwlock to serialize management operations 2015-10-27 21:48:38 +08:00
Asias He
1bbc1920d2 range_streamer: Start to use get_preferred_ip
It is available now.
2015-10-27 21:48:37 +08:00
Asias He
306bab9ead storage_service: Use get_preferred_ip
Now that it is available, use it.
2015-10-27 21:48:37 +08:00
Asias He
55b76a8963 api: No cpu zero trick for remove_node
storage_service::remove_node is guaranteed to run on cpu zero only.
2015-10-27 21:48:37 +08:00
Asias He
b3c7305d25 storage_service: Make remove_node runs on cpu 0 only
We need to serialize nodetool operations to avoid two operations
happening simultaneously. Running on cpu 0 is one step toward this
goal.
2015-10-27 21:48:37 +08:00
Asias He
6c6b1c4ba7 storage_service: Make decommission runs on cpu 0 only
We need to serialize nodetool operations to avoid two operations
happening simultaneously. Running on cpu 0 is one step toward this goal.
2015-10-27 21:48:37 +08:00
Asias He
49daba2599 storage_service: Do not ignore future in decommission
gossiper::stop returns a future which we can not ignore.
2015-10-27 21:48:37 +08:00
Asias He
00311817bd storage_service: Implement shutdown_client_servers 2015-10-27 21:48:37 +08:00
Asias He
83eb36796f storage_service: Kill FIXME for LoadBroadcaster.BROADCAST_INTERVAL
It is available now.
2015-10-27 21:48:37 +08:00
Asias He
1469cec5bf gossiper: Kill free function helper to get heart version and generation number
They can only be executed on cpu 0. Make the gossiper member
functions for them to do so.
2015-10-27 21:48:37 +08:00
Asias He
f573059698 gossiper: Kill free function helper for {unsafe_,}assassinate_endpoint
They can only be executed on cpu 0. Make the gossiper member functions
for them to do so.
2015-10-27 21:48:37 +08:00
Asias He
c5f377eb8b gossip: Simplify get_endpoint_downtime
_unreachable_endpoints is replicated to call cores. No need to query
on core 0.
2015-10-27 21:48:37 +08:00
Asias He
6f1db4fb72 gossip: Simplify get_unreachable_members
_unreachable_endpoints is replicated to call cores. No need to query on
core 0.

This also fixes a bug in storage_proxy::truncate_blocking
which might access _unreachable_endpoints on non-zero cores.
2015-10-27 21:48:37 +08:00
Asias He
a9f96d1f5a gossip: Replicate _unreachable_endpoints to all cores 2015-10-27 21:48:37 +08:00
Asias He
2439a2a982 gossip: Simplify get_live_members
_live_endpoints is replicated to call cores. No need to query on core 0.
2015-10-27 21:48:37 +08:00
Asias He
a28ba9cde8 api: Simplify get_tokens get_node_tokens and get_token_endpoint
token_metadata is replicated to all cores. No need to query on core 0.
2015-10-27 21:48:37 +08:00
Asias He
4e886f0399 storage_service: Implement is_rpc_server_running 2015-10-27 21:48:37 +08:00
Asias He
7f0634b429 storage_service: Implement stop_rpc_server 2015-10-27 21:48:37 +08:00
Asias He
ca66bea619 storage_service: Implement is_native_transport_running 2015-10-27 21:48:37 +08:00
Asias He
7bc49a1efe storage_service: Implement stop_native_transport 2015-10-27 21:48:37 +08:00
Asias He
8218ab7922 storage_service: Implement start_native_transport and start_rpc_server
They are used for APIs. Share the code in main.cc as well.
2015-10-27 21:48:37 +08:00
Lucas Meneghel Rodrigues
42c0acfc44 test.py: Return test output only if subprocess succeeded
The current code will try to print the output of a
subprocess.Popen().communicate() call even if that
call raised an exception and that output is None.

Let's fix this problem by only printing the output
if it's not None.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@scylladb.com>
2015-10-27 15:17:05 +02:00
Asias He
3c47844e8c storage_service: Complete check_for_endpoint_collision
Part of it was stubbed.
2015-10-27 21:17:02 +08:00
Asias He
77a87cb2b6 storage_service: Implement prepare_replacement_info
Needed by replace node operation.
2015-10-27 21:17:02 +08:00
Vlad Zolotarov
5cdbc3701a tests: set broadcast address
Since commit 5613979a85
broadcast address has to be set before it's used for the first
time.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-27 15:16:13 +02:00
Avi Kivity
345f739f28 Merge seastar upstream
* seastar 501e4cb...9d8913a (3):
  > Add mutable to with_lock and do_with
  > app-template: disable collectd by default
  > reactor: use fdatasync() instead of fsync()
2015-10-27 15:13:36 +02:00
Avi Kivity
42a5c8b92e Merge "CQL request load balancing" from Pekka
"Currently, CQL requests are processed on the same CPU core where the
connection lives in. This series adds infrastructure for migrating CQL
processing to other cores and implements a round-robin load balancing
algorithm that can be enabled with the "--load-balance=round-robin"
command line option. Load balancing is not enabled by default because we
need to first run performance tests to determine if the simple
round-robin algorithm is sufficient, or wheter we need to implement more
sophisticated dynamic load balancing."
2015-10-27 15:04:44 +02:00
Gleb Natapov
58154333e8 storage_proxy: send out mutation diffs to each destination 2015-10-27 14:58:35 +02:00
Pekka Enberg
a772938e73 transport/server: Round-robin CQL request load balancing
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-10-27 13:24:58 +02:00
Pekka Enberg
ed0607c10e transport/server: Merge client state changes in process_request()
In preparation for processing queries on shards other than where the
connection lives in, merge client state changes in process_request().

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-27 13:24:58 +02:00
Pekka Enberg
4641dfff24 service: Copy client state to query state
In preparation for processing CQL requests on different core than where
the connection lives in, copy client state to query state for
processing and merge back the results after we're done.

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-27 13:24:58 +02:00
Pekka Enberg
27c678b2a5 transport/server: Use bytes_view instead of moving temporary buffer around
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-10-27 13:13:25 +02:00
Pekka Enberg
4482406aee transport/server: Write response from process_request()
In preparation for spreading request processing to multiple cores, make
sure CQL response is written out on the connection shard.

Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-10-27 13:13:25 +02:00
Pekka Enberg
3b6eba1344 transport/server: Remove _query_states from connection
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-10-27 13:13:25 +02:00
Pekka Enberg
3884f1c8b6 transport/server.cc: Fix formatting glitch
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
2015-10-27 13:13:25 +02:00
Gleb Natapov
122f03e689 storage_proxy: calculate mutation diffs during reconcile. 2015-10-27 13:02:15 +02:00
Gleb Natapov
8bbe4bdbd4 storage_proxy: rename reconciliate to reconcile
'reconciliate' does not seams to be a world.
2015-10-27 12:57:02 +02:00
Vlad Zolotarov
3a3867588a tests::cql_test_env: set broadcast address
cql_query_test hasn't configured Broadcast address before
it was used for the first time.

Broadcast address is an essential Node's configuration.

There is an assert in utils::fb_utils::get_broadcast_address()
that ensures that broadcast address has been properly configured
before it's used for the first time and it is triggered without
this patch.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-27 12:38:56 +02:00
Avi Kivity
0754e9a34d Merge "Even more commitlog fixes" from Calle
"Fixes for commitlog (debug) test failures related to shutdowns.
Note that most the fixes here are only really related to the tests
failing, not really real scylla runs. However, at some point we'll
have real shutdown in scylla as well (not just hard exit), at which
point this becomes more relevant there as well.

Main issue was post-flush continuation chains for stats update
remaining unexecuted, due to task reordering, once the commitlog
object itself had been destroyed. This could have been handled by just
making the stats object a shared pointer, but in general it seems more
prudent to enforce having all tasks completed after shutdown.

* Change commitlog shutdown to use gate+wait for all outstanding ops
  (flush, write, timer). Thus we can ensure everything is finished
  when returning from "shutdown".
* Fix bug with "commitlog::clear" (test method) not doing the intended deed
* Most importantly, fix the tests themselves, cleaning up old crud, and
  fixing invalid assumptions (CL behaviour changed quite a bit since tests
  were created), and remove races.

Disclaimer: I've _never_ managed to reproduce the debug tests failing
like in jenkins locally (though I managed to provoke other failures),
but at least jenkins runs with this series have been clean. Knock knock."
2015-10-27 12:16:20 +02:00
Paweł Dziepak
f46cba7bc8 sstable: simplify key reader
Now that #475 is solved an read_indexes() guarantees to return disjont
sets of keys sstable key reader can be simplified, namely, only two key
lookups are needed (the first and the last one) and there is no need for
range splitting.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-27 10:33:02 +02:00
Avi Kivity
fa0f00e9d2 Merge "Add EC2MultiRegionSnitch and Co." from Vlad
"This series add the mighty EC2MultiRegionSnitch and some missing
multi-DC related functionality:
   - Use the proper Broadcast Address: either the one from the
    .yaml configuration (if present) or the one configured by some
    scylla component (e.g. snitch).
   - Introduce the ability to switch to internal IPs when connecting
     to Nodes in the same data center.
   - Store the known internal IPs in system.peers table and
     load then immediately during boot.

This series also contains some related fixes done on the way."
2015-10-26 18:38:57 +02:00
Gleb Natapov
5bc532261f load_broadcaster: add missing header file protector 2015-10-26 18:38:01 +02:00
Avi Kivity
91bde5e2e8 Merge "sstable improvements" from Raphael 2015-10-26 17:25:58 +02:00
Asias He
6f08c4facb dns: Move gethostbyname to source file
Fix multiple definition of gethostbyname.
2015-10-26 15:59:58 +02:00
Calle Wilund
6dc6b40495 commitlog_test: test fix 2015-10-26 14:57:15 +01:00
Calle Wilund
ceb9f4d647 database: Just do commitlog::shutdown on shutdown. It will do flushes. 2015-10-26 14:56:24 +01:00
Calle Wilund
5299cece4c commitlog: Make "shutdown" do flushing + hard sync of pending ops
* Do close + fsync on all segments
* Make sure all pending cycle/sync ops are guarded with a gate, and
  explicitly wait for this gate on shutdown to make sure we don't
  leave hanging flushes in the task queue.
* Fix bug where "commitlog::clear" did not in fact shut down the CL,
  due to "_shutdown" being already set.

Note: This is (at least currently) not an issue for anything else than tests,
since we don't shutdown the normal server "properly", i.e. the CL itself
will not go away, and hanging tasks are ok, as long as the sync-all is done
(which it was previously). But, to make tests predictable, and future-proof
the CL, this is better.
2015-10-26 14:50:54 +01:00
Raphael S. Carvalho
25a4d6686a sstables: update comment
sstable level is set to zero by default, but it may be set to
a different value if a new sstable is the result of leveled
compaction. This is done outside write_components.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-26 10:39:22 -02:00
Raphael S. Carvalho
028283869f sstables: reuse BASE_SAMPLING_LEVEL constant from downsampling class
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-26 10:35:46 -02:00
Raphael S. Carvalho
b908d3a5e9 sstables: fix prepare_summary
We were incorrectly setting s.header.min_index_interval to
BASE_SAMPLING_LEVEL, which luckily is the default value to
min index interval. BASE_SAMPLING_LEVEL was also used as
the min index interval when checking if the estimated
number of summary entries is greater than the limit.
To fix problems, get min index interval from schema and
use this value to check the limit.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-26 10:27:03 -02:00
Avi Kivity
38df381206 Merge "remove node support" from Asias 2015-10-26 14:23:47 +02:00
Vlad Zolotarov
f70aab2fbb locator: added ec2_multi_region_snitch
This snitch in addition to what EC2Snitch does registers
a reconnectable_snitch_helper that will make messenger_service
connect to internal IPs when it connects to the nodes in the same
data center with the current Node.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v4:
   - Added dual license in newly added files.

New in v3:
   - Returned the Apache license.

New in v2:
   - Update the license to the latest version. ;)
2015-10-26 14:10:47 +02:00
Vlad Zolotarov
5613979a85 utils::fb_utilities: add the ability to set a broadcast address
Add utils::fb_utilities::set_broadcast_address().
Set it to either broadcast_address or listen_address configuration value
if appropriate values are set. If none of the two values above
are set - abort the application.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Simplify the utils::fb_utilities::get_broadcast() logic.
2015-10-26 14:10:39 +02:00
Vlad Zolotarov
a182a33d4d locator::snitch_base: added i_endpoint_snitch::set_local_private_addr()
Sets the value of the local private IP address.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:10:39 +02:00
Vlad Zolotarov
1bb91399cd locator: added reconnectable_snitch_helper
reconnectable_snitch_helper implements i_endpoint_state_change_subscriber
and triggers reconnect using the internal IP to the nodes in the
same data center when one of the following events happen:

   - on_join()
   - on_change() - when INTERNAL_IP state is changed
   - on_alive()

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v4:
   - Added dual license for newly added files.

New in v3:
   - Fix reconnect() logic.
   - Returned the Apache license.
   - Check if the new local address is not already stored in the cache.
   - Get rid of get_ep_addr().

New in v2:
   - Update the license to the latest version. ;)
2015-10-26 14:09:48 +02:00
Vlad Zolotarov
d683d9cfb0 locator::ec2_snitch: moved info parsing and distribution into the separate function
Added load_config() function that reads AWS info and property file
and distributes the read values on all shards.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
703807b67d locator::ec2_snitch: rename ZONE_QUERY_SERVER_ADDR -> AWS_QUERY_SERVER_ADDR
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
d8de1099eb message::messaging_service: introduce _preferred_ip_cache
This map will contain the (internal) IPs corresponding to specific Nodes.
The mapping is also stored in the system.peers table.

So, instead of always connecting to external IP messaging_service::get_rpc_client()
will query _preferred_ip_cache and only if there is no entry for a given
Node will connect to the external IP.

We will call for init_local_preferred_ip_cache() at the end of system table init.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Improved the _preferred_ip_cache description.
   - Code styling issues.

New in v3:
   - Make get_internal_ip() public.
   - get_rpc_client(): return a get_preferred_ip() usage dropped
     in v2 by mistake during rebase.
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
f896f9a908 message::messaging_service: added remove_rpc_client(shard_id)
This function erases shard_info objects from all _clients maps.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Use remove_rpc_client_one() instead of direct map::erase().
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
e9789dd68c message::messaging_service: fixes in rpc_protocol_client_wrapper shut down
- Ensure messaging_service::stop() blocks until all rpc_protocol::client::stop()
     are over.
   - Remove the async code from rpc_protocol_client_wrapper destructor - call
     for stop() everywhere it's needed instead. Ensure that
     rpc_protocol_client_wrapper is always "stopped" when its destructor is called.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v3:
   - Code style fixes.
   - Killed rpc_protocol_client_wrapper::_stopped.
   - Killed rpc_protocol_client_wrapper::~rpc_protocol_client_wrapper().
   - Use std::move() for saving shared pointer before
     erasing the entry from _clients in
     remove_rpc_client_one() in
     order to avoid extra ref count bumping.
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
842b13325d message::messaging_service: make _clients to be std::array
This makes code cleaner. Also it would allow less changes
if we decide to increase _clients size in the future.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
fd811dd707 db::system_keyspace: added get_preferred_ips()
get_preferred_ips() returns all preferred_ip's stored in system.peers
table.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Get rid of extra std::move().
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
f2e1be0fc1 db::system_keyspace::update_preferred_ip(): use net::ipv4_address as a preferred_ip value
Fixes issue #481

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:09:26 +02:00
Vlad Zolotarov
4f603d285e gms::gossiper: call for i_endpoint_snitch::gossiper_starting()
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-26 14:09:26 +02:00
Takuya ASADA
17f2038949 dist: fix upstart script to make it able to start/stop correctly
Scylla is not "daemon" (witch forks twice), but it can be "fork" (forks once) when we don't use "exec" to call startup scripts.
Fixes #495

Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-10-26 13:00:52 +02:00
Takuya ASADA
25398d5a1d dist: statically link to libstdc++ on Ubuntu
Fixes #494

Signed-off-by: Takuya ASADA <syuu@scylladb.com>
2015-10-26 12:59:28 +02:00
Asias He
201d439440 storage_service: Enable remove_node support 2015-10-26 10:33:19 +02:00
Asias He
06b19867d8 api: Fix storage_service remove_node parameter
nodetool removenode takes the parameter of host_id instead of token.

Refs: #496
2015-10-26 10:32:47 +02:00
Asias He
9912a68364 storage_service: Enable remove_node support 2015-10-26 15:29:13 +08:00
Asias He
5f2d97c0b8 api: Fix storage_service remove_node parameter
nodetool removenode takes the parameter of host_id instead of token.

Refs: #496
2015-10-26 15:26:59 +08:00
Avi Kivity
7254c87776 Merge seastar upstream
* seastar 6af5a0d...501e4cb (2):
  > configure: don't fail when sanitizer is unavailable
  > memcached: close socket at the end of request handling
2015-10-25 19:59:45 +02:00
Shlomi Livne
d493b2a7f7 dist: ubuntu update build script file permissions
Signed-off-by: Shlomi Livne <shlomi@cloudius-systems.com>
2015-10-25 12:44:50 +02:00
Avi Kivity
e2e869f150 Merge "API: storage proxy metrics" from Amnon
"This series adds two types of functionality to the storage_proxy, it adds the
API that returns the timeout constants from the config and it aligned the
metrics of the read, write and range to origin StorageProxy metrics."
2015-10-25 11:40:46 +02:00
Avi Kivity
01e301fc9a Merge "fix read_indexes" from Raphael
Fixes issue #474.
2015-10-25 11:25:42 +02:00
Avi Kivity
ec4d1dd7fd Merge "CQL code cleanups" from Pekka
"Yet another round of code cleanups to cql3/*."
2015-10-25 10:35:19 +02:00
Tomasz Grabiec
a3e84c1553 tests: Add test for make_local_reader() and min/max tokens 2015-10-25 10:27:59 +02:00
Tomasz Grabiec
7b1e78ffcd storage_proxy: Fix make_local_reader() for ranges with min/max tokens
shard_of() was undefined for before_all/after_all tokens. Fix by
adding handling for these.
2015-10-25 10:27:58 +02:00
Raphael S. Carvalho
5cdc886f84 tests: add test to read_indexes
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-23 16:57:41 -02:00
Raphael S. Carvalho
af88a6864a sstables: fix read_indexes
read_indexes() will not work for a column family that minimum
index interval is different than sampling level or that sampling
level is lower than BASE_SAMPLING_LEVEl.
That's because the function was using sampling level to determine
the interval between indexes that are stored by index summary.
Instead, method from downsampling will be used to calculate the
effective interval based on both minimum_index_interval and
sampling_level parameters.

Fixes issue #474.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-23 16:57:41 -02:00
Raphael S. Carvalho
e18cf96b01 sstables: convert Downsampling to C++
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-23 16:57:39 -02:00
Pekka Enberg
e48f8d25e2 cql3: Move cf_statement class implementation to source file
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 16:17:17 +03:00
Pekka Enberg
d79d8b00f3 cql3: Move create_keyspace_statement class implementation to source file
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 16:17:17 +03:00
Pekka Enberg
baea79d17d cql3: Move schema_altering_statement class implementation to source file
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 16:17:17 +03:00
Pekka Enberg
6dbee22d2e cql3: Move use_statement class implementation to source file
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 16:17:17 +03:00
Pekka Enberg
ff93a840ae cql3: Remove ifdef'd code from use_statement.hh
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 15:52:02 +03:00
Pekka Enberg
83e6c428be transport: Add messages_fwd.hh and use it
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-23 15:52:02 +03:00
Tomasz Grabiec
7eb0da3ed8 Merge tag 'asias/range_streamer_use_after_free_gossip_print/v1' from seastar-dev.git
range_streamer use after free fix and gossip print cleanups from
Asias.
2015-10-23 14:43:20 +02:00
Asias He
a63871f024 gossip: Print application_state name instead of number
Plus print cleanup.
2015-10-23 17:03:18 +08:00
Asias He
687d88dd0c gossip: Add operator<< operator for application_state 2015-10-23 16:32:36 +08:00
Asias He
80f1b9781a gossip: Simplify make_token_string with boost::adaptors::transformed 2015-10-23 16:13:31 +08:00
Asias He
1ba20f4efd storage_service: Enable single_datacenter_filter in rebuild 2015-10-23 16:13:30 +08:00
Asias He
b172146223 range_streamer: Introduce single_datacenter_filter 2015-10-23 16:13:30 +08:00
Asias He
a934e31379 storage_service: Fix use after free in rebuild
streamer is a stack variable, it is gone when the function returns.
Fix it using a shared pointer.
2015-10-23 16:13:30 +08:00
Asias He
98b34ecc67 boot_strapper: Fix use after free
streamer is a stack variable, it is gone when the function returns.
Fix it using a shared pointer.

Fixes #489
2015-10-23 16:13:30 +08:00
Asias He
e2391b02da storage_service: Add debug info for get_load_map 2015-10-23 16:13:30 +08:00
Avi Kivity
2c16d1f980 Merge "fix nodetool gossipinfo and status" from Asias
"- Implement get_load_map using load_broadcaster
- Fix token in nodetool gossipinfo"
2015-10-23 10:34:13 +03:00
Asias He
bc8d3f0d24 storage_service: Implement get_load_map using load_broadcaster
$nodetool -p 7199 status

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address    Load       Tokens  Owns    Host ID Rack
UN  127.0.0.1  60711      3       ?  78ce8d76-69f8-44fc-a5ae-b932eb4f641b  rack1
UN  127.0.0.2  66237      3       ?  b1eaaee6-c334-4a65-bc0c-95af49bca0b3  rack1
2015-10-23 11:53:46 +08:00
Asias He
a137006d27 main: Set load_broadcaster for storage_service during startup
Note only storage_service on shard 0 will access load_broadcaster
2015-10-23 11:28:06 +08:00
Asias He
992390feda storage_service: Store load_broadcaster into storage_service
It is needed by get_load_map.
2015-10-23 11:25:51 +08:00
Asias He
270e713fea Revert "API: Workaround for load_map"
This reverts commit 497e403387.
2015-10-23 10:45:54 +08:00
Asias He
6b7ca7e334 gossip: Cleanup versioned_value class 2015-10-23 10:06:19 +08:00
Asias He
5556861ac0 gossip: Fix nodetool gossipinfo
Use dht::global_partitioner().{to_sstring and from_sstring) to handle
tokens.

Before:
$ nodetool -p 7199  gossipinfo
127.0.0.1
  generation:1445528714
  heartbeat:105
  0:NORMAL,TOKENS
  2:c1e6c9ef-22c8-3f93-bca1-ea5810bafd36
  3:datacenter1
  4:rack1
  5:2.1.8
  8:127.0.0.1
  11:0
  12:d24aef9c-fc4e-4290-92f4-1fd317b8883a

After:
$ nodetool -p 7199  gossipinfo
127.0.0.1
  generation:1445528714
  heartbeat:105
  0:NORMAL,-3524784140453853209;2276970246802708341;-4108982606669659076
  2:c1e6c9ef-22c8-3f93-bca1-ea5810bafd36
  3:datacenter1
  4:rack1
  5:2.1.8
  8:127.0.0.1
  11:0
  12:d24aef9c-fc4e-4290-92f4-1fd317b8883a
2015-10-23 09:40:59 +08:00
Raphael S. Carvalho
19f2dc9ef9 import Downsampling.java
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-22 14:44:40 -02:00
Gleb Natapov
5b97604735 load_broadcaster: fix linkage error in debug mode
Also move it to service namespace.
2015-10-22 18:18:05 +02:00
Amnon Heiman
14482d4496 API: Add read, write, range estimated histogram implementation for storage_proxy
This patch adds the implmentation for the read, write and range
estimated histogram and total latency.

After this patch the following url will be available:
/storage_proxy/metrics/read/estimated_histogram/
/storage_proxy/metrics/read
/storage_proxy/metrics/write/estimated_histogram/
/storage_proxy/metrics/write
/storage_proxy/metrics/range/estimated_histogram/
/storage_proxy/metrics/range

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 18:54:45 +03:00
Amnon Heiman
e1168c0a34 API: Add estimated histogram to storage_proxy
This patch close the gap between the storage_proxy read, write and range
metrics and the API.

For each of the metrics there will be a histogram, estimated histogram
and total.

The patch contains the definitions for the following:
get_read_estimated_histogram
get_read_latency
get_write_estimated_histogram
get_write_latency
get_range_estimated_histogram
get_range_latency

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>

need mrege storage_proxy
2015-10-22 18:54:45 +03:00
Amnon Heiman
7b8c557f30 storage_service: Add estimated histogram for read, write and range
This patch adds an estimated histogram for read, write and range to the
proxy_service stats.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 18:54:45 +03:00
Amnon Heiman
a071cdce66 API: Add getters to storage_proxy timers timeout
This patch expose the configuration timeout values of the timers.
The timers will return their values in seconds, the swagger definition
file was modified to reflect the change.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 18:54:11 +03:00
Tomasz Grabiec
5bbc902eec mutation_partition: Drop now unnecessary unconst() usage
This change was actually promised by
f74c665671.
2015-10-22 17:12:03 +02:00
Tomasz Grabiec
c7be350961 mutation_partition: Rename reversion_traits to reversal_traits
As pointed out by Nadav, 'reversion' is from 'revert', 'reversal' is
from 'reverse'.
2015-10-22 18:09:07 +03:00
Tomasz Grabiec
f74c665671 mutation_partition: Add non-const-qualified version of range() and use it 2015-10-22 18:09:07 +03:00
Asias He
6c48ce065e storage_service: Make comment clearer in get_changed_ranges_for_leaving
We are not removing the range. Current node and new node will be
responsible for the range are calculated. We only need to stream data to
node = new node - current node. E.g,

Assume we have node 1 and node 2 in the cluster, RF=2. If we remove node2:

Range (3c 25 fa 7e d2 2a 26 b4 , 81 2a a7 32 29 e5 3a 7c ],
current_replica_endpoints={127.0.0.1, 127.0.0.2} new_replica_endpoints={127.0.0.1}

Range (3c 25 fa 7e d2 2a 26 b4 , 81 2a a7 32 29 e5 3a 7c ] already in all replicas

no data will be streamed to node 1 since it already has it.
2015-10-22 18:08:03 +03:00
Avi Kivity
a699bc20bc Merge "Adding the stream metrics API" from Amnon
"This series adds the stream metrics API, the swagger definition are based on
the StreamMetrics class in origin."
2015-10-22 17:18:01 +03:00
Amnon Heiman
5323b29699 API: Add compaction history to the API
This patch adds a definition and a stub for the compaction history. The
implementation should read fromt the compaction history table and return
an array of results.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 17:16:58 +03:00
Avi Kivity
5d37ee29f8 Merge "Adding log level support to the API" from Amnon
"This series adds an API to get and set the log level.
After this series it will be possible to use the folloing url:
GET/POST:
/system/logger
/system/logger/{name}"
2015-10-22 17:15:41 +03:00
Avi Kivity
b4e5b9dcf1 Merge "Add support to nodetool describecluster"
"This series adds the functionality that is required for nodetool
describecluster

It uses the gossiper for get cluster name and get partitioner.  The
describe_schema_versions functionality is missing and a workaround is used so
the command would work.

After this series an example for nodetool describecluster:
./bin/nodetool describecluster
Cluster Information:
	Name: Test Cluster
	Snitch: org.apache.cassandra.locator.SimpleSnitch
	Partitioner: org.apache.cassandra.dht.Murmur3Partitioner
	Schema versions:
		127.0.0.1: [48c4e6c8-5d6a-3800-9a3a-517d3f7b2f26]"
2015-10-22 17:11:30 +03:00
Gleb Natapov
ece6c68288 convert loadBroadcaster 2015-10-22 17:10:20 +03:00
Avi Kivity
8362622eb8 Merge "Support Ubuntu 14.04LTS" from Takuya 2015-10-22 17:03:04 +03:00
Avi Kivity
0129e42b06 Merge "Mutation diff" from Paweł
"This series add code for computing mutation_partition difference.
For mutations A and B:

diffA = A.difference(B);
diffB = B.difference(A);
AB = A.apply(B);

diffA is the minimal mutation that when applied to B makes it equal
to AB and diffB is the minimal mutation that applied to A results in AB.

Fixes #430."
2015-10-22 16:38:25 +03:00
Avi Kivity
f7087da054 Merge "GET methods for snapshots" from Glauber
"The snapshots API need to expose GET methods so people can
query information on them. Now that taking snapshots is supported,
this relatively simple series implement get_snapshot_details, a
column family method, and wire that up through the storage_service."
2015-10-22 15:23:45 +03:00
Calle Wilund
05de462fa9 commitlog: Make flush/segment delete slightly mode defensive + test tolerant
Fix for (mainly) test failures (use-after free)
I.e. test case test_commitlog_delete_when_over_disk_limit causes
use-after free because test shuts down before a pending flush is done,
and the segment manager is actually gone -> crash writing stats.
Now, we could make the stats a shared pointer, but we should never
allow an operation to outlive the segment_manager.
In normal op, we _almost_ guarantee this with the shutdown() call,
but technically, we could have a flush continuation trailing somewhere.

* Make sure we never delete segments from segment_manager until they are
  fully flushed
* Make test disposal method "clear" be more defensive in flushing and
  clearing out segments
2015-10-22 15:19:24 +03:00
Avi Kivity
9dc8d98146 Merge "Make mutation queries respect reversed order" from Tomasz
"Affects CQL statements like the following one:

   select * from table order by ck desc;

Fixes #480."
2015-10-22 15:08:19 +03:00
Takuya ASADA
a03056a915 dist: add dependency packages and build script for ubuntu 2015-10-22 11:55:50 +00:00
Takuya ASADA
e0604b066a dist: add debian/ directory to build .deb package for Ubuntu 2015-10-22 11:55:50 +00:00
Takuya ASADA
592b64e478 dist: mount hugetlbfs on ubuntu 2015-10-22 11:55:50 +00:00
Takuya ASADA
830041d6be dist: share scripts both on redhat and ubuntu 2015-10-22 11:55:50 +00:00
Avi Kivity
a2577fefb9 Merge "Enable decommission support" from Asias
"Tested with:

- start node 1
- insert value
- start node 2
- insert value
- decommission node2

I can see from the log that data range belongs to node2 is streamed to node1
and cqlsh query node1 returns all the data, and node2 is not in the live node
list from node1's view."
2015-10-22 14:44:24 +03:00
Avi Kivity
5f3a46eabb Merge "load_new_sstables" from Glauber
"This patchset implements load_new_sstables, allowing one to move tables inside the
data directory of a CF, and then call "nodetool refresh" to start using them.

Keep in mind that for Cassandra, this is deemed an unsafe operation:
https://issues.apache.org/jira/browse/CASSANDRA-6245

It is still for us something we should not recommend - unless the CF is totally
empty and not yet used, but we can do a much better job in the safety front.

To guarantee that, the process works in four steps:

1) All writes to this specific column family are disabled. This is a horrible thing to
   do, because dirty memory can grow much more than desired during this. Throughout out
   this implementation, we will try to keep the time during which the writes are disabled
   to its bare minimum.

   While disabling the writes, each shard will tell us about the highest generation number
   it has seen.

2) We will scan all tables that we haven't seen before. Those are any tables found in the
   CF datadir, that are higher than the highest generation number seen so far. We will link
   them to new generation numbers that are sequential to the ones we have so far, and end up
   with a new generation number that is returned to the next step

3) The generation number computed in the previous step is now propagated to all CFs, which
   guarantees that all further writes will pick generation numbers that won't conflict with
   the existing tables. Right after doing that, the writes are resumed.

4) The tables we found in step 2 are passed on to each of the CFs. They can now load those
   tables while operations to the CF proceed normally."
2015-10-22 13:42:24 +03:00
Avi Kivity
2b0a504cbc Merge "Adding row chache statistic to column family" from Amnon
"This series adds row cache statistic to the column family that will be expose
via the API."
2015-10-22 13:38:01 +03:00
Paweł Dziepak
740e2166c5 tests/mutation: add test for mutation diff
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
f78a80dfa3 mutation_partition: add method for computing difference
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
85edc3de07 mutation_partition: compute row difference
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
75df23dd3c types: add collection_type_impl::difference()
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
4440f9b85b mutation_partition: add row_marker::is_live()
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
2aa96eb00f mutation_partition: add insert_row()
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
a064181d7c mutation_partition: add row::with_both_ranges()
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
1c05d7b927 mutation_partition: fix row_marker::apply() for equal timestamps
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Paweł Dziepak
7fab0ee867 mutation_partition: add compare_row_marker_for_merge()
A compare_atomic_cell_for_merge() equivalent intended to be used
with row markers.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:08:53 +02:00
Asias He
04291dec28 storage_service: Enable call to excise 2015-10-22 17:41:02 +08:00
Asias He
ee551d070f storage_service: Enable add_expire_time_if_found in excise and handle_state_removing 2015-10-22 17:41:02 +08:00
Asias He
2137ab5522 storage_service: Implement add_expire_time_if_found 2015-10-22 17:41:02 +08:00
Asias He
e2fbd146d7 storage_service: Print keyspace info unbootstrap in debug 2015-10-22 17:41:02 +08:00
Asias He
affab296b0 storage_service: Fix ranges in stream_hints
Use range = make_open_ended_both_sides to present the entire ring.
2015-10-22 17:41:02 +08:00
Asias He
0d2fb9c99d storage_service: Add extract_expire_time 2015-10-22 17:41:02 +08:00
Asias He
58225216b3 storage_service: Fix immediate return for get_changed_ranges_for_leaving
It is a leftover when get_changed_ranges_for_leaving is get stubbed.
2015-10-22 17:41:02 +08:00
Asias He
fb27d682ad storage_service: Fix use after free for stream_plan
sp is a stack variable, it is gone when the function returns.
Fix it using a shared pointer.
2015-10-22 17:41:02 +08:00
Asias He
69b7028f84 storage_service: Fix token contains in handle_state_leaving
std::includes requires sorted container. get_tokens_for returns
std::unordered_set. Fix by put tokens into std::set.
2015-10-22 17:41:02 +08:00
Asias He
4785798904 storage_service: Kill unimplemented in decommission 2015-10-22 17:41:02 +08:00
Asias He
ce6dd0f8f8 storage_service: Implement start_leaving 2015-10-22 17:41:02 +08:00
Paweł Dziepak
513ab87b47 row_cache: update hit and miss stats in scanning reader
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:25:02 +03:00
Paweł Dziepak
b1b830bcbb row_cache: merge cache_entry::compare and ring_position_compare
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-22 12:25:02 +03:00
Tomasz Grabiec
f1306d3771 tests: Add tests for reversed mutation queries 2015-10-22 10:32:08 +02:00
Tomasz Grabiec
cc5cc7117d mutation_query: Respect 'reversed' partition_slice option
Fixes #480
2015-10-22 10:32:08 +02:00
Tomasz Grabiec
9dbd5a92d0 partition_slice_builder: Introduce reversed() 2015-10-22 10:32:08 +02:00
Amnon Heiman
c130381284 Adding live_scanned and tombstone scaned histogram to column family
This series adds a histogrm to the column family for live scanned and
tombstone scaned.

It expose those histogram via the API instead of the stub implmentation,
currently exist.

The implementation update of the histogram will be added in a different
series.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 11:13:28 +03:00
Amnon Heiman
378a97b66b API: Add row cahe hits and miss per column family
Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-22 11:12:14 +03:00
Glauber Costa
fd8e5c7e4c api: load new sstables
Just a wrapper into the storage_service's homonymous call.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:30:04 +02:00
Glauber Costa
673788ed46 storage_service load_new_sstables.
This is the storage_service implementation of load_new_sstables, and this is
where most of the complication lives.

Keep in mind that for Cassandra, this is deemed an unsafe operation:
https://issues.apache.org/jira/browse/CASSANDRA-6245

It is still for us something we should not recommend - unless the CF is
totally empty and not yet used, but we can do a much better job in the safety front.

To guarantee that, the process works in four steps:

1) All writes to this specific column family are disabled. This is a horrible thing to
   do, because dirty memory can grow much more than desired during this. Throughout out
   this implementation, we will try to keep the time during which the writes are disabled
   to its bare minimum.

   While disabling the writes, each shard will tell us about the highest generation number
   it has seen.

2) We will scan all tables that we haven't seen before. Those are any tables found in the
   CF datadir, that are higher than the highest generation number seen so far. We will link
   them to new generation numbers that are sequential to the ones we have so far, and end up
   with a new generation number that is returned to the next step

3) The generation number computed in the previous step is now propagated to all CFs, which
   guarantees that all further writes will pick generation numbers that won't conflict with
   the existing tables. Right after doing that, the writes are resumed.

4) The tables we found in step 2 are passed on to each of the CFs. They can now load those
   tables while operations to the CF proceed normally.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
36cea4313e column family: load new sstables
CF-level code to load new SSTables. There isn't really a lot of complication
here. We don't even need to repopulate the entire SSTable directory: by
requiring that the external service who is coordinating this tell us explicitly
about the new SSTables found in the scan process, we can just load them
specifically and add them to the SSTable map.

All new tables will start their lifes as shared tables, and will be unshared
if it is possible to do so: this all happens inside add_sstable and there isn't
really anything special in this front.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
54aaa58899 sstable_tests: test reshuffle operation
Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
a8db2b28c7 sstable tests: test set_generation
No code works until it's been tested.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
c5950c7bf7 sstable_test: get rid of frees
They exist. They shouldn't.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
f60021f87f sstable_tests: commonize code to compare two components.
The current codes assumes a particular dir/generation pair. We
will use it for a more generic case. This code could really use some
clean up, by the way. We should do it later.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
61be9fb02d reshuffle tables: mechanism to adjust new sstables' generation number
Before loading new SSTables into the node, we need to make sure that their
generation numbers are sequential (at least if we want to follow Cassandra's
footsteps here).

Note that this is unsafe by design. More information can be found at:
https://issues.apache.org/jira/browse/CASSANDRA-6245

However, we can already to slightly better in two ways:

Unlike Cassandra, this method takes as a parameter a generation number. We
will not touch tables that are before that number at all. That number must be
calculated from all shards as the highest generation number they have seen themselves.
Calling load_new_sstables in the absence of new tables will therefore do nothing,
and will be completely safe.

It will also return the highest generation number found after the reshuffling
process.  New writers should start writing after that. Therefore, new tables
that are created will have a generation number that is higher than any of this,
and will therefore be safe.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
1351c1cc13 database: mechanism to stop writing sstables
During certain operations we need to stop writing SSTables. This is needed when
we want to load new SSTables into the system. They will have to be scanned by all
shards, agreed upon, and in most cases even renamed. Letting SSTables be written
at that point makes it inherently racy - specially with the rename.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:06:22 +02:00
Glauber Costa
29e2ad7fd8 column family: commonize code to calculate the desired SSTable generation
We will reuse this for load_new_sstables.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:43 +02:00
Glauber Costa
3f6d47f1f2 sstables: change the current level of an sstable
This will be used, for instance, when importing an SSTable.
We would like to force all new SSTables to sit at level 0 for
compaction purposes.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
e11b828b6f sstables: allow an sstable to set its generation number
In some situations (restoring a backup from load_new_sstables), we want to
change the SSTable generation number. This patch provides a procedure to
achieve that.

It does so by linking the old files to new ones, and then removing the old
ones.

The reason we link instead of removing, is that we want to make sure that in
case there is a crash in the middle, the old data is still accessible.

If the crash happens after the link is done but before we start removing the
old files, that is fine: we will end up with duplicated data that will
disappear after the next compaction.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
a4d8e99f1c sstables: fix create_links so a TemporaryTOC is generated
That is the way to generate groups of files for the SSTables, so we must do it.
Because the links were mostly used by processes like snapshots and backups
where and external tool would (hopefully) verify the results, it was not that
serious.

But we now plan to use links to bring things into the main directory. It must
absolutely be done right.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
876e770df6 sstables: allow create_links to work with an arbitrary generation
During some situations (restoring a snapshot for instance) we may want a file
to get a different generation. This patch changes the code in create_links
slightly, so that it is able to link not only to a different location, but to
files with a different name, possibly in the same location - that is equivalent
to a generation change.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
27efe8bde9 sstables: make read_toc public
This is done on behalf of load_new_sstables: we would like to know which
components are present in the file, but without triggering the read for the
rest of the metadata.

As noted by Avi, using this directly can leave the SSTable in an inconsistent
state. We will have to fix is later since this is not the first offender.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
fcebf6f72d sstable tests: don't use set_generation method
There is no reason aside from testing for a table to just change its generation
number.

There will be, however, when we support loading new sstables. The method
however needs to be completely rewritten, so let's make sure the tests are not
using that.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:02:42 +02:00
Glauber Costa
f3bad2032d database: fix type for sstable generation.
Avoid using long for it, and let's use a fixed size instead.  Let's do signed
instead of unsigned to avoid upsetting any code that we may have converted.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 18:01:20 +02:00
Calle Wilund
412c2a1e5b storage_proxy: mutate_atomically fix for consistency and BL removal
The change to use consistency_level::ONE in send_batchlog_mutation
sort of fixes #478, but is not 100% correct.
When doing async_remove_from_batchlog, the CL is actually supposed to
be ANY.

Also, we should _not_ remove the batch log mutation from any nodes
if the mutate fails, since having it there in case of failure is sort of
the whole point of it. I.e. async_remove_from_batchlog should not be
called from a "finally", but from a "then".

Refs #478
2015-10-21 16:48:27 +02:00
Tomasz Grabiec
764d913d84 Merge branch 'pdziepak/row-cache-range-query/v4' from seastar-dev.git
From Pawel:

This series enables row cache to serve range queries. In order to achieve
that row cache needs to know whether there are some other partitions in
the specified range that are not cached and need to be read from the sstables.
That information is provied by key_readers, which work very similarly to
mutation_readers, but return only the decorated key of partitions in
range. In case of sstables key_readers is implemented to use partition
index.

Approach like this has the disadvantage of needing to access the disk
even if all partitions in the range are cached. There are (at least) two
solutions ways of dealing with that problem:
 - cache partition index - that will also help in all other places where it
   is neededed
 - add a flag to cache_entry which, when set, indicates that the immediate
   successor of the partition is also in the cache. Such flag would be set
   by mutation reader and cleared during eviction. It will also allow
   newly created mutations from memtable to be moved to cache provided that
   both their successors and predecessors are already there.

The key_reader part of this patchsets adds a lot of new code that probably
won't be used in any other place, but the alternative would be to always
interleave reads from cache with reads from sstables and that would be
more heavy on partition index, which isn't cached.

Fixes #185.
2015-10-21 15:26:45 +02:00
Gleb Natapov
6a2a0d628b storage_proxy: use CL=ONE to write logged batch
This is a regression created by logged batch code rework.

Fixes #478.
2015-10-21 15:29:49 +03:00
Avi Kivity
c69c02c162 Merge 2015-10-21 15:17:32 +03:00
Avi Kivity
c49dd5c576 Merge "move dependencies to /opt/scylladb" from Takuya 2015-10-21 15:17:04 +03:00
Glauber Costa
71c1b2fe69 api: get true snapshot size
Thin wrapper around storage service's facility.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 13:48:44 +02:00
Glauber Costa
c0630bedc2 api: get_snapshot_details
That's basically conversion work between what the storage_service returns
and the json types.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 13:48:44 +02:00
Glauber Costa
cf96d68478 storage_service: true snapshot size
For CFStats, one of the things needed is the size used by the snapshots. Since
the bulk of the work is map-reducing it and adding them together, we will just
call get_snapshot_details for the column family, and just selectively add just
what we need. No need for a separate method here.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 13:48:44 +02:00
Glauber Costa
718fea7048 storage_service: get_snapshot_details
The column family object can, for each column family, provide us with a map between
each snapshots it knows about, and two sizes: the total size, and the "real" (or live)
size, which is how much extra space the snapshot is costing us.

This patch map-reduces all CFs to accumulate that system-wide, and then formats that
into an a map of "snapshot_details". That is a more convenient format to be consumed
by our json generator.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 13:48:44 +02:00
Glauber Costa
77513a40db database: get_snapshot_details
For each of the snapshots available, the api may query for some information:
the total size on disk, and the "real" size. As far as I could understand, the
real size is the size that is used by the SSTables themselves, while the total
size includes also the metadata about the snapshot - like the manifest.json
file.

Details follow:

In the original Cassandra code, total size is:

    long sizeOnDisk = FileUtils.folderSize(snapshot);

folderSize recurses on directories, and adds file.length() on files. Again, my
understanding is that file_size() would give us the same as the length() method
for Java.

The other value, real (or true) size is:

    long trueSize = getTrueAllocatedSizeIn(snapshot);

getTrueAllocatedSizeIn seems to be a tree walker, whose visitor is an instance
of TrueFilesSizeVisitor. What that visitor does, is add up the size of the files
within the tree who are "acceptable".

An acceptable file is a file which:

starts with the same prefix as we want (IOW, belongs to the same SSTable, we
will just test that directly), and is not "alive". The alive list is just the
list of all SSTables in the system that are used by the CFs.

What this tries to do, is to make sure that the trueSnapshotSize is just the
extra space on disk used by the snapshot. Since the snapshots are links, then
if a table goes away, it adds to this size. If it would be there anyway, it does
not.

We can do that in a lot simpler fashion: for each file, we will just look at
the original CF directory, and see if we can find the file there. If we can't,
then it counts towards the trueSize. Even for files that are deleted after
compaction, that "eventually" works, and that simplifies the code tremendously
given that we don't have to neither list all files in the system - as Cassandra
does - or go check other shards for liveness information - as we would have to
do.

The scheme I am proposing may need some tweaks when we support multiple data
directories, as the SSTables may not be directly below the snapshot level.
Still, it would be trivial to inform the CF about their possible locations.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-21 13:48:44 +02:00
Avi Kivity
16006949d0 logalloc: make migrator an object, not a function pointer
The migrator tells lsa how to move an object when it is compacted.
Currently it is a function pointer, which means we must know how to move
the object at compile time.  Making it an object allows us to build the
migration function at runtime, making it suitable for runtime-defined types
(such as tuples and user-defined types).

In the future, we may also store the size there for fixed-size types,
reducing lsa overhead.

C++ variable templates would have made this patch smaller, but unfortunately
they are only supported on gcc 5+.
2015-10-21 11:24:56 +02:00
Avi Kivity
e2cd40e3bc Merge "remove and decommission node support part 2" from Asias
"More preparatory patches for remove and decommission node support:

- stream hints and reanges
- unbootstrap
- replication finished notification"
2015-10-21 12:24:14 +03:00
Takuya ASADA
1bf18679bb dist: add more build dependency for binutils
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 09:02:40 +00:00
Takuya ASADA
613c7e8226 dist: use scylla-* dependency packages on scylla-server.spec
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
29847edd4e dist: move antlr3-C++-devel package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
ad80845a1d dist: move antlr3-tool package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
cb18a305db dist: move ragel package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
b4daf31fcf dist: move ninja-build package to /opt/scylladb, remove unused dependency for re2c
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
91005ba366 dist: move boost package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
2e379179d3 dist: move gcc package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
09099081e1 dist: move isl package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
18a6c25434 dist: move binutils package to /opt/scylladb
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
90666cf558 dist: add scylla-env package for CentOS, to use /opt/scylladb as prefix
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
659624a2ee dist: dependency fix for ninja-build
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Takuya ASADA
7340a5a83a dist: fix srpm not found error
Signed-off-by: Takuya ASADA <syuu@cloudius-systems.com>
2015-10-21 08:49:34 +00:00
Asias He
1271ad6894 storage_service: Implement send_replication_notification 2015-10-21 16:11:33 +08:00
Asias He
56e55cd272 storage_proxy: Register replication_finished verb handler 2015-10-21 16:11:33 +08:00
Asias He
ffce7a7af8 storage_service: Implement confirm_replication 2015-10-21 16:11:33 +08:00
Asias He
1965e8751b messaging_service: Add REPLICATION_FINISHED verb
It is used to send replication finished message by storage_service when
removing a node from a cluster.
2015-10-21 16:11:33 +08:00
Asias He
d903bd0dba storage_service: Implement on_leave_cluster in excise 2015-10-21 14:55:01 +08:00
Asias He
4f57f0cdae storage_service: Enable restore_replica_count in remove_node 2015-10-21 14:55:01 +08:00
Asias He
5b170d1ffe storage_service: Complete handle_state_removing
Implement #if 0'ed code.
2015-10-21 14:55:01 +08:00
Asias He
7d656fe127 storage_service: Enable add_leaving_endpoint in handle_state_leaving 2015-10-21 14:55:01 +08:00
Asias He
d3120b3c2f storage_service: Complete is_replacing logic in handle_state_normal 2015-10-21 14:55:01 +08:00
Asias He
434a9e211e storage_service: Kill one FIXME in handle_state_bootstrap
It is already fixed.
2015-10-21 14:55:01 +08:00
Asias He
6f8f4816a5 storage_service: Implement unbootstrap
All the missing functions for unbootstrap are ready, we can implement
unbootstrap now.
2015-10-21 14:55:01 +08:00
Asias He
8a9374b331 storage_service: Implement stream_hints
Needed by unbootstrap.
2015-10-21 14:55:01 +08:00
Asias He
3f5e9baa17 storage_service: Implement stream_ranges
Needed by unbootstrap.
2015-10-21 14:55:01 +08:00
Asias He
d1eaccd234 storage_service: Implement leave_ring
Needed by unbootstrap.
2015-10-21 14:55:01 +08:00
Asias He
2f86feb581 storage_service: Move send_replication_notification to source file 2015-10-21 14:55:01 +08:00
Avi Kivity
5453cfbab7 Merge "snapshots: take + clear" from Glauber
"This is the code for taking a snapshot, and clearing a snapshot."
2015-10-21 08:59:42 +03:00
Paweł Dziepak
2876c9ebc7 unimplemented: drop RANGE_QUERIES
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
c2b53c5282 row_cache: add scanning_and_populating_reader
This reader enables range queries on row cache. An underlying key_reader
is used to obtain information about partitions that belong to the
specified range and if any of them isn't in the cache an underlying
mutation reader is used to read the missing data.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
9abefbfa28 row_cache: add just_cache_scanning_reader
This mutation reader returns mutations from cache that are in a given
range. There may be other mutations in the system (e.g. in sstables)
that won't be returned, so this reader on its own cannot really satisfy
any query.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
c765b38599 row_cache: add modification counter
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
c1e95dd893 row_cache: pass underlying key_source to row_cache
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
6b73d6bb36 row_cache: add cache_entry::ring_position_compare
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
96a42a9c69 column_family: add sstables_as_key_source()
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
b0edaa5bb7 memtable: add as_key_source()
Needed only for tests.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:53 +02:00
Paweł Dziepak
68e1b1f613 tests/sstables: test sstable key_reader
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:47 +02:00
Paweł Dziepak
7fe6d2dc07 sstables: provide key_reader
In order to get just partition keys stored in the sstable its summary
and index are used.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:47 +02:00
Paweł Dziepak
ca278e6b52 tests/key_reader: add tests for key_readers
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:47 +02:00
Paweł Dziepak
7c480f29c3 key_reader: add filtering key reader
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:47 +02:00
Paweł Dziepak
e683d57768 key_reader: add key_from_mutation_reader
This is a wrapper that allows using mutation_reader as key_reader.
Useful mostly in tests.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:47 +02:00
Paweł Dziepak
5604830389 key_reader: add combined_reader
Combined key reader, just like its mutation equivalents, combines
output from multiple key_readers and provides a single sorted stream
of decorated keys.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:27:32 +02:00
Paweł Dziepak
1f0cb9066b add key_reader interface
key_readers provide an interface analogous to mutation_readers, but the
only data they return are decorated keys.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:26:54 +02:00
Paweł Dziepak
31341787e4 mutation: optimize mutation_opt
Since mutation stores all its data externally and the object itself is
basically just a std::unique_ptr<> there is no need for stdx::optional.
Smart pointer set to nullptr represents a disengaged mutation_opt.

Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:24:11 +02:00
Paweł Dziepak
aed403efc2 mutation_reader: move move_and_disengage to a separate header
Signed-off-by: Paweł Dziepak <pdziepak@scylladb.com>
2015-10-20 20:24:11 +02:00
Avi Kivity
cf734132e7 Merge "Flusing of CF:s without replay positions" from Calle
"Fixes: #469

We occasionally generate memtables that are not empty, yet have no
high replay_position set. (Typical case is CL replay, but apparently
there are others).

Moreover, we can do this repeatedly, and thus get caught in the flush
queue ordering restrictions.

Solve this by treating a flush without replay_position as a flush at the
highest running position, i.e. "last" in queue. Note that this will not
affect the actual flush operation, nor CL callbacks, only anyone waiting
for the operation(s) to complete.

To do this, the flush_queue had its restrictions eased, and some introspection
methods added."
2015-10-20 17:36:57 +03:00
Raphael S. Carvalho
93c1035f6e range: add comment explaining !start and !end in lambda
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-20 17:23:35 +03:00
Raphael S. Carvalho
c3a9d342f4 range: rename overlap to overlaps
overlaps() is more grammatical.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-20 17:23:35 +03:00
Avi Kivity
f4bd089b83 Merge "remove and decommission node" from Asias
"Preparatory patch for remove and decommission node support"
2015-10-20 17:00:04 +03:00
Glauber Costa
3a95a9cbe6 api: implement clear snapshot
Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:31 +02:00
Glauber Costa
19bb50f450 api: implement take_snapshot
Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:31 +02:00
Glauber Costa
21f84d77fc storage_service: delete a snapshot
This patch provides an storage service api to delete an snapshot.  Because all
keyspaces and CFs are visible in all shards. This will allow us to fetch the
list of keyspaces in the present shard and issue the filesystem operations in
that same shard.

That simplifies the code tremendously, and because there are not any operations
we need to do previous to the fs ones (like in the case of create snapshot), we
need no synchronization. Even easier.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:31 +02:00
Glauber Costa
2f2a4e83e0 storage_service: take a snapshot of a particular column family
Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:30 +02:00
Glauber Costa
fe3164714f storage_service: take a snapshot of a group of keyspaces
Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:30 +02:00
Glauber Costa
d236b01b48 snapshots: check existence of snapshots
We go to the filesystem to check if the snapshot exists. This should make us
robust against deletions of existing snapshots from the filesystem.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:58:26 +02:00
Glauber Costa
d3aef2c1a5 database: support clear snapshot
This allows for us to delete an existing snapshot. It works at the column
family level, and removing it from the list of keyspace snapshots needs to
happen only when all CFs are processed. Therefore, that is provided as a
separate operation.

The filesystem code is a bit ugly: it can be made better by making our file
lister more generic. First step would be to call it walker, not lister...

For now, we'll use the fact that there are mostly two levels in the snapshot
hierarchy to our advantage, and avoid a full recursion - using the same lambda
for all calls would require us to provide a separate class to handle the state,
that's part of making this generic.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:38:14 +02:00
Glauber Costa
500ee99c93 file lister: allow for more than one directory type
There are situations in which we would like to match more than one directory
type.  One example of that, would be a recursive delete operation: we need to
delete the files inside directories and the directories themselves, but we
still don't want a "delete all" since finding anything other than a directory
or a file is an error, and we should treat it as such.

Since there aren't that many times, it should be ok performance wise to just
use a list. I am using an unordered_set here just because it is easy enough,
but we could actually relax it later if needed. In any case, users of the
interface should not worry about that, and that decision is abstracted away
into lister::dir_entry_types.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-20 15:38:14 +02:00
Asias He
9e5ee17f4a storage_service: Implement rebuild 2015-10-20 21:32:30 +08:00
Asias He
31b50a83d1 storage_service: Implement excise 2015-10-20 21:32:30 +08:00
Asias He
0cf112501e storage_service: Implement restore_replica_count 2015-10-20 21:32:30 +08:00
Asias He
0ebcb1ddef storage_service: Stub send_replication_notification
Needed by restore_replica_count.
2015-10-20 21:32:30 +08:00
Asias He
1c480554eb storage_service: Stub get_new_source_ranges
Needed by restore_replica_count.
2015-10-20 21:32:30 +08:00
Asias He
955e766a49 storage_service: Partially implement decommission 2015-10-20 21:32:30 +08:00
Asias He
893849f8af storage_service: Stub unbootstrap 2015-10-20 21:32:30 +08:00
Asias He
9ebae12614 storage_service: Partially implement remove_node
restoreReplicaCount and excise are missing.
2015-10-20 21:32:30 +08:00
Asias He
142f29483a token_metadata: Implement add_leaving_endpoint 2015-10-20 21:32:30 +08:00
Asias He
f1bc882b90 storage_service: Implement get_changed_ranges_for_leaving 2015-10-20 21:32:30 +08:00
Asias He
937474bf14 abstract_replication_strategy: Make calculate_natural_endpoints public
It is used by storage_service.
2015-10-20 21:32:30 +08:00
Asias He
c5e35ac57e storage_service: Enable _replicating_nodes and _removing_node members 2015-10-20 21:32:30 +08:00
Asias He
f30fbd53ff storage_service: Start to use pending_range_calculator_service 2015-10-20 21:32:30 +08:00
Asias He
934c963d85 init: Init pending_range_calculator_service 2015-10-20 21:32:29 +08:00
Asias He
8d6200c036 service: Convert PendingRangeCalculatorService.java to C++ 2015-10-20 21:32:29 +08:00
Asias He
a5d91519f2 service: Import PendingRangeCalculatorService.java 2015-10-20 21:32:29 +08:00
Asias He
c96bc8bbd2 token_metadata: Implement calculate_pending_ranges 2015-10-20 21:32:14 +08:00
Asias He
a6065397d9 token_metadata: Implement clone_after_all_left 2015-10-20 20:38:43 +08:00
Avi Kivity
5abdc4323a Merge seastar upstream
* seastar 46fd389...6af5a0d (2):
  > sharded: do not try to call nonexistent delete callback
  > use real argv0 in dpdk initialization
2015-10-20 15:19:35 +03:00
Tomasz Grabiec
67d0f9c7df lsa: Restore heap invariant before calling _segments.erase()
This is certainly the right thing to do and seems to fix #403. However
I didn't manage to convince myself that this would cause problems for
binomial_heap, given that binomial_heap::erase() calls siftup()
anyway:

    void erase(handle_type handle)
    {
        node_pointer n = handle.node_;
        siftup(n, force_inf());
        top_element = n;
        pop();
    }

    void increase (handle_type handle)
    {
        node_pointer n = handle.node_;
        siftup(n, *this);

        update_top_element();
        sanity_check();
    }
2015-10-20 15:18:05 +03:00
Asias He
08b762111e storage_service: Fix ignored future in on_dead
All the on_xxx interface in i_endpoint_state_change_subscriber are
called within a seastar::async context.
2015-10-20 15:16:03 +03:00
Amnon Heiman
1e8752d55e API: Fix a confusion in the storage service snapshot details
There was a confusion between the snapshot key and the keyspace in the
snapshot details, this fixes it.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-20 13:53:09 +03:00
Avi Kivity
2575a4602e Merge "Fix for snapshots/create_links and shared SSTables" from Glauber
"Those are fixes needed for the snapshotting process itself. I have bundled this
in the create_snapshot series before to avoid a rebase, but since I will have to
rewrite that to get rid of the snapshot manager (and go to the filesystem),
I am sending those out on their own."
2015-10-20 13:49:17 +03:00
Pekka Enberg
3a3c7f7e79 configure.py: Propagate CFLAGS to seastar config
We need to propagate CFLAGS to seastar config for things like
DEBUG_SHARED_PTR to work.
2015-10-20 10:57:26 +03:00
Amnon Heiman
91d396760e API: add a workaround for the get schema_versions
This adds a workaround for the get schema_version, it will return only a
shcema version of the local node, this is a temporary workaround until
describe_schema_versions will be implemented.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-20 10:56:21 +03:00
Amnon Heiman
383d7ccf4d Add the get cluster and partitioner names to the API
This adds the implementation for the get cluster name and get
partitioner name to the storage_service API.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-20 10:54:55 +03:00
Amnon Heiman
77b4fc74cd gossiper need to set the cluster name on all shareds
The API can call any of the gossiper shareds to get the cluster name, so
the initilization needs to set it in all of them.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-20 10:52:14 +03:00
Amnon Heiman
ff67285091 gossiper: make the get cluster name and partitioner public
The API needs the cluster and the partitioner names, so the methods are
now public.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-20 10:21:19 +03:00
Calle Wilund
786d66cacf commitlog: Fix use-after-free
Remove "finally". Just use a then_wrapped. Which it was originally, before
"handle_exception" was introduced to seastar. Oh, the irony...
2015-10-20 09:56:40 +03:00
Calle Wilund
02732f19f2 database: Handle CF flush with no high replay_position
We occasionally generate memtables that are not empty, yet have no
high replay_position set. (Typical case is CL replay, but apparently
there are others).

Moreover, we can do this repeatedly, and thus get caught in the flush
queue ordering restrictions.

Solve this by treating a flush without replay_position as a flush at the
highest running position, i.e. "last" in queue. Note that this will not
affect the actual flush operation, nor CL callbacks, only anyone waiting
for the operation(s) to complete.
2015-10-20 08:24:04 +02:00
Calle Wilund
31fca82213 flush_queue_test: Add test for multiple ops per key 2015-10-20 08:24:04 +02:00
Calle Wilund
62c0be376c flush_queue: Ease key restriction and allow multiple calls on each key
As long as we guarantee that the execution order for the post ops are
upheld, we can allow insertion of multiple ops on the same key.

Implemented by adding a ref count to each position.

The restriction then becomes that an added key must either be larger
than any already existing key, _OR_ already exist. In the latter case,
we still know that we have not finished this position and signaled
"upwards".
2015-10-20 08:24:04 +02:00
Calle Wilund
ca451acb41 commitlog: Fix use-after-free
Remove "finally". Just use a then_wrapped. Which it was originally, before
"handle_exception" was introduced to seastar. Oh, the irony...
2015-10-20 08:02:46 +02:00
Avi Kivity
2ccb5feabd Merge "Support nodetool cfhistogram"
"This series adds the missing estimated histogram to the column family and to
the API so the nodetool cfhistogram would work."
2015-10-19 17:11:46 +03:00
Raphael S. Carvalho
28ef8feffa tests: fix test for leveled compaction
test_setup::do_with_test_directory is missing. For some reason,
the test wasn't failing without it until now. Adding it is the
correct thing to do anyway.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
2015-10-19 17:07:08 +03:00
Avi Kivity
f4706c7050 Merge "initial support to leveled compaction" from Raphael
"This patchset introduces leveled compaction to Scylla.
We don't handle all corner cases yet, but we already have the strategy
and compaction working as expected. Test cases were written and I also
tested the stability with a load of cassandra-stress.

Leveled compaction may output more than one sstable because there is
a limit on the size of sstables. 160M by default.
Related to handling of partial compaction, it's still something to be
worked on.

Anyway, it will not be a big problem. Why? Suppose that a leveled
compaction will generate 2 sstables, and scylla is interrupted after
the first sstable is completely written but before the second one is
completely written. The next boot will delete the second sstable,
because it was partially written, but will not do anything with the
first one as it was completely written.
As a result, we will have two sstables with redundant data."
2015-10-19 16:17:45 +03:00
Amnon Heiman
5998ee718a API: Add logger API implementation to the system API
This patch adds the ability to set one or all log levels get a log level
and get all logs name.

After this patch the following url will be available:
GET/POST
/system/logger
/system/logger/{name}

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-19 15:05:46 +03:00
Amnon Heiman
ba1e6adf2a Adding the system swagger definition
The system api will include system related command, currently it holds
the logger related API. It holds definition for the following commands:
get_all_logger_names
set_all_logger_level
get_logger_level
set_logger_level

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-19 14:59:54 +03:00
Amnon Heiman
521d9b62dd Add a level_name function to logger
This is a helper function that returns a log level name. It will be used
by the API to report the log levels.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-19 14:59:54 +03:00
Glauber Costa
218fdebbeb snapshot: do not allow exceptions in snapshot creation hang us
With the distribute-and-sync method we are using, if an exception happens in
the snapshot creation for any reason (think file permissions, etc), that will
just hang the server since our shard won't do the necessary work to
synchronize and note that we done our part (or tried to) in snapshot creation.

Make the then clause a finally, so that the sync part is always executed.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-19 13:37:02 +02:00
Glauber Costa
9083a0e5a7 snapshots: fix generation of snapshots with shared sstables
create_links will fail in one of the shards if one of the SSTables happen to be
shared. It should be fine if the link already exists, so let's just ignore that case.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-19 13:37:01 +02:00
Gleb Natapov
156f760663 storage_proxy: drop Origin's truncate code from comment
Drop already translated code.
2015-10-19 14:06:06 +03:00
Gleb Natapov
ae42ec7832 storage_proxy: actually sort endpoints in get_live_sorted_endpoints() 2015-10-19 13:38:37 +03:00
Avi Kivity
75ab27f683 Revert "Merge "move dependencies to /opt/scylladb" from Takuya"
This reverts commit c96b0453f2, reversing
changes made to b862165279e70300d29a075dc913523d56a616d2; there were some
extra commits on that branch.
2015-10-19 13:31:51 +03:00
Avi Kivity
c96b0453f2 Merge "move dependencies to /opt/scylladb" from Takuya
"This moves all dependency packages to /opt/scylladb."
2015-10-19 13:28:39 +03:00
Takuya ASADA
14fab1e36d dist: use scylla-* dependency packages on scylla-server.spec 2015-10-19 09:11:22 +00:00
Takuya ASADA
39e17e04bc dist: move antlr3-C++-devel package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
71182a0a95 dist: move antlr3-tool package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
1c7d8bc0e9 dist: move ragel package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
95c67a3e2e dist: move ninja-build package to /opt/scylladb, remove unused dependency for re2c 2015-10-19 09:11:22 +00:00
Takuya ASADA
ab8fe49b4f dist: move boost package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
2c7861b7ed dist: move gcc package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
23b69d610c dist: move isl package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
6db2ddc53b dist: move binutils package to /opt/scylladb 2015-10-19 09:11:22 +00:00
Takuya ASADA
f06e50a569 dist: add scylla-env package for CentOS, to use /opt/scylladb as prefix 2015-10-19 09:11:22 +00:00
Calle Wilund
b862165279 commitlog_test: Modify test_allocation_failure to not require huge segment
Explicitly use up all the memory in the system as best as we can instead
Still not super reliable, but should have less side effects. And work better
with pre-allocated segment files
2015-10-19 11:32:35 +03:00
Calle Wilund
681718f738 commitlog_test: Modify test_allocation_failure to not require huge segment
Explicitly use up all the memory in the system as best as we can instead
Still not super reliable, but should have less side effects. And work better
with pre-allocated segment files
2015-10-19 10:30:57 +02:00
Avi Kivity
eed43b276c tests: use workspace-local directory for commitlog
Can't rely on default /var/lib/scylla to be there or accessible.
2015-10-19 10:21:16 +02:00
Tomasz Grabiec
19d7d30e67 Replace references to 'urchin' with 'scylla' 2015-10-19 11:08:05 +03:00
Takuya ASADA
ca43a5f2ca dist: dependency fix for ninja-build 2015-10-19 06:59:15 +00:00
Takuya ASADA
721d0f9f64 dist: fix srpm not found error 2015-10-19 06:52:48 +00:00
Takuya ASADA
78813d9617 dist: create rpmbuild dirs 2015-10-19 06:51:03 +00:00
Vlad Zolotarov
7492b662c8 locator::gossiping_property_file_snitch: do_withicate file descriptor in property_file_was_modified()
file::stat() requires "this" to be valid will the end of the call.

Fixes issue #464

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-19 06:51:03 +00:00
Vlad Zolotarov
8c4ce0efee locator::production_snitch_base: fix production_snitch_base signature
Make production_snitch_base constructor signature consistent with
the rest of production snitches.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-19 06:51:03 +00:00
Vlad Zolotarov
4b8b3e7841 locator::production_snitch_base: cleanup
Don't keep the file descriptor beyond load_property_file() scope.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-19 06:51:03 +00:00
Vlad Zolotarov
9dfc08cf9f locator::gossiping_property_file_snitch: use empty string as a default config file name
A non-empty default value of a configuration file name was preventing
the db::config::get_conf_dir() to kick in when a default snitch constructor
was used (this is the way it's always used from scylla).

Fixes issue #459

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-19 06:51:03 +00:00
Avi Kivity
ce046d07da tests: create directories for user column families as well 2015-10-19 06:51:03 +00:00
Avi Kivity
f63002a75e tests: initialize system keyspace (and its directories) for cql_test_env
Now that columnb familiy directories are not created on demand, the tests
started to fail.
2015-10-19 06:51:03 +00:00
Raphael S. Carvalho
dfc95587d6 db: do not ignore compaction strategy class
When building the in-memory schema for a column family, we were
ignoring compaction strategy class because of a bug in the
existing code. Example: suppose that you create a column family
with leveled compaction strategy. This option would be ignored
and the default strategy (size-tiered) would be used instead.
Found this problem while working on leveled compaction.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-19 06:51:03 +00:00
Glauber Costa
c8a6883987 sstables: remove outdated comment
We already write all components. The FIXME is fixed.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-19 06:51:03 +00:00
Avi Kivity
dd2bf81131 tests: disable collectd
No need to blast collectd metrics during test runs.
2015-10-19 09:05:48 +03:00
Avi Kivity
268f7acd11 Merge snitch fixes from Vlad
"This series cleans up a few places in the snitches
code that has been noticed during the work on issues #464
and #459.

The last patch actually fixes the issue #464"
2015-10-18 17:21:30 +03:00
Vlad Zolotarov
fe5e983152 locator::gossiping_property_file_snitch: do_withicate file descriptor in property_file_was_modified()
file::stat() requires "this" to be valid will the end of the call.

Fixes issue #464

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-18 16:58:27 +03:00
Vlad Zolotarov
15606fc8d3 locator::production_snitch_base: fix production_snitch_base signature
Make production_snitch_base constructor signature consistent with
the rest of production snitches.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-18 16:58:27 +03:00
Vlad Zolotarov
5712aa4d48 locator::production_snitch_base: cleanup
Don't keep the file descriptor beyond load_property_file() scope.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-18 16:58:27 +03:00
Vlad Zolotarov
f113a57ba1 locator::gossiping_property_file_snitch: use empty string as a default config file name
A non-empty default value of a configuration file name was preventing
the db::config::get_conf_dir() to kick in when a default snitch constructor
was used (this is the way it's always used from scylla).

Fixes issue #459

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-18 16:56:12 +03:00
Avi Kivity
bb67258c68 tests: create directories for user column families as well 2015-10-18 14:45:42 +03:00
Avi Kivity
9fd73417ae tests: initialize system keyspace (and its directories) for cql_test_env
Now that columnb familiy directories are not created on demand, the tests
started to fail.
2015-10-18 12:25:36 +03:00
Raphael S. Carvalho
a21af32eed db: do not ignore compaction strategy class
When building the in-memory schema for a column family, we were
ignoring compaction strategy class because of a bug in the
existing code. Example: suppose that you create a column family
with leveled compaction strategy. This option would be ignored
and the default strategy (size-tiered) would be used instead.
Found this problem while working on leveled compaction.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-18 11:06:37 +03:00
Glauber Costa
f1c681de60 sstables: remove outdated comment
We already write all components. The FIXME is fixed.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-17 15:28:55 +03:00
Avi Kivity
82f3f76e74 Merge "remove on-demand creation of SSTable directory" from Glauber
"Let's do it better and create the directories when the tables are first
created."
2015-10-17 15:23:56 +03:00
Glauber Costa
c814be253a sstables: no longer touch directory when writing SSTables
After the previous two patches, the CF directory where the SSTable will live is
guaranteed to always exist: system CFs' are touched at boot while newly created
tables' are touched when the creation mutations are announced.

With that in place, there is no more need for the recursive touch in the
SSTables path.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-17 13:08:07 +02:00
Glauber Costa
c3e68ad5a4 guarantee that CF directories exist for system tables
This is done in a single shard, so it lives in main.cc

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-17 13:08:07 +02:00
Glauber Costa
e99e418238 schema_tables: make sure CF directory exists upon creation
In Cassandra, when you create a new column family, a directory for it
immediately appears under the KS directory.

In the past, we have made a decision to delay that creation until the first
SSTable is created, which works well in general.

There is a problem, however, for backup restoration: the standard procedure to
call loadNewSSTables is to do that in an empty directory. But the directory
simply won't be there until we create the first SSTable: bummer!

In the current incarnation of the code in schema_tables.cc, there is already
some code that runs on CPU0 only. That is a perfect place for the directory
creation. So let's do it.

After this patch, a directory for the CF appears right after the CF creation.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-17 13:08:07 +02:00
Glauber Costa
df857eb8c6 database: touch directories for the column family
Current code calls make_directory, which will fail if the directory already exists.
We didn't use this code path much before, but once we start creating CF directories
on CF creation - and not on SSTable creation, that will become our default method.

Use touch_directory instead

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-17 13:08:07 +02:00
Raphael S. Carvalho
e555ad6370 tests: add tests for leveled compaction
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-16 01:57:08 -03:00
Raphael S. Carvalho
06e9836a66 wire up support for leveled compaction strategy
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-16 01:57:04 -03:00
Raphael S. Carvalho
35b75e9b67 adapt compaction procedure to support leveled strategy
Adapt our compaction code to start writing a new sstable if the
one being written reached its maximum size. Leveled strategy works
with that concept. If a strategy other than leveled is being used,
everything will work as before.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-16 01:54:52 -03:00
Raphael S. Carvalho
fbec0d0254 convert LeveledManifest to C++
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-16 01:46:15 -03:00
Raphael S. Carvalho
683e29e0bd tests: add test for range overlap
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:34:58 -03:00
Raphael S. Carvalho
936575efd2 dht: introduce comparator for token
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:34:50 -03:00
Raphael S. Carvalho
24f9c2f85e range: add method to check if two ranges overlap
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:29:54 -03:00
Raphael S. Carvalho
cc2e0dc5d8 sstables: implement function to get sstable level
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:29:54 -03:00
Raphael S. Carvalho
b8e392e6fe sstables: add function to compare sstable by age
Leveled strategy prefers choosing older level-0 sstables as
candidates.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:29:50 -03:00
Raphael S. Carvalho
1d043936af sstables: add function to compare sstables by first key
Used by leveled strategy to sort a list of sstables with the
same level.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:25:08 -03:00
Raphael S. Carvalho
d4eb09704f sstables: add method to get first and last as decorated keys
Useful for leveled strategy which looks for overlapping sstables
by checking if token range overlaps.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:25:04 -03:00
Raphael S. Carvalho
0d8b4af9a0 import LeveledManifest.java
LeveledManifest implements the Leveled compaction strategy.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-15 19:24:58 -03:00
Avi Kivity
c8cc8a0b0f Merge seastar upstream
* seastar 8207f2c...46fd389 (1):
  > rwlock: drop extranous '}'
2015-10-15 17:19:28 +03:00
Gleb Natapov
f37979eeff Make exception string generation code less verbose 2015-10-15 17:14:51 +03:00
Gleb Natapov
510ed4a1a0 Fix operator<< for std::exception_ptr to receive reference to an object 2015-10-15 17:14:50 +03:00
Avi Kivity
bd5ca7b998 Merge seastar upstream
* seastar a2523ae...8207f2c (3):
  > rwlock: provide lock / unlock semantics
  > with_lock: run a function under a lock
  > rwlock: add documentation to the rwlock module
2015-10-15 17:02:50 +03:00
Calle Wilund
7d93861b28 commitlog_test: test fix
Fixes spurious failures in test_commitlog_discard_completed_segments
* Do explicit sync on all segments to prevent async flushed from keeping
  segements alive.
* Use counter instead of actual file counting to avoid racing with
  pre-allocation of segments
2015-10-15 17:01:11 +03:00
Amnon Heiman
1acd47ddce API: Adding implementation for the stream manager metrics
This adds an implementation for the stream manager metrics.

And the following url will be available:
/stream_manager/metrics/outbound
/stream_manager/metrics/incoming/{peer}
/stream_manager/metrics/incoming
/stream_manager/metrics/outgoing/{peer}
/stream_manager/metrics/outgoing

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-15 16:04:36 +03:00
Amnon Heiman
164ccd0525 API: Adding the stream manager Swagger definition
This adds the swagger definition file for the stream manager. The API is
based on the StreamManagerMBean and the StreamMetrics.
The following commands where added:
get_current_streams
get_current_streams_state
get_all_active_streams_outbound
get_total_incoming_bytes
get_all_total_incoming_bytes
get_total_outgoing_bytes
get_all_total_outgoing_bytes
2015-10-15 16:04:11 +03:00
Pekka Enberg
87fae37c9c dist/docker: Add missing "hostname" package
The Fedora base image has changed so we need to add "hostname" that's
used by the Docker-specific launch script to our image.

Fixes Scylla startup.

Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 13:46:53 +03:00
Avi Kivity
a611a235ee Merge "Flush queue bugfixes" from Calle
"Fixes the crashes in debug mode with the flush queue test, and
simplifies and cleans up the queue itself.

Aforementioned crashes happened due to reordering with the signalling
loop in previous version. A task completing could race with a reordered
loop continuation in who would get to signal and remove an item.

Rewritten to use much simpler promise chaining instead (which also allows
return value to propagate from Pre- to post op), ensuring only one actor
modifies the queue entry."
2015-10-15 13:04:40 +03:00
Avi Kivity
67eb176029 Merge "Invalidate CQL prepared statements on schema changes" from Pekka
"This series converts MigrationSubscriber to C++ and wires it up to
invalidate CQL prepared statements on schema changes that affect them."
2015-10-15 11:44:13 +03:00
Pekka Enberg
e77fbfe709 cql3/query_processor: Wire up migration subscriber
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 09:18:53 +03:00
Pekka Enberg
f659e7bc10 cql3: Convert MigrationSubscriber to C++
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 09:18:52 +03:00
Pekka Enberg
3a30486d30 cql3/query_processor: Implement invalidate_prepared_statement()
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 09:18:52 +03:00
Pekka Enberg
c80deeb6fe cql3/query_processor: Add get_query_processor() helper
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 09:18:52 +03:00
Pekka Enberg
1890d276b9 cql3: Add depends_on_{keyspace|column_family} helper to cql_statement
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-15 09:18:52 +03:00
Calle Wilund
ea0f3504c2 flush_queue_test: Clean up and enhance the test a little
Now also tests:

* Value propagation
* Queue wait
2015-10-15 02:15:24 +02:00
Calle Wilund
cd9f5e38f7 flush_queue: Fix task reordering bug, simplify code, allow value propagation
Previous version dit looping on post execution and signaling of waiters.
This could "race" with an op just finishing if task reordering happened.

This version simplifies the code significantly (and raises the question why
it was not written like this in the first place... Shame on me) by simpy
building a promise-dependency chain between _previous_ queue items and next
instead.

Also, the code now handles propagation of return value from the "Func" pre-op
to the "Post" op, with exceptions automatically handled.
2015-10-15 02:10:26 +02:00
Avi Kivity
849464670c commitlog: make new segments more xfs-friendly
xfs doesn't like writes beyond eof (exactly at eof is fine), and due
to continuation reordering, we sometimes do that.

Fix by pre-truncating the segment to its maximum size.
2015-10-14 17:32:59 +03:00
Calle Wilund
206acd8b5b commitlog: Make reader handle pre-allocated files
Silently ignore, and assume eof if reading zeroed file or chunk header data
Reading entries already deal with this.
2015-10-14 17:32:23 +03:00
Calle Wilund
2729d5dd71 commitlog: ensure file size remains <= max_size
Re-check file size overflow after each cycle() call (new buffer),
otherwise we could write more, in the case we are storing a mutation
larger than current buffer size (current pos + sizeof(mut) < max_size, but
after cycle required by sizeof(mut) > buf_remain, the former might not be
true anymore.
2015-10-14 17:32:22 +03:00
Avi Kivity
6a31daffd6 Merge "Unify logged and unlogged batch write code paths" from Gleb
"Logic duplication bothered me for a long time. This series consolidates both
cases as much as possible."
2015-10-14 17:26:40 +03:00
Gleb Natapov
19770268be storage_proxy: use common write code to write batch log mutations.
Reworks write code further so it can be used to write batch log
mutations.
2015-10-14 17:12:57 +03:00
Gleb Natapov
db49a196da storage_proxy: remove code duplication between logged and unlogged batches
Currently logged batch has most of the logic on unlogged batch
duplicated. This patch rework unlogged batch code in such a way that
it can be reused.
2015-10-14 17:12:57 +03:00
Gleb Natapov
c6644d5721 storage_proxy: remove outdated comment 2015-10-14 17:12:57 +03:00
Gleb Natapov
77ceeee2a8 storage_proxy: move array instead of copy it. 2015-10-14 17:12:57 +03:00
Avi Kivity
77daa7a59f Merge "Flush queue ordering" from Calle
"Adds a small utility queue and through this enforces memtable flush ordering
such that a flush may _run_ unchecked, however the "post" operation may
execute once all "lower numbered" (i.e. lower replay position) post ops
has finished.

This means that:
a.) Callbacks to commitlog are now guaranteed to fulfill ordering criteria
b.) Calling column_family::flush() and waiting for the result will also
     wait for any previously initiated flushes to finish. But not those
     initiated _after_."
2015-10-14 15:13:24 +03:00
Calle Wilund
012ab24469 column_family: Add flush queue object to act as ordering guarantee 2015-10-14 14:07:40 +02:00
Calle Wilund
d8658d4536 flush_queue_test
Small test to verify at least some integrity of the util in question
2015-10-14 14:07:39 +02:00
Calle Wilund
4540036a01 Add "flush_queue" helper structure
Small utility to order operation->post operation
so that the "post" step is guaranteed to only be run
when all "post"-ops for lower valued keys (T) have been completed

This is a generalized utility mainly to be testable.
2015-10-14 14:07:38 +02:00
Avi Kivity
ed2481db7f Merge branch-0.10 2015-10-14 15:03:19 +03:00
Asias He
c58ae5432c storage_service: Fix nodetool info return wrong gossiper status
Before:
$ nodetool info
ID                     : a5adfbbf-cfd8-4c88-ab6b-6a34ccc2857c
Gossip active          : false

After:
$ nodetool info
ID                     : a5adfbbf-cfd8-4c88-ab6b-6a34ccc2857c
Gossip active          : true

Fix #354.
2015-10-14 12:37:51 +03:00
Avi Kivity
1a439f2259 Merge seastar upstream
* seastar 78e3924...a2523ae (7):
  > core: fix pipe unread
  > Merge 'xfs-extents'
  > Merge "separate-dma-alignment"
  > output_stream: wait for stream to be taken out of poller in case final flush returns exception.
  > reactor: Use more widely compatible xfs include
  > readme: Add xfslibs-dev to Ubuntu deps
  > pipe: add unread() operation
2015-10-14 11:49:11 +03:00
Pekka Enberg
921dc9ab9f cql3: Add keyspace() and column_family() to select_statement
Signed-off-by: Pekka Enberg <penberg@scylladb.com>
2015-10-14 09:12:40 +03:00
Avi Kivity
cd6054253c Merge "fix consumer parser" from Raphael
Reviewed-by: Nadav Har'El <nyh@scylladb.com>
2015-10-13 18:53:27 +03:00
Raphael S. Carvalho
d05a5fbeb4 tests: add testcase for bug on consumer parser
problem described by commit:
3926748594

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-13 11:49:57 -03:00
Raphael S. Carvalho
3926748594 sstable: fix consumer parser
The first problem is the while loop around the code that processes prestate.
That's wrong because there may be a need to read more data before continuing
to process a prestate.
The second problem is the code assumption that a prestate will be processed
at once, and then unconditionally process the current state.
Both problems are likely to happen when reading a large buffer because more
than one read may be required.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-10-13 11:45:10 -03:00
Avi Kivity
c1cfec3e5a dht: mark boot_strapper logger static
Or it violates the ODR and causes link errors.
2015-10-13 16:42:42 +03:00
Tomasz Grabiec
11eb9a6260 range: Fix range::contains()
A range open-ended on both sides should contain all wrapping ranges.

Spotted by Avi.
2015-10-13 12:14:54 +03:00
Nadav Har'El
39f70a043d main: don't warn twice about the same directory
I was mildly annoyed by seeing two warnings about the same directory not
being XFS, when the sstable directory and the commitlog directory are the
same one (I don't know if this is typical, but this is what I do in all
my tests...). So I wrote this trivial patch to make sure not to test the
same directory twice.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-10-13 11:23:55 +03:00
Avi Kivity
eed11583cb Merge "Add node support" from Asias
"With this, a new node can stream data from existing nodes when joins the cluster.

I tested with the following:

  1) stat a node 1

  2) insert data into node 1

  3) start node 2

I can see from the logger that data is streamed correctly from node 1
to node 2."
2015-10-13 11:06:11 +03:00
Asias He
cf9d9e2ced boot_strapper: Enable range_streamer code in bootstrap
Add code to actually stream data from other nodes during bootstrap.

I tested with the following:

   1) stat a node 1

   2) insert data into node 1

   3) start node 2

I can see from the logger that data is streamed correctly from node 1
to node 2.
2015-10-13 15:54:18 +08:00
Asias He
0d1e5c3961 boot_strapper: Add debug info for get_bootstrap_tokens
Print the token generated for the node who is bootstrapping.
2015-10-13 15:48:53 +08:00
Asias He
e92a759dad locator: Add debug info for abstract_replication_strategy::get_address_ranges
It is useful to check relations between token and its primary range.
2015-10-13 15:46:36 +08:00
Asias He
dc02d76aee range_streamer: Implement fetch_async
It is used by boot_strapper::bootstrap() in bootstrap process to start
the streaming.
2015-10-13 15:45:56 +08:00
Asias He
887c0a36ec range_streamer: Implement add_ranges
It is used by boot_strapper::bootstrap() in bootstrap process.
2015-10-13 15:45:56 +08:00
Asias He
1c1f9bed09 range_streamer: Implement use_strict_sources_for_ranges 2015-10-13 15:45:55 +08:00
Asias He
43d4e62b5a range_streamer: Implement add_source_filter 2015-10-13 15:45:55 +08:00
Asias He
d47ea88aa8 range_streamer: Implement get_all_ranges_with_strict_sources_for 2015-10-13 15:45:55 +08:00
Asias He
84de936e43 range_streamer: Implement get_all_ranges_with_sources_for 2015-10-13 15:45:55 +08:00
Asias He
944e28cd6c range_streamer: Implement get_range_fetch_map 2015-10-13 15:45:55 +08:00
Asias He
d986a4d875 range_streamer: Add constructor 2015-10-13 15:45:55 +08:00
Asias He
1d6c081766 range_streamer: Add i_source_filter and failure_detector_source_filter
It is used to filter out unwanted node.
2015-10-13 15:45:55 +08:00
Asias He
c8b9a6fa06 dht: Convert RangeStreamer to C++ 2015-10-13 15:45:55 +08:00
Asias He
b95521194e dht: Import dht/RangeStreamer 2015-10-13 15:45:55 +08:00
Asias He
b1c92f377d token_metadata: Add get_pending_ranges
One version returns only the ranges
   std::vector<range<token>>

Another version returns a map
   std::unordered_map<range<token>, std::unordered_set<inet_address>>
which is converted from
   std::unordered_multimap<range<token>, inet_address>

They are needed by token_metadata::pending_endpoints_for,
storage_service::get_all_ranges_with_strict_sources_for and
storage_service::decommission.
2015-10-13 15:45:55 +08:00
Asias He
b860f6a393 token_metadata: Add get_pending_ranges_mm
Helper for get_pending_ranges.
2015-10-13 15:45:55 +08:00
Asias He
c96d826fe0 token_metadata: Introduce _pending_ranges member 2015-10-13 15:45:55 +08:00
Asias He
da072b8814 token_metadata: Remove duplicated sortedTokens
It is implemented already.
2015-10-13 15:45:55 +08:00
Asias He
d820c83141 locator: Add abstract_replication_strategy::get_pending_address_ranges
Given the current token_metadata and the new token which will be
inserted into the ring after bootstrap, calculate the ranges this new
node will be responsible for.

This is needed by boot_strapper::bootstrap().
2015-10-13 15:45:55 +08:00
Asias He
1adb27e283 token_metadata: Add clone_only_token_map
Needed by get_pending_address_ranges.
2015-10-13 15:45:55 +08:00
Asias He
527edd69ae locator: Add abstract_replication_strategy::get_range_addresses
Needed by range_streamer::get_all_ranges_with_sources_for.
2015-10-13 15:45:55 +08:00
Asias He
044dcf43de locator: Add abstract_replication_strategy::get_address_ranges
Needed by get_pending_address_ranges.
2015-10-13 15:45:55 +08:00
Asias He
3d0d02816d token_metadata: Add get_primary_ranges_for and get_primary_range_for
Given tokens, return ranges the tokens present. For example, with t1 and
t2, it returns ranges:

(token before t1, t1]
(token before t2, t2]
2015-10-13 15:45:55 +08:00
Asias He
542b1394d7 token_metadata: Add get_predecessor
It is used to get the previous token of this token in the ring.
2015-10-13 15:45:55 +08:00
Asias He
ddfd417c13 locator: Make calculate_natural_endpoints take extra token_metadata parameter
When adding/removing a node, we need to use a temporary token_metadata
with pending tokens.
2015-10-13 15:45:55 +08:00
Asias He
7959c12073 stream_session: Support column_families is empty case
An empty column_families means to get all the column families.
2015-10-13 15:44:59 +08:00
Tomasz Grabiec
a383f91b68 range: Implement range::contains() which takes another range 2015-10-13 15:44:36 +08:00
Avi Kivity
0498cebc58 Merge seastar upstream
* seastar c2e86d5...78e3924 (2):
  > fix output stream batching
  > rpc: server connection shutdown fix

Adjust transport/server.cc for the demise of output_stream::batch_flush()
2015-10-12 14:00:40 +03:00
Avi Kivity
b8c8473505 Merge seastar upstream
* seastar 1995676...c2e86d5 (3):
  > doc: add Seastar tutorial
  > resource: increase default reserve memory
  > http client: moved http_response_parser.rl from apps/seawreck into http directory
2015-10-12 10:29:10 +03:00
Amnon Heiman
6fd3c81db5 keyspace clean up should be a POST not a GET 2015-10-11 15:51:56 +03:00
Avi Kivity
e252475e67 Merge "locator: Adding EC2Snitch" from Vlad
"This series adds EC2Snich.

Since both GossipingPropertyFileSnitch and EC2SnitchXXX snitches family
are using the same property file it was logical to share the corresponding
code. Most of this series does just that... "
2015-10-11 14:55:26 +03:00
Glauber Costa
f03480c054 avoid exception when processing caching_options
While trying to debug an unrelated bug, I was annoyed by the fact that parsing
caching options keep throwing exceptions all the time. Those exceptions have no
reason to happen: we try to convert the value to a number, and if we fail we
fall back to one of the two blessed strings.

We could just as easily just test for those strings beforehand and avoid all of
that.

While we're on it, the exception message should show the value of "r", not "k".

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-11 14:53:55 +03:00
Avi Kivity
2b87c8c372 build: allow defaulting test binaries not to strip debug information
Useful for continuous integration, which has enough disk space.
2015-10-11 12:25:20 +03:00
Glauber Costa
b2fef14ada do not calculate truncation time independently
Currently, we are calculating truncated_at during truncate() independently for
each shard. It will work if we're lucky, but it is fairly easy to trigger cases
in which each shard will end up with a slightly different time.

The main problem here, is that this time is used as the snapshot name when auto
snapshots are enabled. Previous to my last fixes, this would just generate two
separate directories in this case, which is wrong but not severe.

But after the fix, this means that both shards will wait for one another to
synchronize and this will hang the database.

Fix this by making sure that the truncation time is calculated before
invoke_on_all in all needed places.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-09 17:17:11 +03:00
Vlad Zolotarov
c30c1bb1ec tests: added ec2_snitch_test
Checks the following:
   - That EC2Snich is able to receive the availability zone from EC2.
   - That the resulting DC and RACK values are distributed among all
     shards.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:20 +03:00
Vlad Zolotarov
38f77bbfe5 locator: add ec2_snitch
This snitch will read the EC2 availability zone and set the DC
and RACK as follows:

If availability zone is "us-east-1d", then
DC="us-east" and  RACK="1d".

If cassandra-rackdc.properties contains "dc_suffix" field then
DC will be appended with its value.

For instance if dc_suffix=_1_cassandra, then in the example above

DC=us-east_1_cassandra

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:20 +03:00
Vlad Zolotarov
1d63ec4143 conf: added cassandra-rackdc.properties
This is a configuration file used by GossipingPropertyFileSnitch and
EC2SnitchXXX snitches family.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:20 +03:00
Vlad Zolotarov
afd44a6e08 locator::gossiping_property_file_snitch: initialize i_endpoint_snitch::io_cpu_id() in the constructor
This is just cleaner.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
2febae90c9 locator::production_snitch_base: unify property file parsing facilities
- Move property file parsing code into production_snitch_base class.
   - Make a parsing code more general:
      - Save the parsed keys in the hash table.
      - Check only two types of errors:
         - Repeating keys.
         - Add a set of all supported keys and add the check for a key
           being supported.
   - Added production_snitch_base.cc file.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
2db219f074 locator::gossiping_property_file_snitch: remove extra "namespace locator"
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
0cfdca55f3 locator::gossiping_property_file_snitch: make get_name() public as it should be
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
ba68436f2f locator::gossiping_property_file_snitch: get rid of warn() and err() wrappers
Use logger() accessor instead for a better resemblance with the Origin.

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
d196b034e2 locator::snitch_base: Add a default snitch_base::stop() method
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
2015-10-08 20:57:19 +03:00
Vlad Zolotarov
de6cf8db51 db::config: add get_conf_dir()
This function returns the directory containing the configuration
files. It takes into an account the evironment variables as follows:
   - If SCYLLA_CONF is defines - this is the directory
   - else if SCYLLA_HOME is defines, then $SCYLLA_HOME/conf is the directory
   - else "conf" is a directory, namely the configuration files should be
     looked at ./conf

Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>

New in v2:
   - Updated get_conf_dir() description.
2015-10-08 20:57:11 +03:00
Avi Kivity
0c8f906b2d Merge "Fixes for snapshots" from Glauber 2015-10-08 18:21:54 +03:00
Glauber Costa
1549a43823 snapshots: fix json type
We are generating a general object ({}), whereas Cassandra 2.1.x generates an
array ([]). Let's do that as well to avoid surprising parsers.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-08 16:54:51 +02:00
Glauber Costa
cc343eb928 snapshots: handle jsondir creation for empty files case
We still need to write a manifest when there are no files in the snapshot.
But because we have never reached the touch_directory part in the sstables
loop for that case, nobody would have created jsondir in that case.

Since now all the file handling is done in the seal_snapshot phase, we should
just make sure the directory exists before initiating any other disk activity.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-08 16:54:51 +02:00
Glauber Costa
efdfc78c0c snapshots: get rid of empty tables optimization
We currently have one optimization that returns early when there are no tables
to be snapshotted.

However, because of the way we are writing the manifest now, this will cause
the shard that happens to have tables to be waiting forever. So we should get
rid of it. All shards need to pass through the synchronization point.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-08 16:54:51 +02:00
Glauber Costa
0776ca1c52 snapshots: don't hash pending snapshots by snapshot name
If we are hashing more than one CF, the snapshot themselves will all have the same name.
This will cause the files from one of them to spill towards the other when writing the manifest.

The proper hash is the jsondir: that one is unique per manifest file.

Signed-off-by: Glauber Costa <glommer@scylladb.com>
2015-10-08 16:54:51 +02:00
Avi Kivity
e7f58491c3 version: mark master branch as development version 2015-10-08 15:31:50 +03:00
Amnon Heiman
0ec0a5703b API: column family estimated histograms
This patch fix an issue with the read latency estimated historam
implementation and add a call to the estimated number of sstable
histogram.

The later is not yet implemented on the datbase side.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-08 14:59:17 +03:00
Amnon Heiman
6d90eebfb9 column family: Add estimated histogram impl
This patch adds the read and write latency estimated histogram support
and add an estimatd histogram to the number of sstable that were used in
a read.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-08 14:59:17 +03:00
Amnon Heiman
9c16b56b65 estimated_histogram to support sampling
Taking time messurment of an operation can cause peformence degredation,
this patch adds sampling support for the estimated histogram.

It allows to add a sample with a counter that holds what is the actual
total number so far. So the samplling will be counted as multiple
entries in the estimated histogram.

The totatl count of the entries in the histogram will equal the _count
parameter.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-10-08 14:59:17 +03:00
252 changed files with 13149 additions and 3184 deletions

View File

@@ -1,6 +1,6 @@
#!/bin/sh
VERSION=0.10
VERSION=0.11.1
if test -f version
then

View File

@@ -26,6 +26,25 @@
}
]
},
{
"path":"/compaction_manager/compaction_history",
"operations":[
{
"method":"GET",
"summary":"get List of the compaction history",
"type":"array",
"items":{
"type":"history"
},
"nickname":"get_compaction_history",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/compaction_manager/compaction_summary",
"operations":[
@@ -181,6 +200,43 @@
"description":"A list of key, value mapping"
}
}
},
"history": {
"id":"history",
"description":"Compaction history information",
"properties":{
"id":{
"type":"string",
"description":"The UUID"
},
"cf":{
"type":"string",
"description":"The column family name"
},
"ks":{
"type":"string",
"description":"The keyspace name"
},
"compacted_at":{
"type":"long",
"description":"The time of compaction"
},
"bytes_in":{
"type":"long",
"description":"Bytes in"
},
"bytes_out":{
"type":"long",
"description":"Bytes out"
},
"rows_merged":{
"type":"array",
"items":{
"type":"mapper"
},
"description":"The merged rows"
}
}
}
}
}
}

View File

@@ -193,8 +193,8 @@
"operations":[
{
"method":"GET",
"summary":"Get the RPC timeout",
"type":"long",
"summary":"Get the RPC timeout in seconds",
"type":"double",
"nickname":"get_rpc_timeout",
"produces":[
"application/json"
@@ -214,10 +214,10 @@
"parameters":[
{
"name":"timeout",
"description":"Timeout in millis",
"description":"Timeout in seconds",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -229,8 +229,8 @@
"operations":[
{
"method":"GET",
"summary":"Get the read RPC timeout",
"type":"long",
"summary":"Get the read RPC timeout in seconds",
"type":"double",
"nickname":"get_read_rpc_timeout",
"produces":[
"application/json"
@@ -250,10 +250,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout_in_millis",
"description":"The timeout in second",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -265,8 +265,8 @@
"operations":[
{
"method":"GET",
"summary":"Get the write RPC timeout",
"type":"long",
"summary":"Get the write RPC timeout in seconds",
"type":"double",
"nickname":"get_write_rpc_timeout",
"produces":[
"application/json"
@@ -286,10 +286,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout in millisecond",
"description":"timeout in seconds",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -301,8 +301,8 @@
"operations":[
{
"method":"GET",
"summary":"Get counter write rpc timeout",
"type":"long",
"summary":"Get counter write rpc timeout in seconds",
"type":"double",
"nickname":"get_counter_write_rpc_timeout",
"produces":[
"application/json"
@@ -322,10 +322,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout in millisecond",
"description":"timeout in seconds",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -337,8 +337,8 @@
"operations":[
{
"method":"GET",
"summary":"Get CAS contention timeout",
"type":"long",
"summary":"Get CAS contention timeout in seconds",
"type":"double",
"nickname":"get_cas_contention_timeout",
"produces":[
"application/json"
@@ -358,10 +358,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout in millisecond",
"description":"timeout in second",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -373,8 +373,8 @@
"operations":[
{
"method":"GET",
"summary":"Get range rpc timeout",
"type":"long",
"summary":"Get range rpc timeout in seconds",
"type":"double",
"nickname":"get_range_rpc_timeout",
"produces":[
"application/json"
@@ -394,10 +394,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout in millisecond",
"description":"timeout in second",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -409,8 +409,8 @@
"operations":[
{
"method":"GET",
"summary":"Get truncate rpc timeout",
"type":"long",
"summary":"Get truncate rpc timeout in seconds",
"type":"double",
"nickname":"get_truncate_rpc_timeout",
"produces":[
"application/json"
@@ -430,10 +430,10 @@
"parameters":[
{
"name":"timeout",
"description":"timeout in millisecond",
"description":"timeout in second",
"required":true,
"allowMultiple":false,
"type":"long",
"type":"double",
"paramType":"query"
}
]
@@ -717,7 +717,7 @@
]
},
{
"path": "/storage_proxy/metrics/read/latency/histogram",
"path": "/storage_proxy/metrics/read/histogram",
"operations": [
{
"method": "GET",
@@ -732,7 +732,7 @@
]
},
{
"path": "/storage_proxy/metrics/range/latency/histogram",
"path": "/storage_proxy/metrics/range/histogram",
"operations": [
{
"method": "GET",
@@ -807,7 +807,7 @@
]
},
{
"path": "/storage_proxy/metrics/write/latency/histogram",
"path": "/storage_proxy/metrics/write/histogram",
"operations": [
{
"method": "GET",
@@ -820,7 +820,103 @@
"parameters": []
}
]
}
},
{
"path":"/storage_proxy/metrics/read/estimated_histogram/",
"operations":[
{
"method":"GET",
"summary":"Get read estimated latency",
"$ref":"#/utils/estimated_histogram",
"nickname":"get_read_estimated_histogram",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/storage_proxy/metrics/read",
"operations":[
{
"method":"GET",
"summary":"Get read latency",
"type":"int",
"nickname":"get_read_latency",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/storage_proxy/metrics/write/estimated_histogram/",
"operations":[
{
"method":"GET",
"summary":"Get write estimated latency",
"$ref":"#/utils/estimated_histogram",
"nickname":"get_write_estimated_histogram",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/storage_proxy/metrics/write",
"operations":[
{
"method":"GET",
"summary":"Get write latency",
"type":"int",
"nickname":"get_write_latency",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/storage_proxy/metrics/range/estimated_histogram/",
"operations":[
{
"method":"GET",
"summary":"Get range estimated latency",
"$ref":"#/utils/estimated_histogram",
"nickname":"get_range_estimated_histogram",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/storage_proxy/metrics/range",
"operations":[
{
"method":"GET",
"summary":"Get range latency",
"type":"int",
"nickname":"get_range_latency",
"produces":[
"application/json"
],
"parameters":[
]
}
]
}
],
"models":{
"mapper_list":{

View File

@@ -609,7 +609,7 @@
"path":"/storage_service/keyspace_cleanup/{keyspace}",
"operations":[
{
"method":"GET",
"method":"POST",
"summary":"Trigger a cleanup of keys on a single keyspace",
"type":"int",
"nickname":"force_keyspace_cleanup",
@@ -890,8 +890,8 @@
],
"parameters":[
{
"name":"token",
"description":"The token to remove",
"name":"host_id",
"description":"Remove the node with host_id from the cluster",
"required":true,
"allowMultiple":false,
"type":"string",
@@ -1969,9 +1969,9 @@
"id":"snapshot",
"description":"Snapshot detail",
"properties":{
"key":{
"ks":{
"type":"string",
"description":"The key snapshot key"
"description":"The key space snapshot key"
},
"cf":{
"type":"string",
@@ -1993,7 +1993,7 @@
"properties":{
"key":{
"type":"string",
"description":"The keyspace"
"description":"The snapshot key"
},
"value":{
"type":"array",

View File

@@ -25,6 +25,102 @@
]
}
]
},
{
"path":"/stream_manager/metrics/outbound",
"operations":[
{
"method":"GET",
"summary":"Get number of active outbound streams",
"type":"int",
"nickname":"get_all_active_streams_outbound",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/stream_manager/metrics/incoming/{peer}",
"operations":[
{
"method":"GET",
"summary":"Get total incoming bytes",
"type":"int",
"nickname":"get_total_incoming_bytes",
"produces":[
"application/json"
],
"parameters":[
{
"name":"peer",
"description":"The stream peer",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"path"
}
]
}
]
},
{
"path":"/stream_manager/metrics/incoming",
"operations":[
{
"method":"GET",
"summary":"Get all total incoming bytes",
"type":"int",
"nickname":"get_all_total_incoming_bytes",
"produces":[
"application/json"
],
"parameters":[
]
}
]
},
{
"path":"/stream_manager/metrics/outgoing/{peer}",
"operations":[
{
"method":"GET",
"summary":"Get total outgoing bytes",
"type":"int",
"nickname":"get_total_outgoing_bytes",
"produces":[
"application/json"
],
"parameters":[
{
"name":"peer",
"description":"The stream peer",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"path"
}
]
}
]
},
{
"path":"/stream_manager/metrics/outgoing",
"operations":[
{
"method":"GET",
"summary":"Get all total outgoing bytes",
"type":"int",
"nickname":"get_all_total_outgoing_bytes",
"produces":[
"application/json"
],
"parameters":[
]
}
]
}
],
"models":{

114
api/api-doc/system.json Normal file
View File

@@ -0,0 +1,114 @@
{
"apiVersion":"0.0.1",
"swaggerVersion":"1.2",
"basePath":"{{Protocol}}://{{Host}}",
"resourcePath":"/system",
"produces":[
"application/json"
],
"apis":[
{
"path":"/system/logger",
"operations":[
{
"method":"GET",
"summary":"Get all logger names",
"type":"array",
"items":{
"type":"string"
},
"nickname":"get_all_logger_names",
"produces":[
"application/json"
],
"parameters":[
]
},
{
"method":"POST",
"summary":"Set all logger level",
"type":"void",
"nickname":"set_all_logger_level",
"produces":[
"application/json"
],
"parameters":[
{
"name":"level",
"description":"The new log level",
"required":true,
"allowMultiple":false,
"type":"string",
"enum":[
"error",
"warn",
"info",
"debug",
"trace"
],
"paramType":"query"
}
]
}
]
},
{
"path":"/system/logger/{name}",
"operations":[
{
"method":"GET",
"summary":"Get logger level",
"type":"string",
"nickname":"get_logger_level",
"produces":[
"application/json"
],
"parameters":[
{
"name":"name",
"description":"The logger to query about",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"path"
}
]
},
{
"method":"POST",
"summary":"Set logger level",
"type":"void",
"nickname":"set_logger_level",
"produces":[
"application/json"
],
"parameters":[
{
"name":"name",
"description":"The logger to query about",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"path"
},
{
"name":"level",
"description":"The new log level",
"required":true,
"allowMultiple":false,
"type":"string",
"enum":[
"error",
"warn",
"info",
"debug",
"trace"
],
"paramType":"query"
}
]
}
]
}
]
}

View File

@@ -38,6 +38,7 @@
#include "hinted_handoff.hh"
#include "http/exception.hh"
#include "stream_manager.hh"
#include "system.hh"
namespace api {
@@ -108,6 +109,10 @@ future<> set_server(http_context& ctx) {
rb->register_function(r, "stream_manager",
"The stream manager API");
set_stream_manager(ctx, r);
rb->register_function(r, "system",
"The system related API");
set_system(ctx, r);
});
}

View File

@@ -370,7 +370,7 @@ void set_column_family(http_context& ctx, routes& r) {
});
cf::get_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
return get_cf_histogram(ctx, req->param["name"], &column_family::stats::reads);
return get_cf_histogram(ctx, req->param["name"], &column_family::stats::writes);
});
cf::get_all_write_latency_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
@@ -615,30 +615,29 @@ void set_column_family(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(0);
});
cf::get_row_cache_hit.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
//auto id = get_uuid(req->param["name"], ctx.db.local());
return make_ready_future<json::json_return_type>(0);
cf::get_row_cache_hit.set(r, [&ctx] (std::unique_ptr<request> req) {
return map_reduce_cf(ctx, req->param["name"], 0, [](const column_family& cf) {
return cf.get_row_cache().stats().hits;
}, std::plus<int64_t>());
});
cf::get_all_row_cache_hit.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
cf::get_all_row_cache_hit.set(r, [&ctx] (std::unique_ptr<request> req) {
return map_reduce_cf(ctx, 0, [](const column_family& cf) {
return cf.get_row_cache().stats().hits;
}, std::plus<int64_t>());
});
cf::get_row_cache_miss.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
//auto id = get_uuid(req->param["name"], ctx.db.local());
return make_ready_future<json::json_return_type>(0);
cf::get_row_cache_miss.set(r, [&ctx] (std::unique_ptr<request> req) {
return map_reduce_cf(ctx, req->param["name"], 0, [](const column_family& cf) {
return cf.get_row_cache().stats().misses;
}, std::plus<int64_t>());
});
cf::get_all_row_cache_miss.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
cf::get_all_row_cache_miss.set(r, [&ctx] (std::unique_ptr<request> req) {
return map_reduce_cf(ctx, 0, [](const column_family& cf) {
return cf.get_row_cache().stats().misses;
}, std::plus<int64_t>());
});
cf::get_cas_prepare.set(r, [] (std::unique_ptr<request> req) {
@@ -662,41 +661,19 @@ void set_column_family(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(0);
});
cf::get_sstables_per_read_histogram.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
//auto id = get_uuid(req->param["name"], ctx.db.local());
std::vector<double> res;
return make_ready_future<json::json_return_type>(res);
cf::get_sstables_per_read_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
return map_reduce_cf(ctx, req->param["name"], sstables::estimated_histogram(0), [](column_family& cf) {
return cf.get_stats().estimated_sstable_per_read;
},
sstables::merge, utils_json::estimated_histogram());
});
cf::get_tombstone_scanned_histogram.set(r, [] (std::unique_ptr<request> req) {
//TBD
// FIXME
//auto id = get_uuid(req->param["name"], ctx.db.local());
httpd::utils_json::histogram res;
res.count = 0;
res.mean = 0;
res.max = 0;
res.min = 0;
res.sum = 0;
res.variance = 0;
return make_ready_future<json::json_return_type>(res);
cf::get_tombstone_scanned_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
return get_cf_histogram(ctx, req->param["name"], &column_family::stats::tombstone_scanned);
});
cf::get_live_scanned_histogram.set(r, [] (std::unique_ptr<request> req) {
//TBD
// FIXME
//auto id = get_uuid(req->param["name"], ctx.db.local());
//std::vector<double> res;
httpd::utils_json::histogram res;
res.count = 0;
res.mean = 0;
res.max = 0;
res.min = 0;
res.sum = 0;
res.variance = 0;
return make_ready_future<json::json_return_type>(res);
cf::get_live_scanned_histogram.set(r, [&ctx] (std::unique_ptr<request> req) {
return get_cf_histogram(ctx, req->param["name"], &column_family::stats::live_scanned);
});
cf::get_col_update_time_delta_histogram.set(r, [] (std::unique_ptr<request> req) {

View File

@@ -85,7 +85,12 @@ void set_compaction_manager(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(0);
});
cm::get_compaction_history.set(r, [] (std::unique_ptr<request> req) {
//TBD
unimplemented();
std::vector<cm::history> res;
return make_ready_future<json::json_return_type>(res);
});
}

View File

@@ -27,47 +27,43 @@ namespace api {
using namespace json;
void set_gossiper(http_context& ctx, routes& r) {
httpd::gossiper_json::get_down_endpoint.set(r, [](std::unique_ptr<request> req) {
return gms::get_unreachable_members().then([](std::set<gms::inet_address> res) {
return make_ready_future<json::json_return_type>(container_to_vec(res));
});
httpd::gossiper_json::get_down_endpoint.set(r, [] (const_req req) {
auto res = gms::get_local_gossiper().get_unreachable_members();
return container_to_vec(res);
});
httpd::gossiper_json::get_live_endpoint.set(r, [](std::unique_ptr<request> req) {
return gms::get_live_members().then([](std::set<gms::inet_address> res) {
return make_ready_future<json::json_return_type>(container_to_vec(res));
});
httpd::gossiper_json::get_live_endpoint.set(r, [] (const_req req) {
auto res = gms::get_local_gossiper().get_live_members();
return container_to_vec(res);
});
httpd::gossiper_json::get_endpoint_downtime.set(r, [](std::unique_ptr<request> req) {
httpd::gossiper_json::get_endpoint_downtime.set(r, [] (const_req req) {
gms::inet_address ep(req.param["addr"]);
return gms::get_local_gossiper().get_endpoint_downtime(ep);
});
httpd::gossiper_json::get_current_generation_number.set(r, [] (std::unique_ptr<request> req) {
gms::inet_address ep(req->param["addr"]);
return gms::get_endpoint_downtime(ep).then([](int64_t res) {
return gms::get_local_gossiper().get_current_generation_number(ep).then([] (int res) {
return make_ready_future<json::json_return_type>(res);
});
});
httpd::gossiper_json::get_current_generation_number.set(r, [](std::unique_ptr<request> req) {
httpd::gossiper_json::get_current_heart_beat_version.set(r, [] (std::unique_ptr<request> req) {
gms::inet_address ep(req->param["addr"]);
return gms::get_current_generation_number(ep).then([](int res) {
return make_ready_future<json::json_return_type>(res);
});
});
httpd::gossiper_json::get_current_heart_beat_version.set(r, [](std::unique_ptr<request> req) {
gms::inet_address ep(req->param["addr"]);
return gms::get_current_heart_beat_version(ep).then([](int res) {
return gms::get_local_gossiper().get_current_heart_beat_version(ep).then([] (int res) {
return make_ready_future<json::json_return_type>(res);
});
});
httpd::gossiper_json::assassinate_endpoint.set(r, [](std::unique_ptr<request> req) {
if (req->get_query_param("unsafe") != "True") {
return gms::assassinate_endpoint(req->param["addr"]).then([] {
return make_ready_future<json::json_return_type>(json_void());
return gms::get_local_gossiper().assassinate_endpoint(req->param["addr"]).then([] {
return make_ready_future<json::json_return_type>(json_void());
});
}
return gms::unsafe_assassinate_endpoint(req->param["addr"]).then([] {
return make_ready_future<json::json_return_type>(json_void());
return gms::get_local_gossiper().unsafe_assassinate_endpoint(req->param["addr"]).then([] {
return make_ready_future<json::json_return_type>(json_void());
});
});
}

View File

@@ -23,6 +23,9 @@
#include "service/storage_proxy.hh"
#include "api/api-doc/storage_proxy.json.hh"
#include "api/api-doc/utils.json.hh"
#include "service/storage_service.hh"
#include "db/config.hh"
#include "utils/histogram.hh"
namespace api {
@@ -30,6 +33,23 @@ namespace sp = httpd::storage_proxy_json;
using proxy = service::storage_proxy;
using namespace json;
static future<json::json_return_type> sum_estimated_histogram(http_context& ctx, sstables::estimated_histogram proxy::stats::*f) {
return ctx.sp.map_reduce0([f](const proxy& p) {return p.get_stats().*f;}, sstables::estimated_histogram(),
sstables::merge).then([](const sstables::estimated_histogram& val) {
utils_json::estimated_histogram res;
res = val;
return make_ready_future<json::json_return_type>(res);
});
}
static future<json::json_return_type> total_latency(http_context& ctx, utils::ihistogram proxy::stats::*f) {
return ctx.sp.map_reduce0([f](const proxy& p) {return (p.get_stats().*f).mean * (p.get_stats().*f).count;}, 0.0,
std::plus<double>()).then([](double val) {
int64_t res = val;
return make_ready_future<json::json_return_type>(res);
});
}
void set_storage_proxy(http_context& ctx, routes& r) {
sp::get_total_hints.set(r, [](std::unique_ptr<request> req) {
//TBD
@@ -39,7 +59,9 @@ void set_storage_proxy(http_context& ctx, routes& r) {
sp::get_hinted_handoff_enabled.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
// FIXME
// hinted handoff is not supported currently,
// so we should return false
return make_ready_future<json::json_return_type>(false);
});
@@ -96,10 +118,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(0);
});
sp::get_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(1);
sp::get_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().request_timeout_in_ms()/1000.0;
});
sp::set_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -109,10 +129,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_read_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_read_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().read_request_timeout_in_ms()/1000.0;
});
sp::set_read_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -122,10 +140,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_write_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().write_request_timeout_in_ms()/1000.0;
});
sp::set_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -135,11 +151,10 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_counter_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_counter_write_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().counter_write_request_timeout_in_ms()/1000.0;
});
sp::set_counter_write_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
@@ -147,10 +162,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_cas_contention_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_cas_contention_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().cas_contention_timeout_in_ms()/1000.0;
});
sp::set_cas_contention_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -160,10 +173,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_range_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_range_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().range_request_timeout_in_ms()/1000.0;
});
sp::set_range_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -173,10 +184,8 @@ void set_storage_proxy(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
sp::get_truncate_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
sp::get_truncate_rpc_timeout.set(r, [&ctx](const_req req) {
return ctx.db.local().get_config().truncate_request_timeout_in_ms()/1000.0;
});
sp::set_truncate_rpc_timeout.set(r, [](std::unique_ptr<request> req) {
@@ -212,8 +221,14 @@ void set_storage_proxy(http_context& ctx, routes& r) {
sp::get_schema_versions.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
// FIXME
// describe_schema_versions is not implemented yet
// this is a work around
std::vector<sp::mapper_list> res;
sp::mapper_list entry;
entry.key = boost::lexical_cast<std::string>(utils::fb_utilities::get_broadcast_address());
entry.value.push(service::get_local_storage_service().get_schema_version());
res.push_back(entry);
return make_ready_future<json::json_return_type>(res);
});
@@ -316,6 +331,29 @@ void set_storage_proxy(http_context& ctx, routes& r) {
sp::get_read_metrics_latency_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
return sum_histogram_stats(ctx.sp, &proxy::stats::read);
});
sp::get_read_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
return sum_estimated_histogram(ctx, &proxy::stats::estimated_read);
});
sp::get_read_latency.set(r, [&ctx](std::unique_ptr<request> req) {
return total_latency(ctx, &proxy::stats::read);
});
sp::get_write_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
return sum_estimated_histogram(ctx, &proxy::stats::estimated_write);
});
sp::get_write_latency.set(r, [&ctx](std::unique_ptr<request> req) {
return total_latency(ctx, &proxy::stats::write);
});
sp::get_range_estimated_histogram.set(r, [&ctx](std::unique_ptr<request> req) {
return sum_histogram_stats(ctx.sp, &proxy::stats::read);
});
sp::get_range_latency.set(r, [&ctx](std::unique_ptr<request> req) {
return total_latency(ctx, &proxy::stats::range);
});
}
}

View File

@@ -30,8 +30,6 @@
#include "repair/repair.hh"
#include "locator/snitch_base.hh"
#include "column_family.hh"
#include <unordered_map>
#include "utils/fb_utilities.hh"
namespace api {
@@ -52,28 +50,25 @@ void set_storage_service(http_context& ctx, routes& r) {
});
});
ss::get_tokens.set(r, [](std::unique_ptr<request> req) {
return service::sorted_tokens().then([](const std::vector<dht::token>& tokens) {
return make_ready_future<json::json_return_type>(container_to_vec(tokens));
});
ss::get_tokens.set(r, [] (const_req req) {
auto tokens = service::get_local_storage_service().get_token_metadata().sorted_tokens();
return container_to_vec(tokens);
});
ss::get_node_tokens.set(r, [](std::unique_ptr<request> req) {
gms::inet_address addr(req->param["endpoint"]);
return service::get_tokens(addr).then([](const std::vector<dht::token>& tokens) {
return make_ready_future<json::json_return_type>(container_to_vec(tokens));
});
ss::get_node_tokens.set(r, [] (const_req req) {
gms::inet_address addr(req.param["endpoint"]);
auto tokens = service::get_local_storage_service().get_token_metadata().get_tokens(addr);
return container_to_vec(tokens);
});
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, [](std::unique_ptr<request> req) {
return service::get_token_to_endpoint().then([] (const std::map<dht::token, gms::inet_address>& tokens){
std::vector<storage_service_json::mapper> res;
return make_ready_future<json::json_return_type>(map_to_key_value(tokens, res));
});
ss::get_token_endpoint.set(r, [] (const_req req) {
auto token_to_ep = service::get_local_storage_service().get_token_metadata().get_token_to_endpoint();
std::vector<storage_service_json::mapper> res;
return map_to_key_value(token_to_ep, res);
});
ss::get_leaving_nodes.set(r, [](const_req req) {
@@ -148,31 +143,16 @@ void set_storage_service(http_context& ctx, routes& r) {
return get_cf_stats(ctx, &column_family::stats::live_disk_space_used);
});
ss::get_load_map.set(r, [&ctx](std::unique_ptr<request> req) {
// FIXME
// The function should return a mapping between inet address
// and the load (disk space used)
// in origin the implementation is based on the load broadcast
// we do not currently support.
// As a workaround, the local load is calculated (this part is similar
// to origin) and a map with a single entry is return.
return ctx.db.map_reduce0([](database& db) {
int64_t res = 0;
for (auto i : db.get_column_families()) {
res += i.second->get_stats().live_disk_space_used;
}
return res;
}, 0, std::plus<int64_t>()).then([](int64_t size) {
ss::get_load_map.set(r, [] (std::unique_ptr<request> req) {
return service::get_local_storage_service().get_load_map().then([] (auto&& load_map) {
std::vector<ss::mapper> res;
std::unordered_map<gms::inet_address, double> load_map;
load_map[utils::fb_utilities::get_broadcast_address()] = size;
return make_ready_future<json::json_return_type>(map_to_key_value(load_map, res));
});
});
ss::get_current_generation_number.set(r, [](std::unique_ptr<request> req) {
gms::inet_address ep(utils::fb_utilities::get_broadcast_address());
return gms::get_current_generation_number(ep).then([](int res) {
return gms::get_local_gossiper().get_current_generation_number(ep).then([](int res) {
return make_ready_future<json::json_return_type>(res);
});
});
@@ -189,33 +169,61 @@ void set_storage_service(http_context& ctx, routes& r) {
});
ss::get_snapshot_details.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
std::vector<ss::snapshots> res;
return make_ready_future<json::json_return_type>(res);
return service::get_local_storage_service().get_snapshot_details().then([] (auto result) {
std::vector<ss::snapshots> res;
for (auto& map: result) {
ss::snapshots all_snapshots;
all_snapshots.key = map.first;
std::vector<ss::snapshot> snapshot;
for (auto& cf: map.second) {
ss::snapshot s;
s.ks = cf.ks;
s.cf = cf.cf;
s.live = cf.live;
s.total = cf.total;
snapshot.push_back(std::move(s));
}
all_snapshots.value = std::move(snapshot);
res.push_back(std::move(all_snapshots));
}
return make_ready_future<json::json_return_type>(std::move(res));
});
});
ss::take_snapshot.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
auto tag = req->get_query_param("tag");
auto keyname = req->get_query_param("kn");
auto column_family = req->get_query_param("cf");
return make_ready_future<json::json_return_type>(json_void());
std::vector<sstring> keynames = split(req->get_query_param("kn"), ",");
auto resp = make_ready_future<>();
if (column_family.empty()) {
resp = service::get_local_storage_service().take_snapshot(tag, keynames);
} else {
if (keynames.size() > 1) {
throw httpd::bad_param_exception("Only one keyspace allowed when specifying a column family");
}
resp = service::get_local_storage_service().take_column_family_snapshot(keynames[0], column_family, tag);
}
return resp.then([] {
return make_ready_future<json::json_return_type>(json_void());
});
});
ss::del_snapshot.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
auto tag = req->get_query_param("tag");
auto keyname = req->get_query_param("kn");
return make_ready_future<json::json_return_type>(json_void());
std::vector<sstring> keynames = split(req->get_query_param("kn"), ",");
return service::get_local_storage_service().clear_snapshot(tag, keynames).then([] {
return make_ready_future<json::json_return_type>(json_void());
});
});
ss::true_snapshots_size.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(0);
return service::get_local_storage_service().true_snapshots_size().then([] (int64_t size) {
return make_ready_future<json::json_return_type>(size);
});
});
ss::force_keyspace_compaction.set(r, [&ctx](std::unique_ptr<request> req) {
@@ -338,9 +346,8 @@ void set_storage_service(http_context& ctx, routes& r) {
});
ss::remove_node.set(r, [](std::unique_ptr<request> req) {
// FIXME: This api is incorrect. remove_node takes a host id string parameter instead of token.
auto host_id = req->get_query_param("token");
return service::get_local_storage_service().remove_node(std::move(host_id)).then([] {
auto host_id = req->get_query_param("host_id");
return service::get_local_storage_service().remove_node(host_id).then([] {
return make_ready_future<json::json_return_type>(json_void());
});
});
@@ -440,8 +447,10 @@ void set_storage_service(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
ss::is_initialized.set(r, [](const_req req) {
return service::get_local_storage_service().is_initialized();
ss::is_initialized.set(r, [](std::unique_ptr<request> req) {
return service::get_local_storage_service().is_initialized().then([] (bool initialized) {
return make_ready_future<json::json_return_type>(initialized);
});
});
ss::stop_rpc_server.set(r, [](std::unique_ptr<request> req) {
@@ -456,8 +465,10 @@ void set_storage_service(http_context& ctx, routes& r) {
});
});
ss::is_rpc_server_running.set(r, [](const_req req) {
return service::get_local_storage_service().is_rpc_server_running();
ss::is_rpc_server_running.set(r, [] (std::unique_ptr<request> req) {
return service::get_local_storage_service().is_rpc_server_running().then([] (bool running) {
return make_ready_future<json::json_return_type>(running);
});
});
ss::start_native_transport.set(r, [](std::unique_ptr<request> req) {
@@ -472,8 +483,10 @@ void set_storage_service(http_context& ctx, routes& r) {
});
});
ss::is_native_transport_running.set(r, [](const_req req) {
return service::get_local_storage_service().is_native_transport_running();
ss::is_native_transport_running.set(r, [] (std::unique_ptr<request> req) {
return service::get_local_storage_service().is_native_transport_running().then([] (bool running) {
return make_ready_future<json::json_return_type>(running);
});
});
ss::join_ring.set(r, [](std::unique_ptr<request> req) {
@@ -575,11 +588,16 @@ void set_storage_service(http_context& ctx, routes& r) {
});
ss::load_new_ss_tables.set(r, [&ctx](std::unique_ptr<request> req) {
//TBD
unimplemented();
auto keyspace = validate_keyspace(ctx, req->param);
auto column_family = req->get_query_param("cf");
return make_ready_future<json::json_return_type>(json_void());
auto ks = validate_keyspace(ctx, req->param);
auto cf = req->get_query_param("cf");
// No need to add the keyspace, since all we want is to avoid always sending this to the same
// CPU. Even then I am being overzealous here. This is not something that happens all the time.
auto coordinator = std::hash<sstring>()(cf) % smp::count;
return service::get_storage_service().invoke_on(coordinator, [ks = std::move(ks), cf = std::move(cf)] (service::storage_service& s) {
return s.load_new_sstables(ks, cf);
}).then([] {
return make_ready_future<json::json_return_type>(json_void());
});
});
ss::sample_key_range.set(r, [](std::unique_ptr<request> req) {
@@ -631,16 +649,12 @@ void set_storage_service(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(json_void());
});
ss::get_cluster_name.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(json_void());
ss::get_cluster_name.set(r, [](const_req req) {
return gms::get_local_gossiper().get_cluster_name();
});
ss::get_partitioner_name.set(r, [](std::unique_ptr<request> req) {
//TBD
unimplemented();
return make_ready_future<json::json_return_type>(json_void());
ss::get_partitioner_name.set(r, [](const_req req) {
return gms::get_local_gossiper().get_partitioner_name();
});
ss::get_tombstone_warn_threshold.set(r, [](std::unique_ptr<request> req) {

View File

@@ -24,6 +24,7 @@
#include "streaming/stream_result_future.hh"
#include "api/api-doc/stream_manager.json.hh"
#include <vector>
#include "gms/gossiper.hh"
namespace api {
@@ -97,6 +98,80 @@ void set_stream_manager(http_context& ctx, routes& r) {
return make_ready_future<json::json_return_type>(res);
});
});
hs::get_all_active_streams_outbound.set(r, [](std::unique_ptr<request> req) {
return streaming::get_stream_manager().map_reduce0([](streaming::stream_manager& stream) {
return stream.get_initiated_streams().size();
}, 0, std::plus<int64_t>()).then([](int64_t res) {
return make_ready_future<json::json_return_type>(res);
});
});
hs::get_total_incoming_bytes.set(r, [](std::unique_ptr<request> req) {
gms::inet_address ep(req->param["peer"]);
utils::UUID plan_id = gms::get_local_gossiper().get_host_id(ep);
return streaming::get_stream_manager().map_reduce0([plan_id](streaming::stream_manager& stream) {
int64_t res = 0;
streaming::stream_result_future* s = stream.get_receiving_stream(plan_id).get();
if (s != nullptr) {
for (auto si: s->get_coordinator()->get_all_session_info()) {
res += si.get_total_size_received();
}
}
return res;
}, 0, std::plus<int64_t>()).then([](int64_t res) {
return make_ready_future<json::json_return_type>(res);
});
});
hs::get_all_total_incoming_bytes.set(r, [](std::unique_ptr<request> req) {
return streaming::get_stream_manager().map_reduce0([](streaming::stream_manager& stream) {
int64_t res = 0;
for (auto s : stream.get_receiving_streams()) {
if (s.second.get() != nullptr) {
for (auto si: s.second.get()->get_coordinator()->get_all_session_info()) {
res += si.get_total_size_received();
}
}
}
return res;
}, 0, std::plus<int64_t>()).then([](int64_t res) {
return make_ready_future<json::json_return_type>(res);
});
});
hs::get_total_outgoing_bytes.set(r, [](std::unique_ptr<request> req) {
gms::inet_address ep(req->param["peer"]);
utils::UUID plan_id = gms::get_local_gossiper().get_host_id(ep);
return streaming::get_stream_manager().map_reduce0([plan_id](streaming::stream_manager& stream) {
int64_t res = 0;
streaming::stream_result_future* s = stream.get_sending_stream(plan_id).get();
if (s != nullptr) {
for (auto si: s->get_coordinator()->get_all_session_info()) {
res += si.get_total_size_received();
}
}
return res;
}, 0, std::plus<int64_t>()).then([](int64_t res) {
return make_ready_future<json::json_return_type>(res);
});
});
hs::get_all_total_outgoing_bytes.set(r, [](std::unique_ptr<request> req) {
return streaming::get_stream_manager().map_reduce0([](streaming::stream_manager& stream) {
int64_t res = 0;
for (auto s : stream.get_initiated_streams()) {
if (s.second.get() != nullptr) {
for (auto si: s.second.get()->get_coordinator()->get_all_session_info()) {
res += si.get_total_size_received();
}
}
}
return res;
}, 0, std::plus<int64_t>()).then([](int64_t res) {
return make_ready_future<json::json_return_type>(res);
});
});
}
}

70
api/system.cc Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright 2015 Cloudius Systems
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#include "api/api-doc/system.json.hh"
#include "api/api.hh"
#include "http/exception.hh"
#include "log.hh"
namespace api {
namespace hs = httpd::system_json;
void set_system(http_context& ctx, routes& r) {
hs::get_all_logger_names.set(r, [](const_req req) {
return logging::logger_registry().get_all_logger_names();
});
hs::set_all_logger_level.set(r, [](const_req req) {
try {
logging::log_level level = boost::lexical_cast<logging::log_level>(std::string(req.get_query_param("level")));
logging::logger_registry().set_all_loggers_level(level);
} catch (boost::bad_lexical_cast& e) {
throw bad_param_exception("Unknown logging level " + req.get_query_param("level"));
}
return json::json_void();
});
hs::get_logger_level.set(r, [](const_req req) {
try {
return logging::level_name(logging::logger_registry().get_logger_level(req.param["name"]));
} catch (std::out_of_range& e) {
throw bad_param_exception("Unknown logger name " + req.param["name"]);
}
// just to keep the compiler happy
return sstring();
});
hs::set_logger_level.set(r, [](const_req req) {
try {
logging::log_level level = boost::lexical_cast<logging::log_level>(std::string(req.get_query_param("level")));
logging::logger_registry().set_logger_level(req.param["name"], level);
} catch (std::out_of_range& e) {
throw bad_param_exception("Unknown logger name " + req.param["name"]);
} catch (boost::bad_lexical_cast& e) {
throw bad_param_exception("Unknown logging level " + req.get_query_param("level"));
}
return json::json_void();
});
}
}

30
api/system.hh Normal file
View File

@@ -0,0 +1,30 @@
/*
* Copyright 2015 Cloudius Systems
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "api.hh"
namespace api {
void set_system(http_context& ctx, routes& r);
}

View File

@@ -43,11 +43,13 @@ class caching_options {
throw exceptions::configuration_exception("Invalid key value: " + k);
}
try {
boost::lexical_cast<unsigned long>(r);
} catch (boost::bad_lexical_cast& e) {
if ((r != "ALL") && (r != "NONE")) {
throw exceptions::configuration_exception("Invalid key value: " + k);
if ((r == "ALL") || (r == "NONE")) {
return;
} else {
try {
boost::lexical_cast<unsigned long>(r);
} catch (boost::bad_lexical_cast& e) {
throw exceptions::configuration_exception("Invalid key value: " + r);
}
}
}

View File

@@ -29,7 +29,8 @@ enum class compaction_strategy_type {
null,
major,
size_tiered,
// FIXME: Add support to LevelTiered, and DateTiered.
leveled,
// FIXME: Add support to DateTiered.
};
class compaction_strategy_impl;
@@ -54,6 +55,8 @@ public:
return "MajorCompactionStrategy";
case compaction_strategy_type::size_tiered:
return "SizeTieredCompactionStrategy";
case compaction_strategy_type::leveled:
return "LeveledCompactionStrategy";
default:
throw std::runtime_error("Invalid Compaction Strategy");
}
@@ -66,6 +69,8 @@ public:
return compaction_strategy_type::major;
} else if (name == "SizeTieredCompactionStrategy") {
return compaction_strategy_type::size_tiered;
} else if (name == "LeveledCompactionStrategy") {
return compaction_strategy_type::leveled;
} else {
throw exceptions::configuration_exception(sprint("Unable to find compaction strategy class 'org.apache.cassandra.db.compaction.%s", name));
}

View File

@@ -0,0 +1,15 @@
#
# cassandra-rackdc.properties
#
# The lines may include white spaces at the beginning and the end.
# The rack and data center names may also include white spaces.
# All trailing and leading white spaces will be trimmed.
#
# dc=my_data_center
# rack=my_rack
# prefer_local=<false | true>
# dc_suffix=<Data Center name suffix, used by EC2SnitchXXX snitches>
#

View File

@@ -132,7 +132,7 @@ modes = {
},
}
urchin_tests = [
scylla_tests = [
'tests/mutation_test',
'tests/range_test',
'tests/types_test',
@@ -152,6 +152,7 @@ urchin_tests = [
'tests/cql_query_test',
'tests/storage_proxy_test',
'tests/mutation_reader_test',
'tests/key_reader_test',
'tests/mutation_query_test',
'tests/row_cache_test',
'tests/test-serialization',
@@ -169,6 +170,7 @@ urchin_tests = [
'tests/compound_test',
'tests/config_test',
'tests/gossiping_property_file_snitch_test',
'tests/ec2_snitch_test',
'tests/snitch_reset_test',
'tests/network_topology_strategy_test',
'tests/query_processor_test',
@@ -180,13 +182,14 @@ urchin_tests = [
'tests/logalloc_test',
'tests/managed_vector_test',
'tests/crc_test',
'tests/flush_queue_test',
]
apps = [
'scylla',
]
tests = urchin_tests
tests = scylla_tests
all_artifacts = apps + tests
@@ -216,18 +219,20 @@ arg_parser.add_argument('--debuginfo', action = 'store', dest = 'debuginfo', typ
help = 'Enable(1)/disable(0)compiler debug information generation')
arg_parser.add_argument('--static-stdc++', dest = 'staticcxx', action = 'store_true',
help = 'Link libgcc and libstdc++ statically')
arg_parser.add_argument('--tests-debuginfo', action = 'store', dest = 'tests_debuginfo', type = int, default = 0,
help = 'Enable(1)/disable(0)compiler debug information generation for tests')
add_tristate(arg_parser, name = 'hwloc', dest = 'hwloc', help = 'hwloc support')
add_tristate(arg_parser, name = 'xen', dest = 'xen', help = 'Xen support')
args = arg_parser.parse_args()
defines = []
urchin_libs = '-llz4 -lsnappy -lz -lboost_thread -lcryptopp -lrt -lyaml-cpp -lboost_date_time'
scylla_libs = '-llz4 -lsnappy -lz -lboost_thread -lcryptopp -lrt -lyaml-cpp -lboost_date_time'
extra_cxxflags = {}
cassandra_interface = Thrift(source = 'interface/cassandra.thrift', service = 'Cassandra')
urchin_core = (['database.cc',
scylla_core = (['database.cc',
'schema.cc',
'bytes.cc',
'mutation.cc',
@@ -242,6 +247,7 @@ urchin_core = (['database.cc',
'mutation_partition_serializer.cc',
'mutation_reader.cc',
'mutation_query.cc',
'key_reader.cc',
'keys.cc',
'sstables/sstables.cc',
'sstables/compress.cc',
@@ -266,6 +272,8 @@ urchin_core = (['database.cc',
'cql3/maps.cc',
'cql3/functions/functions.cc',
'cql3/statements/cf_prop_defs.cc',
'cql3/statements/cf_statement.cc',
'cql3/statements/create_keyspace_statement.cc',
'cql3/statements/create_table_statement.cc',
'cql3/statements/drop_keyspace_statement.cc',
'cql3/statements/drop_table_statement.cc',
@@ -339,10 +347,12 @@ urchin_core = (['database.cc',
'gms/gossip_digest_ack.cc',
'gms/gossip_digest_ack2.cc',
'gms/endpoint_state.cc',
'gms/application_state.cc',
'dht/i_partitioner.cc',
'dht/murmur3_partitioner.cc',
'dht/byte_ordered_partitioner.cc',
'dht/boot_strapper.cc',
'dht/range_streamer.cc',
'unimplemented.cc',
'query.cc',
'query-result-set.cc',
@@ -356,9 +366,14 @@ urchin_core = (['database.cc',
'locator/simple_snitch.cc',
'locator/rack_inferring_snitch.cc',
'locator/gossiping_property_file_snitch.cc',
'locator/production_snitch_base.cc',
'locator/ec2_snitch.cc',
'locator/ec2_multi_region_snitch.cc',
'message/messaging_service.cc',
'service/migration_task.cc',
'service/storage_service.cc',
'service/pending_range_calculator_service.cc',
'service/load_broadcaster.cc',
'streaming/streaming.cc',
'streaming/stream_task.cc',
'streaming/stream_session.cc',
@@ -384,6 +399,7 @@ urchin_core = (['database.cc',
'init.cc',
'repair/repair.cc',
'exceptions/exceptions.cc',
'dns.cc',
]
+ [Antlr3Grammar('cql3/Cql.g')]
+ [Thrift('interface/cassandra.thrift', 'Cassandra')]
@@ -419,22 +435,24 @@ api = ['api/api.cc',
'api/lsa.cc',
'api/api-doc/stream_manager.json',
'api/stream_manager.cc',
'api/api-doc/system.json',
'api/system.cc'
]
urchin_tests_dependencies = urchin_core + [
scylla_tests_dependencies = scylla_core + [
'tests/cql_test_env.cc',
'tests/cql_assertions.cc',
'tests/result_set_assertions.cc',
'tests/mutation_source_test.cc',
]
urchin_tests_seastar_deps = [
scylla_tests_seastar_deps = [
'seastar/tests/test-utils.cc',
'seastar/tests/test_runner.cc',
]
deps = {
'scylla': ['main.cc'] + urchin_core + api,
'scylla': ['main.cc'] + scylla_core + api,
}
tests_not_using_seastar_test_framework = set([
@@ -464,13 +482,13 @@ tests_not_using_seastar_test_framework = set([
])
for t in tests_not_using_seastar_test_framework:
if not t in urchin_tests:
raise Exception("Test %s not found in urchin_tests" % (t))
if not t in scylla_tests:
raise Exception("Test %s not found in scylla_tests" % (t))
for t in urchin_tests:
deps[t] = urchin_tests_dependencies + [t + '.cc']
for t in scylla_tests:
deps[t] = scylla_tests_dependencies + [t + '.cc']
if t not in tests_not_using_seastar_test_framework:
deps[t] += urchin_tests_seastar_deps
deps[t] += scylla_tests_seastar_deps
deps['tests/sstable_test'] += ['tests/sstable_datafile_test.cc']
@@ -491,6 +509,7 @@ warnings = [w
warnings = ' '.join(warnings)
dbgflag = debug_flag(args.cxx) if args.debuginfo else ''
tests_link_rule = 'link' if args.tests_debuginfo else 'link_stripped'
if args.so:
args.pie = '-shared'
@@ -531,7 +550,8 @@ if args.dpdk:
elif args.dpdk_target:
seastar_flags += ['--dpdk-target', args.dpdk_target]
seastar_flags += ['--compiler', args.cxx, '--cflags=-march=nehalem']
seastar_cflags = args.user_cflags + " -march=nehalem"
seastar_flags += ['--compiler', args.cxx, '--cflags=%s' % (seastar_cflags)]
status = subprocess.call(['./configure.py'] + seastar_flags, cwd = 'seastar')
@@ -665,7 +685,7 @@ with open(buildfile, 'w') as f:
# So we strip the tests by default; The user can very
# quickly re-link the test unstripped by adding a "_g"
# to the test name, e.g., "ninja build/release/testname_g"
f.write('build $builddir/{}/{}: link_stripped.{} {} {}\n'.format(mode, binary, mode, str.join(' ', objs),
f.write('build $builddir/{}/{}: {}.{} {} {}\n'.format(mode, binary, tests_link_rule, mode, str.join(' ', objs),
'seastar/build/{}/libseastar.a'.format(mode)))
if has_thrift:
f.write(' libs = -lthrift -lboost_system $libs\n')

View File

@@ -1224,8 +1224,8 @@ properties[::shared_ptr<cql3::statements::property_definitions> props]
;
property[::shared_ptr<cql3::statements::property_definitions> props]
: k=ident '=' (simple=propertyValue { try { $props->add_property(k->to_string(), simple); } catch (exceptions::syntax_exception e) { add_recognition_error(e.what()); } }
| map=mapLiteral { try { $props->add_property(k->to_string(), convert_property_map(map)); } catch (exceptions::syntax_exception e) { add_recognition_error(e.what()); } })
: k=ident '=' simple=propertyValue { try { $props->add_property(k->to_string(), simple); } catch (exceptions::syntax_exception e) { add_recognition_error(e.what()); } }
| k=ident '=' map=mapLiteral { try { $props->add_property(k->to_string(), convert_property_map(map)); } catch (exceptions::syntax_exception e) { add_recognition_error(e.what()); } }
;
propertyValue returns [sstring str]

View File

@@ -98,6 +98,10 @@ public:
execute_internal(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) = 0;
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const = 0;
virtual bool depends_on_keyspace(const sstring& ks_name) const = 0;
virtual bool depends_on_column_family(const sstring& cf_name) const = 0;
};
}

View File

@@ -272,7 +272,7 @@ lists::setter_by_index::execute(mutation& m, const exploded_clustering_prefix& p
auto existing_list_opt = params.get_prefetched_list(m.key(), row_key, column);
if (!existing_list_opt) {
throw exceptions::invalid_request_exception(sprint("List index %d out of bound, list has size 0", idx));
throw exceptions::invalid_request_exception("Attempted to set an element on a list which is null");
}
collection_mutation::view existing_list_ser = *existing_list_opt;
auto ltype = dynamic_pointer_cast<const list_type_impl>(column.type);
@@ -448,7 +448,7 @@ lists::discarder_by_index::execute(mutation& m, const exploded_clustering_prefix
auto&& existing_list = params.get_prefetched_list(m.key(), row_key, column);
int32_t idx = read_simple_exactly<int32_t>(*cvalue->_bytes);
if (!existing_list) {
throw exceptions::invalid_request_exception("List does not exist");
throw exceptions::invalid_request_exception("Attempted to delete an element from a list which is null");
}
auto&& deserialized = ltype->deserialize_mutation_form(*existing_list);
if (idx < 0 || size_t(idx) >= deserialized.cells.size()) {

View File

@@ -56,14 +56,15 @@ using namespace transport::messages;
logging::logger log("query_processor");
distributed<query_processor> _the_query_processor;
const sstring query_processor::CQL_VERSION = "3.2.0";
class query_processor::internal_state {
service::client_state _cs;
service::query_state _qs;
public:
internal_state()
: _cs(service::client_state::internal_tag()), _qs(_cs) {
: _qs(service::client_state{service::client_state::internal_tag()}) {
}
operator service::query_state&() {
return _qs;
@@ -72,14 +73,13 @@ public:
return _qs;
}
operator service::client_state&() {
return _cs;
return _qs.get_client_state();
}
operator const service::client_state&() const {
return _cs;
return _qs.get_client_state();
}
api::timestamp_type next_timestamp() {
return _cs.get_timestamp();
return _qs.get_client_state().get_timestamp();
}
};
@@ -89,12 +89,23 @@ api::timestamp_type query_processor::next_timestamp() {
query_processor::query_processor(distributed<service::storage_proxy>& proxy,
distributed<database>& db)
: _proxy(proxy), _db(db), _internal_state(new internal_state()) {
: _migration_subscriber{std::make_unique<migration_subscriber>(this)}
, _proxy(proxy)
, _db(db)
, _internal_state(new internal_state())
{
service::get_local_migration_manager().register_listener(_migration_subscriber.get());
}
query_processor::~query_processor()
{}
future<> query_processor::stop()
{
service::get_local_migration_manager().unregister_listener(_migration_subscriber.get());
return make_ready_future<>();
}
future<::shared_ptr<result_message>>
query_processor::process(const sstring_view& query_string, service::query_state& query_state, query_options& options)
{
@@ -212,6 +223,11 @@ query_processor::store_prepared_statement(const std::experimental::string_view&
}
}
void query_processor::invalidate_prepared_statement(bytes statement_id)
{
_prepared_statements.erase(statement_id);
}
static bytes md5_calculate(const std::experimental::string_view& s)
{
constexpr size_t size = CryptoPP::Weak1::MD5::DIGESTSIZE;
@@ -338,5 +354,97 @@ query_processor::process_batch(::shared_ptr<statements::batch_statement> batch,
return batch->execute(_proxy, query_state, options);
}
query_processor::migration_subscriber::migration_subscriber(query_processor* qp)
: _qp{qp}
{
}
void query_processor::migration_subscriber::on_create_keyspace(const sstring& ks_name)
{
}
void query_processor::migration_subscriber::on_create_column_family(const sstring& ks_name, const sstring& cf_name)
{
}
void query_processor::migration_subscriber::on_create_user_type(const sstring& ks_name, const sstring& type_name)
{
}
void query_processor::migration_subscriber::on_create_function(const sstring& ks_name, const sstring& function_name)
{
log.warn("{} event ignored", __func__);
}
void query_processor::migration_subscriber::on_create_aggregate(const sstring& ks_name, const sstring& aggregate_name)
{
log.warn("{} event ignored", __func__);
}
void query_processor::migration_subscriber::on_update_keyspace(const sstring& ks_name)
{
}
void query_processor::migration_subscriber::on_update_column_family(const sstring& ks_name, const sstring& cf_name)
{
}
void query_processor::migration_subscriber::on_update_user_type(const sstring& ks_name, const sstring& type_name)
{
}
void query_processor::migration_subscriber::on_update_function(const sstring& ks_name, const sstring& function_name)
{
}
void query_processor::migration_subscriber::on_update_aggregate(const sstring& ks_name, const sstring& aggregate_name)
{
}
void query_processor::migration_subscriber::on_drop_keyspace(const sstring& ks_name)
{
remove_invalid_prepared_statements(ks_name, std::experimental::nullopt);
}
void query_processor::migration_subscriber::on_drop_column_family(const sstring& ks_name, const sstring& cf_name)
{
remove_invalid_prepared_statements(ks_name, cf_name);
}
void query_processor::migration_subscriber::on_drop_user_type(const sstring& ks_name, const sstring& type_name)
{
}
void query_processor::migration_subscriber::on_drop_function(const sstring& ks_name, const sstring& function_name)
{
log.warn("{} event ignored", __func__);
}
void query_processor::migration_subscriber::on_drop_aggregate(const sstring& ks_name, const sstring& aggregate_name)
{
log.warn("{} event ignored", __func__);
}
void query_processor::migration_subscriber::remove_invalid_prepared_statements(sstring ks_name, std::experimental::optional<sstring> cf_name)
{
std::vector<bytes> invalid;
for (auto& kv : _qp->_prepared_statements) {
auto id = kv.first;
auto stmt = kv.second;
if (should_invalidate(ks_name, cf_name, stmt->statement)) {
invalid.emplace_back(id);
}
}
for (auto& id : invalid) {
get_query_processor().invoke_on_all([id] (auto& qp) {
qp.invalidate_prepared_statement(id);
});
}
}
bool query_processor::migration_subscriber::should_invalidate(sstring ks_name, std::experimental::optional<sstring> cf_name, ::shared_ptr<cql_statement> statement)
{
return statement->depends_on_keyspace(ks_name) && (!cf_name || statement->depends_on_column_family(*cf_name));
}
}

View File

@@ -48,6 +48,7 @@
#include "exceptions/exceptions.hh"
#include "cql3/query_options.hh"
#include "cql3/statements/cf_statement.hh"
#include "service/migration_manager.hh"
#include "service/query_state.hh"
#include "log.hh"
#include "core/distributed.hh"
@@ -61,7 +62,10 @@ class batch_statement;
}
class query_processor {
public:
class migration_subscriber;
private:
std::unique_ptr<migration_subscriber> _migration_subscriber;
distributed<service::storage_proxy>& _proxy;
distributed<database>& _db;
@@ -423,6 +427,8 @@ private:
future<::shared_ptr<transport::messages::result_message::prepared>>
store_prepared_statement(const std::experimental::string_view& query_string, const sstring& keyspace, ::shared_ptr<statements::parsed_statement::prepared> prepared, bool for_thrift);
void invalidate_prepared_statement(bytes statement_id);
#if 0
public ResultMessage processPrepared(CQLStatement statement, QueryState queryState, QueryOptions options)
throws RequestExecutionException, RequestValidationException
@@ -461,111 +467,48 @@ public:
{
return meter.measureDeep(key);
}
private static class MigrationSubscriber implements IMigrationListener
{
private void removeInvalidPreparedStatements(String ksName, String cfName)
{
removeInvalidPreparedStatements(preparedStatements.values().iterator(), ksName, cfName);
removeInvalidPreparedStatements(thriftPreparedStatements.values().iterator(), ksName, cfName);
}
private void removeInvalidPreparedStatements(Iterator<ParsedStatement.Prepared> iterator, String ksName, String cfName)
{
while (iterator.hasNext())
{
if (shouldInvalidate(ksName, cfName, iterator.next().statement))
iterator.remove();
}
}
private boolean shouldInvalidate(String ksName, String cfName, CQLStatement statement)
{
String statementKsName;
String statementCfName;
if (statement instanceof ModificationStatement)
{
ModificationStatement modificationStatement = ((ModificationStatement) statement);
statementKsName = modificationStatement.keyspace();
statementCfName = modificationStatement.columnFamily();
}
else if (statement instanceof SelectStatement)
{
SelectStatement selectStatement = ((SelectStatement) statement);
statementKsName = selectStatement.keyspace();
statementCfName = selectStatement.columnFamily();
}
else
{
return false;
}
return ksName.equals(statementKsName) && (cfName == null || cfName.equals(statementCfName));
}
public void onCreateKeyspace(String ksName) { }
public void onCreateColumnFamily(String ksName, String cfName) { }
public void onCreateUserType(String ksName, String typeName) { }
public void onCreateFunction(String ksName, String functionName) {
if (Functions.getOverloadCount(new FunctionName(ksName, functionName)) > 1)
{
// in case there are other overloads, we have to remove all overloads since argument type
// matching may change (due to type casting)
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, functionName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, functionName);
}
}
public void onCreateAggregate(String ksName, String aggregateName) {
if (Functions.getOverloadCount(new FunctionName(ksName, aggregateName)) > 1)
{
// in case there are other overloads, we have to remove all overloads since argument type
// matching may change (due to type casting)
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, aggregateName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, aggregateName);
}
}
public void onUpdateKeyspace(String ksName) { }
public void onUpdateColumnFamily(String ksName, String cfName) { }
public void onUpdateUserType(String ksName, String typeName) { }
public void onUpdateFunction(String ksName, String functionName) { }
public void onUpdateAggregate(String ksName, String aggregateName) { }
public void onDropKeyspace(String ksName)
{
removeInvalidPreparedStatements(ksName, null);
}
public void onDropColumnFamily(String ksName, String cfName)
{
removeInvalidPreparedStatements(ksName, cfName);
}
public void onDropUserType(String ksName, String typeName) { }
public void onDropFunction(String ksName, String functionName) {
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, functionName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, functionName);
}
public void onDropAggregate(String ksName, String aggregateName)
{
removeInvalidPreparedStatementsForFunction(preparedStatements.values().iterator(), ksName, aggregateName);
removeInvalidPreparedStatementsForFunction(thriftPreparedStatements.values().iterator(), ksName, aggregateName);
}
private void removeInvalidPreparedStatementsForFunction(Iterator<ParsedStatement.Prepared> iterator,
String ksName, String functionName)
{
while (iterator.hasNext())
if (iterator.next().statement.usesFunction(ksName, functionName))
iterator.remove();
}
}
#endif
public:
future<> stop() {
return make_ready_future<>();
}
future<> stop();
friend class migration_subscriber;
};
class query_processor::migration_subscriber : public service::migration_listener {
query_processor* _qp;
public:
migration_subscriber(query_processor* qp);
virtual void on_create_keyspace(const sstring& ks_name) override;
virtual void on_create_column_family(const sstring& ks_name, const sstring& cf_name) override;
virtual void on_create_user_type(const sstring& ks_name, const sstring& type_name) override;
virtual void on_create_function(const sstring& ks_name, const sstring& function_name) override;
virtual void on_create_aggregate(const sstring& ks_name, const sstring& aggregate_name) override;
virtual void on_update_keyspace(const sstring& ks_name) override;
virtual void on_update_column_family(const sstring& ks_name, const sstring& cf_name) override;
virtual void on_update_user_type(const sstring& ks_name, const sstring& type_name) override;
virtual void on_update_function(const sstring& ks_name, const sstring& function_name) override;
virtual void on_update_aggregate(const sstring& ks_name, const sstring& aggregate_name) override;
virtual void on_drop_keyspace(const sstring& ks_name) override;
virtual void on_drop_column_family(const sstring& ks_name, const sstring& cf_name) override;
virtual void on_drop_user_type(const sstring& ks_name, const sstring& type_name) override;
virtual void on_drop_function(const sstring& ks_name, const sstring& function_name) override;
virtual void on_drop_aggregate(const sstring& ks_name, const sstring& aggregate_name) override;
private:
void remove_invalid_prepared_statements(sstring ks_name, std::experimental::optional<sstring> cf_name);
bool should_invalidate(sstring ks_name, std::experimental::optional<sstring> cf_name, ::shared_ptr<cql_statement> statement);
};
extern distributed<query_processor> _the_query_processor;
inline distributed<query_processor>& get_query_processor() {
return _the_query_processor;
}
inline query_processor& get_local_query_processor() {
return _the_query_processor.local();
}
}

View File

@@ -45,6 +45,16 @@ namespace statements {
logging::logger batch_statement::_logger("BatchStatement");
bool batch_statement::depends_on_keyspace(const sstring& ks_name) const
{
return false;
}
bool batch_statement::depends_on_column_family(const sstring& cf_name) const
{
return false;
}
}
}

View File

@@ -96,6 +96,10 @@ public:
|| boost::algorithm::any_of(_statements, [&] (auto&& s) { return s->uses_function(ks_name, function_name); });
}
virtual bool depends_on_keyspace(const sstring& ks_name) const override;
virtual bool depends_on_column_family(const sstring& cf_name) const override;
virtual uint32_t get_bound_terms() override {
return _bound_terms;
}

View File

@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2014-2015 ScyllaDB
*
* Modified by ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cql3/statements/cf_statement.hh"
namespace cql3 {
namespace statements {
cf_statement::cf_statement(::shared_ptr<cf_name> cf_name)
: _cf_name(std::move(cf_name))
{
}
void cf_statement::prepare_keyspace(const service::client_state& state)
{
if (!_cf_name->has_keyspace()) {
// XXX: We explicitely only want to call state.getKeyspace() in this case, as we don't want to throw
// if not logged in any keyspace but a keyspace is explicitely set on the statement. So don't move
// the call outside the 'if' or replace the method by 'prepareKeyspace(state.getKeyspace())'
_cf_name->set_keyspace(state.get_keyspace(), true);
}
}
void cf_statement::prepare_keyspace(sstring keyspace)
{
if (!_cf_name->has_keyspace()) {
_cf_name->set_keyspace(keyspace, true);
}
}
const sstring& cf_statement::keyspace() const
{
assert(_cf_name->has_keyspace()); // "The statement hasn't be prepared correctly";
return _cf_name->get_keyspace();
}
const sstring& cf_statement::column_family() const
{
return _cf_name->get_column_family();
}
}
}

View File

@@ -57,35 +57,16 @@ class cf_statement : public parsed_statement {
protected:
::shared_ptr<cf_name> _cf_name;
cf_statement(::shared_ptr<cf_name> cf_name)
: _cf_name(std::move(cf_name))
{ }
cf_statement(::shared_ptr<cf_name> cf_name);
public:
virtual void prepare_keyspace(const service::client_state& state) {
if (!_cf_name->has_keyspace()) {
// XXX: We explicitely only want to call state.getKeyspace() in this case, as we don't want to throw
// if not logged in any keyspace but a keyspace is explicitely set on the statement. So don't move
// the call outside the 'if' or replace the method by 'prepareKeyspace(state.getKeyspace())'
_cf_name->set_keyspace(state.get_keyspace(), true);
}
}
virtual void prepare_keyspace(const service::client_state& state);
// Only for internal calls, use the version with ClientState for user queries
virtual void prepare_keyspace(sstring keyspace) {
if (!_cf_name->has_keyspace()) {
_cf_name->set_keyspace(keyspace, true);
}
}
virtual void prepare_keyspace(sstring keyspace);
virtual const sstring& keyspace() const {
assert(_cf_name->has_keyspace()); // "The statement hasn't be prepared correctly";
return _cf_name->get_keyspace();
}
virtual const sstring& keyspace() const;
virtual const sstring& column_family() const {
return _cf_name->get_column_family();
}
virtual const sstring& column_family() const;
};
}

View File

@@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2015 ScyllaDB
*
* Modified by ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cql3/statements/create_keyspace_statement.hh"
#include "service/migration_manager.hh"
#include <regex>
namespace cql3 {
namespace statements {
create_keyspace_statement::create_keyspace_statement(const sstring& name, shared_ptr<ks_prop_defs> attrs, bool if_not_exists)
: _name{name}
, _attrs{attrs}
, _if_not_exists{if_not_exists}
{
}
const sstring& create_keyspace_statement::keyspace() const
{
return _name;
}
void create_keyspace_statement::check_access(const service::client_state& state)
{
warn(unimplemented::cause::PERMISSIONS);
#if 0
state.hasAllKeyspacesAccess(Permission.CREATE);
#endif
}
void create_keyspace_statement::validate(distributed<service::storage_proxy>&, const service::client_state& state)
{
std::string name;
name.resize(_name.length());
std::transform(_name.begin(), _name.end(), name.begin(), ::tolower);
if (name == db::system_keyspace::NAME) {
throw exceptions::invalid_request_exception("system keyspace is not user-modifiable");
}
// keyspace name
std::regex name_regex("\\w+");
if (!std::regex_match(name, name_regex)) {
throw exceptions::invalid_request_exception(sprint("\"%s\" is not a valid keyspace name", _name.c_str()));
}
if (name.length() > schema::NAME_LENGTH) {
throw exceptions::invalid_request_exception(sprint("Keyspace names shouldn't be more than %d characters long (got \"%s\")", schema::NAME_LENGTH, _name.c_str()));
}
_attrs->validate();
if (!bool(_attrs->get_replication_strategy_class())) {
throw exceptions::configuration_exception("Missing mandatory replication strategy class");
}
#if 0
// The strategy is validated through KSMetaData.validate() in announceNewKeyspace below.
// However, for backward compatibility with thrift, this doesn't validate unexpected options yet,
// so doing proper validation here.
AbstractReplicationStrategy.validateReplicationStrategy(name,
AbstractReplicationStrategy.getClass(attrs.getReplicationStrategyClass()),
StorageService.instance.getTokenMetadata(),
DatabaseDescriptor.getEndpointSnitch(),
attrs.getReplicationOptions());
#endif
}
future<bool> create_keyspace_statement::announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only)
{
return make_ready_future<>().then([this, is_local_only] {
return service::get_local_migration_manager().announce_new_keyspace(_attrs->as_ks_metadata(_name), is_local_only);
}).then_wrapped([this] (auto&& f) {
try {
f.get();
return true;
} catch (const exceptions::already_exists_exception& e) {
if (_if_not_exists) {
return false;
}
throw e;
}
});
}
shared_ptr<transport::event::schema_change> create_keyspace_statement::change_event()
{
return make_shared<transport::event::schema_change>(transport::event::schema_change::change_type::CREATED, keyspace());
}
}
}

View File

@@ -41,11 +41,8 @@
#pragma once
#include <regex>
#include "cql3/statements/schema_altering_statement.hh"
#include "cql3/statements/ks_prop_defs.hh"
#include "service/migration_manager.hh"
#include "transport/event.hh"
#include "core/shared_ptr.hh"
@@ -69,22 +66,11 @@ public:
* @param name the name of the keyspace to create
* @param attrs map of the raw keyword arguments that followed the <code>WITH</code> keyword.
*/
create_keyspace_statement(const sstring& name, shared_ptr<ks_prop_defs> attrs, bool if_not_exists)
: _name{name}
, _attrs{attrs}
, _if_not_exists{if_not_exists}
{ }
create_keyspace_statement(const sstring& name, shared_ptr<ks_prop_defs> attrs, bool if_not_exists);
virtual const sstring& keyspace() const override {
return _name;
}
virtual const sstring& keyspace() const override;
virtual void check_access(const service::client_state& state) override {
warn(unimplemented::cause::PERMISSIONS);
#if 0
state.hasAllKeyspacesAccess(Permission.CREATE);
#endif
}
virtual void check_access(const service::client_state& state) override;
/**
* The <code>CqlParser</code> only goes as far as extracting the keyword arguments
@@ -93,58 +79,11 @@ public:
*
* @throws InvalidRequestException if arguments are missing or unacceptable
*/
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override {
std::string name;
name.resize(_name.length());
std::transform(_name.begin(), _name.end(), name.begin(), ::tolower);
if (name == db::system_keyspace::NAME) {
throw exceptions::invalid_request_exception("system keyspace is not user-modifiable");
}
// keyspace name
std::regex name_regex("\\w+");
if (!std::regex_match(name, name_regex)) {
throw exceptions::invalid_request_exception(sprint("\"%s\" is not a valid keyspace name", _name.c_str()));
}
if (name.length() > schema::NAME_LENGTH) {
throw exceptions::invalid_request_exception(sprint("Keyspace names shouldn't be more than %d characters long (got \"%s\")", schema::NAME_LENGTH, _name.c_str()));
}
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override;
_attrs->validate();
virtual future<bool> announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only) override;
if (!bool(_attrs->get_replication_strategy_class())) {
throw exceptions::configuration_exception("Missing mandatory replication strategy class");
}
#if 0
// The strategy is validated through KSMetaData.validate() in announceNewKeyspace below.
// However, for backward compatibility with thrift, this doesn't validate unexpected options yet,
// so doing proper validation here.
AbstractReplicationStrategy.validateReplicationStrategy(name,
AbstractReplicationStrategy.getClass(attrs.getReplicationStrategyClass()),
StorageService.instance.getTokenMetadata(),
DatabaseDescriptor.getEndpointSnitch(),
attrs.getReplicationOptions());
#endif
}
virtual future<bool> announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only) override {
return make_ready_future<>().then([this, is_local_only] {
return service::get_local_migration_manager().announce_new_keyspace(_attrs->as_ks_metadata(_name), is_local_only);
}).then_wrapped([this] (auto&& f) {
try {
f.get();
return true;
} catch (const exceptions::already_exists_exception& e) {
if (_if_not_exists) {
return false;
}
throw e;
}
});
}
virtual shared_ptr<transport::event::schema_change> change_event() override {
return make_shared<transport::event::schema_change>(transport::event::schema_change::change_type::CREATED, keyspace());
}
virtual shared_ptr<transport::event::schema_change> change_event() override;
};
}

View File

@@ -541,6 +541,14 @@ modification_statement::validate(distributed<service::storage_proxy>&, const ser
}
}
bool modification_statement::depends_on_keyspace(const sstring& ks_name) const {
return keyspace() == ks_name;
}
bool modification_statement::depends_on_column_family(const sstring& cf_name) const {
return column_family() == cf_name;
}
}
}

View File

@@ -188,6 +188,10 @@ public:
void validate(distributed<service::storage_proxy>&, const service::client_state& state) override;
virtual bool depends_on_keyspace(const sstring& ks_name) const override;
virtual bool depends_on_column_family(const sstring& cf_name) const override;
void add_operation(::shared_ptr<operation> op) {
if (op->column.is_static()) {
_sets_static_columns = true;

View File

@@ -47,6 +47,50 @@ namespace cql3 {
namespace statements {
schema_altering_statement::schema_altering_statement()
: cf_statement{::shared_ptr<cf_name>{}}
, _is_column_family_level{false}
{
}
schema_altering_statement::schema_altering_statement(::shared_ptr<cf_name> name)
: cf_statement{std::move(name)}
, _is_column_family_level{true}
{
}
bool schema_altering_statement::uses_function(const sstring& ks_name, const sstring& function_name) const
{
return cf_statement::uses_function(ks_name, function_name);
}
bool schema_altering_statement::depends_on_keyspace(const sstring& ks_name) const
{
return false;
}
bool schema_altering_statement::depends_on_column_family(const sstring& cf_name) const
{
return false;
}
uint32_t schema_altering_statement::get_bound_terms()
{
return 0;
}
void schema_altering_statement::prepare_keyspace(const service::client_state& state)
{
if (_is_column_family_level) {
cf_statement::prepare_keyspace(state);
}
}
::shared_ptr<parsed_statement::prepared> schema_altering_statement::prepare(database& db)
{
return ::make_shared<parsed_statement::prepared>(this->shared_from_this());
}
future<::shared_ptr<messages::result_message>>
schema_altering_statement::execute0(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options, bool is_local_only) {
// If an IF [NOT] EXISTS clause was used, this may not result in an actual schema change. To avoid doing

View File

@@ -41,16 +41,7 @@
#pragma once
namespace transport {
namespace messages {
class result_message;
}
}
#include "transport/messages_fwd.hh"
#include "transport/event.hh"
#include "cql3/statements/cf_statement.hh"
@@ -76,33 +67,21 @@ private:
future<::shared_ptr<messages::result_message>>
execute0(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options, bool);
protected:
schema_altering_statement()
: cf_statement{::shared_ptr<cf_name>{}}
, _is_column_family_level{false}
{ }
schema_altering_statement();
schema_altering_statement(::shared_ptr<cf_name> name)
: cf_statement{std::move(name)}
, _is_column_family_level{true}
{ }
schema_altering_statement(::shared_ptr<cf_name> name);
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const override {
return cf_statement::uses_function(ks_name, function_name);
}
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const override;
virtual uint32_t get_bound_terms() override {
return 0;
}
virtual bool depends_on_keyspace(const sstring& ks_name) const override;
virtual void prepare_keyspace(const service::client_state& state) override {
if (_is_column_family_level) {
cf_statement::prepare_keyspace(state);
}
}
virtual bool depends_on_column_family(const sstring& cf_name) const override;
virtual ::shared_ptr<prepared> prepare(database& db) override {
return ::make_shared<parsed_statement::prepared>(this->shared_from_this());
}
virtual uint32_t get_bound_terms() override;
virtual void prepare_keyspace(const service::client_state& state) override;
virtual ::shared_ptr<prepared> prepare(database& db) override;
virtual shared_ptr<transport::event::schema_change> change_event() = 0;

View File

@@ -106,6 +106,14 @@ void select_statement::validate(distributed<service::storage_proxy>&, const serv
// Nothing to do, all validation has been done by raw_statemet::prepare()
}
bool select_statement::depends_on_keyspace(const sstring& ks_name) const {
return keyspace() == ks_name;
}
bool select_statement::depends_on_column_family(const sstring& cf_name) const {
return column_family() == cf_name;
}
query::partition_slice
select_statement::make_partition_slice(const query_options& options) {
std::vector<column_id> static_columns;

View File

@@ -132,6 +132,8 @@ public:
virtual uint32_t get_bound_terms() override;
virtual void check_access(const service::client_state& state) override;
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override;
virtual bool depends_on_keyspace(const sstring& ks_name) const;
virtual bool depends_on_column_family(const sstring& cf_name) const;
virtual future<::shared_ptr<transport::messages::result_message>> execute(distributed<service::storage_proxy>& proxy,
service::query_state& state, const query_options& options) override;
@@ -192,18 +194,16 @@ public:
QueryOptions options = QueryOptions.DEFAULT;
return process(rows, options, getLimit(options), System.currentTimeMillis());
}
public String keyspace()
{
return _schema.ks_name;
}
public String columnFamily()
{
return _schema.cfName;
}
#endif
const sstring& keyspace() const {
return _schema->ks_name();
}
const sstring& column_family() const {
return _schema->cf_name();
}
query::partition_slice make_partition_slice(const query_options& options);
#if 0

View File

@@ -68,6 +68,16 @@ bool truncate_statement::uses_function(const sstring& ks_name, const sstring& fu
return parsed_statement::uses_function(ks_name, function_name);
}
bool truncate_statement::depends_on_keyspace(const sstring& ks_name) const
{
return false;
}
bool truncate_statement::depends_on_column_family(const sstring& cf_name) const
{
return false;
}
void truncate_statement::check_access(const service::client_state& state)
{
warn(unimplemented::cause::AUTH);

View File

@@ -60,6 +60,10 @@ public:
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const override;
virtual bool depends_on_keyspace(const sstring& ks_name) const override;
virtual bool depends_on_column_family(const sstring& cf_name) const override;
virtual void check_access(const service::client_state& state) override;
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override;

View File

@@ -47,6 +47,45 @@ namespace cql3 {
namespace statements {
use_statement::use_statement(sstring keyspace)
: _keyspace(keyspace)
{
}
uint32_t use_statement::get_bound_terms()
{
return 0;
}
::shared_ptr<parsed_statement::prepared> use_statement::prepare(database& db)
{
return ::make_shared<parsed_statement::prepared>(this->shared_from_this());
}
bool use_statement::uses_function(const sstring& ks_name, const sstring& function_name) const
{
return parsed_statement::uses_function(ks_name, function_name);
}
bool use_statement::depends_on_keyspace(const sstring& ks_name) const
{
return false;
}
bool use_statement::depends_on_column_family(const sstring& cf_name) const
{
return false;
}
void use_statement::check_access(const service::client_state& state)
{
state.validate_login();
}
void use_statement::validate(distributed<service::storage_proxy>&, const service::client_state& state)
{
}
future<::shared_ptr<transport::messages::result_message>>
use_statement::execute(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) {
state.get_client_state().set_keyspace(proxy.local().get_db(), _keyspace);

View File

@@ -42,17 +42,9 @@
#pragma once
#include "cql3/statements/parsed_statement.hh"
#include "transport/messages_fwd.hh"
#include "cql3/cql_statement.hh"
namespace transport {
namespace messages {
class result_message;
}
}
namespace cql3 {
namespace statements {
@@ -62,49 +54,27 @@ private:
const sstring _keyspace;
public:
use_statement(sstring keyspace)
: _keyspace(keyspace)
{ }
use_statement(sstring keyspace);
virtual uint32_t get_bound_terms() override {
return 0;
}
virtual uint32_t get_bound_terms() override;
virtual ::shared_ptr<prepared> prepare(database& db) override {
return ::make_shared<parsed_statement::prepared>(this->shared_from_this());
}
virtual ::shared_ptr<prepared> prepare(database& db) override;
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const override {
return parsed_statement::uses_function(ks_name, function_name);
}
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const override;
virtual void check_access(const service::client_state& state) override {
state.validate_login();
}
virtual bool depends_on_keyspace(const sstring& ks_name) const override;
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override {
}
virtual bool depends_on_column_family(const sstring& cf_name) const override;
virtual void check_access(const service::client_state& state) override;
virtual void validate(distributed<service::storage_proxy>&, const service::client_state& state) override;
virtual future<::shared_ptr<transport::messages::result_message>>
execute(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) override;
virtual future<::shared_ptr<transport::messages::result_message>>
execute_internal(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) override;
#if 0
virtual future<::shared_ptr<transport::messages::result_message>>
execute(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) override {
state.get_client_state().set_keyspace(_keyspace);
auto result =::make_shared<transport::messages::result_message::set_keyspace>(_keyspace);
return make_ready_future<::shared_ptr<transport::messages::result_message>>(result);
}
virtual future<::shared_ptr<transport::messages::result_message>>
execute_internal(distributed<service::storage_proxy>& proxy, service::query_state& state, const query_options& options) override {
// Internal queries are exclusively on the system keyspace and 'use' is thus useless
throw std::runtime_error("unsupported operation");
}
#endif
};
}

View File

@@ -34,6 +34,7 @@
#include "cql3/column_identifier.hh"
#include "core/seastar.hh"
#include <seastar/core/sleep.hh>
#include <seastar/core/rwlock.hh>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include "sstables/sstables.hh"
@@ -53,20 +54,41 @@
#include "mutation_query.hh"
#include "sstable_mutation_readers.hh"
#include <core/fstream.hh>
#include <seastar/core/enum.hh>
#include "utils/latency.hh"
#include "utils/flush_queue.hh"
using namespace std::chrono_literals;
logging::logger dblog("database");
// Slight extension to the flush_queue type.
class column_family::memtable_flush_queue : public utils::flush_queue<db::replay_position> {
public:
template<typename Func, typename Post>
auto run_cf_flush(db::replay_position rp, Func&& func, Post&& post) {
// special case: empty rp, yet still data.
// We generate a few memtables with no valid, "high_rp", yet
// still containing data -> actual flush.
// And to make matters worse, we can initiate a flush of N such
// tables at the same time.
// Just queue them at the end of the queue and treat them as such.
if (rp == db::replay_position() && !empty()) {
rp = highest_key();
}
return run_with_ordered_post_op(rp, std::forward<Func>(func), std::forward<Post>(post));
}
};
column_family::column_family(schema_ptr schema, config config, db::commitlog& cl, compaction_manager& compaction_manager)
: _schema(std::move(schema))
, _config(std::move(config))
, _memtables(make_lw_shared(memtable_list{}))
, _sstables(make_lw_shared<sstable_list>())
, _cache(_schema, sstables_as_mutation_source(), global_cache_tracker())
, _cache(_schema, sstables_as_mutation_source(), sstables_as_key_source(), global_cache_tracker())
, _commitlog(&cl)
, _compaction_manager(compaction_manager)
, _flush_queue(std::make_unique<memtable_flush_queue>())
{
add_memtable();
if (!_config.enable_disk_writes) {
@@ -79,9 +101,10 @@ column_family::column_family(schema_ptr schema, config config, no_commitlog cl,
, _config(std::move(config))
, _memtables(make_lw_shared(memtable_list{}))
, _sstables(make_lw_shared<sstable_list>())
, _cache(_schema, sstables_as_mutation_source(), global_cache_tracker())
, _cache(_schema, sstables_as_mutation_source(), sstables_as_key_source(), global_cache_tracker())
, _commitlog(nullptr)
, _compaction_manager(compaction_manager)
, _flush_queue(std::make_unique<memtable_flush_queue>())
{
add_memtable();
if (!_config.enable_disk_writes) {
@@ -196,6 +219,24 @@ column_family::make_sstable_reader(const query::partition_range& pr) const {
}
}
key_source column_family::sstables_as_key_source() const {
return [this] (const query::partition_range& range) {
std::vector<key_reader> readers;
readers.reserve(_sstables->size());
std::transform(_sstables->begin(), _sstables->end(), std::back_inserter(readers), [&] (auto&& entry) {
auto& sst = entry.second;
auto rd = sstables::make_key_reader(_schema, sst, range);
if (sst->is_shared()) {
rd = make_filtering_reader(std::move(rd), [] (const dht::decorated_key& dk) {
return dht::shard_of(dk.token()) == engine().cpu_id();
});
}
return rd;
});
return make_combined_reader(_schema, std::move(readers));
};
}
// Exposed for testing, not performance critical.
future<column_family::const_mutation_partition_ptr>
column_family::find_partition(const dht::decorated_key& key) const {
@@ -259,8 +300,8 @@ column_family::make_reader(const query::partition_range& range) const {
// range queries in cache, so that scans can always be satisfied form
// memtable and cache only, as long as data is not evicted.
//
// https://github.com/cloudius-systems/urchin/issues/309
// https://github.com/cloudius-systems/urchin/issues/185
// https://github.com/scylladb/scylla/issues/309
// https://github.com/scylladb/scylla/issues/185
for (auto&& mt : *_memtables) {
readers.emplace_back(mt->make_reader(range));
@@ -315,14 +356,17 @@ column_family::for_all_partitions_slow(std::function<bool (const dht::decorated_
}
class lister {
public:
using dir_entry_types = std::unordered_set<directory_entry_type, enum_hash<directory_entry_type>>;
private:
file _f;
std::function<future<> (directory_entry de)> _walker;
directory_entry_type _expected_type;
dir_entry_types _expected_type;
subscription<directory_entry> _listing;
sstring _dirname;
public:
lister(file f, directory_entry_type type, std::function<future<> (directory_entry)> walker, sstring dirname)
lister(file f, dir_entry_types type, std::function<future<> (directory_entry)> walker, sstring dirname)
: _f(std::move(f))
, _walker(std::move(walker))
, _expected_type(type)
@@ -330,13 +374,13 @@ public:
, _dirname(dirname) {
}
static future<> scan_dir(sstring name, directory_entry_type type, std::function<future<> (directory_entry)> walker);
static future<> scan_dir(sstring name, dir_entry_types type, std::function<future<> (directory_entry)> walker);
protected:
future<> _visit(directory_entry de) {
return guarantee_type(std::move(de)).then([this] (directory_entry de) {
// Hide all synthetic directories and hidden files.
if ((de.type != _expected_type) || (de.name[0] == '.')) {
if ((!_expected_type.count(*(de.type))) || (de.name[0] == '.')) {
return make_ready_future<>();
}
return _walker(de);
@@ -359,8 +403,7 @@ private:
};
future<> lister::scan_dir(sstring name, directory_entry_type type, std::function<future<> (directory_entry)> walker) {
future<> lister::scan_dir(sstring name, lister::dir_entry_types type, std::function<future<> (directory_entry)> walker) {
return engine().open_directory(name).then([type, walker = std::move(walker), name] (file f) {
auto l = make_lw_shared<lister>(std::move(f), type, walker, name);
return l->done().then([l] { });
@@ -386,8 +429,7 @@ future<sstables::entry_descriptor> column_family::probe_file(sstring sstdir, sst
return make_ready_future<entry_descriptor>(std::move(comps));
}
// Make sure new sstables don't overwrite this one.
_sstable_generation = std::max<uint64_t>(_sstable_generation, comps.generation / smp::count + 1);
update_sstables_known_generation(comps.generation);
assert(_sstables->count(comps.generation) == 0);
auto sst = std::make_unique<sstables::sstable>(_schema->ks_name(), _schema->cf_name(), sstdir, comps.generation, comps.version, comps.format);
@@ -477,8 +519,17 @@ column_family::seal_active_memtable() {
);
_highest_flushed_rp = old->replay_position();
return seastar::with_gate(_in_flight_seals, [old, this] {
return flush_memtable_to_sstable(old);
return _flush_queue->run_cf_flush(old->replay_position(), [old, this] {
return repeat([this, old] {
return with_lock(_sstables_lock.for_read(), [this, old] {
_flush_queue->check_open_gate();
return try_flush_memtable_to_sstable(old);
});
});
}, [old, this] {
if (_commitlog) {
_commitlog->discard_completed_segments(_schema->id(), old->replay_position());
}
});
// FIXME: release commit log
// FIXME: provide back-pressure to upper layers
@@ -530,26 +581,13 @@ column_family::try_flush_memtable_to_sstable(lw_shared_ptr<memtable> old) {
try {
ret.get();
// FIXME: until the surrounding function returns a future and
// caller ensures ordering (i.e. finish flushing one or more sequential tables before
// doing the discard), this below is _not_ correct, since the use of replay_position
// depends on us reporting the factual highest position we've actually flushed,
// _and_ all positions (for a given UUID) below having been dealt with.
//
// Note that the whole scheme is also dependent on memtables being "allocated" in order,
// i.e. we may not flush a younger memtable before and older, and we need to use the
// highest rp.
if (_commitlog) {
_commitlog->discard_completed_segments(_schema->id(), old->replay_position());
}
_memtables->erase(boost::range::find(*_memtables, old));
dblog.debug("Memtable replaced");
trigger_compaction();
return make_ready_future<stop_iteration>(stop_iteration::yes);
} catch (std::exception& e) {
dblog.error("failed to write sstable: {}", e.what());
} catch (...) {
dblog.error("failed to write sstable: unknown error");
dblog.error("failed to write sstable: {}", std::current_exception());
}
return sleep(10s).then([] {
return make_ready_future<stop_iteration>(stop_iteration::no);
@@ -557,15 +595,6 @@ column_family::try_flush_memtable_to_sstable(lw_shared_ptr<memtable> old) {
});
}
future<>
column_family::flush_memtable_to_sstable(lw_shared_ptr<memtable> memt) {
return repeat([this, memt] {
return seastar::with_gate(_in_flight_seals, [memt, this] {
return try_flush_memtable_to_sstable(memt);
});
});
}
void
column_family::start() {
// FIXME: add option to disable automatic compaction.
@@ -575,70 +604,136 @@ column_family::start() {
future<>
column_family::stop() {
seal_active_memtable();
return _compaction_manager.remove(this).then([this] {
return _in_flight_seals.close().then([this] {
return make_ready_future<>();
return _flush_queue->close();
});
}
future<std::vector<sstables::entry_descriptor>>
column_family::reshuffle_sstables(int64_t start) {
struct work {
int64_t current_gen;
sstable_list sstables;
std::unordered_map<int64_t, sstables::entry_descriptor> descriptors;
std::vector<sstables::entry_descriptor> reshuffled;
work(int64_t start) : current_gen(start ? start : 1) {}
};
return do_with(work(start), [this] (work& work) {
return lister::scan_dir(_config.datadir, { directory_entry_type::regular }, [this, &work] (directory_entry de) {
auto comps = sstables::entry_descriptor::make_descriptor(de.name);
if (comps.component != sstables::sstable::component_type::TOC) {
return make_ready_future<>();
} else if (comps.generation < work.current_gen) {
return make_ready_future<>();
}
auto sst = make_lw_shared<sstables::sstable>(_schema->ks_name(), _schema->cf_name(),
_config.datadir, comps.generation,
comps.version, comps.format);
work.sstables.emplace(comps.generation, std::move(sst));
work.descriptors.emplace(comps.generation, std::move(comps));
// FIXME: This is the only place in which we actually issue disk activity aside from
// directory metadata operations.
//
// But without the TOC information, we don't know which files we should link.
// The alternative to that would be to change create link to try creating a
// link for all possible files and handling the failures gracefuly, but that's not
// exactly fast either.
//
// Those SSTables are not known by anyone in the system. So we don't have any kind of
// object describing them. There isn't too much of a choice.
return work.sstables[comps.generation]->read_toc();
}).then([&work] {
// Note: cannot be parallel because we will be shuffling things around at this stage. Can't race.
return do_for_each(work.sstables, [&work] (auto& pair) {
auto&& comps = std::move(work.descriptors.at(pair.first));
comps.generation = work.current_gen;
work.reshuffled.push_back(std::move(comps));
if (pair.first == work.current_gen) {
++work.current_gen;
return make_ready_future<>();
}
return pair.second->set_generation(work.current_gen++);
});
}).then([&work] {
return make_ready_future<std::vector<sstables::entry_descriptor>>(std::move(work.reshuffled));
});
});
}
future<>
column_family::compact_sstables(std::vector<sstables::shared_sstable> sstables) {
if (!sstables.size()) {
column_family::compact_sstables(sstables::compaction_descriptor descriptor) {
if (!descriptor.sstables.size()) {
// if there is nothing to compact, just return.
return make_ready_future<>();
}
auto sstables_to_compact = make_lw_shared<std::vector<sstables::shared_sstable>>(std::move(sstables));
return with_lock(_sstables_lock.for_read(), [this, descriptor = std::move(descriptor)] {
auto sstables_to_compact = make_lw_shared<std::vector<sstables::shared_sstable>>(std::move(descriptor.sstables));
auto new_tables = make_lw_shared<std::vector<
std::pair<unsigned, sstables::shared_sstable>>>();
auto create_sstable = [this, new_tables] {
// FIXME: this generation calculation should be in a function.
auto gen = _sstable_generation++ * smp::count + engine().cpu_id();
// FIXME: use "tmp" marker in names of incomplete sstable
auto sst = make_lw_shared<sstables::sstable>(_schema->ks_name(), _schema->cf_name(), _config.datadir, gen,
sstables::sstable::version_types::ka,
sstables::sstable::format_types::big);
sst->set_unshared();
new_tables->emplace_back(gen, sst);
return sst;
};
return sstables::compact_sstables(*sstables_to_compact, *this,
create_sstable).then([this, new_tables, sstables_to_compact] {
// Build a new list of _sstables: We remove from the existing list the
// tables we compacted (by now, there might be more sstables flushed
// later), and we add the new tables generated by the compaction.
// We create a new list rather than modifying it in-place, so that
// on-going reads can continue to use the old list.
auto current_sstables = _sstables;
_sstables = make_lw_shared<sstable_list>();
auto new_tables = make_lw_shared<std::vector<
std::pair<unsigned, sstables::shared_sstable>>>();
auto create_sstable = [this, new_tables] {
// FIXME: this generation calculation should be in a function.
auto gen = _sstable_generation++ * smp::count + engine().cpu_id();
// FIXME: use "tmp" marker in names of incomplete sstable
auto sst = make_lw_shared<sstables::sstable>(_schema->ks_name(), _schema->cf_name(), _config.datadir, gen,
sstables::sstable::version_types::ka,
sstables::sstable::format_types::big);
sst->set_unshared();
new_tables->emplace_back(gen, sst);
return sst;
};
return sstables::compact_sstables(*sstables_to_compact, *this,
create_sstable, descriptor.max_sstable_bytes, descriptor.level).then([this, new_tables, sstables_to_compact] {
// Build a new list of _sstables: We remove from the existing list the
// tables we compacted (by now, there might be more sstables flushed
// later), and we add the new tables generated by the compaction.
// We create a new list rather than modifying it in-place, so that
// on-going reads can continue to use the old list.
auto current_sstables = _sstables;
_sstables = make_lw_shared<sstable_list>();
// zeroing live_disk_space_used and live_sstable_count because the
// sstable list is re-created below.
_stats.live_disk_space_used = 0;
_stats.live_sstable_count = 0;
// zeroing live_disk_space_used and live_sstable_count because the
// sstable list is re-created below.
_stats.live_disk_space_used = 0;
_stats.live_sstable_count = 0;
std::unordered_set<sstables::shared_sstable> s(
sstables_to_compact->begin(), sstables_to_compact->end());
for (const auto& oldtab : *current_sstables) {
if (!s.count(oldtab.second)) {
update_stats_for_new_sstable(oldtab.second->data_size());
_sstables->emplace(oldtab.first, oldtab.second);
std::unordered_set<sstables::shared_sstable> s(
sstables_to_compact->begin(), sstables_to_compact->end());
for (const auto& oldtab : *current_sstables) {
if (!s.count(oldtab.second)) {
update_stats_for_new_sstable(oldtab.second->data_size());
_sstables->emplace(oldtab.first, oldtab.second);
}
for (const auto& newtab : *new_tables) {
// FIXME: rename the new sstable(s). Verify a rename doesn't cause
// problems for the sstable object.
update_stats_for_new_sstable(newtab.second->data_size());
_sstables->emplace(newtab.first, newtab.second);
}
for (const auto& oldtab : *sstables_to_compact) {
oldtab->mark_for_deletion();
}
}
}
});
});
}
for (const auto& newtab : *new_tables) {
// FIXME: rename the new sstable(s). Verify a rename doesn't cause
// problems for the sstable object.
update_stats_for_new_sstable(newtab.second->data_size());
_sstables->emplace(newtab.first, newtab.second);
}
for (const auto& oldtab : *sstables_to_compact) {
oldtab->mark_for_deletion();
}
future<>
column_family::load_new_sstables(std::vector<sstables::entry_descriptor> new_tables) {
return parallel_for_each(new_tables, [this] (auto comps) {
auto sst = make_lw_shared<sstables::sstable>(_schema->ks_name(), _schema->cf_name(), _config.datadir, comps.generation, comps.version, comps.format);
return sst->load().then([this, sst] {
return sst->mutate_sstable_level(0);
}).then([this, sst] {
this->add_sstable(sst);
return make_ready_future<>();
});
});
}
@@ -653,7 +748,7 @@ column_family::compact_all_sstables() {
}
// FIXME: check if the lower bound min_compaction_threshold() from schema
// should be taken into account before proceeding with compaction.
return compact_sstables(std::move(sstables));
return compact_sstables(sstables::compaction_descriptor(std::move(sstables)));
}
void column_family::start_compaction() {
@@ -728,7 +823,7 @@ future<> column_family::populate(sstring sstdir) {
auto verifier = make_lw_shared<std::unordered_map<unsigned long, status>>();
auto descriptor = make_lw_shared<sstable_descriptor>();
return lister::scan_dir(sstdir, directory_entry_type::regular, [this, sstdir, verifier, descriptor] (directory_entry de) {
return lister::scan_dir(sstdir, { directory_entry_type::regular }, [this, sstdir, verifier, descriptor] (directory_entry de) {
// FIXME: The secondary indexes are in this level, but with a directory type, (starting with ".")
return probe_file(sstdir, de.name).then([verifier, descriptor] (auto entry) {
if (verifier->count(entry.generation)) {
@@ -835,7 +930,7 @@ future<> database::populate_keyspace(sstring datadir, sstring ks_name) {
dblog.warn("Skipping undefined keyspace: {}", ks_name);
} else {
dblog.info("Populating Keyspace {}", ks_name);
return lister::scan_dir(ksdir, directory_entry_type::directory, [this, ksdir, ks_name] (directory_entry de) {
return lister::scan_dir(ksdir, { directory_entry_type::directory }, [this, ksdir, ks_name] (directory_entry de) {
auto comps = parse_fname(de.name);
if (comps.size() < 2) {
dblog.error("Keyspace {}: Skipping malformed CF {} ", ksdir, de.name);
@@ -860,7 +955,7 @@ future<> database::populate_keyspace(sstring datadir, sstring ks_name) {
}
future<> database::populate(sstring datadir) {
return lister::scan_dir(datadir, directory_entry_type::directory, [this, datadir] (directory_entry de) {
return lister::scan_dir(datadir, { directory_entry_type::directory }, [this, datadir] (directory_entry de) {
auto& ks_name = de.name;
if (ks_name == "system") {
return make_ready_future<>();
@@ -1163,7 +1258,7 @@ keyspace::column_family_directory(const sstring& name, utils::UUID uuid) const {
future<>
keyspace::make_directory_for_column_family(const sstring& name, utils::UUID uuid) {
return make_directory(column_family_directory(name, uuid));
return touch_directory(column_family_directory(name, uuid));
}
no_such_keyspace::no_such_keyspace(const sstring& ks_name)
@@ -1337,6 +1432,9 @@ column_family::query(const query::read_command& cmd, const std::vector<query::pa
});
}).finally([lc, this]() mutable {
_stats.reads.mark(lc);
if (lc.is_start()) {
_stats.estimated_read.add(lc.latency_in_nano(), _stats.reads.count);
}
});
}
@@ -1547,9 +1645,7 @@ database::stop() {
return _compaction_manager.stop().then([this] {
// try to ensure that CL has done disk flushing
if (_commitlog != nullptr) {
return _commitlog->shutdown().then([this] {
return _commitlog->sync_all_segments();
});
return _commitlog->shutdown();
}
return make_ready_future<>();
}).then([this] {
@@ -1700,7 +1796,18 @@ future<> column_family::snapshot(sstring name) {
return parallel_for_each(tables, [name](sstables::shared_sstable sstable) {
auto dir = sstable->get_dir() + "/snapshots/" + name;
return recursive_touch_directory(dir).then([sstable, dir] {
return sstable->create_links(dir);
return sstable->create_links(dir).then_wrapped([] (future<> f) {
// If the SSTables are shared, one of the CPUs will fail here.
// That is completely fine, though. We only need one link.
try {
f.get();
} catch (std::system_error& e) {
if (e.code() != std::error_code(EEXIST, std::system_category())) {
throw;
}
}
return make_ready_future<>();
});
});
}).then([jsondir, &tables] {
// This is not just an optimization. If we have no files, jsondir may not have been created,
@@ -1710,7 +1817,7 @@ future<> column_family::snapshot(sstring name) {
} else {
return make_ready_future<>();
}
}).then([this, &tables, jsondir] {
}).finally([this, &tables, jsondir] {
auto shard = std::hash<sstring>()(jsondir) % smp::count;
std::unordered_set<sstring> table_names;
for (auto& sst : tables) {
@@ -1749,6 +1856,124 @@ future<> column_family::snapshot(sstring name) {
});
}
future<bool> column_family::snapshot_exists(sstring tag) {
sstring jsondir = _config.datadir + "/snapshots/";
return engine().open_directory(std::move(jsondir)).then_wrapped([] (future<file> f) {
try {
f.get0();
return make_ready_future<bool>(true);
} catch (std::system_error& e) {
if (e.code() != std::error_code(ENOENT, std::system_category())) {
throw;
}
return make_ready_future<bool>(false);
}
});
}
enum class missing { no, yes };
static missing
file_missing(future<> f) {
try {
f.get();
return missing::no;
} catch (std::system_error& e) {
if (e.code() != std::error_code(ENOENT, std::system_category())) {
throw;
}
return missing::yes;
}
}
future<> column_family::clear_snapshot(sstring tag) {
sstring jsondir = _config.datadir + "/snapshots/";
sstring parent = _config.datadir;
if (!tag.empty()) {
jsondir += tag;
parent += "/snapshots/";
}
lister::dir_entry_types dir_and_files = { directory_entry_type::regular, directory_entry_type::directory };
return lister::scan_dir(jsondir, dir_and_files, [this, curr_dir = jsondir, dir_and_files, tag] (directory_entry de) {
// FIXME: We really need a better directory walker. This should eventually be part of the seastar infrastructure.
// It's hard to write this in a fully recursive manner because we need to keep information about the parent directory,
// so we can remove the file. For now, we'll take advantage of the fact that we will at most visit 2 levels and keep
// it ugly but simple.
auto recurse = make_ready_future<>();
if (de.type == directory_entry_type::directory) {
// Should only recurse when tag is empty, meaning delete all snapshots
if (!tag.empty()) {
throw std::runtime_error(sprint("Unexpected directory %s found at %s! Aborting", de.name, curr_dir));
}
auto newdir = curr_dir + "/" + de.name;
recurse = lister::scan_dir(newdir, dir_and_files, [this, curr_dir = newdir] (directory_entry de) {
return remove_file(curr_dir + "/" + de.name);
});
}
return recurse.then([fname = curr_dir + "/" + de.name] {
return remove_file(fname);
});
}).then_wrapped([jsondir] (future<> f) {
// Fine if directory does not exist. If it did, we delete it
if (file_missing(std::move(f)) == missing::no) {
return remove_file(jsondir);
}
return make_ready_future<>();
}).then([parent] {
return sync_directory(parent).then_wrapped([] (future<> f) {
// Should always exist for empty tags, but may not exist for a single tag if we never took
// snapshots. We will check this here just to mask out the exception, without silencing
// unexpected ones.
file_missing(std::move(f));
return make_ready_future<>();
});
});
}
future<std::unordered_map<sstring, column_family::snapshot_details>> column_family::get_snapshot_details() {
std::unordered_map<sstring, snapshot_details> all_snapshots;
return do_with(std::move(all_snapshots), [this] (auto& all_snapshots) {
return lister::scan_dir(_config.datadir + "/snapshots", { directory_entry_type::directory }, [this, &all_snapshots] (directory_entry de) {
auto snapshot_name = de.name;
auto snapshot = _config.datadir + "/snapshots/" + snapshot_name;
all_snapshots.emplace(snapshot_name, snapshot_details());
return lister::scan_dir(snapshot, { directory_entry_type::regular }, [this, &all_snapshots, snapshot, snapshot_name] (directory_entry de) {
return file_size(snapshot + "/" + de.name).then([this, &all_snapshots, snapshot_name, name = de.name] (auto size) {
// The manifest is the only file expected to be in this directory not belonging to the SSTable.
// For it, we account the total size, but zero it for the true size calculation.
//
// All the others should just generate an exception: there is something wrong, so don't blindly
// add it to the size.
if (name != "manifest.json") {
sstables::entry_descriptor::make_descriptor(name);
all_snapshots.at(snapshot_name).total += size;
} else {
size = 0;
}
return make_ready_future<uint64_t>(size);
}).then([this, &all_snapshots, snapshot_name, name = de.name] (auto size) {
// FIXME: When we support multiple data directories, the file may not necessarily
// live in this same location. May have to test others as well.
return file_size(_config.datadir + "/" + name).then_wrapped([&all_snapshots, snapshot_name, size] (auto fut) {
try {
// File exists in the main SSTable directory. Snapshots are not contributing to size
fut.get0();
} catch (std::system_error& e) {
if (e.code() != std::error_code(ENOENT, std::system_category())) {
throw;
}
all_snapshots.at(snapshot_name).live += size;
}
return make_ready_future<>();
});
});
});
}).then([&all_snapshots] {
return std::move(all_snapshots);
});
});
}
future<> column_family::flush() {
// FIXME: this will synchronously wait for this write to finish, but doesn't guarantee
// anything about previous writes.
@@ -1789,26 +2014,27 @@ void column_family::clear() {
future<db::replay_position> column_family::discard_sstables(db_clock::time_point truncated_at) {
assert(_stats.pending_compactions == 0);
db::replay_position rp;
auto gc_trunc = to_gc_clock(truncated_at);
return with_lock(_sstables_lock.for_read(), [this, truncated_at] {
db::replay_position rp;
auto gc_trunc = to_gc_clock(truncated_at);
auto pruned = make_lw_shared<sstable_list>();
auto pruned = make_lw_shared<sstable_list>();
for (auto&p : *_sstables) {
if (p.second->max_data_age() <= gc_trunc) {
rp = std::max(p.second->get_stats_metadata().position, rp);
p.second->mark_for_deletion();
continue;
for (auto&p : *_sstables) {
if (p.second->max_data_age() <= gc_trunc) {
rp = std::max(p.second->get_stats_metadata().position, rp);
p.second->mark_for_deletion();
continue;
}
pruned->emplace(p.first, p.second);
}
pruned->emplace(p.first, p.second);
}
_sstables = std::move(pruned);
_sstables = std::move(pruned);
dblog.debug("cleaning out row cache");
_cache.clear();
return make_ready_future<db::replay_position>(rp);
dblog.debug("cleaning out row cache");
_cache.clear();
return make_ready_future<db::replay_position>(rp);
});
}

View File

@@ -32,6 +32,7 @@
#include "utils/hash.hh"
#include "db_clock.hh"
#include "gc_clock.hh"
#include <chrono>
#include "core/distributed.hh"
#include <functional>
#include <cstdint>
@@ -67,6 +68,9 @@
#include "utils/exponential_backoff_retry.hh"
#include "utils/histogram.hh"
#include "sstables/estimated_histogram.hh"
#include "sstables/compaction.hh"
#include "key_reader.hh"
#include <seastar/core/rwlock.hh>
class frozen_mutation;
class reconcilable_result;
@@ -125,8 +129,15 @@ public:
utils::ihistogram writes{256};
sstables::estimated_histogram estimated_read;
sstables::estimated_histogram estimated_write;
sstables::estimated_histogram estimated_sstable_per_read;
utils::ihistogram tombstone_scanned;
utils::ihistogram live_scanned;
};
struct snapshot_details {
int64_t total;
int64_t live;
};
private:
schema_ptr _schema;
config _config;
@@ -134,8 +145,11 @@ private:
lw_shared_ptr<memtable_list> _memtables;
// generation -> sstable. Ordered by key so we can easily get the most recent.
lw_shared_ptr<sstable_list> _sstables;
// There are situations in which we need to stop writing sstables. Flushers will take
// the read lock, and the ones that wish to stop that process will take the write lock.
rwlock _sstables_lock;
mutable row_cache _cache; // Cache covers only sstables.
unsigned _sstable_generation = 1;
int64_t _sstable_generation = 1;
unsigned _mutation_count = 0;
db::replay_position _highest_flushed_rp;
// Provided by the database that owns this commitlog
@@ -145,15 +159,21 @@ private:
// Whether or not a cf is queued by its compaction manager.
bool _compaction_manager_queued = false;
int _compaction_disabled = 0;
class memtable_flush_queue;
std::unique_ptr<memtable_flush_queue> _flush_queue;
private:
void update_stats_for_new_sstable(uint64_t new_sstable_data_size);
void add_sstable(sstables::sstable&& sstable);
void add_sstable(lw_shared_ptr<sstables::sstable> sstable);
void add_memtable();
future<> flush_memtable_to_sstable(lw_shared_ptr<memtable> memt);
future<stop_iteration> try_flush_memtable_to_sstable(lw_shared_ptr<memtable> memt);
future<> update_cache(memtable&, lw_shared_ptr<sstable_list> old_sstables);
struct merge_comparator;
// update the sstable generation, making sure that new new sstables don't overwrite this one.
void update_sstables_known_generation(unsigned generation) {
_sstable_generation = std::max<uint64_t>(_sstable_generation, generation / smp::count + 1);
}
private:
// Creates a mutation reader which covers sstables.
// Caller needs to ensure that column_family remains live (FIXME: relax this).
@@ -161,7 +181,10 @@ private:
mutation_reader make_sstable_reader(const query::partition_range& range) const;
mutation_source sstables_as_mutation_source();
key_source sstables_as_key_source() const;
partition_presence_checker make_partition_presence_checker(lw_shared_ptr<sstable_list> old_sstables);
// We will use highres because hopefully it won't take more than a few usecs
std::chrono::high_resolution_clock::time_point _sstable_writes_disabled_at;
public:
// Creates a mutation reader which covers all data sources for this column family.
// Caller needs to ensure that column_family remains live (FIXME: relax this).
@@ -208,15 +231,52 @@ public:
void clear(); // discards memtable(s) without flushing them to disk.
future<db::replay_position> discard_sstables(db_clock::time_point);
// Important warning: disabling writes will only have an effect in the current shard.
// The other shards will keep writing tables at will. Therefore, you very likely need
// to call this separately in all shards first, to guarantee that none of them are writing
// new data before you can safely assume that the whole node is disabled.
future<int64_t> disable_sstable_write() {
_sstable_writes_disabled_at = std::chrono::high_resolution_clock::now();
return _sstables_lock.write_lock().then([this] {
return make_ready_future<int64_t>((*_sstables->end()).first);
});
}
// SSTable writes are now allowed again, and generation is updated to new_generation
// returns the amount of microseconds elapsed since we disabled writes.
std::chrono::high_resolution_clock::duration enable_sstable_write(int64_t new_generation) {
update_sstables_known_generation(new_generation);
_sstables_lock.write_unlock();
return std::chrono::high_resolution_clock::now() - _sstable_writes_disabled_at;
}
// Make sure the generation numbers are sequential, starting from "start".
// Generations before "start" are left untouched.
//
// Return the highest generation number seen so far
//
// Word of warning: although this function will reshuffle anything over "start", it is
// very dangerous to do that with live SSTables. This is meant to be used with SSTables
// that are not yet managed by the system.
//
// An example usage would query all shards asking what is the highest SSTable number known
// to them, and then pass that + 1 as "start".
future<std::vector<sstables::entry_descriptor>> reshuffle_sstables(int64_t start);
// FIXME: this is just an example, should be changed to something more
// general. compact_all_sstables() starts a compaction of all sstables.
// It doesn't flush the current memtable first. It's just a ad-hoc method,
// not a real compaction policy.
future<> compact_all_sstables();
// Compact all sstables provided in the vector.
future<> compact_sstables(std::vector<lw_shared_ptr<sstables::sstable>> sstables);
future<> compact_sstables(sstables::compaction_descriptor descriptor);
future<bool> snapshot_exists(sstring name);
future<> load_new_sstables(std::vector<sstables::entry_descriptor> new_tables);
future<> snapshot(sstring name);
future<> clear_snapshot(sstring name);
future<std::unordered_map<sstring, snapshot_details>> get_snapshot_details();
const bool incremental_backups_enabled() const {
return _config.enable_incremental_backups;
@@ -586,6 +646,9 @@ column_family::apply(const mutation& m, const db::replay_position& rp) {
active_memtable().apply(m, rp);
seal_on_overflow();
_stats.writes.mark(lc);
if (lc.is_start()) {
_stats.estimated_write.add(lc.latency_in_nano(), _stats.writes.count);
}
}
inline
@@ -617,6 +680,9 @@ column_family::apply(const frozen_mutation& m, const db::replay_position& rp) {
active_memtable().apply(m, rp);
seal_on_overflow();
_stats.writes.mark(lc);
if (lc.is_start()) {
_stats.estimated_write.add(lc.latency_in_nano(), _stats.writes.count);
}
}
future<> update_schema_version_and_announce(distributed<service::storage_proxy>& proxy);

View File

@@ -177,6 +177,15 @@ public:
stats totals;
void begin_op() {
_gate.enter();
++totals.pending_operations;
}
void end_op() {
--totals.pending_operations;
_gate.leave();
}
segment_manager(config c)
: cfg(c), max_size(
std::min<size_t>(std::numeric_limits<position_type>::max(),
@@ -192,10 +201,14 @@ public:
if (cfg.commit_log_location.empty()) {
cfg.commit_log_location = "/var/lib/scylla/commitlog";
}
logger.trace("Commitlog maximum disk size: {} MB / cpu ({} cpus)",
max_disk_size / (1024*1024), smp::count);
logger.trace("Commitlog {} maximum disk size: {} MB / cpu ({} cpus)",
cfg.commit_log_location, max_disk_size / (1024 * 1024),
smp::count);
_regs = create_counters();
}
~segment_manager() {
logger.trace("Commitlog {} disposed", cfg.commit_log_location);
}
uint64_t next_id() {
return ++_ids;
@@ -218,7 +231,9 @@ public:
void on_timer();
void sync();
void arm(uint32_t extra = 0) {
_timer.arm(std::chrono::milliseconds(cfg.commitlog_sync_period_in_ms + extra));
if (!_shutdown) {
_timer.arm(std::chrono::milliseconds(cfg.commitlog_sync_period_in_ms + extra));
}
}
std::vector<sstring> get_active_names() const;
@@ -371,6 +386,7 @@ public:
}
future<sseg_ptr> flush(uint64_t pos = 0) {
auto me = shared_from_this();
assert(!me.owned());
if (pos == 0) {
pos = _file_pos;
}
@@ -378,38 +394,35 @@ public:
logger.trace("{} already synced! ({} < {})", *this, pos, _flush_pos);
return make_ready_future<sseg_ptr>(std::move(me));
}
logger.trace("Syncing {} -> {}", _flush_pos, pos);
logger.trace("Syncing {} {} -> {}", *this, _flush_pos, pos);
// Make sure all disk writes are done.
// This is not 100% neccesary, we really only need the ones below our flush pos,
// but since we pretty much assume that task ordering will make this the case anyway...
return _dwrite.write_lock().then(
[this, me = std::move(me), pos]() mutable {
[this, me, pos]() mutable {
_dwrite.write_unlock(); // release it already.
pos = std::max(pos, _file_pos);
if (pos <= _flush_pos) {
logger.trace("{} already synced! ({} < {})", *this, pos, _flush_pos);
return make_ready_future<sseg_ptr>(std::move(me));
}
++_segment_manager->totals.pending_operations;
return _file.flush().handle_exception([](auto ex) {
_segment_manager->begin_op();
return _file.flush().then_wrapped([this, pos, me](auto f) {
try {
std::rethrow_exception(ex);
f.get();
// TODO: retry/ignore/fail/stop - optional behaviour in origin.
// we fast-fail the whole commit.
} catch (std::exception& e) {
logger.error("Failed to flush commits to disk: {}", e.what());
throw;
_flush_pos = std::max(pos, _flush_pos);
++_segment_manager->totals.flush_count;
logger.trace("{} synced to {}", *this, _flush_pos);
return make_ready_future<sseg_ptr>(std::move(me));
} catch (...) {
logger.error("Failed to flush commits to disk.");
logger.error("Failed to flush commits to disk: {}", std::current_exception());
throw;
}
}).then([this, pos, me = std::move(me)]() {
_flush_pos = std::max(pos, _flush_pos);
++_segment_manager->totals.flush_count;
logger.trace("{} synced to {}", *this, _flush_pos);
return make_ready_future<sseg_ptr>(std::move(me));
}).finally([this] {
--_segment_manager->totals.pending_operations;
}).finally([this, me] {
_segment_manager->end_op();
});
});
}
@@ -455,6 +468,8 @@ public:
_segment_manager->totals.total_size += k;
}
auto me = shared_from_this();
assert(!me.owned());
if (size == 0) {
return make_ready_future<sseg_ptr>(std::move(me));
}
@@ -489,9 +504,9 @@ public:
// acquire read lock
return _dwrite.read_lock().then([this, size, off, buf = std::move(buf), me]() mutable {
++_segment_manager->totals.pending_operations;
auto written = make_lw_shared<size_t>(0);
auto p = buf.get();
_segment_manager->begin_op();
return repeat([this, size, off, written, p]() mutable {
return _file.dma_write(off + *written, p + *written, size - *written).then_wrapped([this, size, written](auto&& f) {
try {
@@ -517,11 +532,11 @@ public:
});
}).finally([this, buf = std::move(buf)]() mutable {
_segment_manager->release_buffer(std::move(buf));
_segment_manager->end_op();
});
}).then([me] {
return make_ready_future<sseg_ptr>(std::move(me));
}).finally([me, this]() {
--_segment_manager->totals.pending_operations;
_dwrite.read_unlock(); // release
});
}
@@ -540,18 +555,22 @@ public:
+ std::to_string(_segment_manager->max_mutation_size)));
}
// would we make the file too big?
if (position() + s > _segment_manager->max_size) {
// do this in next segment instead.
return finish_and_get_new().then(
[id, size, func = std::move(func)](auto new_seg) {
return new_seg->allocate(id, size, func);
});
}
// enough data?
if (s > (_buffer.size() - _buf_pos)) {
// TODO: iff we have to many writes running, maybe we should
// wait for this?
cycle(s);
for (;;) {
if (position() + s > _segment_manager->max_size) {
// do this in next segment instead.
return finish_and_get_new().then(
[id, size, func = std::move(func)](auto new_seg) {
return new_seg->allocate(id, size, func);
});
}
// enough data?
if (s > (_buffer.size() - _buf_pos)) {
// TODO: iff we have to many writes running, maybe we should
// wait for this?
cycle(s);
continue; // re-check file size overflow
}
break;
}
_gate.enter(); // this might throw. I guess we accept this?
@@ -629,13 +648,19 @@ public:
bool is_still_allocating() const {
return !_closed && position() < _segment_manager->max_size;
}
bool is_clean() {
bool is_clean() const {
return _cf_dirty.empty();
}
bool is_unused() {
bool is_unused() const {
return !is_still_allocating() && is_clean();
}
bool contains(const replay_position& pos) {
bool is_flushed() const {
return position() <= _flush_pos;
}
bool can_delete() const {
return is_unused() && is_flushed();
}
bool contains(const replay_position& pos) const {
return pos.id == _desc.id;
}
sstring get_segment_name() const {
@@ -820,8 +845,11 @@ void db::commitlog::segment_manager::flush_segments(bool force) {
future<db::commitlog::segment_manager::sseg_ptr> db::commitlog::segment_manager::allocate_segment(bool active) {
descriptor d(next_id());
return engine().open_file_dma(cfg.commit_log_location + "/" + d.filename(), open_flags::wo | open_flags::create).then([this, d, active](file f) {
auto s = make_lw_shared<segment>(this, d, std::move(f), active);
return make_ready_future<sseg_ptr>(s);
// xfs doesn't like files extended betond eof, so enlarge the file
return f.truncate(max_size).then([this, d, active, f] () mutable {
auto s = make_lw_shared<segment>(this, d, std::move(f), active);
return make_ready_future<sseg_ptr>(s);
});
});
}
@@ -890,15 +918,19 @@ std::ostream& db::operator<<(std::ostream& out, const db::replay_position& p) {
}
void db::commitlog::segment_manager::discard_unused_segments() {
auto i = std::remove_if(_segments.begin(), _segments.end(), [=](auto& s) {
if (s->is_unused()) {
logger.trace("Checking for unused segments ({} active)", _segments.size());
auto i = std::remove_if(_segments.begin(), _segments.end(), [=](auto s) {
if (s->can_delete()) {
logger.debug("Segment {} is unused", *s);
return true;
}
if (s->is_still_allocating()) {
logger.debug("Not safe to delete segment {}; still allocating.", s);
} else {
} else if (!s->is_clean()) {
logger.debug("Not safe to delete segment {}; dirty is {}", s, segment::cf_mark {*s});
} else {
logger.debug("Not safe to delete segment {}; disk ops pending", s);
}
return false;
});
@@ -918,12 +950,12 @@ future<> db::commitlog::segment_manager::sync_all_segments() {
future<> db::commitlog::segment_manager::shutdown() {
if (!_shutdown) {
_shutdown = true;
_timer.cancel();
return _gate.close().then([this] {
return parallel_for_each(_segments, [this](sseg_ptr s) {
return s->shutdown();
});
_shutdown = true; // no re-arm, no create new segments.
_timer.cancel(); // no more timer calls
return parallel_for_each(_segments, [this](sseg_ptr s) {
return s->shutdown(); // close each segment (no more alloc)
}).then(std::bind(&segment_manager::sync_all_segments, this)).then([this] { // flush all
return _gate.close(); // wait for any pending ops
});
}
return make_ready_future<>();
@@ -936,11 +968,9 @@ future<> db::commitlog::segment_manager::shutdown() {
* Only use from tests.
*/
future<> db::commitlog::segment_manager::clear() {
logger.debug("Clearing all segments");
_shutdown = true;
_timer.cancel();
flush_segments(true);
return sync_all_segments().then([this] {
logger.debug("Clearing commitlog");
return shutdown().then([this] {
logger.debug("Clearing all segments");
for (auto& s : _segments) {
s->mark_clean();
}
@@ -951,30 +981,30 @@ future<> db::commitlog::segment_manager::clear() {
* Called by timer in periodic mode.
*/
void db::commitlog::segment_manager::sync() {
for (auto& s : _segments) {
for (auto s : _segments) {
s->sync(); // we do not care about waiting...
}
}
void db::commitlog::segment_manager::on_timer() {
if (cfg.mode != sync_mode::BATCH) {
sync();
}
// IFF a new segment was put in use since last we checked, and we're
// above threshold, request flush.
if (_new_counter > 0) {
auto max = max_disk_size;
auto cur = totals.total_size_on_disk;
if (max != 0 && cur >= max) {
_new_counter = 0;
logger.debug("Size on disk {} MB exceeds local maximum {} MB", cur / (1024 * 1024), max / (1024 * 1024));
flush_segments();
}
}
// Gate, because we are starting potentially blocking ops
// without waiting for them, so segement_manager could be shut down
// while they are running.
seastar::with_gate(_gate, [this] {
if (cfg.mode != sync_mode::BATCH) {
sync();
}
// IFF a new segment was put in use since last we checked, and we're
// above threshold, request flush.
if (_new_counter > 0) {
auto max = max_disk_size;
auto cur = totals.total_size_on_disk;
if (max != 0 && cur >= max) {
_new_counter = 0;
logger.debug("Size on disk {} MB exceeds local maximum {} MB", cur / (1024 * 1024), max / (1024 * 1024));
flush_segments();
}
}
// take outstanding allocations into regard. This is paranoid,
// but if for some reason the file::open takes longer than timer period,
// we could flood the reserve list with new segments
@@ -1190,6 +1220,10 @@ db::commitlog::read_log_file(file f, commit_load_reader_func next, position_type
});
});
}
future<> stop() {
eof = true;
return make_ready_future<>();
}
future<> read_header() {
return fin.read_exactly(segment::descriptor_header_size).then([this](temporary_buffer<char> buf) {
if (!advance(buf)) {
@@ -1202,6 +1236,12 @@ db::commitlog::read_log_file(file f, commit_load_reader_func next, position_type
auto id = in.read<uint64_t>();
auto checksum = in.read<uint32_t>();
if (ver == 0 && id == 0 && checksum == 0) {
// let's assume this was an empty (pre-allocated)
// file. just skip it.
return stop();
}
crc32_nbo crc;
crc.process(ver);
crc.process<int32_t>(id & 0xffffffff);
@@ -1230,6 +1270,11 @@ db::commitlog::read_log_file(file f, commit_load_reader_func next, position_type
auto next = in.read<uint32_t>();
auto checksum = in.read<uint32_t>();
if (next == 0 && checksum == 0) {
// in a pre-allocating world, this means eof
return stop();
}
crc32_nbo crc;
crc.process<int32_t>(id & 0xffffffff);
crc.process<int32_t>(id >> 32);
@@ -1264,7 +1309,7 @@ db::commitlog::read_log_file(file f, commit_load_reader_func next, position_type
auto checksum = in.read<uint32_t>();
if (size == 0) {
// special urchin case: zero padding due to dma blocks
// special scylla case: zero padding due to dma blocks
auto slack = next - pos;
return skip(slack);
}

View File

@@ -23,6 +23,7 @@
#pragma once
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <unordered_map>
#include "core/sstring.hh"
#include "core/future.hh"
@@ -112,6 +113,32 @@ public:
future<> read_from_file(const sstring&);
future<> read_from_file(file);
/**
* Scans the environment variables for configuration files directory
* definition. It's either $SCYLLA_CONF, $SCYLLA_HOME/conf or "conf" if none
* of SCYLLA_CONF and SCYLLA_HOME is defined.
*
* @return path of the directory where configuration files are located
* according the environment variables definitions.
*/
static boost::filesystem::path get_conf_dir() {
using namespace boost::filesystem;
path confdir;
auto* cd = std::getenv("SCYLLA_CONF");
if (cd != nullptr) {
confdir = path(cd);
} else {
auto* p = std::getenv("SCYLLA_HOME");
if (p != nullptr) {
confdir = path(p);
}
confdir /= "conf";
}
return confdir;
}
typedef std::unordered_map<sstring, sstring> string_map;
typedef std::vector<sstring> string_list;
using seed_provider_type = db::seed_provider_type;
@@ -132,7 +159,7 @@ public:
* type: is the value type (bool, uint32_t etc)
* status: is the current _usage_ of the opt. I.e. if you actually use the value, set it to "Used".
* Most values are set to "Unused", as in "will probably have an effect eventually".
* Values set to "Invalid" have no meaning/usage in urchin, and should (and will currently)
* Values set to "Invalid" have no meaning/usage in scylla, and should (and will currently)
* be signaled to a user providing a config with them, that these settings are pointless.
* desc: documentation.
* value...: enumerated valid values if any. Not currently used, but why not...
@@ -715,6 +742,7 @@ public:
val(api_address, sstring, "", Used, "Http Rest API address") \
val(api_ui_dir, sstring, "swagger-ui/dist/", Used, "The directory location of the API GUI") \
val(api_doc_dir, sstring, "api/api-doc/", Used, "The API definition file directory") \
val(load_balance, sstring, "none", Used, "CQL request load balancing: 'none' or round-robin'") \
/* done! */
#define _make_value_member(name, type, deflt, status, desc, ...) \

View File

@@ -52,6 +52,7 @@
#include "core/do_with.hh"
#include "core/thread.hh"
#include "json.hh"
#include "log.hh"
#include "db/marshal/type_parser.hh"
#include "db/config.hh"
@@ -67,6 +68,8 @@ using namespace db::system_keyspace;
namespace db {
namespace schema_tables {
logging::logger logger("schema_tables");
std::vector<const char*> ALL { KEYSPACES, COLUMNFAMILIES, COLUMNS, TRIGGERS, USERTYPES, /* not present in 2.1.8: FUNCTIONS, AGGREGATES */ };
using days = std::chrono::duration<int, std::ratio<24 * 3600>>;
@@ -670,6 +673,8 @@ future<> merge_tables(distributed<service::storage_proxy>& proxy, schema_result&
if (engine().cpu_id() == 0) {
for (auto&& cfm : created) {
service::migration_manager::notify_create_column_family(cfm).get0();
auto& ks = db.find_keyspace(cfm->ks_name());
ks.make_directory_for_column_family(cfm->cf_name(), cfm->id());
}
for (auto&& cfm : dropped) {
service::migration_manager::notify_drop_column_family(cfm).get0();
@@ -1325,9 +1330,15 @@ void create_table_from_table_row_and_column_rows(schema_builder& builder, const
builder.set_speculative_retry(table_row.get_nonnull<sstring>("speculative_retry"));
}
if (table_row.has("compaction_strategy")) {
auto strategy = table_row.get_nonnull<sstring>("compression_strategy_class");
builder.set_compaction_strategy(sstables::compaction_strategy::type(strategy));
if (table_row.has("compaction_strategy_class")) {
auto strategy = table_row.get_nonnull<sstring>("compaction_strategy_class");
try {
builder.set_compaction_strategy(sstables::compaction_strategy::type(strategy));
} catch (const exceptions::configuration_exception& e) {
// If compaction strategy class isn't supported, fallback to size tiered.
logger.warn("Falling back to size-tiered compaction strategy after the problem: {}", e.what());
builder.set_compaction_strategy(sstables::compaction_strategy_type::size_tiered);
}
}
if (table_row.has("compaction_strategy_options")) {

View File

@@ -505,6 +505,10 @@ future<> setup(distributed<database>& db, distributed<cql3::query_processor>& qp
return check_health();
}).then([] {
return db::schema_tables::save_system_keyspace_schema();
}).then([] {
return net::get_messaging_service().invoke_on_all([] (auto& ms){
return ms.init_local_preferred_ip_cache();
});
});
return make_ready_future<>();
}
@@ -714,11 +718,28 @@ future<std::unordered_map<gms::inet_address, utils::UUID>> load_host_ids() {
future<> update_preferred_ip(gms::inet_address ep, gms::inet_address preferred_ip) {
sstring req = "INSERT INTO system.%s (peer, preferred_ip) VALUES (?, ?)";
return execute_cql(req, PEERS, ep.addr(), preferred_ip).discard_result().then([] {
return execute_cql(req, PEERS, ep.addr(), preferred_ip.addr()).discard_result().then([] {
return force_blocking_flush(PEERS);
});
}
future<std::unordered_map<gms::inet_address, gms::inet_address>> get_preferred_ips() {
sstring req = "SELECT peer, preferred_ip FROM system.%s";
return execute_cql(req, PEERS).then([] (::shared_ptr<cql3::untyped_result_set> cql_res_set) {
std::unordered_map<gms::inet_address, gms::inet_address> res;
for (auto& r : *cql_res_set) {
if (r.has("preferred_ip")) {
res.emplace(gms::inet_address(r.get_as<net::ipv4_address>("peer")),
gms::inet_address(r.get_as<net::ipv4_address>("preferred_ip")));
}
}
return res;
});
}
template <typename Value>
static future<> update_cached_values(gms::inet_address ep, sstring column_name, Value value) {
return make_ready_future<>();

View File

@@ -94,6 +94,7 @@ future<> update_tokens(std::unordered_set<dht::token> tokens);
future<> update_tokens(gms::inet_address ep, std::unordered_set<dht::token> tokens);
future<> update_preferred_ip(gms::inet_address ep, gms::inet_address preferred_ip);
future<std::unordered_map<gms::inet_address, gms::inet_address>> get_preferred_ips();
template <typename Value>
future<> update_peer_info(gms::inet_address ep, sstring column_name, Value value);

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
9

20
debian/control vendored Normal file
View File

@@ -0,0 +1,20 @@
Source: scylla-server
Maintainer: Takuya ASADA <syuu@scylladb.com>
Homepage: http://scylladb.com
Section: database
Priority: optional
Standards-Version: 3.9.2
Build-Depends: debhelper (>= 9), libyaml-cpp-dev, liblz4-dev, libsnappy-dev, libcrypto++-dev, libjsoncpp-dev, libaio-dev, libthrift-dev, thrift-compiler, antlr3-tool, antlr3-c++-dev, ragel, g++-4.9, ninja-build, git, libboost-program-options1.55-dev, libboost-filesystem1.55-dev, libboost-system1.55-dev, libboost-thread1.55-dev, libboost-test1.55-dev
Package: scylla-server
Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}, hugepages
Description: Scylla database server binaries
Scylla is a highly scalable, eventually consistent, distributed, partitioned row DB.
Package: scylla-server-dbg
Architecture: amd64
Depends: scylla-server (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: debugging symbols for scylla-server
Scylla is a highly scalable, eventually consistent, distributed, partitioned row DB.
This package contains the debugging symbols for scylla-server.

16
debian/copyright vendored Normal file
View File

@@ -0,0 +1,16 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Scylla DB
Upstream-Contact: http://www.scylladb.com/
Source: https://github.com/scylladb/scylla
Files: *
Copyright: Copyright (C) 2015 ScyllaDB
License: AGPL-3.0
Files: seastar/*
Copyright: Copyright (C) 2015 ScyllaDB
License: Apache
Files: seastar/dpdk/*
Copyright: Copyright(c) 2015 Intel Corporation. All rights reserved.
License: BSD-3-clause

4
debian/limits.d/scylla.conf vendored Normal file
View File

@@ -0,0 +1,4 @@
scylla - memlock unlimited
scylla - nofile 100000
scylla - as unlimited
scylla - nproc 8096

50
debian/rules vendored Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/make -f
DOC = $(CURDIR)/debian/scylla-server/usr/share/doc/scylla-server
SCRIPTS = $(CURDIR)/debian/scylla-server/usr/lib/scylla
LIMITS= $(CURDIR)/debian/scylla-server/etc/security/limits.d
LIBS = $(CURDIR)/debian/scylla-server/usr/lib
override_dh_auto_build:
./configure.py --disable-xen --enable-dpdk --mode=release --static-stdc++ --compiler=g++-4.9
ninja
override_dh_auto_clean:
rm -rf build/release seastar/build
rm -rf Cql.tokens
rm -rf build.ninja seastar/build.ninja
override_dh_auto_install:
mkdir -p $(CURDIR)/debian/scylla-server/etc/default/ && \
cp $(CURDIR)/dist/redhat/sysconfig/scylla-server \
$(CURDIR)/debian/scylla-server/etc/default/
mkdir -p $(LIMITS) && \
cp $(CURDIR)/debian/limits.d/scylla.conf $(LIMITS)
mkdir -p $(DOC) && \
cp $(CURDIR)/*.md $(DOC)
cp $(CURDIR)/NOTICE.txt $(DOC)
cp $(CURDIR)/ORIGIN $(DOC)
cp -r $(CURDIR)/licenses $(DOC)
mkdir -p $(SCRIPTS) && \
cp $(CURDIR)/seastar/dpdk/tools/dpdk_nic_bind.py $(SCRIPTS)
cp $(CURDIR)/dist/common/scripts/* $(SCRIPTS)
mkdir -p $(CURDIR)/debian/scylla-server/usr/bin/ && \
cp $(CURDIR)/build/release/scylla \
$(CURDIR)/debian/scylla-server/usr/bin/
mkdir -p $(CURDIR)/debian/scylla-server/var/lib/scylla/data
mkdir -p $(CURDIR)/debian/scylla-server/var/lib/scylla/commitlog
mkdir -p $(CURDIR)/debian/scylla-server/var/lib/scylla/conf
cp $(CURDIR)/conf/scylla.yaml \
$(CURDIR)/debian/scylla-server/var/lib/scylla/conf
cp $(CURDIR)/conf/cassandra-rackdc.properties \
$(CURDIR)/debian/scylla-server/var/lib/scylla/conf
override_dh_strip:
dh_strip --dbg-package=scylla-server-dbg
%:
dh $@

View File

@@ -14,3 +14,4 @@ elif [ "$NETWORK_MODE" = "dpdk" ]; then
echo $NR_HUGEPAGES > $n/hugepages/hugepages-2048kB/nr_hugepages
done
fi
hugeadm --create-mounts

13
debian/scripts/scylla_run vendored Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh -e
args="--datadir $DATA_DIR --commitlog-directory $COMMITLOG_DIR $SCYLLA_ARGS"
if [ "$NETWORK_MODE" = "virtio" ]; then
args="$args --network-stack native"
elif [ "$NETWORK_MODE" = "dpdk" ]; then
args="$args --network-stack native --dpdk-pmd"
elif [ "$NETWORK_MODE" = "posix" ]; then
args="$args --network-stack posix"
fi
exec sudo -u $USER env HOME=/var/lib/scylla /usr/bin/scylla $args

24
debian/scylla-server.postinst vendored Normal file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -e
if [ "$1" = configure ]; then
adduser --system \
--quiet \
--home /var/lib/scylla \
--no-create-home \
--disabled-password \
--group scylla
chown -R scylla:scylla /var/lib/scylla
fi
# Automatically added by dh_installinit
if [ -x "/etc/init.d/scylla-server" ]; then
if [ ! -e "/etc/init/scylla-server.conf" ]; then
update-rc.d scylla-server defaults >/dev/null
fi
fi
# End automatically added section
# Automatically added by dh_installinit
update-rc.d -f scylla-server remove >/dev/null || exit $?
# End automatically added section

9
debian/scylla-server.preinst vendored Normal file
View File

@@ -0,0 +1,9 @@
# Automatically added by dh_installinit
if [ "$1" = install ] || [ "$1" = upgrade ]; then
if [ -e "/etc/init.d/scylla-server" ] && [ -L "/etc/init.d/scylla-server" ] \
&& [ $(readlink -f "/etc/init.d/scylla-server") = /lib/init/upstart-job ]
then
rm -f "/etc/init.d/scylla-server"
fi
fi
# End automatically added section

33
debian/scylla-server.upstart vendored Normal file
View File

@@ -0,0 +1,33 @@
# scylla-server - ScyllaDB
#
# ScyllaDB
description "ScyllaDB server"
start on runlevel [2345]
stop on runlevel [!2345]
umask 022
console log
pre-start script
cd /var/lib/scylla
. /etc/default/scylla-server
export OPTS_FILE NETWORK_MODE TAP BRIDGE ETHDRV ETHPCIID NR_HUGEPAGES USER GROUP SCYLLA_ARGS
/usr/lib/scylla/scylla_prepare
end script
script
cd /var/lib/scylla
. /etc/default/scylla-server
export OPTS_FILE NETWORK_MODE TAP BRIDGE ETHDRV ETHPCIID NR_HUGEPAGES USER GROUP SCYLLA_ARGS
exec /usr/lib/scylla/scylla_run
end script
post-stop script
cd /var/lib/scylla
. /etc/default/scylla-server
export OPTS_FILE NETWORK_MODE TAP BRIDGE ETHDRV ETHPCIID NR_HUGEPAGES USER GROUP SCYLLA_ARGS
/usr/lib/scylla/scylla_stop
end script

View File

@@ -38,40 +38,36 @@
#include "dht/boot_strapper.hh"
#include "service/storage_service.hh"
#include "dht/range_streamer.hh"
#include "gms/failure_detector.hh"
#include "log.hh"
static logging::logger logger("boot_strapper");
namespace dht {
future<> boot_strapper::bootstrap() {
// FIXME: Stream data from other nodes
service::get_local_storage_service().finish_bootstrapping();
return make_ready_future<>();
#if 0
if (logger.isDebugEnabled())
logger.debug("Beginning bootstrap process");
logger.debug("Beginning bootstrap process: sorted_tokens={}", _token_metadata.sorted_tokens());
RangeStreamer streamer = new RangeStreamer(tokenMetadata, tokens, address, "Bootstrap");
streamer.addSourceFilter(new RangeStreamer.FailureDetectorSourceFilter(FailureDetector.instance));
for (String keyspaceName : Schema.instance.getNonSystemKeyspaces())
{
AbstractReplicationStrategy strategy = Keyspace.open(keyspaceName).getReplicationStrategy();
streamer.addRanges(keyspaceName, strategy.getPendingAddressRanges(tokenMetadata, tokens, address));
auto streamer = make_lw_shared<range_streamer>(_db, _token_metadata, _tokens, _address, "Bootstrap");
streamer->add_source_filter(std::make_unique<range_streamer::failure_detector_source_filter>(gms::get_local_failure_detector()));
for (const auto& keyspace_name : _db.local().get_non_system_keyspaces()) {
auto& ks = _db.local().find_keyspace(keyspace_name);
auto& strategy = ks.get_replication_strategy();
std::vector<range<token>> ranges = strategy.get_pending_address_ranges(_token_metadata, _tokens, _address);
logger.debug("Will stream keyspace={}, ranges={}", keyspace_name, ranges);
streamer->add_ranges(keyspace_name, ranges);
}
try
{
streamer.fetchAsync().get();
StorageService.instance.finishBootstrapping();
}
catch (InterruptedException e)
{
throw new RuntimeException("Interrupted while waiting on boostrap to complete. Bootstrap will have to be restarted.");
}
catch (ExecutionException e)
{
throw new RuntimeException("Error during boostrap: " + e.getCause().getMessage(), e.getCause());
}
#endif
return streamer->fetch_async().then_wrapped([streamer] (auto&& f) {
try {
auto state = f.get0();
} catch (...) {
throw std::runtime_error(sprint("Error during boostrap: %s", std::current_exception()));
}
service::get_local_storage_service().finish_bootstrapping();
return make_ready_future<>();
});
}
std::unordered_set<token> boot_strapper::get_bootstrap_tokens(token_metadata metadata, database& db) {
@@ -100,7 +96,9 @@ std::unordered_set<token> boot_strapper::get_bootstrap_tokens(token_metadata met
// if (numTokens == 1)
// logger.warn("Picking random token for a single vnode. You should probably add more vnodes; failing that, you should probably specify the token manually");
return get_random_tokens(metadata, num_tokens);
auto tokens = get_random_tokens(metadata, num_tokens);
logger.debug("Get bootstrap_tokens={}", tokens);
return tokens;
}
std::unordered_set<token> boot_strapper::get_random_tokens(token_metadata metadata, size_t num_tokens) {

View File

@@ -49,14 +49,16 @@ class boot_strapper {
using inet_address = gms::inet_address;
using token_metadata = locator::token_metadata;
using token = dht::token;
distributed<database>& _db;
/* endpoint that needs to be bootstrapped */
inet_address _address;
/* token of the node being bootstrapped. */
std::unordered_set<token> _tokens;
token_metadata _token_metadata;
public:
boot_strapper(inet_address addr, std::unordered_set<token> tokens, token_metadata tmd)
: _address(addr)
boot_strapper(distributed<database>& db, inet_address addr, std::unordered_set<token> tokens, token_metadata tmd)
: _db(db)
, _address(addr)
, _tokens(tokens)
, _token_metadata(tmd) {
}

View File

@@ -44,11 +44,19 @@ token byte_ordered_partitioner::midpoint(const token& t1, const token& t2) const
unsigned
byte_ordered_partitioner::shard_of(const token& t) const {
if (t._data.empty()) {
return 0;
switch (t._kind) {
case token::kind::before_all_keys:
return 0;
case token::kind::after_all_keys:
return smp::count - 1;
case token::kind::key:
if (t._data.empty()) {
return 0;
}
// treat first byte as a fraction in the range [0, 1) and divide it evenly:
return (uint8_t(t._data[0]) * smp::count) >> 8;
}
// treat first byte as a fraction in the range [0, 1) and divide it evenly:
return (uint8_t(t._data[0]) * smp::count) >> 8;
assert(0);
}
using registry = class_registrator<i_partitioner, byte_ordered_partitioner>;

View File

@@ -161,12 +161,7 @@ std::ostream& operator<<(std::ostream& out, const token& t) {
} else if (t._kind == token::kind::before_all_keys) {
out << "minimum token";
} else {
auto flags = out.flags();
for (auto c : t._data) {
unsigned char x = c;
out << std::hex << std::setw(2) << std::setfill('0') << +x << " ";
}
out.flags(flags);
out << global_partitioner().to_sstring(t);
}
return out;
}
@@ -297,6 +292,10 @@ int ring_position_comparator::operator()(const ring_position& lh, const ring_pos
return lh.tri_compare(s, rh);
}
int token_comparator::operator()(const token& t1, const token& t2) const {
return tri_compare(t1, t2);
}
void token::serialize(bytes::iterator& out) const {
uint8_t kind = _kind == dht::token::kind::before_all_keys ? 0 :
_kind == dht::token::kind::key ? 1 : 2;

View File

@@ -159,6 +159,8 @@ public:
}
};
using decorated_key_opt = std::experimental::optional<decorated_key>;
class i_partitioner {
public:
virtual ~i_partitioner() {}
@@ -390,6 +392,11 @@ struct ring_position_comparator {
int operator()(const ring_position& lh, const ring_position& rh) const;
};
struct token_comparator {
// Return values are those of a trichotomic comparison.
int operator()(const token& t1, const token& t2) const;
};
std::ostream& operator<<(std::ostream& out, const token& t);
std::ostream& operator<<(std::ostream& out, const decorated_key& t);

View File

@@ -178,11 +178,19 @@ murmur3_partitioner::get_token_validator() {
unsigned
murmur3_partitioner::shard_of(const token& t) const {
int64_t l = long_token(t);
// treat l as a fraction between 0 and 1 and use 128-bit arithmetic to
// divide that range evenly among shards:
uint64_t adjusted = uint64_t(l) + uint64_t(std::numeric_limits<int64_t>::min());
return (__int128(adjusted) * smp::count) >> 64;
switch (t._kind) {
case token::kind::before_all_keys:
return 0;
case token::kind::after_all_keys:
return smp::count - 1;
case token::kind::key:
int64_t l = long_token(t);
// treat l as a fraction between 0 and 1 and use 128-bit arithmetic to
// divide that range evenly among shards:
uint64_t adjusted = uint64_t(l) + uint64_t(std::numeric_limits<int64_t>::min());
return (__int128(adjusted) * smp::count) >> 64;
}
assert(0);
}
using registry = class_registrator<i_partitioner, murmur3_partitioner>;

271
dht/range_streamer.cc Normal file
View File

@@ -0,0 +1,271 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified by Cloudius Systems
* Copyright 2015 Cloudius Systems
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dht/range_streamer.hh"
#include "utils/fb_utilities.hh"
#include "locator/snitch_base.hh"
#include "database.hh"
#include "gms/gossiper.hh"
#include "log.hh"
#include "streaming/stream_plan.hh"
#include "streaming/stream_state.hh"
namespace dht {
logging::logger logger("range_streamer");
using inet_address = gms::inet_address;
static std::unordered_map<range<token>, std::unordered_set<inet_address>>
unordered_multimap_to_unordered_map(const std::unordered_multimap<range<token>, inet_address>& multimap) {
std::unordered_map<range<token>, std::unordered_set<inet_address>> ret;
for (auto x : multimap) {
auto& range_token = x.first;
auto& ep = x.second;
auto it = ret.find(range_token);
if (it != ret.end()) {
it->second.emplace(ep);
} else {
ret.emplace(range_token, std::unordered_set<inet_address>{ep});
}
}
return ret;
}
std::unordered_multimap<inet_address, range<token>>
range_streamer::get_range_fetch_map(const std::unordered_multimap<range<token>, inet_address>& ranges_with_sources,
const std::unordered_set<std::unique_ptr<i_source_filter>>& source_filters,
const sstring& keyspace) {
std::unordered_multimap<inet_address, range<token>> range_fetch_map_map;
for (auto x : unordered_multimap_to_unordered_map(ranges_with_sources)) {
const range<token>& range_ = x.first;
const std::unordered_set<inet_address>& addresses = x.second;
bool found_source = false;
for (auto address : addresses) {
if (address == utils::fb_utilities::get_broadcast_address()) {
// If localhost is a source, we have found one, but we don't add it to the map to avoid streaming locally
found_source = true;
continue;
}
auto filtered = false;
for (const auto& filter : source_filters) {
if (!filter->should_include(address)) {
filtered = true;
break;
}
}
if (filtered) {
continue;
}
range_fetch_map_map.emplace(address, range_);
found_source = true;
break; // ensure we only stream from one other node for each range
}
if (!found_source) {
throw std::runtime_error(sprint("unable to find sufficient sources for streaming range %s in keyspace %s", range_, keyspace));
}
}
return range_fetch_map_map;
}
std::unordered_multimap<range<token>, inet_address>
range_streamer::get_all_ranges_with_sources_for(const sstring& keyspace_name, std::vector<range<token>> desired_ranges) {
logger.debug("{} ks={}", __func__, keyspace_name);
auto& ks = _db.local().find_keyspace(keyspace_name);
auto& strat = ks.get_replication_strategy();
// std::unordered_multimap<range<token>, inet_address>
auto tm = _metadata.clone_only_token_map();
auto range_addresses = unordered_multimap_to_unordered_map(strat.get_range_addresses(tm));
std::unordered_multimap<range<token>, inet_address> range_sources;
auto& snitch = locator::i_endpoint_snitch::get_local_snitch_ptr();
for (auto& desired_range : desired_ranges) {
auto found = false;
for (auto& x : range_addresses) {
const range<token>& src_range = x.first;
if (src_range.contains(desired_range, dht::tri_compare)) {
std::unordered_set<inet_address>& addresses = x.second;
auto preferred = snitch->get_sorted_list_by_proximity(_address, addresses);
for (inet_address& p : preferred) {
range_sources.emplace(desired_range, p);
}
found = true;
}
}
if (!found) {
throw std::runtime_error(sprint("No sources found for %s", desired_range));
}
}
return range_sources;
}
std::unordered_multimap<range<token>, inet_address>
range_streamer::get_all_ranges_with_strict_sources_for(const sstring& keyspace_name, std::vector<range<token>> desired_ranges) {
logger.debug("{} ks={}", __func__, keyspace_name);
assert (_tokens.empty() == false);
auto& ks = _db.local().find_keyspace(keyspace_name);
auto& strat = ks.get_replication_strategy();
//Active ranges
auto metadata_clone = _metadata.clone_only_token_map();
auto range_addresses = unordered_multimap_to_unordered_map(strat.get_range_addresses(metadata_clone));
//Pending ranges
metadata_clone.update_normal_tokens(_tokens, _address);
auto pending_range_addresses = unordered_multimap_to_unordered_map(strat.get_range_addresses(metadata_clone));
//Collects the source that will have its range moved to the new node
std::unordered_multimap<range<token>, inet_address> range_sources;
for (auto& desired_range : desired_ranges) {
for (auto& x : range_addresses) {
const range<token>& src_range = x.first;
if (src_range.contains(desired_range, dht::tri_compare)) {
auto old_endpoints = x.second;
auto it = pending_range_addresses.find(desired_range);
assert (it != pending_range_addresses.end());
auto new_endpoints = it->second;
//Due to CASSANDRA-5953 we can have a higher RF then we have endpoints.
//So we need to be careful to only be strict when endpoints == RF
if (old_endpoints.size() == strat.get_replication_factor()) {
std::unordered_set<inet_address> diff;
std::set_difference(old_endpoints.begin(), old_endpoints.end(),
new_endpoints.begin(), new_endpoints.end(), std::inserter(diff, diff.begin()));
old_endpoints = std::move(diff);
if (old_endpoints.size() != 1) {
throw std::runtime_error(sprint("Expected 1 endpoint but found ", old_endpoints.size()));
}
}
range_sources.emplace(desired_range, *(old_endpoints.begin()));
}
}
//Validate
auto nr = range_sources.count(desired_range);
if (nr < 1) {
throw std::runtime_error(sprint("No sources found for %s", desired_range));
}
if (nr > 1) {
throw std::runtime_error(sprint("Multiple endpoints found for %s", desired_range));
}
inet_address source_ip = range_sources.find(desired_range)->second;
auto& gossiper = gms::get_local_gossiper();
auto source_state = gossiper.get_endpoint_state_for_endpoint(source_ip);
if (gossiper.is_enabled() && source_state && !source_state->is_alive()) {
throw std::runtime_error(sprint("A node required to move the data consistently is down (%s). If you wish to move the data from a potentially inconsistent replica, restart the node with -Dcassandra.consistent.rangemovement=false", source_ip));
}
}
return range_sources;
}
bool range_streamer::use_strict_sources_for_ranges(const sstring& keyspace_name) {
auto& ks = _db.local().find_keyspace(keyspace_name);
auto& strat = ks.get_replication_strategy();
// FIXME: DatabaseDescriptor.isReplacing()
auto is_replacing = false;
return !is_replacing
&& use_strict_consistency()
&& !_tokens.empty()
&& _metadata.get_all_endpoints().size() != strat.get_replication_factor();
}
void range_streamer::add_ranges(const sstring& keyspace_name, std::vector<range<token>> ranges) {
auto ranges_for_keyspace = use_strict_sources_for_ranges(keyspace_name)
? get_all_ranges_with_strict_sources_for(keyspace_name, ranges)
: get_all_ranges_with_sources_for(keyspace_name, ranges);
if (logger.is_enabled(logging::log_level::debug)) {
for (auto& x : ranges_for_keyspace) {
logger.debug("{} : range {} exists on {}", _description, x.first, x.second);
}
}
// TODO: share code with unordered_multimap_to_unordered_map
std::unordered_map<inet_address, std::vector<range<token>>> tmp;
for (auto& x : get_range_fetch_map(ranges_for_keyspace, _source_filters, keyspace_name)) {
auto& addr = x.first;
auto& range_ = x.second;
auto it = tmp.find(addr);
if (it != tmp.end()) {
it->second.push_back(range_);
} else {
tmp.emplace(addr, std::vector<range<token>>{range_});
}
}
if (logger.is_enabled(logging::log_level::debug)) {
for (auto& x : tmp) {
logger.debug("{} : range {} from source {} for keyspace {}", _description, x.second, x.first, keyspace_name);
}
}
_to_fetch.emplace(keyspace_name, std::move(tmp));
}
future<streaming::stream_state> range_streamer::fetch_async() {
for (auto& fetch : _to_fetch) {
const auto& keyspace = fetch.first;
for (auto& x : fetch.second) {
auto& source = x.first;
auto& ranges = x.second;
auto preferred = net::get_local_messaging_service().get_preferred_ip(source);
/* Send messages to respective folks to stream data over to me */
if (logger.is_enabled(logging::log_level::debug)) {
logger.debug("{}ing from {} ranges {}", _description, source, ranges);
}
_stream_plan.request_ranges(source, preferred, keyspace, ranges);
}
}
return _stream_plan.execute();
}
} // dht

176
dht/range_streamer.hh Normal file
View File

@@ -0,0 +1,176 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified by Cloudius Systems
* Copyright 2015 Cloudius Systems
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "locator/token_metadata.hh"
#include "locator/snitch_base.hh"
#include "streaming/stream_plan.hh"
#include "streaming/stream_state.hh"
#include "gms/inet_address.hh"
#include "gms/i_failure_detector.hh"
#include "range.hh"
#include <seastar/core/distributed.hh>
#include <unordered_map>
#include <memory>
class database;
namespace dht {
/**
* Assists in streaming ranges to a node.
*/
class range_streamer {
public:
using inet_address = gms::inet_address;
using token_metadata = locator::token_metadata;
using stream_plan = streaming::stream_plan;
using stream_state = streaming::stream_state;
using i_failure_detector = gms::i_failure_detector;
static bool use_strict_consistency() {
//FIXME: Boolean.parseBoolean(System.getProperty("cassandra.consistent.rangemovement","true"));
return true;
}
public:
/**
* A filter applied to sources to stream from when constructing a fetch map.
*/
class i_source_filter {
public:
virtual bool should_include(inet_address endpoint) = 0;
};
/**
* Source filter which excludes any endpoints that are not alive according to a
* failure detector.
*/
class failure_detector_source_filter : public i_source_filter {
private:
gms::i_failure_detector& _fd;
public:
failure_detector_source_filter(i_failure_detector& fd) : _fd(fd) { }
virtual bool should_include(inet_address endpoint) override { return _fd.is_alive(endpoint); }
};
/**
* Source filter which excludes any endpoints that are not in a specific data center.
*/
class single_datacenter_filter : public i_source_filter {
private:
sstring _source_dc;
public:
single_datacenter_filter(const sstring& source_dc)
: _source_dc(source_dc) {
}
virtual bool should_include(inet_address endpoint) override {
auto& snitch_ptr = locator::i_endpoint_snitch::get_local_snitch_ptr();
return snitch_ptr->get_datacenter(endpoint) == _source_dc;
}
};
range_streamer(distributed<database>& db, token_metadata& tm, std::unordered_set<token> tokens, inet_address address, sstring description)
: _db(db)
, _metadata(tm)
, _tokens(std::move(tokens))
, _address(address)
, _description(std::move(description))
, _stream_plan(_description, true) {
}
range_streamer(distributed<database>& db, token_metadata& tm, inet_address address, sstring description)
: range_streamer(db, tm, std::unordered_set<token>(), address, description) {
}
void add_source_filter(std::unique_ptr<i_source_filter> filter) {
_source_filters.emplace(std::move(filter));
}
void add_ranges(const sstring& keyspace_name, std::vector<range<token>> ranges);
private:
bool use_strict_sources_for_ranges(const sstring& keyspace_name);
/**
* Get a map of all ranges and their respective sources that are candidates for streaming the given ranges
* to us. For each range, the list of sources is sorted by proximity relative to the given destAddress.
*/
std::unordered_multimap<range<token>, inet_address>
get_all_ranges_with_sources_for(const sstring& keyspace_name, std::vector<range<token>> desired_ranges);
/**
* Get a map of all ranges and the source that will be cleaned up once this bootstrapped node is added for the given ranges.
* For each range, the list should only contain a single source. This allows us to consistently migrate data without violating
* consistency.
*/
std::unordered_multimap<range<token>, inet_address>
get_all_ranges_with_strict_sources_for(const sstring& keyspace_name, std::vector<range<token>> desired_ranges);
private:
/**
* @param rangesWithSources The ranges we want to fetch (key) and their potential sources (value)
* @param sourceFilters A (possibly empty) collection of source filters to apply. In addition to any filters given
* here, we always exclude ourselves.
* @return
*/
static std::unordered_multimap<inet_address, range<token>>
get_range_fetch_map(const std::unordered_multimap<range<token>, inet_address>& ranges_with_sources,
const std::unordered_set<std::unique_ptr<i_source_filter>>& source_filters,
const sstring& keyspace);
#if 0
public static Multimap<InetAddress, Range<Token>> getWorkMap(Multimap<Range<Token>, InetAddress> rangesWithSourceTarget, String keyspace)
{
return getRangeFetchMap(rangesWithSourceTarget, Collections.<ISourceFilter>singleton(new FailureDetectorSourceFilter(FailureDetector.instance)), keyspace);
}
// For testing purposes
Multimap<String, Map.Entry<InetAddress, Collection<Range<Token>>>> toFetch()
{
return toFetch;
}
#endif
public:
future<streaming::stream_state> fetch_async();
private:
distributed<database>& _db;
token_metadata& _metadata;
std::unordered_set<token> _tokens;
inet_address _address;
sstring _description;
std::unordered_multimap<sstring, std::unordered_map<inet_address, std::vector<range<token>>>> _to_fetch;
std::unordered_set<std::unique_ptr<i_source_filter>> _source_filters;
stream_plan _stream_plan;
};
} // dht

37
dist/ami/build_ami.sh vendored
View File

@@ -1,9 +1,7 @@
#!/bin/sh -e
if [ ! -e dist/ami/build_ami.sh ] || [ ! -e ../scylla-jmx/dist/redhat/build_rpm.sh ] || [ ! -e ../cassandra/dist/redhat/build_rpm.sh ]; then
if [ ! -e dist/ami/build_ami.sh ]; then
echo "run build_ami.sh in top of scylla dir"
echo "please make sure scylla-jmx is checked out under the same directory as scylla"
echo "please make sure cassandra with scylla tools branch checked out under the same directory as scylla"
exit 1
fi
@@ -14,39 +12,6 @@ if [ ! -f variables.json ]; then
exit 1
fi
if [ ! -f files/scylla-server.rpm ] || [ ! -f files/scylla-server-debuginfo.rpm ]; then
cd ../../
dist/redhat/build_rpm.sh
SCYLLA_VERSION=$(cat build/SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat build/SCYLLA-RELEASE-FILE)
RPM=`ls build/rpms/scylla-server-$SCYLLA_VERSION-$SCYLLA_RELEASE*.x86_64.rpm|grep -v debuginfo`
cp $RPM dist/ami/files/scylla-server.rpm
cp build/rpms/scylla-server-debuginfo-$SCYLLA_VERSION-$SCYLLA_RELEASE*.x86_64.rpm dist/ami/files/scylla-server-debuginfo.rpm
cd -
fi
if [ ! -f files/scylla-jmx.rpm ]; then
CWD=`pwd`
cd ../../../scylla-jmx
dist/redhat/build_rpm.sh
SCYLLA_VERSION=$(cat build/SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat build/SCYLLA-RELEASE-FILE)
RPM=`ls build/rpms/scylla-jmx-$SCYLLA_VERSION-$SCYLLA_RELEASE*.noarch.rpm`
cp $RPM $CWD/files/scylla-jmx.rpm
cd -
fi
if [ ! -f files/scylla-tools.rpm ]; then
CWD=`pwd`
cd ../../../cassandra
dist/redhat/build_rpm.sh
SCYLLA_VERSION=$(cat build/SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat build/SCYLLA-RELEASE-FILE)
RPM=`ls build/rpms/scylla-tools-$SCYLLA_VERSION-$SCYLLA_RELEASE*.noarch.rpm`
cp $RPM $CWD/files/scylla-tools.rpm
cd -
fi
if [ ! -d packer ]; then
wget https://dl.bintray.com/mitchellh/packer/packer_0.8.6_linux_amd64.zip
mkdir packer

View File

@@ -1,27 +1,49 @@
#!/bin/sh -e
if [ -f /dev/md0 ]; then
if [ -b /dev/md0 ]; then
echo "RAID already constructed."
exit 1
fi
mdadm --create --verbose --force --run /dev/md0 --level=0 -c256 --raid-devices=2 /dev/xvdb /dev/xvdc
blockdev --setra 65536 /dev/md0
mkfs.xfs /dev/md0 -f
echo "DEVICE /dev/xvdb /dev/xvdc" > /etc/mdadm.conf
mdadm --detail --scan >> /etc/mdadm.conf
UUID=`blkid /dev/md0 | awk '{print $2}'`
mkdir /data
echo "$UUID /data xfs noatime 0 0" >> /etc/fstab
mount /data
dnf update -y
DISKS=""
NR=0
for i in xvd{b..z}; do
if [ -b /dev/$i ];then
echo Found disk /dev/$i
DISKS="$DISKS /dev/$i"
NR=$((NR+1))
fi
done
echo Creating RAID0 for scylla using $NR disk\(s\): $DISKS
if [ $NR -ge 1 ]; then
mdadm --create --verbose --force --run /dev/md0 --level=0 -c256 --raid-devices=$NR $DISKS
blockdev --setra 65536 /dev/md0
mkfs.xfs /dev/md0 -f
echo "DEVICE $DISKS" > /etc/mdadm.conf
mdadm --detail --scan >> /etc/mdadm.conf
UUID=`blkid /dev/md0 | awk '{print $2}'`
mkdir /data
echo "$UUID /data xfs noatime 0 0" >> /etc/fstab
mount /data
else
echo "WARN: Scylla is not using XFS to store data. Perforamnce will suffer." > /home/fedora/WARN_PLEASE_READ.TXT
fi
mkdir -p /data/data
mkdir -p /data/commitlog
chown scylla:scylla /data/*
CPU_NR=`cat /proc/cpuinfo |grep processor|wc -l`
if [ $CPU_NR -ge 8 ]; then
NR=$((CPU_NR - 1))
echo SCYLLA_ARGS=\"--cpuset 1-$NR --smp $NR\" >> /etc/sysconfig/scylla-server
echo SET_NIC=\"yes\" >> /etc/sysconfig/scylla-server
fi
/usr/lib/scylla/scylla-ami/ds2_configure.py
systemctl disable scylla-setup.service
systemctl enable scylla-server.service

11
dist/ami/files/scylla.repo vendored Normal file
View File

@@ -0,0 +1,11 @@
[scylla]
name=Scylla for Fedora $releasever - $basearch
baseurl=https://s3.amazonaws.com/downloads.scylladb.com/rpm/fedora/$releasever/$basearch/
enabled=1
gpgcheck=0
[scylla-generic]
name=Scylla for Fedora $releasever
baseurl=https://s3.amazonaws.com/downloads.scylladb.com/rpm/fedora/$releasever/noarch/
enabled=1
gpgcheck=0

20
dist/ami/files/setup-ami.sh vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh -e
setenforce 0
sed -e "s/enforcing/disabled/" /etc/sysconfig/selinux > /tmp/selinux
mv /tmp/selinux /etc/sysconfig/
dnf update -y
mv /home/fedora/scylla.repo /etc/yum.repos.d/
dnf install -y scylla-server scylla-server-debuginfo scylla-jmx scylla-tools
dnf install -y mdadm xfsprogs
cp /home/fedora/coredump.conf /etc/systemd/coredump.conf
mv /home/fedora/scylla-setup.service /usr/lib/systemd/system
mv /home/fedora/scylla-setup.sh /usr/lib/scylla
chmod a+rx /usr/lib/scylla/scylla-setup.sh
mv /home/fedora/scylla-ami /usr/lib/scylla/scylla-ami
chmod a+rx /usr/lib/scylla/scylla-ami/ds2_configure.py
systemctl enable scylla-setup.service
sed -e 's!/var/lib/scylla/data!/data/data!' -e 's!commitlog_directory: /var/lib/scylla/commitlog!commitlog_directory: /data/commitlog!' /var/lib/scylla/conf/scylla.yaml > /tmp/scylla.yaml
mv /tmp/scylla.yaml /var/lib/scylla/conf
grep -v ' - mounts' /etc/cloud/cloud.cfg > /tmp/cloud.cfg
mv /tmp/cloud.cfg /etc/cloud/cloud.cfg

15
dist/ami/scylla.json vendored
View File

@@ -24,20 +24,7 @@
{
"type": "shell",
"inline": [
"sudo dnf update -y",
"sudo dnf install -y /home/fedora/*.rpm",
"sudo dnf install -y mdadm xfsprogs",
"sudo cp /home/fedora/coredump.conf /etc/systemd/coredump.conf",
"sudo mv /home/fedora/scylla-setup.service /usr/lib/systemd/system",
"sudo mv /home/fedora/scylla-setup.sh /usr/lib/scylla",
"sudo chmod a+rx /usr/lib/scylla/scylla-setup.sh",
"sudo mv /home/fedora/scylla-ami /usr/lib/scylla/scylla-ami",
"sudo chmod a+rx /usr/lib/scylla/scylla-ami/ds2_configure.py",
"sudo systemctl enable scylla-setup.service",
"sudo sed -e 's!/var/lib/scylla/data!/data/data!' -e 's!commitlog_directory: /var/lib/scylla/commitlog!commitlog_directory: /data/commitlog!' /var/lib/scylla/conf/scylla.yaml > /tmp/scylla.yaml",
"sudo mv /tmp/scylla.yaml /var/lib/scylla/conf",
"grep -v ' - mounts' /etc/cloud/cloud.cfg > /tmp/cloud.cfg",
"sudo mv /tmp/cloud.cfg /etc/cloud/cloud.cfg"
"sudo sh -x -e /home/fedora/setup-ami.sh"
]
}
],

20
dist/common/scripts/scylla_prepare vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/sh -e
if [ "$NETWORK_MODE" = "virtio" ]; then
ip tuntap del mode tap dev $TAP
ip tuntap add mode tap dev $TAP user $USER one_queue vnet_hdr
ip link set dev $TAP up
ip link set dev $TAP master $BRIDGE
chown $USER.$GROUP /dev/vhost-net
elif [ "$NETWORK_MODE" = "dpdk" ]; then
modprobe uio
modprobe uio_pci_generic
/usr/lib/scylla/dpdk_nic_bind.py --force --bind=uio_pci_generic $ETHPCIID
for n in /sys/devices/system/node/node?; do
echo $NR_HUGEPAGES > $n/hugepages/hugepages-2048kB/nr_hugepages
done
fi
. /etc/os-release
if [ "$NAME" = "Ubuntu" ]; then
hugeadm --create-mounts
fi

View File

@@ -14,4 +14,4 @@ if [ "$SET_NIC" == "yes" ]; then
sudo sh /usr/lib/scylla/posix_net_conf.sh >/dev/null 2>&1 || true
fi
exec sudo -u $USER env HOME=/var/lib/scylla /usr/bin/scylla $args
exec sudo -u $USER env HOME=/var/lib/scylla SCYLLA_HOME=/var/lib/scylla /usr/bin/scylla $args

8
dist/common/scripts/scylla_stop vendored Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh -e
if [ "$NETWORK_MODE" = "virtio" ]; then
ip tuntap del mode tap dev $TAP
elif [ "$NETWORK_MODE" = "dpdk" ]; then
/usr/lib/scylla/dpdk_nic_bind.py -u $ETHPCIID
/usr/lib/scylla/dpdk_nic_bind.py -b $ETHDRV $ETHPCIID
fi

View File

@@ -37,6 +37,7 @@ if [ "$OS" = "Fedora" ]; then
rpmbuild -bs --define "_topdir $RPMBUILD" $RPMBUILD/SPECS/scylla-server.spec
mock rebuild --resultdir=`pwd`/build/rpms $RPMBUILD/SRPMS/scylla-server-$VERSION*.src.rpm
else
. /etc/profile.d/scylla.sh
sudo yum-builddep -y $RPMBUILD/SPECS/scylla-server.spec
rpmbuild -ba --define "_topdir $RPMBUILD" $RPMBUILD/SPECS/scylla-server.spec
fi

View File

@@ -1,33 +1,3 @@
#!/bin/sh
#
# antlr3 script
# JPackage Project <http://www.jpackage.org/>
# Source functions library
_prefer_jre="true"
. /usr/share/java-utils/java-functions
# Source system prefs
if [ -f /etc/java/antlr3.conf ] ; then
. /etc/java/antlr3.conf
fi
# Source user prefs
if [ -f $HOME/.antlr3rc ] ; then
. $HOME/.antlr3rc
fi
# Configuration
MAIN_CLASS=org.antlr.Tool
BASE_FLAGS=''
BASE_OPTIONS=''
BASE_JARS="antlr3.jar"
# Set parameters
set_jvm
set_classpath $BASE_JARS
set_flags $BASE_FLAGS
set_options $BASE_OPTIONS
# Let's start
run "$@"
exec /usr/bin/java -jar /opt/scylladb/lib/java/antlr3.jar $*

81
dist/redhat/centos_dep/binutils.diff vendored Normal file
View File

@@ -0,0 +1,81 @@
--- binutils.spec 2015-10-19 05:45:55.106745163 +0000
+++ binutils.spec.1 2015-10-19 05:45:55.807742899 +0000
@@ -17,7 +17,7 @@
%define enable_deterministic_archives 1
Summary: A GNU collection of binary utilities
-Name: %{?cross}binutils%{?_with_debug:-debug}
+Name: scylla-%{?cross}binutils%{?_with_debug:-debug}
Version: 2.25
Release: 5%{?dist}
License: GPLv3+
@@ -29,6 +29,7 @@
# instead.
Source: http://ftp.gnu.org/gnu/binutils/binutils-%{version}.tar.bz2
+%define _prefix /opt/scylladb
Source2: binutils-2.19.50.0.1-output-format.sed
Patch01: binutils-2.20.51.0.2-libtool-lib64.patch
@@ -82,6 +83,9 @@
BuildRequires: texinfo >= 4.0, gettext, flex, bison, zlib-devel
# BZ 920545: We need pod2man in order to build the manual pages.
BuildRequires: /usr/bin/pod2man
+
+Requires: scylla-env
+
# Required for: ld-bootstrap/bootstrap.exp bootstrap with --static
# It should not be required for: ld-elf/elf.exp static {preinit,init,fini} array
%if %{run_testsuite}
@@ -105,8 +109,8 @@
%if "%{build_gold}" == "both"
Requires(post): coreutils
-Requires(post): %{_sbindir}/alternatives
-Requires(preun): %{_sbindir}/alternatives
+Requires(post): /sbin/alternatives
+Requires(preun): /sbin/alternatives
%endif
# On ARM EABI systems, we do want -gnueabi to be part of the
@@ -131,11 +135,12 @@
%package devel
Summary: BFD and opcodes static and dynamic libraries and header files
Group: System Environment/Libraries
-Provides: binutils-static = %{version}-%{release}
+Provides: scylla-binutils-static = %{version}-%{release}
+Requires: scylla-env
Requires(post): /sbin/install-info
Requires(preun): /sbin/install-info
Requires: zlib-devel
-Requires: binutils = %{version}-%{release}
+Requires: scylla-binutils = %{version}-%{release}
%description devel
This package contains BFD and opcodes static and dynamic libraries.
@@ -411,11 +416,11 @@
%post
%if "%{build_gold}" == "both"
%__rm -f %{_bindir}/%{?cross}ld
-%{_sbindir}/alternatives --install %{_bindir}/%{?cross}ld %{?cross}ld \
+/sbin/alternatives --install %{_bindir}/%{?cross}ld %{?cross}ld \
%{_bindir}/%{?cross}ld.bfd %{ld_bfd_priority}
-%{_sbindir}/alternatives --install %{_bindir}/%{?cross}ld %{?cross}ld \
+/sbin/alternatives --install %{_bindir}/%{?cross}ld %{?cross}ld \
%{_bindir}/%{?cross}ld.gold %{ld_gold_priority}
-%{_sbindir}/alternatives --auto %{?cross}ld
+/sbin/alternatives --auto %{?cross}ld
%endif
%if %{isnative}
/sbin/ldconfig
@@ -433,8 +438,8 @@
%preun
%if "%{build_gold}" == "both"
if [ $1 = 0 ]; then
- %{_sbindir}/alternatives --remove %{?cross}ld %{_bindir}/%{?cross}ld.bfd
- %{_sbindir}/alternatives --remove %{?cross}ld %{_bindir}/%{?cross}ld.gold
+ /sbin/alternatives --remove %{?cross}ld %{_bindir}/%{?cross}ld.bfd
+ /sbin/alternatives --remove %{?cross}ld %{_bindir}/%{?cross}ld.gold
fi
%endif
%if %{isnative}

523
dist/redhat/centos_dep/boost.diff vendored Normal file
View File

@@ -0,0 +1,523 @@
--- boost.spec 2015-05-03 17:32:13.000000000 +0000
+++ boost.spec.1 2015-10-19 06:03:12.670534256 +0000
@@ -6,6 +6,11 @@
# We should be able to install directly.
%define boost_docdir __tmp_docdir
%define boost_examplesdir __tmp_examplesdir
+%define _without_python3 --without-python3
+%define _without_mpich --without-mpich
+%define _without_openmpi --without-openmpi
+%define _without_context --without-context
+%define _prefix /opt/scylladb
%ifarch ppc64le
%bcond_with mpich
@@ -28,18 +33,19 @@
%bcond_without python3
-Name: boost
+Name: scylla-boost
+%define orig_name boost
Summary: The free peer-reviewed portable C++ source libraries
Version: 1.57.0
%define version_enc 1_57_0
Release: 6%{?dist}
License: Boost and MIT and Python
-%define toplev_dirname %{name}_%{version_enc}
+%define toplev_dirname %{orig_name}_%{version_enc}
URL: http://www.boost.org
Group: System Environment/Libraries
-Source0: http://downloads.sourceforge.net/%{name}/%{toplev_dirname}.tar.bz2
+Source0: http://downloads.sourceforge.net/%{orig_name}/%{toplev_dirname}.tar.bz2
Source1: ver.py
Source2: libboost_thread.so
@@ -47,34 +53,36 @@
# equal to the Boost version (e.g., 1.41.0).
%define sonamever %{version}
+Requires: scylla-env
+
# boost is an "umbrella" package that pulls in all other boost
# components, except for MPI and Python 3 sub-packages. Those are
# special in that they are rarely necessary, and it's not a big burden
# to have interested parties install them explicitly.
-Requires: boost-atomic%{?_isa} = %{version}-%{release}
-Requires: boost-chrono%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-atomic%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-chrono%{?_isa} = %{version}-%{release}
%if %{with context}
-Requires: boost-context%{?_isa} = %{version}-%{release}
-Requires: boost-coroutine%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-context%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-coroutine%{?_isa} = %{version}-%{release}
%endif
-Requires: boost-date-time%{?_isa} = %{version}-%{release}
-Requires: boost-filesystem%{?_isa} = %{version}-%{release}
-Requires: boost-graph%{?_isa} = %{version}-%{release}
-Requires: boost-iostreams%{?_isa} = %{version}-%{release}
-Requires: boost-locale%{?_isa} = %{version}-%{release}
-Requires: boost-log%{?_isa} = %{version}-%{release}
-Requires: boost-math%{?_isa} = %{version}-%{release}
-Requires: boost-program-options%{?_isa} = %{version}-%{release}
-Requires: boost-python%{?_isa} = %{version}-%{release}
-Requires: boost-random%{?_isa} = %{version}-%{release}
-Requires: boost-regex%{?_isa} = %{version}-%{release}
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
-Requires: boost-signals%{?_isa} = %{version}-%{release}
-Requires: boost-system%{?_isa} = %{version}-%{release}
-Requires: boost-test%{?_isa} = %{version}-%{release}
-Requires: boost-thread%{?_isa} = %{version}-%{release}
-Requires: boost-timer%{?_isa} = %{version}-%{release}
-Requires: boost-wave%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-date-time%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-filesystem%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-graph%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-iostreams%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-locale%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-log%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-math%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-program-options%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-python%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-random%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-regex%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-signals%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-test%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-thread%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-timer%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-wave%{?_isa} = %{version}-%{release}
BuildRequires: m4
BuildRequires: libstdc++-devel%{?_isa}
@@ -151,6 +159,7 @@
%package atomic
Summary: Run-Time component of boost atomic library
Group: System Environment/Libraries
+Requires: scylla-env
%description atomic
@@ -162,7 +171,8 @@
%package chrono
Summary: Run-Time component of boost chrono library
Group: System Environment/Libraries
-Requires: boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
%description chrono
@@ -171,6 +181,7 @@
%package container
Summary: Run-Time component of boost container library
Group: System Environment/Libraries
+Requires: scylla-env
%description container
@@ -183,6 +194,7 @@
%package context
Summary: Run-Time component of boost context switching library
Group: System Environment/Libraries
+Requires: scylla-env
%description context
@@ -192,6 +204,7 @@
%package coroutine
Summary: Run-Time component of boost coroutine library
Group: System Environment/Libraries
+Requires: scylla-env
%description coroutine
Run-Time support for Boost.Coroutine, a library that provides
@@ -203,6 +216,7 @@
%package date-time
Summary: Run-Time component of boost date-time library
Group: System Environment/Libraries
+Requires: scylla-env
%description date-time
@@ -212,7 +226,8 @@
%package filesystem
Summary: Run-Time component of boost filesystem library
Group: System Environment/Libraries
-Requires: boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
%description filesystem
@@ -223,7 +238,8 @@
%package graph
Summary: Run-Time component of boost graph library
Group: System Environment/Libraries
-Requires: boost-regex%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-regex%{?_isa} = %{version}-%{release}
%description graph
@@ -243,9 +259,10 @@
%package locale
Summary: Run-Time component of boost locale library
Group: System Environment/Libraries
-Requires: boost-chrono%{?_isa} = %{version}-%{release}
-Requires: boost-system%{?_isa} = %{version}-%{release}
-Requires: boost-thread%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-chrono%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-thread%{?_isa} = %{version}-%{release}
%description locale
@@ -255,6 +272,7 @@
%package log
Summary: Run-Time component of boost logging library
Group: System Environment/Libraries
+Requires: scylla-env
%description log
@@ -265,6 +283,7 @@
%package math
Summary: Math functions for boost TR1 library
Group: System Environment/Libraries
+Requires: scylla-env
%description math
@@ -274,6 +293,7 @@
%package program-options
Summary: Run-Time component of boost program_options library
Group: System Environment/Libraries
+Requires: scylla-env
%description program-options
@@ -284,6 +304,7 @@
%package python
Summary: Run-Time component of boost python library
Group: System Environment/Libraries
+Requires: scylla-env
%description python
@@ -298,6 +319,7 @@
%package python3
Summary: Run-Time component of boost python library for Python 3
Group: System Environment/Libraries
+Requires: scylla-env
%description python3
@@ -310,8 +332,9 @@
%package python3-devel
Summary: Shared object symbolic links for Boost.Python 3
Group: System Environment/Libraries
-Requires: boost-python3%{?_isa} = %{version}-%{release}
-Requires: boost-devel%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-python3%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-devel%{?_isa} = %{version}-%{release}
%description python3-devel
@@ -322,6 +345,7 @@
%package random
Summary: Run-Time component of boost random library
Group: System Environment/Libraries
+Requires: scylla-env
%description random
@@ -330,6 +354,7 @@
%package regex
Summary: Run-Time component of boost regular expression library
Group: System Environment/Libraries
+Requires: scylla-env
%description regex
@@ -338,6 +363,7 @@
%package serialization
Summary: Run-Time component of boost serialization library
Group: System Environment/Libraries
+Requires: scylla-env
%description serialization
@@ -346,6 +372,7 @@
%package signals
Summary: Run-Time component of boost signals and slots library
Group: System Environment/Libraries
+Requires: scylla-env
%description signals
@@ -354,6 +381,7 @@
%package system
Summary: Run-Time component of boost system support library
Group: System Environment/Libraries
+Requires: scylla-env
%description system
@@ -364,6 +392,7 @@
%package test
Summary: Run-Time component of boost test library
Group: System Environment/Libraries
+Requires: scylla-env
%description test
@@ -373,7 +402,8 @@
%package thread
Summary: Run-Time component of boost thread library
Group: System Environment/Libraries
-Requires: boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
%description thread
@@ -385,8 +415,9 @@
%package timer
Summary: Run-Time component of boost timer library
Group: System Environment/Libraries
-Requires: boost-chrono%{?_isa} = %{version}-%{release}
-Requires: boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-chrono%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
%description timer
@@ -397,11 +428,12 @@
%package wave
Summary: Run-Time component of boost C99/C++ pre-processing library
Group: System Environment/Libraries
-Requires: boost-chrono%{?_isa} = %{version}-%{release}
-Requires: boost-date-time%{?_isa} = %{version}-%{release}
-Requires: boost-filesystem%{?_isa} = %{version}-%{release}
-Requires: boost-system%{?_isa} = %{version}-%{release}
-Requires: boost-thread%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-chrono%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-date-time%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-filesystem%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-system%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-thread%{?_isa} = %{version}-%{release}
%description wave
@@ -412,27 +444,20 @@
%package devel
Summary: The Boost C++ headers and shared development libraries
Group: Development/Libraries
-Requires: boost%{?_isa} = %{version}-%{release}
-Provides: boost-python-devel
+Requires: scylla-env
+Requires: scylla-boost%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-python-devel
Requires: libicu-devel%{?_isa}
-# Odeint was shipped in Fedora 18, but later became part of Boost.
-# Note we also obsolete odeint-doc down there.
-# https://bugzilla.redhat.com/show_bug.cgi?id=892850
-Provides: odeint = 2.2-5
-Obsoletes: odeint < 2.2-5
-Provides: odeint-devel = 2.2-5
-Obsoletes: odeint-devel < 2.2-5
-
%description devel
Headers and shared object symbolic links for the Boost C++ libraries.
%package static
Summary: The Boost C++ static development libraries
Group: Development/Libraries
-Requires: boost-devel%{?_isa} = %{version}-%{release}
-Obsoletes: boost-devel-static < 1.34.1-14
-Provides: boost-devel-static = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-devel%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-devel-static = %{version}-%{release}
%description static
Static Boost C++ libraries.
@@ -443,11 +468,7 @@
%if 0%{?rhel} >= 6
BuildArch: noarch
%endif
-Provides: boost-python-docs = %{version}-%{release}
-
-# See the description above.
-Provides: odeint-doc = 2.2-5
-Obsoletes: odeint-doc < 2.2-5
+Provides: scylla-boost-python-docs = %{version}-%{release}
%description doc
This package contains the documentation in the HTML format of the Boost C++
@@ -460,7 +481,7 @@
%if 0%{?rhel} >= 6
BuildArch: noarch
%endif
-Requires: boost-devel = %{version}-%{release}
+Requires: scylla-boost-devel = %{version}-%{release}
%description examples
This package contains example source files distributed with boost.
@@ -471,9 +492,10 @@
%package openmpi
Summary: Run-Time component of Boost.MPI library
Group: System Environment/Libraries
+Requires: scylla-env
Requires: openmpi%{?_isa}
BuildRequires: openmpi-devel
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
%description openmpi
@@ -483,10 +505,11 @@
%package openmpi-devel
Summary: Shared library symbolic links for Boost.MPI
Group: System Environment/Libraries
-Requires: boost-devel%{?_isa} = %{version}-%{release}
-Requires: boost-openmpi%{?_isa} = %{version}-%{release}
-Requires: boost-openmpi-python%{?_isa} = %{version}-%{release}
-Requires: boost-graph-openmpi%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-devel%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-openmpi%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-openmpi-python%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-graph-openmpi%{?_isa} = %{version}-%{release}
%description openmpi-devel
@@ -496,9 +519,10 @@
%package openmpi-python
Summary: Python run-time component of Boost.MPI library
Group: System Environment/Libraries
-Requires: boost-openmpi%{?_isa} = %{version}-%{release}
-Requires: boost-python%{?_isa} = %{version}-%{release}
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-openmpi%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-python%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
%description openmpi-python
@@ -508,8 +532,9 @@
%package graph-openmpi
Summary: Run-Time component of parallel boost graph library
Group: System Environment/Libraries
-Requires: boost-openmpi%{?_isa} = %{version}-%{release}
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-boost-openmpi%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
%description graph-openmpi
@@ -526,11 +551,11 @@
%package mpich
Summary: Run-Time component of Boost.MPI library
Group: System Environment/Libraries
+Requires: scylla-env
Requires: mpich%{?_isa}
BuildRequires: mpich-devel
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
-Provides: boost-mpich2 = %{version}-%{release}
-Obsoletes: boost-mpich2 < 1.53.0-9
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-mpich2 = %{version}-%{release}
%description mpich
@@ -540,12 +565,12 @@
%package mpich-devel
Summary: Shared library symbolic links for Boost.MPI
Group: System Environment/Libraries
-Requires: boost-devel%{?_isa} = %{version}-%{release}
-Requires: boost-mpich%{?_isa} = %{version}-%{release}
-Requires: boost-mpich-python%{?_isa} = %{version}-%{release}
-Requires: boost-graph-mpich%{?_isa} = %{version}-%{release}
-Provides: boost-mpich2-devel = %{version}-%{release}
-Obsoletes: boost-mpich2-devel < 1.53.0-9
+Requires: scylla-env
+Requires: scylla-boost-devel%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-mpich%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-mpich-python%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-graph-mpich%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-mpich2-devel = %{version}-%{release}
%description mpich-devel
@@ -555,11 +580,11 @@
%package mpich-python
Summary: Python run-time component of Boost.MPI library
Group: System Environment/Libraries
-Requires: boost-mpich%{?_isa} = %{version}-%{release}
-Requires: boost-python%{?_isa} = %{version}-%{release}
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
-Provides: boost-mpich2-python = %{version}-%{release}
-Obsoletes: boost-mpich2-python < 1.53.0-9
+Requires: scylla-env
+Requires: scylla-boost-mpich%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-python%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-mpich2-python = %{version}-%{release}
%description mpich-python
@@ -569,10 +594,10 @@
%package graph-mpich
Summary: Run-Time component of parallel boost graph library
Group: System Environment/Libraries
-Requires: boost-mpich%{?_isa} = %{version}-%{release}
-Requires: boost-serialization%{?_isa} = %{version}-%{release}
-Provides: boost-graph-mpich2 = %{version}-%{release}
-Obsoletes: boost-graph-mpich2 < 1.53.0-9
+Requires: scylla-env
+Requires: scylla-boost-mpich%{?_isa} = %{version}-%{release}
+Requires: scylla-boost-serialization%{?_isa} = %{version}-%{release}
+Provides: scylla-boost-graph-mpich2 = %{version}-%{release}
%description graph-mpich
@@ -586,7 +611,8 @@
%package build
Summary: Cross platform build system for C++ projects
Group: Development/Tools
-Requires: boost-jam
+Requires: scylla-env
+Requires: scylla-boost-jam
BuildArch: noarch
%description build
@@ -600,6 +626,7 @@
%package jam
Summary: A low-level build tool
Group: Development/Tools
+Requires: scylla-env
%description jam
Boost.Jam (BJam) is the low-level build engine tool for Boost.Build.
@@ -1134,7 +1161,7 @@
%files devel
%defattr(-, root, root, -)
%doc LICENSE_1_0.txt
-%{_includedir}/%{name}
+%{_includedir}/%{orig_name}
%{_libdir}/libboost_atomic.so
%{_libdir}/libboost_chrono.so
%{_libdir}/libboost_container.so

View File

@@ -13,15 +13,15 @@ mkdir -p build/srpms
cd build/srpms
if [ ! -f binutils-2.25-5.fc22.src.rpm ]; then
wget http://ftp.riken.jp/Linux/fedora/releases/22/Everything/source/SRPMS/b/binutils-2.25-5.fc22.src.rpm
wget http://download.fedoraproject.org/pub/fedora/linux/releases/22/Everything/source/SRPMS/b/binutils-2.25-5.fc22.src.rpm
fi
if [ ! -f isl-0.14-3.fc22.src.rpm ]; then
wget http://ftp.riken.jp/Linux/fedora/releases/22/Everything/source/SRPMS/i/isl-0.14-3.fc22.src.rpm
wget http://download.fedoraproject.org/pub/fedora/linux/releases/22/Everything/source/SRPMS/i/isl-0.14-3.fc22.src.rpm
fi
if [ ! -f gcc-5.1.1-4.fc22.src.rpm ]; then
wget http://ftp.riken.jp/Linux/fedora/updates/22/SRPMS/g/gcc-5.1.1-4.fc22.src.rpm
wget http://download.fedoraproject.org/pub/fedora/linux/updates/22/SRPMS/g/gcc-5.1.1-4.fc22.src.rpm
fi
if [ ! -f boost-1.57.0-6.fc22.src.rpm ]; then
@@ -36,10 +36,6 @@ if [ ! -f ragel-6.8-3.fc22.src.rpm ]; then
wget http://download.fedoraproject.org/pub/fedora/linux/releases/22/Everything/source/SRPMS/r/ragel-6.8-3.fc22.src.rpm
fi
if [ ! -f re2c-0.13.5-9.fc22.src.rpm ]; then
wget http://download.fedoraproject.org/pub/fedora/linux/releases/22/Everything/source/SRPMS/r/re2c-0.13.5-9.fc22.src.rpm
fi
cd -
sudo yum install -y epel-release
@@ -49,63 +45,76 @@ sudo ln -sf /usr/bin/python3.4 /usr/bin/python3
sudo yum install -y python-devel libicu-devel openmpi-devel mpich-devel libstdc++-devel bzip2-devel zlib-devel
sudo yum install -y flex bison dejagnu zlib-static glibc-static sharutils bc libstdc++-static gmp-devel texinfo texinfo-tex systemtap-sdt-devel mpfr-devel libmpc-devel elfutils-devel elfutils-libelf-devel glibc-devel.x86_64 glibc-devel.i686 gcc-gnat libgnat doxygen graphviz dblatex texlive-collection-latex docbook5-style-xsl python-sphinx cmake
sudo yum install -y gcc-objc
sudo yum install -y asciidoc
sudo yum install -y gettext
if [ ! -f $RPMBUILD/RPMS/x86_64/binutils-2.25-5.el7.centos.x86_64.rpm ]; then
rpmbuild --define "_topdir $RPMBUILD" --rebuild build/srpms/binutils-2.25-5.fc22.src.rpm
if [ ! -f $RPMBUILD/RPMS/noarch/scylla-env-1.0-1.el7.centos.noarch.rpm ]; then
cd dist/redhat/centos_dep
tar cpf $RPMBUILD/SOURCES/scylla-env-1.0.tar scylla-env-1.0
cd -
rpmbuild --define "_topdir $RPMBUILD" --ba dist/redhat/centos_dep/scylla-env.spec
fi
do_install binutils-2.25-5.el7.centos.x86_64.rpm
do_install scylla-env-1.0-1.el7.centos.noarch.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/isl-0.14-3.el7.centos.x86_64.rpm ]; then
rpmbuild --define "_topdir $RPMBUILD" --rebuild build/srpms/isl-0.14-3.fc22.src.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-binutils-2.25-5.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/binutils-2.25-5.fc22.src.rpm
patch $RPMBUILD/SPECS/binutils.spec < dist/redhat/centos_dep/binutils.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/binutils.spec
fi
do_install isl-0.14-3.el7.centos.x86_64.rpm
do_install isl-devel-0.14-3.el7.centos.x86_64.rpm
do_install scylla-binutils-2.25-5.el7.centos.x86_64.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/gcc-5.1.1-4.el7.centos.x86_64.rpm ]; then
rpmbuild --define "_topdir $RPMBUILD" --define "fedora 21" --rebuild build/srpms/gcc-5.1.1-4.fc22.src.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-isl-0.14-3.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/isl-0.14-3.fc22.src.rpm
patch $RPMBUILD/SPECS/isl.spec < dist/redhat/centos_dep/isl.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/isl.spec
fi
do_install *5.1.1-4*
do_install scylla-isl-0.14-3.el7.centos.x86_64.rpm
do_install scylla-isl-devel-0.14-3.el7.centos.x86_64.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/boost-1.57.0-6.el7.centos.x86_64.rpm ]; then
rpmbuild --define "_topdir $RPMBUILD" --without python3 --rebuild build/srpms/boost-1.57.0-6.fc22.src.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-gcc-5.1.1-4.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/gcc-5.1.1-4.fc22.src.rpm
patch $RPMBUILD/SPECS/gcc.spec < dist/redhat/centos_dep/gcc.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/gcc.spec
fi
do_install boost*
do_install scylla-*5.1.1-4*
if [ ! -f $RPMBUILD/RPMS/x86_64/re2c-0.13.5-9.el7.centos.x86_64.rpm ]; then
rpmbuild --define "_topdir $RPMBUILD" --rebuild build/srpms/re2c-0.13.5-9.fc22.src.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-boost-1.57.0-6.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/boost-1.57.0-6.fc22.src.rpm
patch $RPMBUILD/SPECS/boost.spec < dist/redhat/centos_dep/boost.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/boost.spec
fi
do_install re2c-0.13.5-9.el7.centos.x86_64.rpm
do_install scylla-boost*
if [ ! -f $RPMBUILD/RPMS/x86_64/ninja-build-1.5.3-2.el7.centos.x86_64.rpm ]; then
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-ninja-build-1.5.3-2.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/ninja-build-1.5.3-2.fc22.src.rpm
patch $RPMBUILD/SPECS/ninja-build.spec < dist/redhat/centos_dep/ninja-build.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/ninja-build.spec
fi
do_install ninja-build-1.5.3-2.el7.centos.x86_64.rpm
do_install scylla-ninja-build-1.5.3-2.el7.centos.x86_64.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/ragel-6.8-3.el7.centos.x86_64.rpm ]; then
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-ragel-6.8-3.el7.centos.x86_64.rpm ]; then
rpm --define "_topdir $RPMBUILD" -ivh build/srpms/ragel-6.8-3.fc22.src.rpm
patch $RPMBUILD/SPECS/ragel.spec < dist/redhat/centos_dep/ragel.diff
rpmbuild --define "_topdir $RPMBUILD" -ba $RPMBUILD/SPECS/ragel.spec
fi
do_install ragel-6.8-3.el7.centos.x86_64.rpm
do_install scylla-ragel-6.8-3.el7.centos.x86_64.rpm
if [ ! -f $RPMBUILD/RPMS/noarch/antlr3-tool-3.5.2-1.el7.centos.noarch.rpm ]; then
mkdir build/antlr3-tool-3.5.2
cp dist/redhat/centos_dep/antlr3 build/antlr3-tool-3.5.2
cd build/antlr3-tool-3.5.2
if [ ! -f $RPMBUILD/RPMS/noarch/scylla-antlr3-tool-3.5.2-1.el7.centos.noarch.rpm ]; then
mkdir build/scylla-antlr3-tool-3.5.2
cp dist/redhat/centos_dep/antlr3 build/scylla-antlr3-tool-3.5.2
cd build/scylla-antlr3-tool-3.5.2
wget http://www.antlr3.org/download/antlr-3.5.2-complete-no-st3.jar
cd -
cd build
tar cJpf $RPMBUILD/SOURCES/antlr3-tool-3.5.2.tar.xz antlr3-tool-3.5.2
tar cJpf $RPMBUILD/SOURCES/scylla-antlr3-tool-3.5.2.tar.xz scylla-antlr3-tool-3.5.2
cd -
rpmbuild --define "_topdir $RPMBUILD" -ba dist/redhat/centos_dep/antlr3-tool.spec
rpmbuild --define "_topdir $RPMBUILD" -ba dist/redhat/centos_dep/scylla-antlr3-tool.spec
fi
do_install antlr3-tool-3.5.2-1.el7.centos.noarch.rpm
do_install scylla-antlr3-tool-3.5.2-1.el7.centos.noarch.rpm
if [ ! -f $RPMBUILD/RPMS/x86_64/antlr3-C++-devel-3.5.2-1.el7.centos.x86_64.rpm ];then
if [ ! -f $RPMBUILD/RPMS/x86_64/scylla-antlr3-C++-devel-3.5.2-1.el7.centos.x86_64.rpm ];then
wget -O build/3.5.2.tar.gz https://github.com/antlr/antlr3/archive/3.5.2.tar.gz
mv build/3.5.2.tar.gz $RPMBUILD/SOURCES
rpmbuild --define "_topdir $RPMBUILD" -ba dist/redhat/centos_dep/antlr3-C++-devel.spec
rpmbuild --define "_topdir $RPMBUILD" -ba dist/redhat/centos_dep/scylla-antlr3-C++-devel.spec
fi
do_install antlr3-C++-devel-3.5.2-1.el7.centos.x86_64.rpm
do_install scylla-antlr3-C++-devel-3.5.2-1.el7.centos.x86_64.rpm

1316
dist/redhat/centos_dep/gcc.diff vendored Normal file

File diff suppressed because it is too large Load Diff

39
dist/redhat/centos_dep/isl.diff vendored Normal file
View File

@@ -0,0 +1,39 @@
--- isl.spec 2015-01-06 16:24:49.000000000 +0000
+++ isl.spec.1 2015-10-18 12:12:38.000000000 +0000
@@ -1,5 +1,5 @@
Summary: Integer point manipulation library
-Name: isl
+Name: scylla-isl
Version: 0.14
License: MIT
Group: System Environment/Libraries
@@ -17,8 +17,10 @@
BuildRequires: gmp-devel
BuildRequires: pkgconfig
+Requires: scylla-env
Source0: http://isl.gforge.inria.fr/isl-%{version}.tar.xz
+%define _prefix /opt/scylladb
%description
isl is a library for manipulating sets and relations of integer points
@@ -32,7 +34,8 @@
%package devel
Summary: Development for building integer point manipulation library
-Requires: isl%{?_isa} == %{version}-%{release}
+Requires: scylla-env
+Requires: scylla-isl%{?_isa} == %{version}-%{release}
Requires: gmp-devel%{?_isa}
Group: Development/Libraries
@@ -47,7 +50,7 @@
graphs), dependence analysis and bounds on piecewise step-polynomials.
%prep
-%setup -q
+%setup -q -n isl-%{version}
%build
%configure

View File

@@ -1,29 +1,34 @@
--- rpmbuild/SPECS/ninja-build.spec 2015-02-08 17:53:10.000000000 -0500
+++ rpmbuild/SPECS/ninja-build.spec.1 2015-09-17 21:21:52.343000000 -0400
@@ -8,7 +8,7 @@
Source1: ninja.vim
# https://github.com/martine/ninja/pull/882
Patch0: ninja-1.5.3-verbose-build.patch
-BuildRequires: asciidoc
+#BuildRequires: asciidoc
BuildRequires: gtest-devel
BuildRequires: python2-devel
BuildRequires: re2c >= 0.11.3
@@ -28,7 +28,7 @@
%build
CFLAGS="%{optflags}" LDFLAGS="%{?__global_ldflags}" \
%{__python2} configure.py --bootstrap --verbose
-./ninja -v manual
+#./ninja -v manual
./ninja -v ninja_test
%install
@@ -48,7 +48,7 @@
./ninja_test
%files
-%doc COPYING HACKING.md README doc/manual.html
+%doc COPYING HACKING.md README
%{_bindir}/ninja-build
%{_datadir}/bash-completion/completions/ninja-bash-completion
%{_datadir}/emacs/site-lisp/ninja-mode.el
1c1
< Name: ninja-build
---
> Name: scylla-ninja-build
8d7
< Source1: ninja.vim
10a10
> Requires: scylla-env
14,16c14,15
< BuildRequires: re2c >= 0.11.3
< Requires: emacs-filesystem
< Requires: vim-filesystem
---
> #BuildRequires: scylla-re2c >= 0.11.3
> %define _prefix /opt/scylladb
35,37c34
< # TODO: Install ninja_syntax.py?
< mkdir -p %{buildroot}/{%{_bindir},%{_datadir}/bash-completion/completions,%{_datadir}/emacs/site-lisp,%{_datadir}/vim/vimfiles/syntax,%{_datadir}/vim/vimfiles/ftdetect,%{_datadir}/zsh/site-functions}
<
---
> mkdir -p %{buildroot}/opt/scylladb/bin
39,43d35
< install -pm644 misc/bash-completion %{buildroot}%{_datadir}/bash-completion/completions/ninja-bash-completion
< install -pm644 misc/ninja-mode.el %{buildroot}%{_datadir}/emacs/site-lisp/ninja-mode.el
< install -pm644 misc/ninja.vim %{buildroot}%{_datadir}/vim/vimfiles/syntax/ninja.vim
< install -pm644 %{SOURCE1} %{buildroot}%{_datadir}/vim/vimfiles/ftdetect/ninja.vim
< install -pm644 misc/zsh-completion %{buildroot}%{_datadir}/zsh/site-functions/_ninja
53,58d44
< %{_datadir}/bash-completion/completions/ninja-bash-completion
< %{_datadir}/emacs/site-lisp/ninja-mode.el
< %{_datadir}/vim/vimfiles/syntax/ninja.vim
< %{_datadir}/vim/vimfiles/ftdetect/ninja.vim
< # zsh does not have a -filesystem package
< %{_datadir}/zsh/

View File

@@ -1,14 +1,44 @@
--- rpmbuild/SPECS/ragel.spec 2014-08-18 07:55:49.000000000 -0400
+++ rpmbuild/SPECS/ragel.spec.1 2015-09-17 22:06:27.623000000 -0400
@@ -49,8 +49,10 @@
--- ragel.spec 2014-08-18 11:55:49.000000000 +0000
+++ ragel.spec.1 2015-10-18 12:18:23.000000000 +0000
@@ -1,17 +1,20 @@
-Name: ragel
+Name: scylla-ragel
+%define orig_name ragel
Version: 6.8
Release: 3%{?dist}
Summary: Finite state machine compiler
%files
%defattr(-,root,root,-)
-%doc COPYING ragel.vim CREDITS ChangeLog
+%doc COPYING ragel.vim
%doc doc/ragel-guide.pdf
+%{_docdir}/%{name}/CREDITS
+%{_docdir}/%{name}/ChangeLog
%{_bindir}/ragel
%{_mandir}/*/*
Group: Development/Tools
License: GPLv2+
-URL: http://www.complang.org/%{name}/
-Source0: http://www.complang.org/%{name}/%{name}-%{version}.tar.gz
+URL: http://www.complang.org/%{orig_name}/
+Source0: http://www.complang.org/%{orig_name}/%{orig_name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
# for documentation building
BuildRequires: gcc-objc, autoconf, gcc-c++
+Requires: scylla-env
Requires: gawk
+%define _prefix /opt/scylladb
%description
Ragel compiles finite state machines from regular languages into executable C,
@@ -21,7 +24,7 @@
done using inline operators that do not disrupt the regular language syntax.
%prep
-%setup -q
+%setup -q -n %{orig_name}-%{version}
# Pass fedora cflags correctly
sed -i.flags \
@@ -34,7 +37,7 @@
%build
# set the names of the other programming commandline programs
-%configure --docdir=%{_docdir}/%{name} RUBY=ruby JAVAC=javac GMCS=gmcs
+%configure --docdir=%{_docdir}/%{name}-%{version} RUBY=ruby JAVAC=javac GMCS=gmcs
make %{?_smp_mflags}

View File

@@ -1,6 +1,6 @@
%global antlr_version 3.5.2
Name: antlr3-C++-devel
Name: scylla-antlr3-C++-devel
Version: %{antlr_version}
Release: 1%{?dist}
Summary: C++ runtime support for ANTLR-generated parsers
@@ -8,6 +8,8 @@ Summary: C++ runtime support for ANTLR-generated parsers
License: BSD
URL: http://www.antlr3.org/
Source0: https://github.com/antlr/antlr3/archive/%{antlr_version}.tar.gz
Requires: scylla-env
%define _prefix /opt/scylladb
%description
C++ runtime support for ANTLR-generated parsers.

View File

@@ -1,6 +1,6 @@
%global antlr_version 3.5.2
Name: antlr3-tool
Name: scylla-antlr3-tool
Version: %{antlr_version}
Release: 1%{?dist}
Summary: ANother Tool for Language Recognition
@@ -11,6 +11,8 @@ Source0: %{name}-%{version}.tar.xz
BuildArch: noarch
Requires: java-1.7.0-openjdk
Requires: scylla-env
%define _prefix /opt/scylladb
%description
ANother Tool for Language Recognition, is a language tool

View File

@@ -0,0 +1 @@
/opt/scylladb/lib64

View File

@@ -0,0 +1,2 @@
set path = ($PATH /opt/scylladb/bin /opt/scylladb/sbin)

View File

@@ -0,0 +1 @@
export PATH=$PATH:/opt/scylladb/bin:/opt/scylladb/sbin

40
dist/redhat/centos_dep/scylla-env.spec vendored Normal file
View File

@@ -0,0 +1,40 @@
Name: scylla-env
Version: 1.0
Release: 1%{?dist}
Summary: Scylla is a highly scalable, eventually consistent, distributed, partitioned row DB.
Group: Applications/Databases
License: AGPLv3
URL: http://www.scylladb.com/
Source0: scylla-env-1.0.tar
BuildArch: noarch
%description
%prep
%setup -q
%build
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/ld.so.conf.d
install -m 644 profile.d/* $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
install -m 644 ld.so.conf.d/* $RPM_BUILD_ROOT%{_sysconfdir}/ld.so.conf.d
%post
%{_sbindir}/ldconfig
%files
%doc
%{_sysconfdir}/profile.d/scylla.sh
%{_sysconfdir}/profile.d/scylla.csh
%{_sysconfdir}/ld.so.conf.d/scylla.x86_64.conf
%changelog

View File

@@ -8,9 +8,9 @@ License: AGPLv3
URL: http://www.scylladb.com/
Source0: %{name}-@@VERSION@@-@@RELEASE@@.tar
BuildRequires: libaio-devel boost-devel libstdc++-devel cryptopp-devel hwloc-devel numactl-devel libpciaccess-devel libxml2-devel zlib-devel thrift-devel yaml-cpp-devel lz4-devel snappy-devel jsoncpp-devel systemd-devel xz-devel openssl-devel libcap-devel libselinux-devel libgcrypt-devel libgpg-error-devel elfutils-devel krb5-devel libcom_err-devel libattr-devel pcre-devel elfutils-libelf-devel bzip2-devel keyutils-libs-devel ninja-build ragel antlr3-tool antlr3-C++-devel xfsprogs-devel make
%{?fedora:BuildRequires: python3 gcc-c++ libasan libubsan}
%{?rhel:BuildRequires: python34 gcc-c++ >= 5.1.1}
BuildRequires: libaio-devel boost-devel libstdc++-devel cryptopp-devel hwloc-devel numactl-devel libpciaccess-devel libxml2-devel zlib-devel thrift-devel yaml-cpp-devel lz4-devel snappy-devel jsoncpp-devel systemd-devel xz-devel openssl-devel libcap-devel libselinux-devel libgcrypt-devel libgpg-error-devel elfutils-devel krb5-devel libcom_err-devel libattr-devel pcre-devel elfutils-libelf-devel bzip2-devel keyutils-libs-devel xfsprogs-devel make
%{?fedora:BuildRequires: ninja-build ragel antlr3-tool antlr3-C++-devel python3 gcc-c++ libasan libubsan}
%{?rhel:BuildRequires: scylla-ninja-build scylla-ragel scylla-antlr3-tool scylla-antlr3-C++-devel python34 scylla-gcc-c++ >= 5.1.1}
Requires: systemd-libs xfsprogs
%description
@@ -23,7 +23,7 @@ Requires: systemd-libs xfsprogs
./configure.py --with scylla --disable-xen --enable-dpdk --mode=release
%endif
%if 0%{?rhel}
./configure.py --with scylla --disable-xen --enable-dpdk --mode=release --static-stdc++
./configure.py --with scylla --disable-xen --enable-dpdk --mode=release --static-stdc++ --compiler=/opt/scylladb/bin/g++
%endif
ninja-build -j2
@@ -39,7 +39,7 @@ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m644 dist/redhat/sysconfig/scylla-server $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/
install -m644 dist/redhat/limits.d/scylla.conf $RPM_BUILD_ROOT%{_sysconfdir}/security/limits.d/
install -m644 dist/redhat/systemd/scylla-server.service $RPM_BUILD_ROOT%{_unitdir}/
install -m755 dist/redhat/scripts/* $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m755 dist/common/scripts/* $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m755 seastar/scripts/posix_net_conf.sh $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m755 seastar/dpdk/tools/dpdk_nic_bind.py $RPM_BUILD_ROOT%{_prefix}/lib/scylla/
install -m755 build/release/scylla $RPM_BUILD_ROOT%{_bindir}
@@ -55,6 +55,7 @@ install -d -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/scylla/data
install -d -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/scylla/commitlog
install -d -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/scylla/conf
install -m644 conf/scylla.yaml $RPM_BUILD_ROOT%{_sharedstatedir}/scylla/conf/
install -m644 conf/cassandra-rackdc.properties $RPM_BUILD_ROOT%{_sharedstatedir}/scylla/conf/
%pre
/usr/sbin/groupadd scylla 2> /dev/null || :
@@ -101,6 +102,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(0755,scylla,scylla) %dir %{_sharedstatedir}/scylla/commitlog
%attr(0755,root,root) %dir %{_sharedstatedir}/scylla/conf/
%{_sharedstatedir}/scylla/conf/scylla.yaml
%{_sharedstatedir}/scylla/conf/cassandra-rackdc.properties
%changelog
* Tue Jul 21 2015 Takuya ASADA <syuu@cloudius-systems.com>

27
dist/ubuntu/build_deb.sh vendored Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/sh -e
if [ ! -e dist/ubuntu/build_deb.sh ]; then
echo "run build_deb.sh in top of scylla dir"
exit 1
fi
sudo apt-get -y update
./dist/ubuntu/dep/build_dependency.sh
sudo apt-get -y install libyaml-cpp-dev liblz4-dev libsnappy-dev libcrypto++-dev libboost1.55-dev libjsoncpp-dev libaio-dev ragel ninja-build git libyaml-cpp0.5 liblz4-1 libsnappy1 libcrypto++9 libboost-program-options1.55.0 libboost-program-options1.55-dev libboost-system1.55.0 libboost-system1.55-dev libboost-thread1.55.0 libboost-thread1.55-dev libboost-test1.55.0 libboost-test1.55-dev libjsoncpp0 libaio1 hugepages software-properties-common libboost-filesystem1.55-dev libboost-filesystem1.55.0
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get -y update
sudo apt-get -y install g++-4.9
VERSION=$(./SCYLLA-VERSION-GEN)
SCYLLA_VERSION=$(cat build/SCYLLA-VERSION-FILE)
SCYLLA_RELEASE=$(cat build/SCYLLA-RELEASE-FILE)
if [ "$SCYLLA_VERSION" = "development" ]; then
SCYLLA_VERSION=0development
fi
cp dist/ubuntu/changelog.in debian/changelog
sed -i -e "s/@@VERSION@@/$SCYLLA_VERSION/g" debian/changelog
sed -i -e "s/@@RELEASE@@/$SCYLLA_RELEASE/g" debian/changelog
debuild -r fakeroot --no-tgz-check -us -uc

5
dist/ubuntu/changelog.in vendored Normal file
View File

@@ -0,0 +1,5 @@
scylla-server (@@VERSION@@-@@RELEASE@@-ubuntu1) trusty; urgency=medium
* Initial release.
-- Takuya ASADA <syuu@scylladb.com> Mon, 24 Aug 2015 09:22:55 +0000

View File

@@ -0,0 +1,5 @@
antlr3-c++-dev (3.5.2-ubuntu1) trusty; urgency=medium
* Initial release.
-- Takuya ASADA <syuu@scylladb.com> Mon, 24 Aug 2015 09:22:55 +0000

View File

@@ -0,0 +1 @@
9

View File

@@ -0,0 +1,12 @@
Source: antlr3-c++-dev
Maintainer: Takuya ASADA <syuu@scylladb.com>
Section: misc
Priority: optional
Standards-Version: 3.5.2
Build-Depends: debhelper (>= 9)
Package: antlr3-c++-dev
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: language tool for constructing recognizers, compilers etc
A language tool that provides a framework for constructing recognizers, interpreters, compilers, and translators from grammatical descriptions containing actions in a variety of target languages.

View File

@@ -0,0 +1,12 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ANTLR
Upstream-Contact: http://www.antlr.org/
Source: https://github.com/antlr/antlr3
Files: *
Copyright: Copyright (c) 2005-2009 Gokulakannan Somasundaram, ElectronDB
License: BSD-3-clause
Files: debian/*
Copyright: Copyright (c) 2015 ScyllaDB
License: AGPL-3.0

View File

@@ -0,0 +1,8 @@
#!/usr/bin/make -f
override_dh_auto_install:
mkdir -p $(CURDIR)/debian/antlr3-c++-dev/usr/include
cp $(CURDIR)/runtime/Cpp/include/* \
$(CURDIR)/debian/antlr3-c++-dev/usr/include
%:
dh $@

3
dist/ubuntu/dep/antlr3-tool-3.5.2/antlr3 vendored Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
exec /usr/bin/java -jar /usr/share/java/antlr-3.5.2-complete-no-st3.jar $*

View File

@@ -0,0 +1,5 @@
antlr3-tool (3.5.2-ubuntu1) trusty; urgency=medium
* Initial release.
-- Takuya ASADA <syuu@scylladb.com> Mon, 24 Aug 2015 09:22:55 +0000

Some files were not shown because too many files have changed in this diff Show More