|
41 | 41 | import weakref |
42 | 42 | from weakref import WeakValueDictionary |
43 | 43 |
|
44 | | -from cassandra import (ConsistencyLevel, AuthenticationFailed, |
| 44 | +from cassandra import (ConsistencyLevel, AuthenticationFailed, InvalidRequest, |
45 | 45 | OperationTimedOut, UnsupportedOperation, |
46 | 46 | SchemaTargetType, DriverException, ProtocolVersion, |
47 | 47 | UnresolvableContactPoints) |
|
51 | 51 | EndPoint, DefaultEndPoint, DefaultEndPointFactory, |
52 | 52 | ContinuousPagingState, SniEndPointFactory, ConnectionBusy) |
53 | 53 | from cassandra.cqltypes import UserType |
| 54 | +import cassandra.cqltypes as types |
54 | 55 | from cassandra.encoder import Encoder |
55 | 56 | from cassandra.protocol import (QueryMessage, ResultMessage, |
56 | 57 | ErrorMessage, ReadTimeoutErrorMessage, |
|
79 | 80 | named_tuple_factory, dict_factory, tuple_factory, FETCH_SIZE_UNSET, |
80 | 81 | HostTargetingStatement) |
81 | 82 | from cassandra.marshal import int64_pack |
| 83 | +from cassandra.tablets import Tablet, Tablets |
82 | 84 | from cassandra.timestamps import MonotonicTimestampGenerator |
83 | 85 | from cassandra.compat import Mapping |
84 | 86 | from cassandra.util import _resolve_contact_points_to_string_map, Version |
@@ -1784,6 +1786,14 @@ def connect(self, keyspace=None, wait_for_all_pools=False): |
1784 | 1786 | self.shutdown() |
1785 | 1787 | raise |
1786 | 1788 |
|
| 1789 | + # Update the information about tablet support after connection handshake. |
| 1790 | + self.load_balancing_policy._tablets_routing_v1 = self.control_connection._tablets_routing_v1 |
| 1791 | + child_policy = self.load_balancing_policy.child_policy if hasattr(self.load_balancing_policy, 'child_policy') else None |
| 1792 | + while child_policy is not None: |
| 1793 | + if hasattr(child_policy, '_tablet_routing_v1'): |
| 1794 | + child_policy._tablet_routing_v1 = self.control_connection._tablets_routing_v1 |
| 1795 | + child_policy = child_policy.child_policy if hasattr(child_policy, 'child_policy') else None |
| 1796 | + |
1787 | 1797 | self.profile_manager.check_supported() # todo: rename this method |
1788 | 1798 |
|
1789 | 1799 | if self.idle_heartbeat_interval: |
@@ -2398,7 +2408,6 @@ def add_prepared(self, query_id, prepared_statement): |
2398 | 2408 | with self._prepared_statement_lock: |
2399 | 2409 | self._prepared_statements[query_id] = prepared_statement |
2400 | 2410 |
|
2401 | | - |
2402 | 2411 | class Session(object): |
2403 | 2412 | """ |
2404 | 2413 | A collection of connection pools for each host in the cluster. |
@@ -3550,6 +3559,7 @@ class PeersQueryType(object): |
3550 | 3559 | _schema_meta_page_size = 1000 |
3551 | 3560 |
|
3552 | 3561 | _uses_peers_v2 = True |
| 3562 | + _tablets_routing_v1 = False |
3553 | 3563 |
|
3554 | 3564 | # for testing purposes |
3555 | 3565 | _time = time |
@@ -3683,6 +3693,8 @@ def _try_connect(self, host): |
3683 | 3693 | # If sharding information is available, it's a ScyllaDB cluster, so do not use peers_v2 table. |
3684 | 3694 | if connection.features.sharding_info is not None: |
3685 | 3695 | self._uses_peers_v2 = False |
| 3696 | + |
| 3697 | + self._tablets_routing_v1 = connection.features.tablets_routing_v1 |
3686 | 3698 |
|
3687 | 3699 | # use weak references in both directions |
3688 | 3700 | # _clear_watcher will be called when this ControlConnection is about to be finalized |
@@ -4609,7 +4621,10 @@ def _query(self, host, message=None, cb=None): |
4609 | 4621 | connection = None |
4610 | 4622 | try: |
4611 | 4623 | # TODO get connectTimeout from cluster settings |
4612 | | - connection, request_id = pool.borrow_connection(timeout=2.0, routing_key=self.query.routing_key if self.query else None) |
| 4624 | + if self.query: |
| 4625 | + connection, request_id = pool.borrow_connection(timeout=2.0, routing_key=self.query.routing_key, keyspace=self.query.keyspace, table=self.query.table) |
| 4626 | + else: |
| 4627 | + connection, request_id = pool.borrow_connection(timeout=2.0) |
4613 | 4628 | self._connection = connection |
4614 | 4629 | result_meta = self.prepared_statement.result_metadata if self.prepared_statement else [] |
4615 | 4630 |
|
@@ -4728,6 +4743,19 @@ def _set_result(self, host, connection, pool, response): |
4728 | 4743 | self._warnings = getattr(response, 'warnings', None) |
4729 | 4744 | self._custom_payload = getattr(response, 'custom_payload', None) |
4730 | 4745 |
|
| 4746 | + if self._custom_payload and self.session.cluster.control_connection._tablets_routing_v1 and 'tablets-routing-v1' in self._custom_payload: |
| 4747 | + protocol = self.session.cluster.protocol_version |
| 4748 | + info = self._custom_payload.get('tablets-routing-v1') |
| 4749 | + ctype = types.lookup_casstype('TupleType(LongType, LongType, ListType(TupleType(UUIDType, Int32Type)))') |
| 4750 | + tablet_routing_info = ctype.from_binary(info, protocol) |
| 4751 | + first_token = tablet_routing_info[0] |
| 4752 | + last_token = tablet_routing_info[1] |
| 4753 | + tablet_replicas = tablet_routing_info[2] |
| 4754 | + tablet = Tablet.from_row(first_token, last_token, tablet_replicas) |
| 4755 | + keyspace = self.query.keyspace |
| 4756 | + table = self.query.table |
| 4757 | + self.session.cluster.metadata._tablets.add_tablet(keyspace, table, tablet) |
| 4758 | + |
4731 | 4759 | if isinstance(response, ResultMessage): |
4732 | 4760 | if response.kind == RESULT_KIND_SET_KEYSPACE: |
4733 | 4761 | session = getattr(self, 'session', None) |
|
0 commit comments