1 /*
2   This is free and unencumbered software released into the public domain.
3 
4   Anyone is free to copy, modify, publish, use, compile, sell, or
5   distribute this software, either in source code form or as a compiled
6   binary, for any purpose, commercial or non-commercial, and by any
7   means.
8 
9   In jurisdictions that recognize copyright laws, the author or authors
10   of this software dedicate any and all copyright interest in the
11   software to the public domain. We make this dedication for the benefit
12   of the public at large and to the detriment of our heirs and
13   successors. We intend this dedication to be an overt act of
14   relinquishment in perpetuity of all present and future rights to this
15   software under copyright law.
16 
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23   OTHER DEALINGS IN THE SOFTWARE.
24 
25   For more information, please refer to <http://unlicense.org/>
26 */
27 
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "cassandra.h"
34 
print_error_description(CassError rc)35 void print_error_description(CassError rc) {
36   fprintf(stderr, "Error Description: %s\n", cass_error_desc(rc));
37 }
38 
print_error(CassFuture * future)39 void print_error(CassFuture* future) {
40   const char* message;
41   size_t message_length;
42   cass_future_error_message(future, &message, &message_length);
43   fprintf(stderr, "Error: %.*s\n", (int)message_length, message);
44 }
45 
create_quorum_execution_profile()46 CassExecProfile* create_quorum_execution_profile() {
47   CassExecProfile* profile = cass_execution_profile_new();
48   cass_execution_profile_set_consistency(profile, CASS_CONSISTENCY_QUORUM);
49   cass_execution_profile_set_request_timeout(profile, 300000); /* Five minute request timeout */
50   return profile;
51 }
52 
create_reduced_latency_write_execution_profile()53 CassExecProfile* create_reduced_latency_write_execution_profile() {
54   CassExecProfile* profile = cass_execution_profile_new();
55   cass_execution_profile_set_load_balance_round_robin(profile);
56   cass_execution_profile_set_token_aware_routing(profile, cass_true);
57   cass_execution_profile_set_consistency(profile, CASS_CONSISTENCY_ANY);
58   return profile;
59 }
60 
create_cluster(const char * hosts)61 CassCluster* create_cluster(const char* hosts) {
62   CassCluster* cluster = cass_cluster_new();
63   cass_cluster_set_contact_points(cluster, hosts);
64   return cluster;
65 }
66 
connect_session(CassSession * session,const CassCluster * cluster)67 CassError connect_session(CassSession* session, const CassCluster* cluster) {
68   /* Provide the cluster object as configuration to connect the session */
69   CassError rc = CASS_OK;
70   CassFuture* future = cass_session_connect(session, cluster);
71 
72   rc = cass_future_error_code(future);
73   if (rc != CASS_OK) {
74     /* Handle error */
75     print_error(future);
76   }
77   cass_future_free(future);
78 
79   return rc;
80 }
81 
execute_query(CassSession * session,const char * query)82 CassError execute_query(CassSession* session, const char* query) {
83   /* Build statement and execute query */
84   CassError rc = CASS_OK;
85   CassFuture* future = NULL;
86   CassStatement* statement = cass_statement_new(query, 0);
87   future = cass_session_execute(session, statement);
88 
89   rc = cass_future_error_code(future);
90   if (rc != CASS_OK) {
91     /* Handle error */
92     print_error(future);
93   }
94 
95   cass_future_free(future);
96   cass_statement_free(statement);
97 
98   return rc;
99 }
100 
insert_into_examples(CassSession * session,const char * profile_name,const char * key,const cass_bool_t value)101 CassError insert_into_examples(CassSession* session, const char* profile_name, const char* key,
102                                const cass_bool_t value) {
103   CassError rc = CASS_OK;
104   CassStatement* statement = NULL;
105   CassFuture* future = NULL;
106   const char* query = "INSERT INTO examples.execution_profiles \
107                         (key, value) VALUES (?, ?)";
108 
109   /* Build statement and execute query */
110   statement = cass_statement_new(query, 2);
111   if (profile_name != NULL) {
112     rc = cass_statement_set_execution_profile(statement, profile_name);
113     if (rc != CASS_OK) {
114       print_error_description(rc);
115     }
116   }
117   cass_statement_set_keyspace(statement, "execution_profiles");
118   cass_statement_add_key_index(statement, 0);
119   cass_statement_bind_string(statement, 0, key);
120   cass_statement_bind_bool(statement, 1, value);
121   future = cass_session_execute(session, statement);
122 
123   rc = cass_future_error_code(future);
124   if (rc != CASS_OK) {
125     /* Handle error */
126     print_error(future);
127   }
128 
129   cass_future_free(future);
130   cass_statement_free(statement);
131 
132   return rc;
133 }
134 
select_from_examples(CassSession * session,const char * profile_name,const char * key,cass_bool_t * return_value)135 CassError select_from_examples(CassSession* session, const char* profile_name, const char* key,
136                                cass_bool_t* return_value) {
137   CassError rc = CASS_OK;
138   CassStatement* statement = NULL;
139   CassFuture* future = NULL;
140 
141   /* Build statement and execute query */
142   const char* query = "SELECT * FROM examples.execution_profiles WHERE key = ?";
143   statement = cass_statement_new(query, 1);
144   if (profile_name != NULL) {
145     rc = cass_statement_set_execution_profile(statement, profile_name);
146     if (rc != CASS_OK) {
147       print_error_description(rc);
148     }
149   }
150   cass_statement_bind_string(statement, 0, key);
151   future = cass_session_execute(session, statement);
152 
153   rc = cass_future_error_code(future);
154   if (rc != CASS_OK) {
155     /* Handle error */
156     print_error(future);
157   } else {
158     /* Retrieve result set and get the first row */
159     const CassResult* result = cass_future_get_result(future);
160     const CassRow* row = cass_result_first_row(result);
161     if (row) {
162       const CassValue* value = cass_row_get_column_by_name(row, "value");
163       cass_value_get_bool(value, return_value);
164       printf("SELECT: Key = %s | Value = %s\n", key,
165              (*return_value == cass_true ? "true" : "false"));
166     }
167 
168     cass_result_free(result);
169   }
170 
171   cass_future_free(future);
172   cass_statement_free(statement);
173 
174   return rc;
175 }
176 
main(int argc,char * argv[])177 int main(int argc, char* argv[]) {
178   /* Setup default objects */
179   CassCluster* cluster = NULL;
180   CassSession* session = cass_session_new();
181   CassExecProfile* profile = NULL;
182   cass_bool_t value = cass_false;
183   const char* hosts = "127.0.0.1,127.0.0.2,127.0.0.3";
184 
185   /* Add contact points and create the cluster */
186   if (argc > 1) {
187     hosts = argv[1];
188   }
189   cluster = create_cluster(hosts);
190 
191   /* Create and set execution profiles; freeing once added to configuration */
192   profile = create_reduced_latency_write_execution_profile();
193   cass_cluster_set_execution_profile(cluster, "reduced_latency", profile);
194   cass_execution_profile_free(profile);
195   profile = create_quorum_execution_profile();
196   cass_cluster_set_execution_profile(cluster, "quorum", profile);
197   cass_execution_profile_free(profile);
198 
199   /* Provide the cluster object as configuration to connect the session */
200   if (connect_session(session, cluster) != CASS_OK) {
201     cass_cluster_free(cluster);
202     cass_session_free(session);
203     return -1;
204   }
205 
206   /* Create a keyspace and table for the execution profile example  */
207   execute_query(session, "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { \
208                   'class': 'SimpleStrategy', 'replication_factor': '3' \
209                 }");
210   execute_query(session, "CREATE TABLE IF NOT EXISTS examples.execution_profiles ( \
211                   key text PRIMARY KEY, \
212                   value boolean \
213                 )");
214 
215   /* Insert values using 'reduced_latency' profile */
216   insert_into_examples(session, "reduced_latency", "one", cass_true);
217   insert_into_examples(session, "reduced_latency", "two", cass_false);
218   insert_into_examples(session, "reduced_latency", "three", cass_true);
219   insert_into_examples(session, "reduced_latency", "four", cass_false);
220   insert_into_examples(session, "reduced_latency", "five", cass_true);
221 
222   /* Select the values from the cluster using the 'quorum' profile */
223   select_from_examples(session, "quorum", "one", &value);
224   assert(value == cass_true);
225   select_from_examples(session, "quorum", "two", &value);
226   assert(value == cass_false);
227   select_from_examples(session, "quorum", "three", &value);
228   assert(value == cass_true);
229   select_from_examples(session, "quorum", "four", &value);
230   assert(value == cass_false);
231   select_from_examples(session, "quorum", "five", &value);
232   assert(value == cass_true);
233 
234   cass_cluster_free(cluster);
235   cass_session_free(session);
236 
237   return 0;
238 }
239