|
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
|
@@ -938,6 +940,11 @@ def default_retry_policy(self, policy):
|
938 | 940 | establish connection pools. This can cause a rush of connections and queries if not mitigated with this factor.
|
939 | 941 | """
|
940 | 942 |
|
| 943 | + experimental_tablet_feature_enabled = False |
| 944 | + """ |
| 945 | + If true tablet experimental feature is enabled, its interface and use may change. |
| 946 | + """ |
| 947 | + |
941 | 948 | prepare_on_all_hosts = True
|
942 | 949 | """
|
943 | 950 | Specifies whether statements should be prepared on all hosts, or just one.
|
@@ -1124,6 +1131,7 @@ def __init__(self,
|
1124 | 1131 | schema_metadata_page_size=1000,
|
1125 | 1132 | address_translator=None,
|
1126 | 1133 | status_event_refresh_window=2,
|
| 1134 | + experimental_tablet_feature_enabled=False, # This field is experimental and may be changed / removed in the future |
1127 | 1135 | prepare_on_all_hosts=True,
|
1128 | 1136 | reprepare_on_up=True,
|
1129 | 1137 | execution_profiles=None,
|
@@ -1341,6 +1349,7 @@ def __init__(self,
|
1341 | 1349 | self.schema_event_refresh_window = schema_event_refresh_window
|
1342 | 1350 | self.topology_event_refresh_window = topology_event_refresh_window
|
1343 | 1351 | self.status_event_refresh_window = status_event_refresh_window
|
| 1352 | + self.experimental_tablet_feature_enabled = experimental_tablet_feature_enabled |
1344 | 1353 | self.connect_timeout = connect_timeout
|
1345 | 1354 | self.prepare_on_all_hosts = prepare_on_all_hosts
|
1346 | 1355 | self.reprepare_on_up = reprepare_on_up
|
@@ -1393,9 +1402,8 @@ def __init__(self,
|
1393 | 1402 | self.control_connection = ControlConnection(
|
1394 | 1403 | self, self.control_connection_timeout,
|
1395 | 1404 | self.schema_event_refresh_window, self.topology_event_refresh_window,
|
1396 |
| - self.status_event_refresh_window, |
1397 |
| - schema_metadata_enabled, token_metadata_enabled, |
1398 |
| - schema_meta_page_size=schema_metadata_page_size) |
| 1405 | + self.status_event_refresh_window, schema_metadata_enabled, |
| 1406 | + token_metadata_enabled, schema_meta_page_size=schema_metadata_page_size) |
1399 | 1407 |
|
1400 | 1408 | if client_id is None:
|
1401 | 1409 | self.client_id = uuid.uuid4()
|
@@ -2389,6 +2397,9 @@ def add_prepared(self, query_id, prepared_statement):
|
2389 | 2397 | with self._prepared_statement_lock:
|
2390 | 2398 | self._prepared_statements[query_id] = prepared_statement
|
2391 | 2399 |
|
| 2400 | + # Experimental, this interface and use may change |
| 2401 | + def check_tablets_enabled(self): |
| 2402 | + return self.experimental_tablet_feature_enabled |
2392 | 2403 |
|
2393 | 2404 | class Session(object):
|
2394 | 2405 | """
|
@@ -3687,6 +3698,9 @@ def _try_connect(self, host):
|
3687 | 3698 | "SCHEMA_CHANGE": partial(_watch_callback, self_weakref, '_handle_schema_change')
|
3688 | 3699 | }, register_timeout=self._timeout)
|
3689 | 3700 |
|
| 3701 | + if self._cluster.check_tablets_enabled(): |
| 3702 | + self._init_tablets() |
| 3703 | + |
3690 | 3704 | sel_peers = self._get_peers_query(self.PeersQueryType.PEERS, connection)
|
3691 | 3705 | sel_local = self._SELECT_LOCAL if self._token_meta_enabled else self._SELECT_LOCAL_NO_TOKENS
|
3692 | 3706 | peers_query = QueryMessage(query=sel_peers, consistency_level=ConsistencyLevel.ONE)
|
@@ -3993,6 +4007,34 @@ def _refresh_node_list_and_token_map(self, connection, preloaded_results=None,
|
3993 | 4007 | log.debug("[control connection] Rebuilding token map due to topology changes")
|
3994 | 4008 | self._cluster.metadata.rebuild_token_map(partitioner, token_map)
|
3995 | 4009 |
|
| 4010 | + # Experimental, this interface and use may change |
| 4011 | + def _init_tablets(self): |
| 4012 | + self._cluster.metadata._tablets = Tablets({}) |
| 4013 | + |
| 4014 | + # Experimental, this interface and use may change |
| 4015 | + def add_tablet(self, keyspace, table, tablet): |
| 4016 | + tablets = self._cluster.metadata._tablets._tablets |
| 4017 | + tablets_for_table = tablets.setdefault((keyspace, table), []) |
| 4018 | + start = None |
| 4019 | + end = len(tablets_for_table) - 1 |
| 4020 | + for id, t in enumerate(tablets_for_table): |
| 4021 | + if t.last_token > tablet.first_token and t.first_token < tablet.last_token: |
| 4022 | + if start == None: |
| 4023 | + start = id |
| 4024 | + end = id |
| 4025 | + if start != None: |
| 4026 | + del tablets_for_table[start:end + 1] |
| 4027 | + |
| 4028 | + insert_idx = len(tablets_for_table) |
| 4029 | + for id, t in enumerate(tablets_for_table): |
| 4030 | + if t.first_token > tablet.first_token: |
| 4031 | + insert_idx = id |
| 4032 | + break |
| 4033 | + tablets_for_table.insert(insert_idx, tablet) |
| 4034 | + |
| 4035 | + tablets[(keyspace, table)] = tablets_for_table |
| 4036 | + self._cluster.metadata._tablets = Tablets(tablets) |
| 4037 | + |
3996 | 4038 | @staticmethod
|
3997 | 4039 | def _is_valid_peer(row):
|
3998 | 4040 | return bool(_NodeInfo.get_broadcast_rpc_address(row) and row.get("host_id") and
|
@@ -4600,7 +4642,10 @@ def _query(self, host, message=None, cb=None):
|
4600 | 4642 | connection = None
|
4601 | 4643 | try:
|
4602 | 4644 | # TODO get connectTimeout from cluster settings
|
4603 |
| - connection, request_id = pool.borrow_connection(timeout=2.0, routing_key=self.query.routing_key if self.query else None) |
| 4645 | + if self.query: |
| 4646 | + connection, request_id = pool.borrow_connection(timeout=2.0, routing_key=self.query.routing_key, keyspace=self.query.keyspace, table=self.query.table) |
| 4647 | + else: |
| 4648 | + connection, request_id = pool.borrow_connection(timeout=2.0) |
4604 | 4649 | self._connection = connection
|
4605 | 4650 | result_meta = self.prepared_statement.result_metadata if self.prepared_statement else []
|
4606 | 4651 |
|
@@ -4719,6 +4764,17 @@ def _set_result(self, host, connection, pool, response):
|
4719 | 4764 | self._warnings = getattr(response, 'warnings', None)
|
4720 | 4765 | self._custom_payload = getattr(response, 'custom_payload', None)
|
4721 | 4766 |
|
| 4767 | + if self._custom_payload and self.session.cluster.check_tablets_enabled(): |
| 4768 | + ctype = types.lookup_casstype('ListType(TupleType(UUIDType, Int32Type))') |
| 4769 | + tablet_replicas = ctype.from_binary(self._custom_payload.get('tablet_replicas'), 3) |
| 4770 | + ctype_token = types.lookup_casstype('LongType') |
| 4771 | + first_token = ctype_token.from_binary(self._custom_payload.get('token_range')[:8], 3) |
| 4772 | + last_token = ctype_token.from_binary(self._custom_payload.get('token_range')[8:], 3) |
| 4773 | + tablet = Tablet.from_row(first_token, last_token, tablet_replicas) |
| 4774 | + keyspace = self.query.keyspace |
| 4775 | + table = self.query.table |
| 4776 | + self.session.cluster.control_connection.add_tablet(keyspace, table, tablet) |
| 4777 | + |
4722 | 4778 | if isinstance(response, ResultMessage):
|
4723 | 4779 | if response.kind == RESULT_KIND_SET_KEYSPACE:
|
4724 | 4780 | session = getattr(self, 'session', None)
|
|
0 commit comments