-
Notifications
You must be signed in to change notification settings - Fork 0
WIP: Persistent logging Implementation #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #ifndef JITSERVERLOGGER_BASEPERSISTENTLOGGER_H | ||
| #define JITSERVERLOGGER_BASEPERSISTENTLOGGER_H | ||
| #include <stdint.h> | ||
|
|
||
| class BasePersistentLogger | ||
| { | ||
| protected: | ||
| const char * _databaseIP; | ||
| uint32_t _databasePort; | ||
| const char* _databaseUsername; | ||
| const char* _databasePassword; | ||
| const char* _databaseName; | ||
|
|
||
| public: | ||
| virtual bool connect() = 0; | ||
| virtual void disconnect() = 0; | ||
|
|
||
| BasePersistentLogger(const char * databaseIP, uint32_t databasePort, const char * databaseName) | ||
| { | ||
| _databaseIP = databaseIP; | ||
| _databasePort = databasePort; | ||
| _databaseName = databaseName; | ||
| _databaseUsername = ""; | ||
| _databasePassword = ""; | ||
| } | ||
| BasePersistentLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, | ||
| const char *databaseUsername, const char *databasePassword) | ||
| { | ||
| _databaseIP = databaseIP; | ||
| _databasePort = databasePort; | ||
| _databaseName = databaseName; | ||
| _databaseUsername = databaseUsername; | ||
| _databasePassword = databasePassword; | ||
| } | ||
| virtual bool logMethod(const char* method, uint64_t clientID, const char *logContent) = 0; | ||
| }; | ||
|
|
||
| #endif //JITSERVERLOGGER_BASEPERSISTENTLOGGER_H | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,229 @@ | ||
| #include <time.h> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is 'time" actually needed?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| #include <stdio.h> | ||
|
|
||
| #include "CassandraLogger.hpp" | ||
| #include "LoadDBLibs.hpp" | ||
| CassandraLogger::CassandraLogger(const char *databaseIP, | ||
| uint32_t databasePort, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alignment seems off here.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| const char *databaseName): BasePersistentLogger(databaseIP, databasePort, databaseName) | ||
| { | ||
| _session = NULL; | ||
| _connectFuture = NULL; | ||
| _cluster = NULL; | ||
| } | ||
|
|
||
| CassandraLogger::CassandraLogger(const char *databaseIP, uint32_t databasePort, | ||
| const char *databaseName, const char *databaseUsername, const char *databasePassword) | ||
| : BasePersistentLogger(databaseIP, databasePort, databaseName, databaseUsername, databasePassword) | ||
| { | ||
| _session = NULL; | ||
| _connectFuture = NULL; | ||
| _cluster = NULL; | ||
| } | ||
|
|
||
| bool CassandraLogger::createKeySpace() | ||
| { | ||
| char queryString[256]; | ||
| snprintf(queryString, 256, "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = {'class':'SimpleStrategy','replication_factor':1};", _databaseName); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Must check the return value of |
||
| OCassStatement* statement = Ocass_statement_new(queryString, 0); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this fail and return NULL? If so, it needs a check. |
||
|
|
||
| OCassFuture* queryFuture = Ocass_session_execute(_session, statement); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible for |
||
| Ocass_statement_free(statement); | ||
| if (Ocass_future_error_code(queryFuture) != 0) | ||
| { | ||
| /* Display connection error message */ | ||
| const char* message; | ||
| size_t messageLength; | ||
| Ocass_future_error_message(queryFuture, &message, &messageLength); | ||
| fprintf(stderr, "PersistentLogging - Cassandra Database Keyspace Creation Error: '%.*s'\n", (int)messageLength, message); | ||
|
|
||
| Ocass_future_free(queryFuture); | ||
| return false; | ||
| } | ||
|
|
||
| Ocass_future_free(queryFuture); | ||
| return true; | ||
|
|
||
| } | ||
| bool CassandraLogger::createTable(const char *tableName) | ||
| { | ||
| char queryString[256]; | ||
| snprintf(queryString, 256, "CREATE TABLE IF NOT EXISTS %s.%s (clientID text, methodName text, logContent text, insertionDate date,insertionTime time, primary key (clientID, methodName, insertionDate, insertionTime));", _databaseName, tableName); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Must check the return value of snprintf for overflow. |
||
| OCassStatement* statement = Ocass_statement_new(queryString, 0); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
| OCassFuture* queryFuture = Ocass_session_execute(_session, statement); | ||
| Ocass_statement_free(statement); | ||
| if (Ocass_future_error_code(queryFuture) != 0) | ||
| { | ||
| /* Display connection error message */ | ||
| const char* message; | ||
| size_t messageLength; | ||
| Ocass_future_error_message(queryFuture, &message, &messageLength); | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Table Creation Error: '%.*s'\n", (int)messageLength, message); | ||
|
|
||
| Ocass_future_free(queryFuture); | ||
| return false; | ||
| } | ||
|
|
||
| Ocass_future_free(queryFuture); | ||
| return true; | ||
| } | ||
| bool CassandraLogger::connect() | ||
| { | ||
| /* Setup and connect to cluster */ | ||
| _cluster = Ocass_cluster_new(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
| _session = Ocass_session_new(); | ||
| /*authenticate using databaseUsername and databasePassword*/ | ||
| Ocass_cluster_set_credentials(_cluster, _databaseUsername, _databasePassword); | ||
| /*Set protocol version */ | ||
| int rc_set_protocol = Ocass_cluster_set_protocol_version(_cluster, 4); | ||
| if (rc_set_protocol != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_protocol)); | ||
| Ocass_session_free(_session); | ||
| Ocass_cluster_free(_cluster); | ||
| return false; | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| } | ||
|
|
||
| /* Add contact points */ | ||
| int rc_set_ip = Ocass_cluster_set_contact_points(_cluster, _databaseIP); | ||
| if (rc_set_ip != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_ip)); | ||
| Ocass_session_free(_session); | ||
| Ocass_cluster_free(_cluster); | ||
| return false; | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| } | ||
|
|
||
| /*Set port number*/ | ||
| int rc_set_port = Ocass_cluster_set_port(_cluster, _databasePort); | ||
| if (rc_set_port != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_port)); | ||
| Ocass_session_free(_session); | ||
| Ocass_cluster_free(_cluster); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank lines |
||
| return false; | ||
|
|
||
| } | ||
|
|
||
| /* Provide the cluster object as configuration to connect the session */ | ||
| _connectFuture = Ocass_session_connect(_session, _cluster); | ||
|
|
||
| if (Ocass_future_error_code(_connectFuture) != 0) | ||
| { | ||
| /* Display connection error message */ | ||
| const char* message; | ||
| size_t messageLength; | ||
| Ocass_future_error_message(_connectFuture, &message, &messageLength); | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Connection Error: '%.*s'\n", (int)messageLength, message); | ||
| Ocass_session_free(_session); | ||
| Ocass_cluster_free(_cluster); | ||
| Ocass_future_free(_connectFuture); | ||
| return false; | ||
| } | ||
| return true; | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line |
||
| } | ||
|
|
||
|
|
||
| bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const char *logContent) | ||
| { | ||
|
|
||
| // create table space and table first | ||
| if (!createKeySpace()) return false; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| const char* tableName = "logs"; | ||
| if (!createTable(tableName)) return false; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| char queryString[256]; | ||
|
|
||
| snprintf(queryString, 256, "INSERT INTO %s.%s (clientID, methodName, logContent, insertionDate, insertionTime) VALUES (?, ?, ?, ?, ?)", _databaseName,tableName); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check for buffer overflow. |
||
| OCassStatement* statement | ||
| = Ocass_statement_new(queryString, 5); | ||
|
Comment on lines
+141
to
+142
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two lines can be on the same line There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, need to check that |
||
|
|
||
| /* Bind the values using the indices of the bind variables */ | ||
| char strClientID[64]; | ||
| snprintf(strClientID, 64, "%lu", clientID); | ||
| int rc_set_bind_pk = Ocass_statement_bind_string(statement, 0, strClientID); | ||
| if (rc_set_bind_pk != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_pk)); | ||
| Ocass_statement_free(statement); | ||
| return false; | ||
| } | ||
|
|
||
| int rc_set_bind_method = Ocass_statement_bind_string(statement, 1, method); | ||
| if (rc_set_bind_pk != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_method)); | ||
| Ocass_statement_free(statement); | ||
| return false; | ||
| } | ||
| int rc_set_bind_log_content = Ocass_statement_bind_string(statement, 2, logContent); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line here. Should be moved above. |
||
| if (rc_set_bind_log_content != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_log_content)); | ||
| Ocass_statement_free(statement); | ||
| return false; | ||
| } | ||
|
|
||
| time_t now = time(NULL); /* Time in seconds from Epoch */ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed about using portlib API for time, unless there is a strict requirement for using
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| /* Converts the time since the Epoch in seconds to the 'date' type */ | ||
| Ocass_uint32_t year_month_day_of_insertion = Ocass_date_from_epoch(now); | ||
| /* Converts the time since the Epoch in seconds to the 'time' type */ | ||
| Ocass_int64_t time_of_insertion = Ocass_time_from_epoch(now); | ||
|
|
||
| /* 'date' uses an unsigned 32-bit integer */ | ||
| int rc_set_bind_insertion_date = Ocass_statement_bind_uint32(statement, 3, year_month_day_of_insertion); | ||
|
|
||
| if (rc_set_bind_insertion_date != 0) | ||
| { | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n", Ocass_error_desc(rc_set_bind_insertion_date)); | ||
| Ocass_statement_free(statement); | ||
| return false; | ||
| } | ||
| /* 'time' uses a signed 64-bit integer */ | ||
| int rc_set_bind_insertion_time = Ocass_statement_bind_int64(statement, 4, time_of_insertion); | ||
| if (rc_set_bind_insertion_time != 0) | ||
| { | ||
| fprintf(stderr ,"Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_insertion_time)); | ||
| Ocass_statement_free(statement); | ||
| return false; | ||
| } | ||
|
|
||
| OCassFuture* queryFuture = Ocass_session_execute(_session, statement); | ||
|
|
||
| /* Statement objects can be freed immediately after being executed */ | ||
| Ocass_statement_free(statement); | ||
| if (Ocass_future_error_code(queryFuture) != 0) | ||
| { | ||
| /* Display connection error message */ | ||
| const char* message; | ||
| size_t messageLength; | ||
| Ocass_future_error_message(queryFuture, &message, &messageLength); | ||
| fprintf(stderr, "Persistent Logging - Cassandra Database Query Execution Error: '%.*s'\n", (int)messageLength, message); | ||
| Ocass_future_free(queryFuture); | ||
| return false; | ||
| } | ||
|
|
||
| Ocass_future_free(queryFuture); | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| void CassandraLogger::disconnect() | ||
| { | ||
| Ocass_future_free(_connectFuture); | ||
| Ocass_session_free(_session); | ||
| Ocass_cluster_free(_cluster); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #ifndef CASSANDRALOGGER_H | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every new file needs license information
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| #define CASSANDRALOGGER_H | ||
|
|
||
| #include "LoadDBLibs.hpp" | ||
| #include "BasePersistentLogger.hpp" | ||
| class CassandraLogger : public BasePersistentLogger | ||
| { | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line |
||
| private: | ||
| OCassCluster* _cluster; | ||
| OCassSession* _session; | ||
| OCassFuture* _connectFuture; | ||
| bool createKeySpace(); | ||
| bool createTable(const char *tableName); | ||
|
|
||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line |
||
| public: | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line |
||
| bool connect() override; | ||
| void disconnect() override; | ||
| CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, | ||
| const char *databaseUsername, const char *databasePassword); | ||
| CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName); | ||
| bool logMethod(const char *method, uint64_t clientID, const char *logContent) override; | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line |
||
| }; | ||
|
|
||
| #endif // CASSANDRALOGGER_H | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes that the strings receives as parameters continue to exist after the object is constructed.
I'll have to verify if that's the case.