1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #include "protocol.hpp"
18 
19 #include "cassandra.h"
20 
21 #define DSE_PROTOCOL_VERSION_BIT 0x40
22 #define DSE_PROTOCOL_VERSION_MASK 0x3F
23 
24 using namespace datastax;
25 using namespace datastax::internal::core;
26 
is_protocol_at_least_v5_or_dse_v2(int version)27 static bool is_protocol_at_least_v5_or_dse_v2(int version) {
28   if (version & DSE_PROTOCOL_VERSION_BIT) {
29     return version >= CASS_PROTOCOL_VERSION_DSEV2;
30   } else {
31     return version >= CASS_PROTOCOL_VERSION_V5;
32   }
33 }
34 
ProtocolVersion()35 ProtocolVersion::ProtocolVersion()
36     : value_(-1) {}
37 
ProtocolVersion(int value)38 ProtocolVersion::ProtocolVersion(int value)
39     : value_(value) {}
40 
lowest_supported()41 ProtocolVersion ProtocolVersion::lowest_supported() {
42   return ProtocolVersion(CASS_PROTOCOL_VERSION_V3);
43 }
44 
highest_supported(bool is_dse)45 ProtocolVersion ProtocolVersion::highest_supported(bool is_dse) {
46   return ProtocolVersion(is_dse ? CASS_PROTOCOL_VERSION_DSEV2 : CASS_PROTOCOL_VERSION_V4);
47 }
48 
newest_beta()49 ProtocolVersion ProtocolVersion::newest_beta() { return ProtocolVersion(CASS_PROTOCOL_VERSION_V5); }
50 
value() const51 int ProtocolVersion::value() const { return value_; }
52 
is_valid() const53 bool ProtocolVersion::is_valid() const {
54   return *this >= lowest_supported() && *this <= highest_supported(is_dse());
55 }
56 
is_beta() const57 bool ProtocolVersion::is_beta() const { return *this == newest_beta(); }
58 
is_dse() const59 bool ProtocolVersion::is_dse() const { return (value_ & DSE_PROTOCOL_VERSION_BIT) != 0; }
60 
to_string() const61 String ProtocolVersion::to_string() const {
62   if (value_ > 0) {
63     OStringStream ss;
64     if (is_dse()) {
65       ss << "DSEv" << (value_ & DSE_PROTOCOL_VERSION_MASK);
66     } else {
67       ss << "v" << value_;
68     }
69     return ss.str();
70   } else {
71     return "<invalid>";
72   }
73 }
74 
previous() const75 ProtocolVersion ProtocolVersion::previous() const {
76   if (*this <= lowest_supported()) {
77     return ProtocolVersion(); // Invalid
78   } else if (is_dse() && value_ <= CASS_PROTOCOL_VERSION_DSEV1) {
79     // Start trying Cassandra protocol versions
80     return ProtocolVersion::highest_supported(false);
81   } else {
82     return ProtocolVersion(value_ - 1);
83   }
84 }
85 
supports_set_keyspace() const86 bool ProtocolVersion::supports_set_keyspace() const {
87   assert(value_ > 0 && "Invalid protocol version");
88   return is_protocol_at_least_v5_or_dse_v2(value_);
89 }
90 
supports_result_metadata_id() const91 bool ProtocolVersion::supports_result_metadata_id() const {
92   assert(value_ > 0 && "Invalid protocol version");
93   return is_protocol_at_least_v5_or_dse_v2(value_);
94 }
95