File network_interface_sr.cpp¶
File List > communication > network_interface_sr.cpp
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* network_interface_sr.cpp - Server side network interface functions
* for client requests.
*/
#ident "$Id$"
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "filesys.hpp"
#include "filesys_temp.hpp"
#include "porting.h"
#include "porting_inline.hpp"
#include "perf_monitor.h"
#include "memory_alloc.h"
#include "storage_common.h"
#include "xserver_interface.h"
#include "statistics_sr.h"
#include "btree_load.h"
#include "perf_monitor.h"
#include "log_impl.h"
#include "log_lsa.hpp"
#include "boot_sr.h"
#include "locator_sr.h"
#include "server_interface.h"
#include "oid.h"
#include "error_manager.h"
#include "object_representation.h"
#include "network.h"
#include "log_comm.h"
#include "network_interface_sr.h"
#include "page_buffer.h"
#include "file_manager.h"
#include "boot_sr.h"
#include "arithmetic.h"
#include "serial.h"
#include "query_manager.h"
#include "transaction_sr.h"
#include "release_string.h"
#include "critical_section.h"
#include "statistics.h"
#include "chartype.h"
#include "heap_file.h"
#include "pl_sr.h"
#include "replication.h"
#include "server_support.h"
#include "connection_sr.h"
#include "log_writer.h"
#include "databases_file.h"
#include "es.h"
#include "es_posix.h"
#include "event_log.h"
#include "trace_log.h"
#include "tsc_timer.h"
#include "vacuum.h"
#include "object_primitive.h"
#include "tz_support.h"
#include "dbtype.h"
#include "thread_manager.hpp" // for thread_get_thread_entry_info
#include "compile_context.h"
#include "load_session.hpp"
#include "session.h"
#include "xasl.h"
#include "xasl_cache.h"
#include "elo.h"
#include "transaction_transient.hpp"
#include "method_invoke_group.hpp"
#include "log_manager.h"
#include "crypt_opfunc.h"
#include "flashback.h"
#include "pl_struct_compile.hpp"
#include "pl_compile_handler.hpp"
#include "pl_session.hpp"
#include "pl_executor.hpp"
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
#if defined (SUPPRESS_STRLEN_WARNING)
#define strlen(s1) ((int) strlen(s1))
#endif /* defined (SUPPRESS_STRLEN_WARNING) */
#define NET_COPY_AREA_SENDRECV_SIZE (OR_INT_SIZE * 3)
#define NET_SENDRECV_BUFFSIZE (OR_INT_SIZE)
#define STATDUMP_BUF_SIZE (2 * 16 * 1024)
#define QUERY_INFO_BUF_SIZE (2048 + STATDUMP_BUF_SIZE)
#define NET_DEFER_END_QUERIES_MAX 10
/* Query execution with commit. */
#define QEWC_SAFE_GUARD_SIZE 1024
// To have the safe area is just a safe guard to avoid potential issues of bad size calculation.
#define QEWC_MAX_DATA_SIZE (DB_PAGESIZE - QEWC_SAFE_GUARD_SIZE)
/* This file is only included in the server. So set the on_server flag on */
unsigned int db_on_server = 1;
STATIC_INLINE TRAN_STATE stran_server_commit_internal (THREAD_ENTRY *thread_p, unsigned int rid, bool retain_lock,
bool *should_conn_reset) __attribute__ ((ALWAYS_INLINE));
STATIC_INLINE TRAN_STATE stran_server_abort_internal (THREAD_ENTRY *thread_p, unsigned int rid, bool retain_lock,
bool *should_conn_reset) __attribute__ ((ALWAYS_INLINE));
STATIC_INLINE void stran_server_auto_commit_or_abort (THREAD_ENTRY *thread_p, unsigned int rid,
QUERY_ID *p_end_queries, int n_query_ids, bool need_abort,
bool has_updated, bool *end_query_allowed,
TRAN_STATE *tran_state, bool *should_conn_reset)
__attribute__ ((ALWAYS_INLINE));
STATIC_INLINE int stran_can_end_after_query_execution (THREAD_ENTRY *thread_p, int query_flag, QFILE_LIST_ID *list_id,
bool *can_end_transaction) __attribute__ ((ALWAYS_INLINE));
static bool need_to_abort_tran (THREAD_ENTRY *thread_p, int *errid);
static int server_capabilities (void);
static int check_client_capabilities (THREAD_ENTRY *thread_p, int client_cap, int rel_compare,
REL_COMPATIBILITY *compatibility, const char *client_host);
static void sbtree_find_unique_internal (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen);
static int er_log_slow_query (THREAD_ENTRY *thread_p, EXECUTION_INFO *info, int time,
UINT64 *diff_stats, char *queryinfo_string);
static int trace_log_slow_query (THREAD_ENTRY *thread_p, EXECUTION_INFO *info, int time, UINT64 *diff_stats,
char *queryinfo_string, int trace_level);
static void event_log_many_ioreads (THREAD_ENTRY *thread_p, EXECUTION_INFO *info, int time, UINT64 *diff_stats);
static void event_log_extend_pages (THREAD_ENTRY *thread_p, EXECUTION_INFO *info);
static void set_tdes_query_exec_info (int tran_index, char *sql_user_text);
/*
* stran_server_commit_internal - commit transaction on server.
*
* return:
*
* thread_p(in): thred entry.
* rid(in): request id.
* retain_lock(in): true, if retains lock.
* should_conn_reset(out): reset on commit.
*
* NOTE: This function must be called at transaction commit.
*/
STATIC_INLINE TRAN_STATE
stran_server_commit_internal (THREAD_ENTRY *thread_p, unsigned int rid, bool retain_lock, bool *should_conn_reset)
{
bool has_updated;
TRAN_STATE state;
assert (should_conn_reset != NULL);
has_updated = logtb_has_updated (thread_p);
state = xtran_server_commit (thread_p, retain_lock);
PL_SESSION *session = cubpl::get_session ();
if (!session || session->is_sp_running () == false)
{
net_cleanup_server_queues (rid);
}
if (state != TRAN_UNACTIVE_COMMITTED && state != TRAN_UNACTIVE_COMMITTED_INFORMING_PARTICIPANTS)
{
/* Likely the commit failed.. somehow */
(void) return_error_to_client (thread_p, rid);
}
*should_conn_reset = xtran_should_connection_reset (thread_p, has_updated);
return state;
}
/*
* stran_server_abort_internal - abort transaction on server.
*
* return:
*
* thread_p(in): thred entry.
* rid(in): request id.
* should_conn_reset(out): reset on commit.
*
* NOTE: This function must be called at transaction abort.
*/
STATIC_INLINE TRAN_STATE
stran_server_abort_internal (THREAD_ENTRY *thread_p, unsigned int rid, bool *should_conn_reset)
{
TRAN_STATE state;
bool has_updated;
has_updated = logtb_has_updated (thread_p);
state = xtran_server_abort (thread_p);
PL_SESSION *session = cubpl::get_session ();
if (!session || session->is_sp_running () == false)
{
net_cleanup_server_queues (rid);
}
if (state != TRAN_UNACTIVE_ABORTED && state != TRAN_UNACTIVE_ABORTED_INFORMING_PARTICIPANTS)
{
/* Likely the abort failed.. somehow */
(void) return_error_to_client (thread_p, rid);
}
*should_conn_reset = xtran_should_connection_reset (thread_p, has_updated);
return state;
}
/*
* stran_server_auto_commit_or_abort - do server-side auto-commit or abort
*
* return: nothing
*
* thread_p(in): thread entry
* rid(in): request id
* p_end_queries(in): queries to end
* n_query_ids(in): the number of queries to end
* need_abort(in): true, if need to abort
* has_updated(in):true, if has updated before abort
* end_query_allowed(in/out): true, if end query is allowed
* tran_state(in/out): transaction state
* should_conn_reset(in/out): reset on commit
*
* Note: This function must be called only when the query is executed with commit, soon after query execution.
* When we call this function, it is possible that transaction was aborted.
*/
STATIC_INLINE void
stran_server_auto_commit_or_abort (THREAD_ENTRY *thread_p, unsigned int rid, QUERY_ID *p_end_queries,
int n_query_ids, bool need_abort, bool has_updated, bool *end_query_allowed,
TRAN_STATE *tran_state, bool *should_conn_reset)
{
int error_code, all_error_code, i;
assert (tran_state != NULL && should_conn_reset != NULL && end_query_allowed != NULL);
*should_conn_reset = false;
if (*end_query_allowed == false)
{
if (prm_get_bool_value (PRM_ID_DEBUG_AUTOCOMMIT))
{
_er_log_debug (ARG_FILE_LINE, "stran_server_auto_commit_or_abort: active transaction.\n");
}
return;
}
/* We commit/abort transaction, after ending queries. */
all_error_code = NO_ERROR;
if ((*tran_state != TRAN_UNACTIVE_ABORTED) && (*tran_state != TRAN_UNACTIVE_ABORTED_INFORMING_PARTICIPANTS))
{
/* If not already aborted, ends the queries. */
for (i = 0; i < n_query_ids; i++)
{
if (p_end_queries[i] > 0)
{
error_code = xqmgr_end_query (thread_p, p_end_queries[i]);
if (error_code != NO_ERROR)
{
all_error_code = error_code;
/* Continue to try to close as many queries as possible. */
}
}
}
}
if (all_error_code != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
*end_query_allowed = false;
}
else if (need_abort == false)
{
/* Needs commit. */
*tran_state = stran_server_commit_internal (thread_p, rid, false, should_conn_reset);
if (prm_get_bool_value (PRM_ID_DEBUG_AUTOCOMMIT))
{
_er_log_debug (ARG_FILE_LINE, "stran_server_auto_commit_or_abort: transaction committed. \n");
}
}
else
{
/* Needs abort. */
if ((*tran_state != TRAN_UNACTIVE_ABORTED) && (*tran_state != TRAN_UNACTIVE_ABORTED_INFORMING_PARTICIPANTS))
{
/* We have an error and the transaction was not aborted. Since is auto commit transaction, we can abort it.
* In this way, we can avoid abort request.
*/
*tran_state = stran_server_abort_internal (thread_p, rid, should_conn_reset);
if (prm_get_bool_value (PRM_ID_DEBUG_AUTOCOMMIT))
{
_er_log_debug (ARG_FILE_LINE, "stran_server_auto_commit_or_abort: transaction aborted. \n");
}
}
else
{
/* Transaction was already aborted. */
*should_conn_reset = xtran_should_connection_reset (thread_p, has_updated);
}
}
}
/*
* need_to_abort_tran - check whether the transaction should be aborted
*
* return: true/false
*
* thread_p(in): thread entry
* errid(out): the latest error code
*/
static bool
need_to_abort_tran (THREAD_ENTRY *thread_p, int *errid)
{
LOG_TDES *tdes;
bool flag_abort = false;
assert (thread_p != NULL);
#if 0 /* TODO */
assert (er_errid () != NO_ERROR);
#endif
*errid = er_errid ();
if (*errid == ER_LK_UNILATERALLY_ABORTED || *errid == ER_DB_NO_MODIFICATIONS)
{
flag_abort = true;
}
/*
* DEFENCE CODE:
* below block means ER_LK_UNILATERALLY_ABORTED occurs but another error
* set after that.
* So, re-set that error to rollback in client side.
*/
tdes = LOG_FIND_CURRENT_TDES (thread_p);
if (tdes != NULL && tdes->tran_abort_reason != TRAN_NORMAL && flag_abort == false)
{
flag_abort = true;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_LK_UNILATERALLY_ABORTED, 4, thread_p->tran_index,
tdes->client.get_db_user (), tdes->client.get_host_name (), tdes->client.process_id);
}
return flag_abort;
}
/*
* return_error_to_client -
*
* return: state of operation
*
* rid(in):
*
* NOTE:
*/
TRAN_STATE
return_error_to_client (THREAD_ENTRY *thread_p, unsigned int rid)
{
LOG_TDES *tdes;
int errid;
bool flag_abort = false;
char *area;
OR_ALIGNED_BUF (1024) a_buffer;
char *buffer;
int length = 1024;
TRAN_STATE tran_state = TRAN_UNACTIVE_UNKNOWN;
CSS_CONN_ENTRY *conn;
assert (thread_p != NULL);
conn = thread_p->conn_entry;
assert (conn != NULL);
tdes = LOG_FIND_CURRENT_TDES (thread_p);
if (tdes != NULL)
{
tran_state = tdes->state;
}
flag_abort = need_to_abort_tran (thread_p, &errid);
/* check some errors which require special actions */
/*
* ER_LK_UNILATERALLY_ABORTED may have occurred due to deadlock.
* If it happened, do server-side rollback of the transaction.
* If ER_DB_NO_MODIFICATIONS error is occurred in server-side,
* it means that the user tried to update the database
* when the server was disabled to modify. (aka standby mode)
*/
if (flag_abort == true)
{
/* need to hide the previous error, ER_LK_UNILATERALLY_ABORTED to rollback the current transaction. */
er_stack_push ();
tran_state = tran_server_unilaterally_abort_tran (thread_p);
er_stack_pop ();
}
if (errid == ER_DB_NO_MODIFICATIONS)
{
conn->reset_on_commit = true;
}
buffer = OR_ALIGNED_BUF_START (a_buffer);
area = er_get_area_error (buffer, &length);
if (area != NULL)
{
conn->db_error = errid;
css_send_error_to_client (conn, rid, area, length);
conn->db_error = 0;
}
if (tdes != NULL)
{
tdes->tran_abort_reason = TRAN_NORMAL;
}
return tran_state;
}
/*
* server_capabilities -
*
* return:
*/
static int
server_capabilities (void)
{
int capabilities = 0;
capabilities |= NET_CAP_INTERRUPT_ENABLED;
if (db_Disable_modifications > 0)
{
capabilities |= NET_CAP_UPDATE_DISABLED;
}
if (boot_Server_status == BOOT_SERVER_MAINTENANCE)
{
capabilities |= NET_CAP_REMOTE_DISABLED;
}
if (css_is_ha_repl_delayed () == true)
{
capabilities |= NET_CAP_HA_REPL_DELAY;
}
if (HA_GET_MODE () == HA_MODE_REPLICA)
{
assert_release (css_ha_server_state () == HA_SERVER_STATE_STANDBY);
capabilities |= NET_CAP_HA_REPLICA;
}
return capabilities;
}
/*
* check_client_capabilities -
*
* return:
* client_cap(in): client capability
*
*/
static int
check_client_capabilities (THREAD_ENTRY *thread_p, int client_cap, int rel_compare, REL_COMPATIBILITY *compatibility,
const char *client_host)
{
int server_cap;
assert (compatibility != NULL);
server_cap = server_capabilities ();
/* interrupt-ability should be same */
if ((server_cap ^ client_cap) & NET_CAP_INTERRUPT_ENABLED)
{
client_cap ^= NET_CAP_INTERRUPT_ENABLED;
}
/* network protocol compatibility */
if (*compatibility == REL_NOT_COMPATIBLE)
{
if (rel_compare < 0 && (client_cap & NET_CAP_FORWARD_COMPATIBLE))
{
/*
* The client is older than the server but the client has a forward
* compatible capability.
*/
*compatibility = REL_FORWARD_COMPATIBLE;
}
if (rel_compare > 0 && (client_cap & NET_CAP_BACKWARD_COMPATIBLE))
{
/*
* The client is newer than the server but the client has a backward
* compatible capability.
*/
*compatibility = REL_BACKWARD_COMPATIBLE;
}
}
/* remote connection capability */
if (server_cap & NET_CAP_REMOTE_DISABLED)
{
/* do capability check on client side */
er_log_debug (ARG_FILE_LINE, "NET_CAP_REMOTE_DISABLED server %s %d client %s %d\n", boot_Host_name,
server_cap & NET_CAP_REMOTE_DISABLED, client_host, client_cap & NET_CAP_REMOTE_DISABLED);
}
if (client_cap & NET_CAP_HA_IGNORE_REPL_DELAY)
{
thread_p->conn_entry->ignore_repl_delay = true;
er_log_debug (ARG_FILE_LINE, "NET_CAP_HA_IGNORE_REPL_DELAY client %s %d\n", client_host,
client_cap & NET_CAP_HA_IGNORE_REPL_DELAY);
}
return client_cap;
}
/*
* server_ping - return that the server is alive
* return:
* rid(in): request id
*/
void
server_ping (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int client_val, server_val;
er_log_debug (ARG_FILE_LINE, "The server_ping() is called.");
/* you can get something useful from the request */
or_unpack_int (request, &client_val);
/* you can envelope something useful into the reply */
server_val = 0;
or_pack_int (reply, server_val);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_INT_SIZE);
}
/*
* server_ping_with_handshake -
*
* return:
*
* rid(in): request id
* request(in):
* reqlen(in):
*
* NOTE: Handler for the SERVER_PING_WITH_HANDSHAKE request.
* We record the client's version string here and send back our own
* version string so the client can determine compatibility.
*/
int
server_ping_with_handshake (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (REL_MAX_RELEASE_LENGTH + (OR_INT_SIZE * 3) + CUB_MAXHOSTNAMELEN) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int reply_size = OR_ALIGNED_BUF_SIZE (a_reply);
char *ptr, *client_release, *client_host;
const char *server_release;
int client_capabilities, client_bit_platform, status = CSS_NO_ERRORS;
int client_type;
int strlen1, strlen2;
REL_COMPATIBILITY compat;
server_release = rel_release_string ();
if (reqlen > 0)
{
ptr = or_unpack_string_nocopy (request, &client_release);
ptr = or_unpack_int (ptr, &client_capabilities);
ptr = or_unpack_int (ptr, &client_bit_platform);
ptr = or_unpack_int (ptr, &client_type);
ptr = or_unpack_string_nocopy (ptr, &client_host);
if (client_release != NULL)
{
client_release = css_add_client_version_string (thread_p, client_release);
}
}
else
{
client_release = NULL;
client_bit_platform = 0;
client_type = DB_CLIENT_TYPE_UNKNOWN;
client_capabilities = 0;
client_host = NULL;
}
/* check bits model */
if (client_bit_platform != rel_bit_platform ())
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_DIFFERENT_BIT_PLATFORM, 2, rel_bit_platform (),
client_bit_platform);
(void) return_error_to_client (thread_p, rid);
status = CSS_UNPLANNED_SHUTDOWN;
}
/* If we can't get the client version, we have to disconnect it. */
if (client_release == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_HAND_SHAKE, 1, client_host);
(void) return_error_to_client (thread_p, rid);
status = CSS_UNPLANNED_SHUTDOWN;
}
/*
* 1. get the result of compatibility check.
* 2. check if the both capabilities of client and server are compatible.
* 3. check if the client has a capability to make it compatible.
*/
compat = rel_get_net_compatible (client_release, server_release);
if (check_client_capabilities (thread_p, client_capabilities, rel_compare (client_release, server_release),
&compat, client_host) != client_capabilities)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_HAND_SHAKE, 1, client_host);
(void) return_error_to_client (thread_p, rid);
}
if (compat == REL_NOT_COMPATIBLE)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_DIFFERENT_RELEASE, 2, server_release, client_release);
(void) return_error_to_client (thread_p, rid);
status = CSS_UNPLANNED_SHUTDOWN;
}
/* update connection counters for reserved connections */
if (css_increment_num_conn ((BOOT_CLIENT_TYPE) client_type) != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CSS_CLIENTS_EXCEEDED, 1, NUM_NORMAL_TRANS);
(void) return_error_to_client (thread_p, rid);
status = CSS_UNPLANNED_SHUTDOWN;
}
else
{
thread_p->conn_entry->client_type = (BOOT_CLIENT_TYPE) client_type;
}
reply_size = (or_packed_string_length (server_release, &strlen1) + (OR_INT_SIZE * 3)
+ or_packed_string_length (boot_Host_name, &strlen2));
ptr = or_pack_string_with_length (reply, (char *) server_release, strlen1);
ptr = or_pack_string (ptr, NULL); /* for backward compatibility */
ptr = or_pack_int (ptr, server_capabilities ());
ptr = or_pack_int (ptr, rel_bit_platform ());
ptr = or_pack_string_with_length (ptr, boot_Host_name, strlen2);
css_send_data_to_client (thread_p->conn_entry, rid, reply, reply_size);
return status;
}
/*
* slocator_fetch -
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_fetch (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid;
int chn;
LOCK lock;
OID class_oid;
int class_chn;
int prefetch;
LC_COPYAREA *copy_area;
char *ptr;
int success;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
int num_objs = 0;
int fetch_version_type;
ptr = or_unpack_oid (request, &oid);
ptr = or_unpack_int (ptr, &chn);
ptr = or_unpack_lock (ptr, &lock);
ptr = or_unpack_int (ptr, &fetch_version_type);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &class_chn);
ptr = or_unpack_int (ptr, &prefetch);
copy_area = NULL;
success =
xlocator_fetch (thread_p, &oid, chn, lock, (LC_FETCH_VERSION_TYPE) fetch_version_type,
(LC_FETCH_VERSION_TYPE) fetch_version_type, &class_oid, class_chn, prefetch, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [desc_ptr, copy_area]() noexcept
{
if (desc_ptr)
{
free (desc_ptr);
}
if (copy_area)
{
locator_free_copy_area (copy_area);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), desc_ptr,
desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_get_class -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_get_class (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID class_oid, oid;
int class_chn;
LOCK lock;
int prefetching;
LC_COPYAREA *copy_area;
int success;
char *ptr;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + OR_OID_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
int num_objs = 0;
ptr = or_unpack_oid (request, &class_oid);
ptr = or_unpack_int (ptr, &class_chn);
ptr = or_unpack_oid (ptr, &oid);
ptr = or_unpack_lock (ptr, &lock);
ptr = or_unpack_int (ptr, &prefetching);
copy_area = NULL;
success = xlocator_get_class (thread_p, &class_oid, class_chn, &oid, lock, prefetching, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_oid (ptr, &class_oid);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [copy_area, desc_ptr]() noexcept
{
if (desc_ptr)
{
free (desc_ptr);
}
if (copy_area)
{
locator_free_copy_area (copy_area);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), desc_ptr,
desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_fetch_all -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_fetch_all (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
HFID hfid;
LOCK lock;
OID class_oid, last_oid;
int nobjects, nfetched;
LC_COPYAREA *copy_area;
int success;
char *ptr;
int fetch_version_type;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + (OR_INT_SIZE * 5) + OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
int num_objs = 0;
int nparallel_process, nparallel_process_idx, request_pages;
NET_ENDIAN server_endian = get_endian_type ();
int client_endian;
int encode_endian = 1;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_lock (ptr, &lock);
ptr = or_unpack_int (ptr, &fetch_version_type);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &nobjects);
ptr = or_unpack_int (ptr, &nfetched);
ptr = or_unpack_oid (ptr, &last_oid);
ptr = or_unpack_int (ptr, &request_pages);
ptr = or_unpack_int (ptr, &nparallel_process);
ptr = or_unpack_int (ptr, &nparallel_process_idx);
ptr = or_unpack_int (ptr, &client_endian);
if ((NET_ENDIAN) client_endian == server_endian && server_endian != NET_ENDIAN_UNKNOWN)
{
encode_endian = 0;
}
assert ((nparallel_process <= 1) || (nparallel_process_idx >= 0 && nparallel_process_idx < nparallel_process));
if (nparallel_process > 1)
{
thread_p->_unload_cnt_parallel_process = nparallel_process;
thread_p->_unload_parallel_process_idx = nparallel_process_idx;
}
else
{
thread_p->_unload_cnt_parallel_process = NO_UNLOAD_PARALLEL_PROCESSIING;
thread_p->_unload_parallel_process_idx = NO_UNLOAD_PARALLEL_PROCESSIING;
}
copy_area = NULL;
success =
xlocator_fetch_all (thread_p, &hfid, &lock, (LC_FETCH_VERSION_TYPE) fetch_version_type, &class_oid, &nobjects,
&nfetched, &last_oid, ©_area, request_pages);
if (nparallel_process > 1)
{
thread_p->_unload_cnt_parallel_process = NO_UNLOAD_PARALLEL_PROCESSIING;
thread_p->_unload_parallel_process_idx = NO_UNLOAD_PARALLEL_PROCESSIING;
}
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs =
locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, (bool) encode_endian);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, encode_endian);
ptr = or_pack_lock (ptr, lock);
ptr = or_pack_int (ptr, nobjects);
ptr = or_pack_int (ptr, nfetched);
ptr = or_pack_oid (ptr, &last_oid);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (encode_endian && desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
/* desc_ptr points a memory address somewhere in copy_area if encode_endian is 0 */
if (!desc_size && desc_ptr)
{
if (encode_endian)
{
free (desc_ptr);
}
desc_ptr = NULL;
}
if (!content_size && copy_area)
{
if (encode_endian || (!encode_endian && !desc_ptr))
{
locator_free_copy_area (copy_area);
copy_area = NULL;
}
content_ptr = NULL;
}
auto deleter = [copy_area, encode_endian, desc_ptr]() noexcept
{
if (encode_endian && desc_ptr)
{
free (desc_ptr);
}
if (copy_area)
{
locator_free_copy_area (copy_area);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), desc_ptr,
desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_does_exist -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_does_exist (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid, class_oid;
int chn, class_chn, prefetch, doesexist;
int need_fetching;
LOCK lock;
int fetch_version_type;
LC_COPYAREA *copy_area;
char *ptr;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE + OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
int num_objs = 0;
ptr = or_unpack_oid (request, &oid);
ptr = or_unpack_int (ptr, &chn);
ptr = or_unpack_lock (ptr, &lock);
ptr = or_unpack_int (ptr, &fetch_version_type);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &class_chn);
ptr = or_unpack_int (ptr, &need_fetching);
ptr = or_unpack_int (ptr, &prefetch);
copy_area = NULL;
doesexist =
xlocator_does_exist (thread_p, &oid, chn, lock, (LC_FETCH_VERSION_TYPE) fetch_version_type, &class_oid, class_chn,
need_fetching, prefetch, ©_area);
if (doesexist == LC_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, doesexist);
ptr = or_pack_oid (ptr, &class_oid);
if (copy_area == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [copy_area, desc_ptr]() noexcept
{
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), desc_ptr,
desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_notify_isolation_incons -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_notify_isolation_incons (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
LC_COPYAREA *copy_area;
char *ptr;
int success;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
int num_objs = 0;
copy_area = NULL;
success = xlocator_notify_isolation_incons (thread_p, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [copy_area, desc_ptr]() noexcept
{
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), desc_ptr,
desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_repl_force - process log applier's request to replicate data
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_repl_force (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int size, packed_size;
int success;
LC_COPYAREA *copy_area = NULL, *reply_copy_area = NULL;
char *ptr;
int csserror;
OR_ALIGNED_BUF (NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int content_size;
char *content_ptr = NULL, *new_content_ptr = NULL;
char *reply_content_ptr = NULL;
int num_objs;
char *packed_desc = NULL;
int packed_desc_size;
LC_COPYAREA_MANYOBJS *mobjs, *reply_mobjs;
char *desc_ptr = NULL;
int desc_size;
ptr = or_unpack_int (request, &num_objs);
ptr = or_unpack_int (ptr, &packed_desc_size);
ptr = or_unpack_int (ptr, &content_size);
csserror = 0;
copy_area = locator_recv_allocate_copyarea (num_objs, &content_ptr, content_size);
if (copy_area)
{
if (num_objs > 0)
{
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &packed_desc, &packed_size);
}
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto exit_on_error;
}
else
{
locator_unpack_copy_area_descriptor (num_objs, copy_area, packed_desc, -1);
mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copy_area);
if (content_size > 0)
{
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &new_content_ptr, &size);
if (new_content_ptr != NULL)
{
memcpy (content_ptr, new_content_ptr, size);
thread_p->release_packet (new_content_ptr);
new_content_ptr = NULL;
}
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto exit_on_error;
}
/* make copy_area (estimated size) to report errors */
reply_copy_area =
locator_recv_allocate_copyarea (num_objs, &reply_content_ptr, content_size + OR_INT_SIZE * num_objs);
reply_mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (reply_copy_area);
reply_mobjs->num_objs = 0;
}
success = xlocator_repl_force (thread_p, copy_area, &reply_copy_area);
/*
* Send the descriptor and content to handle errors
*/
num_objs =
locator_send_copy_area (reply_copy_area, &reply_content_ptr, &content_size, &desc_ptr, &desc_size, true);
ptr = or_pack_int (reply, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (success != NO_ERROR && success != ER_LC_PARTIALLY_FAILED_TO_FLUSH)
{
(void) return_error_to_client (thread_p, rid);
}
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && reply_copy_area)
{
locator_free_copy_area (reply_copy_area);
reply_copy_area = NULL;
reply_content_ptr = NULL;
}
auto deleter = [desc_ptr, reply_copy_area]() noexcept
{
if (reply_copy_area)
{
locator_free_copy_area (reply_copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply),
desc_ptr, desc_size, reply_content_ptr, content_size, std::move (deleter));
}
}
if (packed_desc)
{
thread_p->release_packet (packed_desc);
packed_desc = NULL;
}
if (copy_area != NULL)
{
locator_free_copy_area (copy_area);
}
return ;
exit_on_error:
if (packed_desc)
{
thread_p->release_packet (packed_desc);
packed_desc = NULL;
}
if (copy_area != NULL)
{
locator_free_copy_area (copy_area);
}
if (reply_copy_area != NULL)
{
locator_free_copy_area (reply_copy_area);
}
if (desc_ptr)
{
free_and_init (desc_ptr);
}
return;
}
/*
* slocator_force -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_force (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int received_size, packed_size;
int success;
LC_COPYAREA *copy_area = NULL;
char *ptr;
int csserror;
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int content_size;
char *content_ptr = NULL, *new_content_ptr = NULL;
int num_objs;
char *packed_desc = NULL;
int packed_desc_size;
int multi_update_flags;
LC_COPYAREA_MANYOBJS *mobjs;
int i, num_ignore_error_list;
int ignore_error_list[-ER_LAST_ERROR];
ptr = or_unpack_int (request, &num_objs);
ptr = or_unpack_int (ptr, &multi_update_flags);
ptr = or_unpack_int (ptr, &packed_desc_size);
ptr = or_unpack_int (ptr, &content_size);
ptr = or_unpack_int (ptr, &num_ignore_error_list);
for (i = 0; i < num_ignore_error_list; i++)
{
ptr = or_unpack_int (ptr, &ignore_error_list[i]);
}
csserror = 0;
copy_area = locator_recv_allocate_copyarea (num_objs, &content_ptr, content_size);
if (copy_area)
{
if (num_objs > 0)
{
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &packed_desc, &packed_size);
assert (csserror || packed_desc_size == packed_size);
}
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto end;
}
else
{
locator_unpack_copy_area_descriptor (num_objs, copy_area, packed_desc, -1);
mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copy_area);
mobjs->multi_update_flags = multi_update_flags;
if (content_size > 0)
{
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &new_content_ptr, &received_size);
if (new_content_ptr != NULL)
{
memcpy (content_ptr, new_content_ptr, received_size);
thread_p->release_packet (new_content_ptr);
new_content_ptr = NULL;
}
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto end;
}
}
success = xlocator_force (thread_p, copy_area, num_ignore_error_list, ignore_error_list);
/*
* Send the descriptor part since some information about the objects
* (e.g., OIDs) may be send back to client.
* Don't need to send the content since it is not updated.
*/
locator_pack_copy_area_descriptor (num_objs, copy_area, packed_desc, packed_desc_size);
ptr = or_pack_int (reply, success);
ptr = or_pack_int (ptr, packed_desc_size);
ptr = or_pack_int (ptr, 0);
if (success != NO_ERROR && success != ER_LC_PARTIALLY_FAILED_TO_FLUSH)
{
(void) return_error_to_client (thread_p, rid);
}
if (!packed_desc_size && packed_desc)
{
thread_p->conn_entry->release_packet (packed_desc);
packed_desc = NULL;
}
auto deleter = [conn = thread_p->conn_entry, packed_desc]() noexcept
{
if (packed_desc)
{
conn->release_packet (packed_desc);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply),
packed_desc, packed_desc_size, NULL, 0, std::move (deleter));
}
}
if (copy_area != NULL)
{
locator_free_copy_area (copy_area);
}
return ;
end:
if (packed_desc)
{
thread_p->release_packet (packed_desc);
packed_desc = NULL;
}
if (copy_area != NULL)
{
locator_free_copy_area (copy_area);
}
}
/*
* slocator_fetch_lockset -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_fetch_lockset (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
LC_COPYAREA *copy_area;
LC_LOCKSET *lockset;
OR_ALIGNED_BUF (NET_SENDRECV_BUFFSIZE + NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr, *content_ptr;
int desc_size, content_size;
char *packed = NULL;
int packed_size;
char *ptr;
bool first_call;
int num_objs;
int send_size;
ptr = or_unpack_int (request, &packed_size);
if (packed_size == 0 || css_receive_data_from_client (thread_p->conn_entry, rid, &packed, (int *) &packed_size))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
if (packed)
{
thread_p->release_packet (packed);
}
return;
}
lockset = locator_allocate_and_unpack_lockset (packed, packed_size, true, true, false);
thread_p->release_packet (packed);
if ((lockset == NULL) || (lockset->length <= 0))
{
(void) return_error_to_client (thread_p, rid);
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, ER_FAILED);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
first_call = true;
do
{
desc_ptr = NULL;
num_objs = 0;
copy_area = NULL;
success = xlocator_fetch_lockset (thread_p, lockset, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
send_size = locator_pack_lockset (lockset, first_call, false);
packed = lockset->packed;
packed_size = lockset->packed_size;
ptr = or_pack_int (reply, send_size);
ptr = or_pack_int (ptr, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL && lockset == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (desc_ptr)
{
free_and_init (desc_ptr);
}
}
else
{
if (!send_size && packed)
{
locator_free_packed (packed, packed_size);
packed = NULL;
}
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [packed = lockset->packed, packed_size = lockset->packed_size, copy_area, desc_ptr]() noexcept
{
if (packed)
{
locator_free_packed (packed, packed_size);
}
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_3_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), packed,
send_size, desc_ptr, desc_size, content_ptr, content_size, std::move (deleter));
lockset->packed = NULL;
lockset->packed_size = 0;
}
first_call = false;
}
while (copy_area && lockset
&& ((lockset->num_classes_of_reqobjs > lockset->num_classes_of_reqobjs_processed)
|| (lockset->num_reqobjs > lockset->num_reqobjs_processed)));
if (lockset)
{
locator_free_lockset (lockset);
}
}
/*
* slocator_fetch_all_reference_lockset -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_fetch_all_reference_lockset (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid;
int chn;
LOCK lock;
OID class_oid;
int class_chn;
int prune_level;
int quit_on_errors;
int success;
LC_COPYAREA *copy_area;
LC_LOCKSET *lockset;
OR_ALIGNED_BUF (NET_SENDRECV_BUFFSIZE + NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
char *ptr;
int num_objs = 0;
char *packed = NULL;
int packed_size;
int send_size = 0;
ptr = or_unpack_oid (request, &oid);
ptr = or_unpack_int (ptr, &chn);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &class_chn);
ptr = or_unpack_lock (ptr, &lock);
ptr = or_unpack_int (ptr, &quit_on_errors);
ptr = or_unpack_int (ptr, &prune_level);
lockset = NULL;
copy_area = NULL;
success =
xlocator_fetch_all_reference_lockset (thread_p, &oid, chn, &class_oid, class_chn, lock, quit_on_errors, prune_level,
&lockset, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (lockset != NULL && lockset->length > 0)
{
send_size = locator_pack_lockset (lockset, true, true);
packed = lockset->packed;
packed_size = lockset->packed_size;
if (!packed)
{
(void) return_error_to_client (thread_p, rid);
success = ER_FAILED;
}
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, send_size);
ptr = or_pack_int (ptr, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL && lockset == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
else
{
if (!send_size && lockset)
{
locator_free_lockset (lockset);
lockset = NULL;
packed = NULL;
}
if (!desc_size && desc_ptr)
{
free_and_init (desc_ptr);
}
if (!content_size && copy_area)
{
locator_free_copy_area (copy_area);
copy_area = NULL;
content_ptr = NULL;
}
auto deleter = [copy_area, desc_ptr, lockset]() noexcept
{
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
if (lockset)
{
locator_free_lockset (lockset);
}
};
css_send_reply_and_3_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), packed,
send_size, desc_ptr, desc_size, content_ptr, content_size, std::move (deleter));
}
}
/*
* slocator_find_class_oid -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_find_class_oid (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
LC_FIND_CLASSNAME found;
char *classname;
OID class_oid;
LOCK lock;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_string_nocopy (request, &classname);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_lock (ptr, &lock);
found = xlocator_find_class_oid (thread_p, classname, &class_oid, lock);
if (found == LC_CLASSNAME_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, found);
ptr = or_pack_oid (ptr, &class_oid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_reserve_classnames -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_reserve_classnames (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
LC_FIND_CLASSNAME reserved = LC_CLASSNAME_ERROR;
int num_classes;
char **classnames;
OID *class_oids;
char *ptr;
int i;
int malloc_size;
char *malloc_area;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &num_classes);
malloc_size = ((sizeof (char *) + sizeof (OID)) * num_classes);
malloc_area = (char *) db_private_alloc (thread_p, malloc_size);
if (malloc_area != NULL)
{
classnames = (char **) malloc_area;
class_oids = (OID *) ((char *) malloc_area + (sizeof (char *) * num_classes));
for (i = 0; i < num_classes; i++)
{
ptr = or_unpack_string_nocopy (ptr, &classnames[i]);
ptr = or_unpack_oid (ptr, &class_oids[i]);
}
reserved = xlocator_reserve_class_names (thread_p, num_classes, (const char **) classnames, class_oids);
}
if (reserved == LC_CLASSNAME_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, reserved);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (malloc_area)
{
db_private_free_and_init (thread_p, malloc_area);
}
}
/*
* slocator_get_reserved_class_name_oid () - Send to client whether class name was
* reserved by it.
*
* return : Void.
* thread_p (in) : Thread entry.
* rid (in) : ??
* request (in) : Request data.
* reqlen (in) : Request.
*/
void
slocator_get_reserved_class_name_oid (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *classname;
OID class_oid = OID_INITIALIZER;
OR_ALIGNED_BUF (OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int error = NO_ERROR;
(void) or_unpack_string_nocopy (request, &classname);
error = xlocator_get_reserved_class_name_oid (thread_p, classname, &class_oid);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
(void) return_error_to_client (thread_p, rid);
}
else
{
assert (!OID_ISNULL (&class_oid));
}
(void) or_pack_oid (reply, &class_oid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_delete_class_name -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_delete_class_name (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *classname;
LC_FIND_CLASSNAME deleted;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_string_nocopy (request, &classname);
deleted = xlocator_delete_class_name (thread_p, classname);
if (deleted == LC_CLASSNAME_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, deleted);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_rename_class_name -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_rename_class_name (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *oldname, *newname;
OID class_oid;
LC_FIND_CLASSNAME renamed;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_string_nocopy (request, &oldname);
ptr = or_unpack_string_nocopy (ptr, &newname);
ptr = or_unpack_oid (ptr, &class_oid);
renamed = xlocator_rename_class_name (thread_p, oldname, newname, &class_oid);
if (renamed == LC_CLASSNAME_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, renamed);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_assign_oid -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_assign_oid (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
HFID hfid;
int expected_length;
OID class_oid, perm_oid;
char *classname;
int success;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_int (ptr, &expected_length);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_string_nocopy (ptr, &classname);
success = ((xlocator_assign_oid (thread_p, &hfid, &perm_oid, expected_length, &class_oid, classname) == NO_ERROR)
? NO_ERROR : ER_FAILED);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
ptr = or_pack_oid (ptr, &perm_oid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sqst_server_get_statistics -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqst_server_get_statistics (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID classoid;
unsigned int timestamp;
char *ptr;
char *buffer;
int buffer_length;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_oid (request, &classoid);
ptr = or_unpack_int (ptr, (int *) ×tamp);
buffer = xstats_get_statistics_from_server (thread_p, &classoid, timestamp, &buffer_length);
if (buffer == NULL && buffer_length < 0)
{
(void) return_error_to_client (thread_p, rid);
buffer_length = 0;
}
(void) or_pack_int (reply, buffer_length);
auto deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer,
buffer_length, std::move (deleter));
}
/*
* slog_checkpoint -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slog_checkpoint (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
log_wakeup_checkpoint_daemon ();
/* just send back a dummy message */
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
#if defined(ENABLE_UNUSED_FUNCTION)
/*
* slogtb_has_updated -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_has_updated (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int has_updated;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
has_updated = logtb_has_updated (thread_p);
(void) or_pack_int (reply, has_updated);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
#endif /* ENABLE_UNUSED_FUNCTION */
/*
* slogtb_set_interrupt -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_set_interrupt (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int set;
(void) or_unpack_int (request, &set);
xlogtb_set_interrupt (thread_p, set);
/*
* No reply expected...
*/
}
/*
* slogtb_set_suppress_repl_on_transaction -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_set_suppress_repl_on_transaction (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int set;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &set);
xlogtb_set_suppress_repl_on_transaction (thread_p, set);
/* always success */
(void) or_pack_int (reply, NO_ERROR);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slogtb_reset_wait_msecs -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_reset_wait_msecs (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int wait_msecs;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &wait_msecs);
wait_msecs = xlogtb_reset_wait_msecs (thread_p, wait_msecs);
(void) or_pack_int (reply, wait_msecs);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slogtb_reset_isolation -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_reset_isolation (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int isolation, error_code;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_int (request, &isolation);
error_code = (int) xlogtb_reset_isolation (thread_p, (TRAN_ISOLATION) isolation);
if (error_code != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, error_code);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slogpb_dump_stat -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogpb_dump_stat (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (NULL, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("logpb_dump_stat_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (NULL, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xlogpb_dump_stat (outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (NULL, buffer);
}
/*
* slog_find_lob_locator -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slog_find_lob_locator (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *locator;
/*ES_URI real_locator;*/
std::byte *real_locator;
int real_loc_size;
LOB_LOCATOR_STATE state;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
(void) or_unpack_string_nocopy (request, &locator);
real_locator = new std::byte[ES_MAX_URI_LEN + 1];
state = xtx_find_lob_locator (thread_p, locator, (char *) real_locator);
real_loc_size = strlen ((char *) real_locator) + 1;
ptr = or_pack_int (reply, real_loc_size);
(void) or_pack_int (ptr, (int) state);
auto deleter = [real_locator]() noexcept
{
if (real_locator != NULL)
{
delete[] real_locator;
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply),
(char *) real_locator,
real_loc_size, std::move (deleter));
}
/*
* slog_add_lob_locator -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slog_add_lob_locator (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *locator;
LOB_LOCATOR_STATE state;
int tmp_int, error;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &locator);
ptr = or_unpack_int (ptr, &tmp_int);
state = (LOB_LOCATOR_STATE) tmp_int;
error = xtx_add_lob_locator (thread_p, locator, state);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slog_change_state_of_locator -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slog_change_state_of_locator (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *locator, *new_locator;
LOB_LOCATOR_STATE state;
int tmp_int, error;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &locator);
ptr = or_unpack_string_nocopy (ptr, &new_locator);
ptr = or_unpack_int (ptr, &tmp_int);
state = (LOB_LOCATOR_STATE) tmp_int;
error = xtx_change_state_of_locator (thread_p, locator, new_locator, state);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slog_drop_lob_locator -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slog_drop_lob_locator (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *locator;
int error;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &locator);
error = xtx_drop_lob_locator (thread_p, locator);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
slog_supplement_statement (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr, *start_ptr;
int ddl_type;
int obj_type;
OID classoid;
OID oid;
char *stmt_text;
char *supplemental_data;
int data_len;
LOG_TDES *tdes;
/* CAS and Server are able to have different parameter value, when broker restarted with changed parameter value */
if (prm_get_integer_value (PRM_ID_SUPPLEMENTAL_LOG) == 1)
{
ptr = or_unpack_int (request, &ddl_type);
ptr = or_unpack_int (ptr, &obj_type);
ptr = or_unpack_oid (ptr, &classoid);
ptr = or_unpack_oid (ptr, &oid);
or_unpack_string_nocopy (ptr, &stmt_text);
/* ddl_type | obj_type | class OID | OID | stmt_text len | stmt_text */
data_len =
OR_INT_SIZE + OR_INT_SIZE + OR_OID_SIZE + OR_OID_SIZE + OR_INT_SIZE + or_packed_string_length (stmt_text, NULL);
supplemental_data = (char *) malloc (data_len + MAX_ALIGNMENT);
if (supplemental_data == NULL)
{
success = ER_OUT_OF_VIRTUAL_MEMORY;
goto end;
}
ptr = start_ptr = supplemental_data;
ptr = or_pack_int (ptr, ddl_type);
ptr = or_pack_int (ptr, obj_type);
ptr = or_pack_oid (ptr, &classoid);
ptr = or_pack_oid (ptr, &oid);
ptr = or_pack_int (ptr, strlen (stmt_text));
ptr = or_pack_string (ptr, stmt_text);
data_len = ptr - start_ptr;
tdes = LOG_FIND_CURRENT_TDES (thread_p);
if (!tdes->has_supplemental_log)
{
log_append_supplemental_info (thread_p, LOG_SUPPLEMENT_TRAN_USER, strlen (tdes->client.get_db_user ()),
tdes->client.get_db_user ());
tdes->has_supplemental_log = true;
}
log_append_supplemental_info (thread_p, LOG_SUPPLEMENT_DDL, data_len, (void *) supplemental_data);
free_and_init (supplemental_data);
}
end:
(void) or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sacl_reload -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sacl_reload (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
error = xacl_reload (thread_p);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sacl_dump -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sacl_dump (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("acl_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xacl_dump (thread_p, outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* slock_dump -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slock_dump (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int is_contention;
int send_size;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &buffer_size);
ptr = or_unpack_int (ptr, &is_contention);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("lock_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xlock_dump (thread_p, outfp, is_contention);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size, TIMEOUT_INFINITE);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* shf_create -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_create (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
HFID hfid;
char *ptr;
OID class_oid;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_HFID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int reuse_oid = 0;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &reuse_oid);
error = xheap_create (thread_p, &hfid, &class_oid, (bool) reuse_oid);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_errcode (reply, error);
ptr = or_pack_hfid (ptr, &hfid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* shf_destroy -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_destroy (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
#if defined(ENABLE_UNUSED_FUNCTION)
int error;
HFID hfid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_hfid (request, &hfid);
error = xheap_destroy (thread_p, &hfid, NULL);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
#endif /* ENABLE_UNUSED_FUNCTION */
}
/*
* shf_destroy_when_new -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_destroy_when_new (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
HFID hfid;
OID class_oid;
int force;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &force);
error = xheap_destroy_newly_created (thread_p, &hfid, &class_oid, (bool) force);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* shf_heap_reclaim_addresses -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_heap_reclaim_addresses (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
HFID hfid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL;
if (boot_can_compact (thread_p) == false)
{
(void) or_pack_errcode (reply, ER_COMPACTDB_ALREADY_STARTED);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
ptr = or_unpack_hfid (request, &hfid);
error = xheap_reclaim_addresses (thread_p, &hfid);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
if (css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply)) != NO_ERROR)
{
boot_compact_stop (thread_p);
}
}
/*
* shf_get_maxslotted_reclength -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_get_maxslotted_reclength (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int maxslotted_reclength;
(void) xheap_get_maxslotted_reclength (maxslotted_reclength);
reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_pack_int (reply, maxslotted_reclength);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sfile_apply_tde_to_class_files -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sfile_apply_tde_to_class_files (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
char *ptr;
OID class_oid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_oid (request, &class_oid);
error = xfile_apply_tde_to_class_files (thread_p, &class_oid);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
stde_get_data_keys (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int area_size = -1;
char *reply, *area, *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
int err = NO_ERROR;
reply = OR_ALIGNED_BUF_START (a_reply);
if (!tde_is_loaded ())
{
(void) return_error_to_client (thread_p, rid);
area = NULL;
area_size = 0;
err = ER_TDE_CIPHER_IS_NOT_LOADED;
}
else
{
area_size = 3 * or_packed_stream_length (TDE_DATA_KEY_LENGTH);
area = (char *) malloc (area_size);
if (area == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_size = 0;
}
else
{
ptr = or_pack_stream (area, (char *) tde_Cipher.data_keys.perm_key, TDE_DATA_KEY_LENGTH);
ptr = or_pack_stream (ptr, (char *) tde_Cipher.data_keys.temp_key, TDE_DATA_KEY_LENGTH);
ptr = or_pack_stream (ptr, (char *) tde_Cipher.data_keys.log_key, TDE_DATA_KEY_LENGTH);
}
}
ptr = or_pack_int (reply, area_size);
ptr = or_pack_int (ptr, err);
auto deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area, area_size,
std::move (deleter));
}
/*
* stde_is_loaded -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stde_is_loaded (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_pack_int (reply, tde_is_loaded ());
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stde_get_mk_file_path -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stde_get_mk_file_path (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char mk_path[PATH_MAX] = { 0, };
int pathlen = 0;
int area_size = -1;
char *reply, *area, *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
int err = NO_ERROR;
reply = OR_ALIGNED_BUF_START (a_reply);
tde_make_keys_file_fullname (mk_path, boot_db_full_name (), false);
area_size = or_packed_string_length (mk_path, &pathlen);
area = (char *) malloc (area_size);
if (area == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_size = 0;
}
else
{
ptr = or_pack_string_with_length (area, (char *) mk_path, pathlen);
}
ptr = or_pack_int (reply, area_size);
ptr = or_pack_int (ptr, err);
auto deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area, area_size,
std::move (deleter));
}
/*
* stde_get_set_mk_info -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stde_get_mk_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
char *ptr;
int mk_index;
time_t created_time, set_time;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE + OR_BIGINT_SIZE + OR_BIGINT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
error = xtde_get_mk_info (thread_p, &mk_index, &created_time, &set_time);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_errcode (reply, error);
ptr = or_pack_int (ptr, mk_index);
ptr = or_pack_int64 (ptr, created_time);
ptr = or_pack_int64 (ptr, set_time);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stde_change_mk_on_server -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stde_change_mk_on_server (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
char *ptr;
int mk_index;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &mk_index);
error = xtde_change_mk_without_flock (thread_p, mk_index);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_commit -
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_commit (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state;
int xretain_lock;
bool retain_lock, should_conn_reset = false;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int row_count = DB_ROW_COUNT_NOT_SET;
int n_query_ids = 0, i = 0;
QUERY_ID query_id;
ptr = or_unpack_int (request, &xretain_lock);
ptr = or_unpack_int (ptr, &row_count);
/* First end deferred queries */
ptr = or_unpack_int (ptr, &n_query_ids);
for (i = 0; i < n_query_ids; i++)
{
ptr = or_unpack_ptr (ptr, &query_id);
if (query_id > 0)
{
(void) xqmgr_end_query (thread_p, query_id);
}
}
retain_lock = (bool) xretain_lock;
/* set row count */
xsession_set_row_count (thread_p, row_count);
state = stran_server_commit_internal (thread_p, rid, retain_lock, &should_conn_reset);
ptr = or_pack_int (reply, (int) state);
ptr = or_pack_int (ptr, (int) should_conn_reset);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_abort -
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_abort (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state;
bool should_conn_reset = false, has_updated;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
has_updated = logtb_has_updated (thread_p);
state = stran_server_abort_internal (thread_p, rid, &should_conn_reset);
ptr = or_pack_int (reply, state);
ptr = or_pack_int (ptr, (int) should_conn_reset);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_has_updated -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_has_updated (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int has_updated;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
has_updated = xtran_server_has_updated (thread_p);
(void) or_pack_int (reply, has_updated);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_start_topop -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_start_topop (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
LOG_LSA topop_lsa;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
success = (xtran_server_start_topop (thread_p, &topop_lsa) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
ptr = or_pack_log_lsa (ptr, &topop_lsa);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_end_topop -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_end_topop (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state;
LOG_LSA topop_lsa;
int xresult;
LOG_RESULT_TOPOP result;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
(void) or_unpack_int (request, &xresult);
result = (LOG_RESULT_TOPOP) xresult;
state = xtran_server_end_topop (thread_p, result, &topop_lsa);
ptr = or_pack_int (reply, (int) state);
ptr = or_pack_log_lsa (ptr, &topop_lsa);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_savepoint -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_savepoint (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
char *savept_name;
LOG_LSA topop_lsa;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &savept_name);
success = (xtran_server_savepoint (thread_p, savept_name, &topop_lsa) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
ptr = or_pack_log_lsa (ptr, &topop_lsa);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_partial_abort -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_partial_abort (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state;
char *savept_name;
LOG_LSA savept_lsa;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &savept_name);
state = xtran_server_partial_abort (thread_p, savept_name, &savept_lsa);
if (state != TRAN_UNACTIVE_ABORTED)
{
/* Likely the abort failed.. somehow */
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, (int) state);
ptr = or_pack_log_lsa (ptr, &savept_lsa);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_is_active_and_has_updated -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_is_active_and_has_updated (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int isactive_has_updated;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
isactive_has_updated = xtran_server_is_active_and_has_updated (thread_p);
(void) or_pack_int (reply, isactive_has_updated);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_wait_server_active_trans -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_wait_server_active_trans (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int status;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
status = xtran_wait_server_active_trans (thread_p);
(void) or_pack_int (reply, status);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_is_blocked -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_is_blocked (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int tran_index;
bool blocked;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &tran_index);
blocked = xtran_is_blocked (thread_p, tran_index);
(void) or_pack_int (reply, blocked ? 1 : 0);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_set_global_tran_info -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_set_global_tran_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
int gtrid;
void *info;
int size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, >rid);
if (css_receive_data_from_client (thread_p->conn_entry, rid, (char **) &info, (int *) &size))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
success = (xtran_server_set_global_tran_info (thread_p, gtrid, info, size) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (info != NULL)
{
thread_p->release_packet (info);
}
}
/*
* stran_server_get_global_tran_info -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_get_global_tran_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
int gtrid;
void *buffer;
int size;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply), *ptr;
ptr = or_unpack_int (request, >rid);
ptr = or_unpack_int (ptr, &size);
buffer = malloc (size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
success = (xtran_server_get_global_tran_info (thread_p, gtrid, buffer, size) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
size = 0;
}
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, success);
auto deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), (char *) buffer,
size, std::move (deleter));
}
/*
* stran_server_2pc_start -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_2pc_start (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int gtrid = NULL_TRANID;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
gtrid = xtran_server_2pc_start (thread_p);
if (gtrid < 0)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, gtrid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_2pc_prepare -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_2pc_prepare (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state = TRAN_UNACTIVE_UNKNOWN;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
state = xtran_server_2pc_prepare (thread_p);
if (state != TRAN_UNACTIVE_2PC_PREPARE && state != TRAN_UNACTIVE_COMMITTED)
{
/* the prepare failed. */
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, state);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_2pc_recovery_prepared -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_2pc_recovery_prepared (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int count, *gtrids, size, i;
int reply_size;
char *reply, *ptr;
(void) or_unpack_int (request, &size);
gtrids = (int *) malloc (sizeof (int) * size);
if (gtrids == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
count = xtran_server_2pc_recovery_prepared (thread_p, gtrids, size);
if (count < 0 || count > size)
{
(void) return_error_to_client (thread_p, rid);
}
reply_size = OR_INT_SIZE + (OR_INT_SIZE * size);
reply = (char *) malloc (reply_size);
if (reply == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
free_and_init (gtrids);
return;
}
(void) memset (reply, 0, reply_size);
ptr = or_pack_int (reply, count);
for (i = 0; i < count; i++)
{
ptr = or_pack_int (ptr, gtrids[i]);
}
css_send_data_to_client (thread_p->conn_entry, rid, reply, reply_size);
free_and_init (gtrids);
free_and_init (reply);
}
/*
* stran_server_2pc_attach_global_tran -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_2pc_attach_global_tran (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int gtrid;
int tran_index;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, >rid);
tran_index = xtran_server_2pc_attach_global_tran (thread_p, gtrid);
if (tran_index == NULL_TRAN_INDEX)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, tran_index);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_server_2pc_prepare_global_tran -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_server_2pc_prepare_global_tran (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
TRAN_STATE state;
int gtrid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, >rid);
state = xtran_server_2pc_prepare_global_tran (thread_p, gtrid);
if (state != TRAN_UNACTIVE_2PC_PREPARE && state != TRAN_UNACTIVE_COMMITTED)
{
/* Likely the prepare failed.. somehow */
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, state);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_lock_rep_read -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_lock_rep_read (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int lock_rr_tran;
int success;
ptr = request;
ptr = or_unpack_int (ptr, &lock_rr_tran);
success = xtran_lock_rep_read (thread_p, (LOCK) lock_rr_tran);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_initialize_server -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_initialize_server (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
}
/*
* sboot_register_client -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_register_client (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int xint;
BOOT_CLIENT_CREDENTIAL client_credential;
BOOT_SERVER_CREDENTIAL server_credential;
int tran_index, client_lock_wait;
TRAN_ISOLATION client_isolation;
TRAN_STATE tran_state;
int area_size, strlen1, strlen2, strlen3, strlen4;
char *reply, *area, *ptr;
packing_unpacker unpacker;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
reply = OR_ALIGNED_BUF_START (a_reply);
memset (&server_credential, 0, sizeof (server_credential));
unpacker.set_buffer (request, (size_t) reqlen);
unpacker.unpack_all (client_credential, client_lock_wait, xint);
client_isolation = (TRAN_ISOLATION) xint;
tran_index = xboot_register_client (thread_p, &client_credential, client_lock_wait, client_isolation, &tran_state,
&server_credential);
if (tran_index == NULL_TRAN_INDEX)
{
(void) return_error_to_client (thread_p, rid);
area = NULL;
area_size = 0;
}
else
{
area_size = (OR_INT_SIZE /* tran_index */
+ OR_INT_SIZE /* tran_state */
+ or_packed_string_length (server_credential.db_full_name, &strlen1) /* db_full_name */
+ or_packed_string_length (server_credential.host_name, &strlen2) /* host_name */
+ or_packed_string_length (server_credential.lob_path, &strlen3) /* lob_path */
+ OR_INT_SIZE /* process_id */
+ OR_OID_SIZE /* root_class_oid */
+ OR_HFID_SIZE /* root_class_hfid */
+ OR_INT_SIZE /* page_size */
+ OR_INT_SIZE /* log_page_size */
+ OR_FLOAT_SIZE /* disk_compatibility */
+ OR_INT_SIZE /* ha_server_state */
+ OR_INT_SIZE /* db_charset */
+ or_packed_string_length (server_credential.db_lang, &strlen4) /* db_lang */ );
area = (char *) malloc (area_size);
if (area == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_size = 0;
}
else
{
ptr = or_pack_int (area, tran_index);
ptr = or_pack_int (ptr, (int) tran_state);
ptr = or_pack_string_with_length (ptr, server_credential.db_full_name, strlen1);
ptr = or_pack_string_with_length (ptr, server_credential.host_name, strlen2);
ptr = or_pack_string_with_length (ptr, server_credential.lob_path, strlen3);
ptr = or_pack_int (ptr, server_credential.process_id);
ptr = or_pack_oid (ptr, &server_credential.root_class_oid);
ptr = or_pack_hfid (ptr, &server_credential.root_class_hfid);
ptr = or_pack_int (ptr, (int) server_credential.page_size);
ptr = or_pack_int (ptr, (int) server_credential.log_page_size);
ptr = or_pack_float (ptr, server_credential.disk_compatibility);
ptr = or_pack_int (ptr, (int) server_credential.ha_server_state);
ptr = or_pack_int (ptr, server_credential.db_charset);
ptr = or_pack_string_with_length (ptr, server_credential.db_lang, strlen4);
}
}
ptr = or_pack_int (reply, area_size);
auto deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area, area_size,
std::move (deleter));
}
/*
* sboot_notify_unregister_client -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_notify_unregister_client (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
CSS_CONN_ENTRY *conn;
int tran_index;
int success = NO_ERROR;
int r;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &tran_index);
if (thread_p == NULL)
{
thread_p = thread_get_thread_entry_info ();
if (thread_p == NULL)
{
return;
}
}
conn = thread_p->conn_entry;
assert (conn != NULL);
/* There's an interesting race condition among client, worker thread and connection handler.
* Please find CBRD-21375 for detail.
*
* It is important to synchronize worker thread with connection handler to avoid the race condition.
* To change conn->status and send reply to client should be atomic.
* Otherwise, connection handler may disconnect the connection and it prevents client from receiving the reply.
*/
r = rmutex_lock (thread_p, &conn->rmutex);
assert (r == NO_ERROR);
xboot_notify_unregister_client (thread_p, tran_index);
(void) or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
r = rmutex_unlock (thread_p, &conn->rmutex);
assert (r == NO_ERROR);
}
/*
* sboot_backup -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_backup (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
char *backup_path;
FILEIO_BACKUP_LEVEL backup_level;
int delete_unneeded_logarchives;
char *backup_verbose_file;
int num_threads;
FILEIO_ZIP_METHOD zip_method;
FILEIO_ZIP_LEVEL zip_level;
int skip_activelog;
int sleep_msecs;
int separate_keys;
ptr = or_unpack_string_nocopy (request, &backup_path);
ptr = or_unpack_int (ptr, (int *) &backup_level);
ptr = or_unpack_int (ptr, &delete_unneeded_logarchives);
ptr = or_unpack_string_nocopy (ptr, &backup_verbose_file);
ptr = or_unpack_int (ptr, &num_threads);
ptr = or_unpack_int (ptr, (int *) &zip_method);
ptr = or_unpack_int (ptr, (int *) &zip_level);
ptr = or_unpack_int (ptr, (int *) &skip_activelog);
ptr = or_unpack_int (ptr, (int *) &sleep_msecs);
ptr = or_unpack_int (ptr, (int *) &separate_keys);
success =
xboot_backup (thread_p, backup_path, backup_level, delete_unneeded_logarchives, backup_verbose_file, num_threads,
zip_method, zip_level, skip_activelog, sleep_msecs, separate_keys);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
/*
* To indicate results we really only need 2 ints, but the remote
* bo and callback routine was expecting to receive 3 ints.
*/
ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, success);
ptr = or_pack_int (ptr, 0xEEABCDFFL); /* padding, not used */
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_add_volume_extension -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_add_volume_extension (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
DBDEF_VOL_EXT_INFO ext_info;
int tmp;
VOLID volid;
char *unpack_char; /* to suppress warning */
ptr = or_unpack_string_nocopy (request, &unpack_char);
ext_info.path = unpack_char;
ptr = or_unpack_string_nocopy (ptr, &unpack_char);
ext_info.name = unpack_char;
ptr = or_unpack_string_nocopy (ptr, &unpack_char);
ext_info.comments = unpack_char;
ptr = or_unpack_int (ptr, &ext_info.max_npages);
ptr = or_unpack_int (ptr, &ext_info.max_writesize_in_sec);
ptr = or_unpack_int (ptr, &tmp);
ext_info.purpose = (DB_VOLPURPOSE) tmp;
ptr = or_unpack_int (ptr, &tmp);
ext_info.overwrite = (bool) tmp;
ptr = or_unpack_int (ptr, &tmp);
ext_info.voltype = (DB_VOLTYPE) tmp;
volid = xboot_add_volume_extension (thread_p, &ext_info);
if (volid == NULL_VOLID)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, (int) volid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_check_db_consistency -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_check_db_consistency (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int check_flag;
int num = 0, i;
OID *oids = NULL;
BTID index_btid;
if (request == NULL)
{
check_flag = CHECKDB_ALL_CHECK_EXCEPT_PREV_LINK;
}
else
{
ptr = or_unpack_int (request, &check_flag);
ptr = or_unpack_int (ptr, &num);
oids = (OID *) malloc (sizeof (OID) * num);
if (oids == NULL)
{
success = ER_FAILED;
goto function_exit;
}
for (i = 0; i < num; i++)
{
ptr = or_unpack_oid (ptr, &oids[i]);
}
ptr = or_unpack_btid (ptr, &index_btid);
}
success = xboot_check_db_consistency (thread_p, check_flag, oids, num, &index_btid);
success = success == NO_ERROR ? NO_ERROR : ER_FAILED;
free_and_init (oids);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
function_exit:
/*
* To indicate results we really only need 2 ints, but the remote
* bo and callback routine was expecting to receive 3 ints.
*/
ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, success);
ptr = or_pack_int (ptr, 0xEEABCDFFL); /* padding, not used */
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_find_number_permanent_volumes -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_find_number_permanent_volumes (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int nvols;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
nvols = xboot_find_number_permanent_volumes (thread_p);
(void) or_pack_int (reply, nvols);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_find_number_temp_volumes -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_find_number_temp_volumes (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int nvols;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
nvols = xboot_find_number_temp_volumes (thread_p);
(void) or_pack_int (reply, nvols);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_find_last_permanent -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_find_last_permanent (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
VOLID volid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
volid = xboot_find_last_permanent (thread_p);
(void) or_pack_int (reply, (int) volid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_find_last_temp -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_find_last_temp (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int nvols;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
nvols = xboot_find_last_temp (thread_p);
(void) or_pack_int (reply, nvols);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_change_ha_mode -
*/
void
sboot_change_ha_mode (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int req_state, force, timeout;
HA_SERVER_STATE state;
DB_INFO *db;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &req_state);
state = (HA_SERVER_STATE) req_state;
ptr = or_unpack_int (ptr, &force);
ptr = or_unpack_int (ptr, &timeout);
if (state > HA_SERVER_STATE_IDLE && state < HA_SERVER_STATE_DEAD)
{
if (css_change_ha_server_state (thread_p, state, force, timeout, false) != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ERR_CSS_ERROR_FROM_SERVER, 1, "Cannot change server HA mode");
(void) return_error_to_client (thread_p, rid);
}
else
{
/* it is good chance to call 'css_set_ha_num_of_hosts' */
db = cfg_find_db (boot_db_name ());
if (db != NULL)
{
css_set_ha_num_of_hosts (db->num_hosts);
cfg_free_directory (db);
}
}
}
state = css_ha_server_state ();
or_pack_int (reply, (int) state);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_notify_ha_log_applier_state -
*/
void
sboot_notify_ha_log_applier_state (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int i, status;
HA_LOG_APPLIER_STATE state;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &i);
state = (HA_LOG_APPLIER_STATE) i;
if (state >= HA_LOG_APPLIER_STATE_UNREGISTERED && state <= HA_LOG_APPLIER_STATE_ERROR)
{
status = css_notify_ha_log_applier_state (thread_p, state);
if (status != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ERR_CSS_ERROR_FROM_SERVER, 1, "Error in log applier state");
(void) return_error_to_client (thread_p, rid);
}
}
else
{
status = ER_FAILED;
}
or_pack_int (reply, status);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sqst_update_statistics -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqst_update_statistics (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error, with_fullscan;
OID classoid;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
CLASS_ATTR_NDV class_attr_ndv = CLASS_ATTR_NDV_INITIALIZER;
ptr = or_unpack_int (request, &class_attr_ndv.attr_cnt);
class_attr_ndv.attr_ndv = (ATTR_NDV *) db_private_alloc (thread_p, sizeof (ATTR_NDV) * (class_attr_ndv.attr_cnt + 1));
if (class_attr_ndv.attr_ndv == NULL)
{
(void) return_error_to_client (thread_p, rid);
}
for (int i = 0; i < class_attr_ndv.attr_cnt + 1; i++)
{
ptr = or_unpack_int (ptr, &class_attr_ndv.attr_ndv[i].id);
ptr = or_unpack_int64 (ptr, &class_attr_ndv.attr_ndv[i].ndv);
}
ptr = or_unpack_oid (ptr, &classoid);
ptr = or_unpack_int (ptr, &with_fullscan);
error =
xstats_update_statistics (thread_p, &classoid, (with_fullscan ? STATS_WITH_FULLSCAN : STATS_WITH_SAMPLING),
&class_attr_ndv);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (class_attr_ndv.attr_ndv != NULL)
{
db_private_free_and_init (thread_p, class_attr_ndv.attr_ndv);
}
}
/*
* sbtree_add_index -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_add_index (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTID btid;
BTID *return_btid = NULL;
TP_DOMAIN *key_type;
OID class_oid;
int attr_id, unique_pk;
char *ptr;
int deduplicate_key_pos = -1;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_BTID_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_btid (request, &btid);
ptr = or_unpack_domain (ptr, &key_type, 0);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &attr_id);
ptr = or_unpack_int (ptr, &unique_pk);
ptr = or_unpack_int (ptr, &deduplicate_key_pos); /* support for SUPPORT_DEDUPLICATE_KEY_MODE */
return_btid =
xbtree_add_index (thread_p, &btid, key_type, &class_oid, attr_id, unique_pk, 0, 0, 0, deduplicate_key_pos);
if (return_btid == NULL)
{
(void) return_error_to_client (thread_p, rid);
ptr = or_pack_int (reply, er_errid ());
}
else
{
ptr = or_pack_int (reply, NO_ERROR);
}
ptr = or_pack_btid (ptr, &btid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sbtree_load_index -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_load_index (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTID btid;
BTID *return_btid = NULL;
OID *class_oids = NULL;
HFID *hfids = NULL;
int unique_pk, not_null_flag;
OID fk_refcls_oid;
BTID fk_refcls_pk_btid;
char *bt_name, *fk_name;
int n_classes, n_attrs, *attr_ids = NULL;
int *attr_prefix_lengths = NULL;
TP_DOMAIN *key_type;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE * 2 + OR_BTID_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *pred_stream = NULL;
int pred_stream_size = 0, expr_stream_size = 0;
int pred_stream_received, expr_stream_received;
int func_col_id = -1, func_attr_index_start = -1;
int index_info_type;
char *expr_stream = NULL;
int csserror;
int index_status = 0;
int ib_thread_count = 0;
ptr = or_unpack_btid (request, &btid);
ptr = or_unpack_string_nocopy (ptr, &bt_name);
ptr = or_unpack_domain (ptr, &key_type, 0);
ptr = or_unpack_int (ptr, &n_classes);
ptr = or_unpack_int (ptr, &n_attrs);
ptr = or_unpack_oid_array (ptr, n_classes, &class_oids);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
goto end;
}
ptr = or_unpack_int_array (ptr, (n_classes * n_attrs), &attr_ids);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
goto end;
}
if (n_classes == 1)
{
ptr = or_unpack_int_array (ptr, n_attrs, &attr_prefix_lengths);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
goto end;
}
}
ptr = or_unpack_hfid_array (ptr, n_classes, &hfids);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
goto end;
}
ptr = or_unpack_int (ptr, &unique_pk);
ptr = or_unpack_int (ptr, ¬_null_flag);
ptr = or_unpack_oid (ptr, &fk_refcls_oid);
ptr = or_unpack_btid (ptr, &fk_refcls_pk_btid);
ptr = or_unpack_string_nocopy (ptr, &fk_name);
ptr = or_unpack_int (ptr, &index_info_type);
switch (index_info_type)
{
case 0:
ptr = or_unpack_int (ptr, &pred_stream_size);
if (pred_stream_size > 0)
{
csserror =
css_receive_data_from_client (thread_p->conn_entry, rid, (char **) &pred_stream, &pred_stream_received);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto end;
}
}
break;
case 1:
ptr = or_unpack_int (ptr, &expr_stream_size);
ptr = or_unpack_int (ptr, &func_col_id);
ptr = or_unpack_int (ptr, &func_attr_index_start);
if (expr_stream_size > 0)
{
csserror =
css_receive_data_from_client (thread_p->conn_entry, rid, (char **) &expr_stream, &expr_stream_received);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto end;
}
}
break;
default:
break;
}
ptr = or_unpack_int (ptr, &index_status); /* Get index status. */
ptr = or_unpack_int (ptr, &ib_thread_count); /* Get thread count. */
if (index_status == OR_ONLINE_INDEX_BUILDING_IN_PROGRESS)
{
return_btid =
xbtree_load_online_index (thread_p, &btid, bt_name, key_type, class_oids, n_classes, n_attrs, attr_ids,
attr_prefix_lengths, hfids, unique_pk, not_null_flag, &fk_refcls_oid,
&fk_refcls_pk_btid, fk_name, pred_stream, pred_stream_size, expr_stream,
expr_stream_size, func_col_id, func_attr_index_start, ib_thread_count);
}
else
{
return_btid =
xbtree_load_index (thread_p, &btid, bt_name, key_type, class_oids, n_classes, n_attrs, attr_ids,
attr_prefix_lengths, hfids, unique_pk, not_null_flag, &fk_refcls_oid, &fk_refcls_pk_btid,
fk_name, pred_stream, pred_stream_size, expr_stream, expr_stream_size, func_col_id,
func_attr_index_start);
}
if (return_btid == NULL)
{
(void) return_error_to_client (thread_p, rid);
}
end:
int err;
if (return_btid == NULL)
{
ASSERT_ERROR_AND_SET (err);
ptr = or_pack_int (reply, err);
}
else
{
err = NO_ERROR;
ptr = or_pack_int (reply, err);
}
if (index_status == OR_ONLINE_INDEX_BUILDING_IN_PROGRESS)
{
// it may not be really necessary. it just help things don't go worse that client keep caching ex-lock.
int tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
LOCK cls_lock = lock_get_object_lock (&class_oids[0], oid_Root_class_oid);
// in case of shutdown, index loader might be interrupted and got error
// otherwise, it should restore SCH_M_LOCK
assert ((err != NO_ERROR && css_is_shutdowning_server ()) || cls_lock == SCH_M_LOCK);
ptr = or_pack_int (ptr, (int) cls_lock);
}
else
{
ptr = or_pack_int (ptr, SCH_M_LOCK); // irrelevant
}
ptr = or_pack_btid (ptr, &btid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (class_oids != NULL)
{
db_private_free_and_init (thread_p, class_oids);
}
if (attr_ids != NULL)
{
db_private_free_and_init (thread_p, attr_ids);
}
if (attr_prefix_lengths != NULL)
{
db_private_free_and_init (thread_p, attr_prefix_lengths);
}
if (hfids != NULL)
{
db_private_free_and_init (thread_p, hfids);
}
if (expr_stream != NULL)
{
thread_p->release_packet (expr_stream);
}
if (pred_stream)
{
thread_p->release_packet (pred_stream);
}
}
/*
* sbtree_delete_index -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_delete_index (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTID btid;
int success;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_btid (request, &btid);
success = (xbtree_delete_index (thread_p, &btid) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, (int) success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_remove_class_from_index -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_remove_class_from_index (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid;
BTID btid;
HFID hfid;
int success;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_oid (request, &oid);
ptr = or_unpack_btid (ptr, &btid);
ptr = or_unpack_hfid (ptr, &hfid);
success = (xlocator_remove_class_from_index (thread_p, &oid, &btid, &hfid) == NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, (int) success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sbtree_find_unique -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_find_unique (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
sbtree_find_unique_internal (thread_p, rid, request, reqlen);
}
static void
sbtree_find_unique_internal (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTID btid;
OID class_oid;
OID oid;
DB_VALUE key;
char *ptr;
int success;
OR_ALIGNED_BUF (OR_OID_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = request;
ptr = or_unpack_value (ptr, &key);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_btid (ptr, &btid);
OID_SET_NULL (&oid);
success = xbtree_find_unique (thread_p, &btid, S_SELECT_WITH_LOCK, &key, &class_oid, &oid, false);
if (success == BTREE_ERROR_OCCURRED)
{
(void) return_error_to_client (thread_p, rid);
}
/* free storage if the key was a string */
pr_clear_value (&key);
ptr = or_pack_int (reply, success);
ptr = or_pack_oid (ptr, &oid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sbtree_find_multi_uniques -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_find_multi_uniques (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
OID class_oid;
OR_ALIGNED_BUF (2 * OR_INT_SIZE) a_reply;
char *ptr = NULL, *area = NULL;
BTID *btids = NULL;
DB_VALUE *keys = NULL;
OID *oids = NULL;
int count, needs_pruning, i, found = 0, area_size = 0;
SCAN_OPERATION_TYPE op_type;
int error = NO_ERROR;
BTREE_SEARCH result = BTREE_KEY_FOUND;
ptr = or_unpack_oid (request, &class_oid);
ptr = or_unpack_int (ptr, &needs_pruning);
ptr = or_unpack_int (ptr, &i);
op_type = (SCAN_OPERATION_TYPE) i;
ptr = or_unpack_int (ptr, &count);
if (count <= 0)
{
assert_release (count > 0);
error = ER_FAILED;
goto cleanup;
}
btids = (BTID *) db_private_alloc (thread_p, count * sizeof (BTID));
if (btids == NULL)
{
error = ER_FAILED;
goto cleanup;
}
for (i = 0; i < count; i++)
{
ptr = or_unpack_btid (ptr, &btids[i]);
}
keys = (DB_VALUE *) db_private_alloc (thread_p, count * sizeof (DB_VALUE));
if (keys == NULL)
{
error = ER_FAILED;
goto cleanup;
}
for (i = 0; i < count; i++)
{
ptr = or_unpack_db_value (ptr, &keys[i]);
}
result = xbtree_find_multi_uniques (thread_p, &class_oid, needs_pruning, btids, keys, count, op_type, &oids, &found);
if (result == BTREE_ERROR_OCCURRED)
{
error = ER_FAILED;
goto cleanup;
}
/* start packing result */
if (found > 0)
{
/* area size is (int:number of OIDs) + size of packed OIDs */
area_size = OR_INT_SIZE + (found * sizeof (OID));
area = (char *) malloc (area_size);
if (area == NULL)
{
error = ER_FAILED;
goto cleanup;
}
ptr = or_pack_int (area, found);
for (i = 0; i < found; i++)
{
ptr = or_pack_oid (ptr, &oids[i]);
}
}
else
{
area_size = 0;
area = NULL;
}
/* pack area size */
ptr = or_pack_int (OR_ALIGNED_BUF_START (a_reply), area_size);
/* pack error (should be NO_ERROR here) */
ptr = or_pack_int (ptr, error);
deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply),
OR_ALIGNED_BUF_SIZE (a_reply), area, area_size, std::move (deleter));
cleanup:
if (btids != NULL)
{
db_private_free (thread_p, btids);
}
if (keys != NULL)
{
for (i = 0; i < count; i++)
{
pr_clear_value (&keys[i]);
}
db_private_free (thread_p, keys);
}
if (oids != NULL)
{
db_private_free (thread_p, oids);
}
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
ptr = or_pack_int (OR_ALIGNED_BUF_START (a_reply), 0);
ptr = or_pack_int (ptr, error);
ptr = or_pack_int (ptr, 0);
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply),
OR_ALIGNED_BUF_SIZE (a_reply), NULL, 0, []() noexcept {});
}
}
/*
* sbtree_class_test_unique -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_class_test_unique (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
success = xbtree_class_test_unique (thread_p, request, reqlen);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, (int) success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sdk_totalpgs -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sdk_totalpgs (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
DKNPAGES npages;
VOLID volid;
int int_volid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &int_volid);
volid = (VOLID) int_volid;
npages = xdisk_get_total_numpages (thread_p, volid);
if (npages < 0)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, npages);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sdk_freepgs -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sdk_freepgs (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
DKNPAGES npages;
VOLID volid;
int int_volid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &int_volid);
volid = (VOLID) int_volid;
npages = xdisk_get_free_numpages (thread_p, volid);
if (npages < 0)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, npages);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sdk_remarks -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sdk_remarks (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int int_volid;
char *remark;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int area_length, strlen;
char *area;
(void) or_unpack_int (request, &int_volid);
remark = xdisk_get_remarks (thread_p, (VOLID) int_volid);
if (remark == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_length = 0;
area = NULL;
}
else
{
area_length = or_packed_string_length (remark, &strlen);
area = (char *) malloc (area_length);
if (area == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_length = 0;
}
else
{
(void) or_pack_string_with_length (area, remark, strlen);
}
}
(void) or_pack_int (reply, area_length);
auto deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
area_length, std::move (deleter));
if (remark != NULL)
{
/* since this was copied to the client, we don't need it on the server */
free_and_init (remark);
}
}
/*
* sdk_vlabel -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sdk_vlabel (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (PATH_MAX) a_vol_fullname;
char *vol_fullname = OR_ALIGNED_BUF_START (a_vol_fullname);
int int_volid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int area_length, strlen;
char *area;
(void) or_unpack_int (request, &int_volid);
if (xdisk_get_fullname (thread_p, (VOLID) int_volid, vol_fullname) == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_length = 0;
area = NULL;
}
else
{
area_length = or_packed_string_length (vol_fullname, &strlen);
area = (char *) malloc (area_length);
if (area == NULL)
{
(void) return_error_to_client (thread_p, rid);
area_length = 0;
}
else
{
(void) or_pack_string_with_length (area, vol_fullname, strlen);
}
}
(void) or_pack_int (reply, area_length);
auto deleter = [area]() noexcept
{
if (area != NULL)
{
free (area);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
area_length, std::move (deleter));
}
/*
* sqfile_get_list_file_page -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqfile_get_list_file_page (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
QUERY_ID query_id;
int volid, pageid;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *aligned_page_buf;
int page_size;
int error = NO_ERROR;
aligned_page_buf = (char *) malloc (IO_MAX_PAGE_SIZE);
// cppcheck-suppress uninitdata
deleter = [aligned_page_buf]() noexcept
{
if (aligned_page_buf != NULL)
{
free (aligned_page_buf);
}
};
ptr = or_unpack_ptr (request, &query_id);
ptr = or_unpack_int (ptr, &volid);
ptr = or_unpack_int (ptr, &pageid);
if (volid == NULL_VOLID && pageid == NULL_PAGEID)
{
goto empty_page;
}
error = xqfile_get_list_file_page (thread_p, query_id, volid, pageid, aligned_page_buf, &page_size);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
goto empty_page;
}
if (page_size == 0)
{
goto empty_page;
}
ptr = or_pack_int (reply, page_size);
ptr = or_pack_int (ptr, error);
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), aligned_page_buf,
page_size, std::move (deleter));
return;
empty_page:
/* setup empty list file page and return it */
qmgr_setup_empty_list_file (aligned_page_buf);
page_size = QFILE_PAGE_HEADER_SIZE;
ptr = or_pack_int (reply, page_size);
ptr = or_pack_int (ptr, error);
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), aligned_page_buf,
page_size, std::move (deleter));
}
/*
* sqmgr_prepare_query - Process a SERVER_QM_PREPARE request
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
* Receive XASL stream and return XASL file id (QFILE_LIST_ID) as a result.
* If xasl_buffer == NULL, the server will look up the XASL cache and then
* return the cached XASL file id if found, otherwise return NULL QFILE_LIST_ID.
* This function is a counter part to qmgr_prepare_query().
*/
void
sqmgr_prepare_query (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
XASL_ID xasl_id;
char *ptr = NULL;
char *reply = NULL, *reply_buffer = NULL;
int csserror, reply_buffer_size = 0, get_xasl_header = 0;
int xasl_cache_pinned = 0, recompile_xasl_cache_pinned = 0;
int recompile_xasl = 0;
XASL_NODE_HEADER xasl_header;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE + OR_XASL_ID_SIZE) a_reply;
int error = NO_ERROR;
COMPILE_CONTEXT context = { NULL, NULL, 0, NULL, NULL, 0, false, false, false, SHA1_HASH_INITIALIZER };
XASL_STREAM stream = { NULL, NULL, NULL, 0 };
bool was_recompile_xasl = false;
bool force_recompile = false;
char *buffer = NULL;
reply = OR_ALIGNED_BUF_START (a_reply);
/* unpack query alias string from the request data */
ptr = or_unpack_string_nocopy (request, &context.sql_hash_text);
/* unpack query plan from the request data */
ptr = or_unpack_string_nocopy (ptr, &context.sql_plan_text);
/* unpack query string from the request data */
ptr = or_unpack_string_nocopy (ptr, &context.sql_user_text);
/* unpack size of XASL stream */
ptr = or_unpack_int (ptr, &stream.buffer_size);
/* unpack get XASL node header boolean */
ptr = or_unpack_int (ptr, &get_xasl_header);
/* unpack pinned xasl cache flag boolean */
ptr = or_unpack_int (ptr, &xasl_cache_pinned);
context.is_xasl_pinned_reference = (bool) xasl_cache_pinned;
/* unpack recompile flag boolean */
ptr = or_unpack_int (ptr, &recompile_xasl_cache_pinned);
context.recompile_xasl_pinned = (bool) recompile_xasl_cache_pinned;
/* unpack recompile_xasl flag boolean */
ptr = or_unpack_int (ptr, &recompile_xasl);
context.recompile_xasl = (bool) recompile_xasl;
/* unpack sha1 */
ptr = or_unpack_sha1 (ptr, &context.sha1);
if (get_xasl_header)
{
/* need to get XASL node header */
stream.xasl_header = &xasl_header;
INIT_XASL_NODE_HEADER (stream.xasl_header);
}
if (stream.buffer_size > 0)
{
/* receive XASL stream from the client */
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &buffer, &stream.buffer_size);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
if (buffer)
{
thread_p->release_packet (buffer);
}
return;
}
stream.buffer = (char *) malloc (stream.buffer_size);
memcpy (stream.buffer, buffer, stream.buffer_size);
thread_p->release_packet (buffer);
}
/* call the server routine of query prepare */
stream.xasl_id = &xasl_id;
XASL_ID_SET_NULL (stream.xasl_id);
/* Force recompile must be set to true if client did not intend to recompile, but must reconsider. This can happen
* if recompile threshold is checked and if one of the related classes suffered significant changes to justify the
* recompiling.
* If client already means to recompile, force_recompile is not required.
* xqmgr_prepare_query will change context.recompile_xasl if force recompile is required.
*/
was_recompile_xasl = context.recompile_xasl;
error = xqmgr_prepare_query (thread_p, &context, &stream);
if (stream.buffer)
{
free_and_init (stream.buffer);
}
if (error != NO_ERROR)
{
ASSERT_ERROR ();
(void) return_error_to_client (thread_p, rid);
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
}
else
{
/* Check if we need to force client to recompile. */
force_recompile = !was_recompile_xasl && context.recompile_xasl;
if (stream.xasl_id != NULL && !XASL_ID_IS_NULL (stream.xasl_id) && (get_xasl_header || force_recompile))
{
/* pack XASL node header */
reply_buffer_size = get_xasl_header ? XASL_NODE_HEADER_SIZE : 0;
reply_buffer_size += force_recompile ? OR_INT_SIZE : 0;
assert (reply_buffer_size > 0);
reply_buffer = (char *) malloc (reply_buffer_size);
if (reply_buffer == NULL)
{
reply_buffer_size = 0;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) reply_buffer_size);
error = ER_OUT_OF_VIRTUAL_MEMORY;
}
else
{
ptr = reply_buffer;
if (get_xasl_header)
{
OR_PACK_XASL_NODE_HEADER (ptr, stream.xasl_header);
}
if (force_recompile)
{
/* Doesn't really matter what we pack... */
ptr = or_pack_int (ptr, 1);
}
}
}
ptr = or_pack_int (reply, reply_buffer_size);
ptr = or_pack_int (ptr, NO_ERROR);
/* pack XASL file id as a reply */
OR_PACK_XASL_ID (ptr, stream.xasl_id);
}
auto deleter = [reply_buffer]() noexcept
{
if (reply_buffer != NULL)
{
free (reply_buffer);
}
};
/* send reply and data to the client */
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), reply_buffer,
reply_buffer_size, std::move (deleter));
}
/*
* stran_can_end_after_query_execution - Check whether can end transaction after query execution.
*
* return:error code
*
* thread_p(in): thread entry
* query_flag(in): query flag
* list_id(in): list id
* can_end_transaction(out): true, if transaction can be safely ended
*
*/
STATIC_INLINE int
stran_can_end_after_query_execution (THREAD_ENTRY *thread_p, int query_flag, QFILE_LIST_ID *list_id,
bool *can_end_transaction)
{
QFILE_LIST_SCAN_ID scan_id;
QFILE_TUPLE_RECORD tuple_record = { NULL, 0 };
SCAN_CODE qp_scan;
OR_BUF buf;
TP_DOMAIN **domains;
const PR_TYPE *pr_type;
int i, flag, compressed_size = 0, decompressed_size = 0, diff_size, val_length;
char *tuple_p;
bool found_compressible_string_domain, exceed_a_page;
assert (list_id != NULL && list_id->type_list.domp != NULL && can_end_transaction != NULL);
*can_end_transaction = false;
if (list_id->page_cnt != 1)
{
/* Needs fetch request. Do not allow ending transaction. */
return NO_ERROR;
}
if (list_id->last_offset >= QEWC_MAX_DATA_SIZE)
{
/* Needs fetch request. Do not allow ending transaction. */
return NO_ERROR;
}
if (query_flag & RESULT_HOLDABLE)
{
/* Holdable result, do not check for compression. */
*can_end_transaction = true;
return NO_ERROR;
}
domains = list_id->type_list.domp;
found_compressible_string_domain = false;
for (i = 0; i < list_id->type_list.type_cnt; i++)
{
pr_type = domains[i]->type;
assert (pr_type != NULL);
if (pr_type->id == DB_TYPE_VARCHAR)
{
found_compressible_string_domain = true;
break;
}
}
if (!found_compressible_string_domain)
{
/* Not compressible domains, do not check for compression. */
*can_end_transaction = true;
return NO_ERROR;
}
if (qfile_open_list_scan (list_id, &scan_id) != NO_ERROR)
{
return ER_FAILED;
}
/* Estimates the data and header information. */
diff_size = 0;
exceed_a_page = false;
while (!exceed_a_page)
{
qp_scan = qfile_scan_list_next (thread_p, &scan_id, &tuple_record, PEEK);
if (qp_scan != S_SUCCESS)
{
break;
}
tuple_p = tuple_record.tpl;
or_init (&buf, tuple_p, QFILE_GET_TUPLE_LENGTH (tuple_p));
tuple_p += QFILE_TUPLE_LENGTH_SIZE;
for (i = 0; i < list_id->type_list.type_cnt; i++)
{
flag = QFILE_GET_TUPLE_VALUE_FLAG (tuple_p);
val_length = QFILE_GET_TUPLE_VALUE_LENGTH (tuple_p);
tuple_p += QFILE_TUPLE_VALUE_HEADER_SIZE;
pr_type = domains[i]->type;
if (flag != V_UNBOUND && (pr_type->id == DB_TYPE_VARCHAR))
{
buf.ptr = tuple_p;
or_get_varchar_compression_lengths (&buf, &compressed_size, &decompressed_size);
if (compressed_size != 0)
{
/* Compression used. */
diff_size += decompressed_size - compressed_size;
if (list_id->last_offset + diff_size >= QEWC_MAX_DATA_SIZE)
{
/* Needs fetch request. Do not allow ending transaction. */
exceed_a_page = true;
break;
}
}
}
tuple_p += val_length;
}
}
qfile_close_scan (thread_p, &scan_id);
if (qp_scan == S_ERROR)
{
// might be interrupted
return ER_FAILED;
}
*can_end_transaction = !exceed_a_page;
return NO_ERROR;
}
/*
* sqmgr_execute_query - Process a SERVER_QM_EXECUTE request
*
* return:error or no error
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
* Receive XASL file id and parameter values if exist and return list file id
* that contains query result. If an error occurs, return NULL QFILE_LIST_ID.
* This function is a counter part to qmgr_execute_query().
*/
void
sqmgr_execute_query (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
XASL_ID xasl_id;
QFILE_LIST_ID *list_id;
int csserror, dbval_cnt, data_size, replydata_size, page_size;
QUERY_ID query_id = NULL_QUERY_ID;
char *ptr, *data = NULL, *reply, *replydata = NULL;
PAGE_PTR page_ptr;
char *aligned_page_buf;
QUERY_FLAG query_flag;
OR_ALIGNED_BUF (OR_INT_SIZE * 7 + OR_PTR_ALIGNED_SIZE + OR_CACHE_TIME_SIZE) a_reply;
CACHE_TIME clt_cache_time;
CACHE_TIME srv_cache_time;
int query_timeout;
XASL_CACHE_ENTRY *xasl_cache_entry_p = NULL;
char data_buf[EXECUTE_QUERY_MAX_ARGUMENT_DATA_SIZE + MAX_ALIGNMENT], *aligned_data_buf = NULL;
bool has_updated;
int response_time = 0;
TSC_TICKS start_tick, end_tick;
TSCTIMEVAL tv_diff;
int queryinfo_string_length = 0;
char *queryinfo_string = NULL;
UINT64 *base_stats = NULL;
UINT64 *current_stats = NULL;
UINT64 *diff_stats = NULL;
char *sql_id = NULL;
int error_code = NO_ERROR, all_error_code = NO_ERROR;
int trace_level, trace_slow_msec, trace_ioreads;
bool tran_abort = false, has_xasl_entry = false;
EXECUTION_INFO info = { NULL, NULL, NULL };
QUERY_ID net_Deferred_end_queries[NET_DEFER_END_QUERIES_MAX], *p_net_Deferred_end_queries = net_Deferred_end_queries;
int n_query_ids = 0, i = 0;
bool end_query_allowed, should_conn_reset;
LOG_TDES *tdes;
TRAN_STATE tran_state;
bool is_tran_auto_commit;
trace_level = prm_get_integer_value (PRM_ID_SQL_TRACE_EXECUTION_PLAN);
trace_slow_msec = prm_get_integer_value (PRM_ID_SQL_TRACE_SLOW_MSECS);
trace_ioreads = prm_get_integer_value (PRM_ID_SQL_TRACE_IOREADS);
if (trace_slow_msec >= 0 || trace_ioreads > 0)
{
perfmon_start_watch (thread_p);
base_stats = perfmon_allocate_values ();
if (base_stats == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
if (trace_level != TRACE_LOG_LEVEL_OFF)
{
xperfmon_server_copy_stats (thread_p, base_stats, false);
}
else
{
xperfmon_server_copy_stats_for_trace (thread_p, base_stats);
}
tsc_getticks (&start_tick);
if (trace_slow_msec >= 0)
{
thread_p->event_stats.trace_slow_query = true;
}
}
reply = OR_ALIGNED_BUF_START (a_reply);
/* unpack XASL file id (XASL_ID), number of parameter values, size of the recieved data, and query execution mode
* flag from the request data */
ptr = request;
OR_UNPACK_XASL_ID (ptr, &xasl_id);
ptr = or_unpack_int (ptr, &dbval_cnt);
ptr = or_unpack_int (ptr, &data_size);
ptr = or_unpack_int (ptr, &query_flag);
OR_UNPACK_CACHE_TIME (ptr, &clt_cache_time);
ptr = or_unpack_int (ptr, &query_timeout);
is_tran_auto_commit = IS_TRAN_AUTO_COMMIT (query_flag);
xsession_set_tran_auto_commit (thread_p, is_tran_auto_commit);
if (IS_QUERY_EXECUTE_WITH_COMMIT (query_flag))
{
ptr = or_unpack_int (ptr, &n_query_ids);
if (n_query_ids + 1 > NET_DEFER_END_QUERIES_MAX)
{
p_net_Deferred_end_queries = (QUERY_ID *) malloc ((n_query_ids + 1) * sizeof (QUERY_ID));
if (p_net_Deferred_end_queries == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1,
(size_t) (n_query_ids + 1) * sizeof (QUERY_ID));
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
}
for (i = 0; i < n_query_ids; i++)
{
ptr = or_unpack_ptr (ptr, p_net_Deferred_end_queries + i);
}
}
if (IS_QUERY_EXECUTED_WITHOUT_DATA_BUFFERS (query_flag))
{
assert (data_size < EXECUTE_QUERY_MAX_ARGUMENT_DATA_SIZE);
aligned_data_buf = PTR_ALIGN (data_buf, MAX_ALIGNMENT);
data = aligned_data_buf;
memcpy (data, ptr, data_size);
}
else if (0 < dbval_cnt)
{
/* receive parameter values (DB_VALUE) from the client */
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &data, &data_size);
if (csserror || data == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
if (data)
{
thread_p->release_packet (data);
}
return; /* error */
}
}
CACHE_TIME_RESET (&srv_cache_time);
/* call the server routine of query execute */
list_id = xqmgr_execute_query (thread_p, &xasl_id, &query_id, dbval_cnt, data, &query_flag, &clt_cache_time,
&srv_cache_time, query_timeout, &xasl_cache_entry_p);
if (data != NULL && data != aligned_data_buf)
{
thread_p->release_packet (data);
}
if (xasl_cache_entry_p != NULL)
{
info = xasl_cache_entry_p->sql_info;
}
end_query_allowed = IS_QUERY_EXECUTE_WITH_COMMIT (query_flag);
tdes = LOG_FIND_CURRENT_TDES (thread_p);
tran_state = tdes->state;
has_updated = false;
null_list:
if (list_id == NULL && !CACHE_TIME_EQ (&clt_cache_time, &srv_cache_time))
{
ASSERT_ERROR_AND_SET (error_code);
if (error_code != NO_ERROR)
{
if (info.sql_hash_text != NULL)
{
if (qmgr_get_sql_id (thread_p, &sql_id, info.sql_hash_text, strlen (info.sql_hash_text)) != NO_ERROR)
{
sql_id = NULL;
}
}
if (error_code != ER_QPROC_XASLNODE_RECOMPILE_REQUESTED)
{
er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_QUERY_EXECUTION_ERROR, 3, error_code,
sql_id ? sql_id : "(UNKNOWN SQL_ID)",
info.sql_user_text ? info.sql_user_text : "(UNKNOWN USER_TEXT)");
}
if (sql_id != NULL)
{
free_and_init (sql_id);
}
}
tran_abort = need_to_abort_tran (thread_p, &error_code);
if (tran_abort)
{
if (xasl_cache_entry_p != NULL)
{
/* Remove transaction id from xasl cache entry before return_error_to_client, where current transaction
* may be aborted. Otherwise, another transaction may be resumed and xasl_cache_entry_p may be removed by
* that transaction, during class deletion. */
has_xasl_entry = true;
xcache_unfix (thread_p, xasl_cache_entry_p);
xasl_cache_entry_p = NULL;
}
}
if (IS_QUERY_EXECUTE_WITH_COMMIT (query_flag))
{
/* Get has update before aborting transaction. */
has_updated = logtb_has_updated (thread_p);
}
tran_state = return_error_to_client (thread_p, rid);
}
page_size = 0;
page_ptr = NULL;
if (list_id != NULL)
{
/* get the first page of the list file */
if (VPID_ISNULL (& (list_id->first_vpid)))
{
// Note that not all list files have a page, for instance, insert.
page_ptr = NULL;
}
else
{
page_ptr = qmgr_get_old_page (thread_p, & (list_id->first_vpid), list_id->tfile_vfid);
if (page_ptr != NULL)
{
/* calculate page size */
if (QFILE_GET_TUPLE_COUNT (page_ptr) == -2 || QFILE_GET_OVERFLOW_PAGE_ID (page_ptr) != NULL_PAGEID)
{
page_size = DB_PAGESIZE;
}
else
{
int offset = QFILE_GET_LAST_TUPLE_OFFSET (page_ptr);
page_size = (offset + QFILE_GET_TUPLE_LENGTH (page_ptr + offset));
}
aligned_page_buf = (char *) malloc (page_size);
memcpy (aligned_page_buf, page_ptr, page_size);
qmgr_free_old_page_and_init (thread_p, page_ptr, list_id->tfile_vfid);
page_ptr = aligned_page_buf;
/* for now, allow end query if there is only one page and more ... */
if (stran_can_end_after_query_execution (thread_p, query_flag, list_id, &end_query_allowed) != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
// When !end_query_allowed, it means this execution request is followed by fetch request(s).
}
else
{
// might be interrupted to fetch query result
ASSERT_ERROR ();
QFILE_FREE_AND_INIT_LIST_ID (list_id);
goto null_list;
}
}
}
replydata_size = list_id ? or_listid_length (list_id) : 0;
if (0 < replydata_size)
{
/* pack list file id as a reply data */
replydata = (char *) malloc (replydata_size);
if (replydata != NULL)
{
(void) or_pack_listid (replydata, list_id);
}
else
{
replydata_size = 0;
(void) return_error_to_client (thread_p, rid);
}
}
/* We may release the xasl cache entry when the transaction aborted. To refer the contents of the freed entry for
* the case will cause defects. */
if (tran_abort == false)
{
if (trace_slow_msec >= 0 || trace_ioreads > 0)
{
tsc_getticks (&end_tick);
tsc_elapsed_time_usec (&tv_diff, end_tick, start_tick);
response_time = (tv_diff.tv_sec * 1000) + (tv_diff.tv_usec / 1000);
if (base_stats == NULL)
{
base_stats = perfmon_allocate_values ();
if (base_stats == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
}
current_stats = perfmon_allocate_values ();
if (current_stats == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
goto exit;
}
diff_stats = perfmon_allocate_values ();
if (diff_stats == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
goto exit;
}
if (trace_level != TRACE_LOG_LEVEL_OFF)
{
bool need_pgbuf_stat = (trace_level == TRACE_LOG_LEVEL_DETAIL && response_time >= trace_slow_msec);
xperfmon_server_copy_stats (thread_p, current_stats, need_pgbuf_stat);
perfmon_calc_diff_stats (diff_stats, current_stats, base_stats, need_pgbuf_stat);
}
else
{
xperfmon_server_copy_stats_for_trace (thread_p, current_stats);
perfmon_calc_diff_stats_for_trace (diff_stats, current_stats, base_stats);
}
if (response_time >= trace_slow_msec)
{
queryinfo_string = (char *) malloc (QUERY_INFO_BUF_SIZE);
queryinfo_string_length =
trace_log_slow_query (thread_p, &info, response_time, diff_stats, queryinfo_string, trace_level);
}
if (trace_ioreads > 0
&& diff_stats[pstat_Metadata[PSTAT_PB_NUM_IOREADS].start_offset] >= (UINT64) trace_ioreads)
{
event_log_many_ioreads (thread_p, &info, response_time, diff_stats);
}
perfmon_stop_watch (thread_p);
}
if (thread_p->event_stats.extend_pages > 0)
{
event_log_extend_pages (thread_p, &info);
}
}
if (xasl_cache_entry_p != NULL)
{
has_xasl_entry = true;
xcache_unfix (thread_p, xasl_cache_entry_p);
xasl_cache_entry_p = NULL;
}
/* pack 'QUERY_END' as a first argument of the reply */
ptr = or_pack_int (reply, QUERY_END);
/* pack size of list file id to return as a second argument of the reply */
ptr = or_pack_int (ptr, replydata_size);
/* pack size of a page to return as a third argumnet of the reply */
ptr = or_pack_int (ptr, page_size);
ptr = or_pack_int (ptr, queryinfo_string_length);
/* query id to return as a fourth argument of the reply */
ptr = or_pack_ptr (ptr, query_id);
/* result cache created time */
OR_PACK_CACHE_TIME (ptr, &srv_cache_time);
if (IS_QUERY_EXECUTE_WITH_COMMIT (query_flag))
{
/* Try to end transaction and pack the result. */
p_net_Deferred_end_queries[n_query_ids++] = query_id;
if (error_code != NO_ERROR)
{
if (error_code != ER_INTERRUPTED && has_xasl_entry)
{
tran_abort = true;
assert (end_query_allowed == true);
}
else
{
/* Do not abort the transaction, since XASL cache does not exists, so other fetch may be requested.
* Or, the execution was interrupted.
*/
end_query_allowed = false;
}
}
stran_server_auto_commit_or_abort (thread_p, rid, p_net_Deferred_end_queries, n_query_ids,
tran_abort, has_updated, &end_query_allowed, &tran_state, &should_conn_reset);
/* pack end query result */
if (end_query_allowed == true)
{
/* query ended */
ptr = or_pack_int (ptr, NO_ERROR);
}
else
{
/* query not ended */
ptr = or_pack_int (ptr, !NO_ERROR);
}
/* pack commit/abart/active result */
ptr = or_pack_int (ptr, (int) tran_state);
ptr = or_pack_int (ptr, (int) should_conn_reset);
}
#if !defined(NDEBUG)
/* suppress valgrind UMW error */
memset (ptr, 0, OR_ALIGNED_BUF_SIZE (a_reply) - (ptr - reply));
#endif
deleter = [replydata, page_ptr, queryinfo_string]() noexcept
{
if (replydata)
{
free (replydata);
}
if (page_ptr)
{
free (page_ptr);
}
if (queryinfo_string)
{
free (queryinfo_string);
}
};
css_send_reply_and_3_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), replydata,
replydata_size, page_ptr, page_size, queryinfo_string, queryinfo_string_length, std::move (deleter));
/* free QFILE_LIST_ID duplicated by xqmgr_execute_query() */
if (list_id != NULL)
{
QFILE_FREE_AND_INIT_LIST_ID (list_id);
}
exit:
if (p_net_Deferred_end_queries != net_Deferred_end_queries)
{
free_and_init (p_net_Deferred_end_queries);
}
if (base_stats != NULL)
{
free_and_init (base_stats);
}
if (current_stats != NULL)
{
free_and_init (current_stats);
}
if (diff_stats != NULL)
{
free_and_init (diff_stats);
}
}
/*
* trace_log_slow_query - log slow query to trace log file
* return:
* thread_p(in):
* info(in):
* time(in):
* diff_stats(in):
*/
static int
trace_log_slow_query (THREAD_ENTRY *thread_p, EXECUTION_INFO *info, int time, UINT64 *diff_stats,
char *queryinfo_string, int trace_level)
{
FILE *log_fp;
char stat_buf[STATDUMP_BUF_SIZE];
char *sql_id;
int indent = 2;
int tran_index;
int queryinfo_string_length = 0;
const char *line = "--------------------------------------------------------------------------------";
const char *title = "SLOW_QUERY";
LOG_TDES *tdes;
tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
tdes = LOG_FIND_TDES (tran_index);
if (tdes == NULL)
{
return 0;
}
if (trace_level != TRACE_LOG_LEVEL_OFF)
{
perfmon_trace_dump_stats_to_buffer (diff_stats, stat_buf, STATDUMP_BUF_SIZE, trace_level);
}
else
{
info->sql_plan_text = NULL;
stat_buf[0] = '\0';
}
if (info->sql_hash_text == NULL
|| qmgr_get_sql_id (thread_p, &sql_id, info->sql_hash_text, strlen (info->sql_hash_text)) != NO_ERROR)
{
sql_id = NULL;
}
log_fp = trace_log_start (thread_p, title);
if (log_fp == NULL)
{
return 0;
}
trace_log_print_client_info (tran_index, indent);
queryinfo_string_length =
snprintf (queryinfo_string, QUERY_INFO_BUF_SIZE, "%s\n%s\n%s\n %s\n\n SQL_ID: %s\n sql: %s\n", line, title, line,
info->sql_user_text ? info->sql_user_text : "(UNKNOWN USER_TEXT)", sql_id ? sql_id : "(UNKNOWN SQL_ID)",
info->sql_hash_text ? info->sql_hash_text : "(UNKNOWN HASH_TEXT)");
fprintf (log_fp, "%*c%s\n", indent, ' ', info->sql_plan_text ? info->sql_plan_text : "");
if (tdes->num_exec_queries <= MAX_NUM_EXEC_QUERY_HISTORY)
{
trace_log_bind_values (thread_p, log_fp, tran_index, tdes->num_exec_queries - 1);
}
fprintf (log_fp, "%*ctime: %dmsec\n", indent, ' ', time);
fprintf (log_fp, "\n\n%s%s%s\n", queryinfo_string, stat_buf, line);
trace_log_end (thread_p);
if (sql_id != NULL)
{
free (sql_id);
}
if (queryinfo_string_length >= QUERY_INFO_BUF_SIZE)
{
/* string is truncated */
queryinfo_string_length = QUERY_INFO_BUF_SIZE - 1;
queryinfo_string[queryinfo_string_length] = '\0';
}
return queryinfo_string_length;
}
/*
* event_log_many_ioreads - log many ioreads to event log file
* return:
* thread_p(in):
* info(in):
* time(in):
* diff_stats(in):
* num_bind_vals(in):
* bind_vals(in):
*/
static void
event_log_many_ioreads (THREAD_ENTRY *thread_p, EXECUTION_INFO *info, int time, UINT64 *diff_stats)
{
FILE *log_fp;
int indent = 2;
LOG_TDES *tdes;
int tran_index;
tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
tdes = LOG_FIND_TDES (tran_index);
log_fp = event_log_start (thread_p, "MANY_IOREADS");
if (tdes == NULL || log_fp == NULL)
{
return;
}
event_log_print_client_info (tran_index, indent);
event_log_sql_without_user_oid (log_fp, "%*csql: %s\n", indent,
info->sql_hash_text ? info->sql_hash_text : "(UNKNOWN HASH_TEXT)");
if (tdes->num_exec_queries <= MAX_NUM_EXEC_QUERY_HISTORY)
{
event_log_bind_values (thread_p, log_fp, tran_index, tdes->num_exec_queries - 1);
}
fprintf (log_fp, "%*ctime: %d\n", indent, ' ', time);
fprintf (log_fp, "%*cioreads: %lld\n\n", indent, ' ',
(long long int) diff_stats[pstat_Metadata[PSTAT_PB_NUM_IOREADS].start_offset]);
event_log_end (thread_p);
}
/*
* event_log_extend_pages - log volume extend pages to event log file
* return:
* thread_p(in):
* info(in):
* num_bind_vals(in):
* bind_vals(in):
*/
static void
event_log_extend_pages (THREAD_ENTRY *thread_p, EXECUTION_INFO *info)
{
FILE *log_fp;
int indent = 2;
LOG_TDES *tdes;
int tran_index;
tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
tdes = LOG_FIND_TDES (tran_index);
log_fp = event_log_start (thread_p, "EXTEND_VOLUME_INFO");
if (tdes == NULL || log_fp == NULL)
{
return;
}
event_log_print_client_info (tran_index, indent);
event_log_sql_without_user_oid (log_fp, "%*csql: %s\n", indent,
info->sql_hash_text ? info->sql_hash_text : "(UNKNOWN HASH_TEXT)");
fprintf (log_fp, "%*ctime: %dms\n", indent, ' ', TO_MSEC (thread_p->event_stats.extend_time));
fprintf (log_fp, "%*cpages: %d\n\n", indent, ' ', thread_p->event_stats.extend_pages);
/* printing bind values for placeholders (?) is skipped due to performance issues when logging long column values (e.g. LOB) in event_log_bind_values(). */
event_log_end (thread_p);
}
/*
* sqmgr_prepare_and_execute_query -
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqmgr_prepare_and_execute_query (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
int var_count, var_datasize, var_actual_datasize;
QUERY_ID query_id;
QFILE_LIST_ID *q_result;
int csserror, listid_length;
char *xasl_stream;
int xasl_stream_size;
char *ptr, *var_data, *list_data;
OR_ALIGNED_BUF (OR_INT_SIZE * 4 + OR_PTR_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
PAGE_PTR page_ptr;
int page_size;
int dummy_plan_size = 0;
char *aligned_page_buf = NULL;
QUERY_FLAG flag;
int query_timeout;
bool is_tran_auto_commit;
xasl_stream = NULL;
xasl_stream_size = 0;
var_data = NULL;
var_datasize = 0;
list_data = NULL;
page_ptr = NULL;
page_size = 0;
q_result = NULL;
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &xasl_stream, (int *) &xasl_stream_size);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto cleanup;
}
ptr = or_unpack_int (request, &var_count);
ptr = or_unpack_int (ptr, &var_datasize);
ptr = or_unpack_int (ptr, &flag);
ptr = or_unpack_int (ptr, &query_timeout);
if (var_count && var_datasize)
{
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, &var_data, (int *) &var_actual_datasize);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto cleanup;
}
}
is_tran_auto_commit = IS_TRAN_AUTO_COMMIT (flag);
xsession_set_tran_auto_commit (thread_p, is_tran_auto_commit);
/*
* After this point, xqmgr_prepare_and_execute_query has assumed
* responsibility for freeing xasl_stream...
*/
q_result =
xqmgr_prepare_and_execute_query (thread_p, xasl_stream, xasl_stream_size, &query_id, var_count, var_data, &flag,
query_timeout);
if (var_data)
{
thread_p->release_packet (var_data);
var_data = NULL;
}
if (xasl_stream)
{
thread_p->release_packet (xasl_stream);
xasl_stream = NULL;
}
if (q_result == NULL)
{
(void) return_error_to_client (thread_p, rid);
listid_length = 0;
}
else
{
listid_length = or_listid_length (q_result);
}
/* listid_length can be reset after pb_fetch() return move this after reset statement ptr = or_pack_int(ptr,
* listid_length); */
if (listid_length)
{
if (VPID_ISNULL (&q_result->first_vpid))
{
page_ptr = NULL;
}
else
{
page_ptr = qmgr_get_old_page (thread_p, &q_result->first_vpid, q_result->tfile_vfid);
}
if (page_ptr)
{
if ((QFILE_GET_TUPLE_COUNT (page_ptr) == -2) || (QFILE_GET_OVERFLOW_PAGE_ID (page_ptr) != NULL_PAGEID))
{
page_size = DB_PAGESIZE;
}
else
{
int offset = QFILE_GET_LAST_TUPLE_OFFSET (page_ptr);
page_size = (offset + QFILE_GET_TUPLE_LENGTH (page_ptr + offset));
}
/* to free page_ptr early */
aligned_page_buf = (char *) malloc (page_size);
memcpy (aligned_page_buf, page_ptr, page_size);
qmgr_free_old_page_and_init (thread_p, page_ptr, q_result->tfile_vfid);
}
else
{
/*
* During query execution, ER_LK_UNILATERALLY_ABORTED may have
* occurred.
* xqmgr_sync_query() had set this error
* so that the transaction will be rolled back.
*/
if (er_errid () < 0)
{
(void) return_error_to_client (thread_p, rid);
listid_length = 0;
}
/* if query type is not select, page ptr can be null */
}
if ((page_size > DB_PAGESIZE) || (page_size < 0))
{
page_size = 0;
}
if (listid_length > 0)
{
list_data = (char *) malloc (listid_length);
if (list_data == NULL)
{
listid_length = 0;
}
}
if (list_data)
{
or_pack_listid (list_data, q_result);
}
}
else
{
/* pack a couple of zeros for page_size and query_id since the client will unpack them. */
listid_length = 0;
page_size = 0;
query_id = 0;
}
ptr = or_pack_int (reply, (int) QUERY_END);
ptr = or_pack_int (ptr, listid_length);
ptr = or_pack_int (ptr, page_size);
ptr = or_pack_int (ptr, dummy_plan_size);
ptr = or_pack_ptr (ptr, query_id);
#if !defined(NDEBUG)
/* suppress valgrind UMW error */
memset (ptr, 0, OR_ALIGNED_BUF_SIZE (a_reply) - (ptr - reply));
#endif
deleter = [list_data, aligned_page_buf]() noexcept
{
if (list_data)
{
free (list_data);
}
if (aligned_page_buf)
{
free (aligned_page_buf);
}
};
css_send_reply_and_2_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), list_data,
listid_length, aligned_page_buf, page_size, std::move (deleter));
cleanup:
if (xasl_stream)
{
thread_p->release_packet (xasl_stream);
}
if (var_data)
{
thread_p->release_packet (var_data);
}
/* since the listid was copied over to the client, we don't need this one on the server */
if (q_result)
{
QFILE_FREE_AND_INIT_LIST_ID (q_result);
}
}
/*
* sqmgr_end_query -
*
* return:
*
* thrd(in):
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqmgr_end_query (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
QUERY_ID query_id;
int error_code = NO_ERROR;
int all_error_code = NO_ERROR;
int n_query_ids = 0, i = 0;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
request = or_unpack_int (request, &n_query_ids);
for (i = 0; i < n_query_ids; i++)
{
request = or_unpack_ptr (request, &query_id);
if (query_id > 0)
{
error_code = xqmgr_end_query (thread_p, query_id);
if (error_code != NO_ERROR)
{
all_error_code = error_code;
/* Continue to try to close as many queries as possible. */
}
}
}
if (all_error_code != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_int (reply, all_error_code);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sqmgr_drop_all_query_plans - Process a SERVER_QM_DROP_ALL_PLANS request
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
* Clear all XASL cache entires out upon request of the client.
* This function is a counter part to qmgr_drop_all_query_plans().
*/
void
sqmgr_drop_all_query_plans (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int status;
char *reply;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
reply = OR_ALIGNED_BUF_START (a_reply);
/* call the server routine of query drop plan */
status = xqmgr_drop_all_query_plans (thread_p);
if (status != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
/* pack status (DB_IN32) as a reply */
(void) or_pack_int (reply, status);
/* send reply and data to the client */
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sqmgr_drop_query_plans_by_sha1 - Process a NET_SERVER_QM_QUERY_DROP_SHA1_PLANS request
*
* return:
*
* rid(in):
* request(in)qmgr_drop_query_plans_by_sha1:
* reqlen(in):
*
* NOTE:
* Clear all XASL cache entires out upon request of the client.
* This function is a counter part to qmgr_drop_query_plans_by_sha1().
*/
void
sqmgr_drop_query_plans_by_sha1 (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int status;
char *reply, *sha1;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
reply = OR_ALIGNED_BUF_START (a_reply);
or_unpack_string_nocopy (request, &sha1);
/* call the server routine of query drop plan */
status = xqmgr_drop_query_plans_by_sha1 (thread_p, sha1);
if (status != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
/* pack status (DB_IN32) as a reply */
(void) or_pack_int (reply, status);
/* send reply and data to the client */
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sqmgr_dump_query_plans -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqmgr_dump_query_plans (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("qplan_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xqmgr_dump_query_plans (thread_p, outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* sqmgr_dump_query_cache -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqmgr_dump_query_cache (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("qcache_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xqmgr_dump_query_cache (thread_p, outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* sqp_get_sys_timestamp -
*
* return:
*
* rid(in):
*
* NOTE:
*/
void
sqp_get_sys_timestamp (THREAD_ENTRY *thread_p, unsigned int rid, char *request_ignore, int reqlen_ignore)
{
#if defined(ENABLE_UNUSED_FUNCTION)
OR_ALIGNED_BUF (OR_UTIME_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
DB_VALUE sys_timestamp;
db_sys_timestamp (&sys_timestamp);
(void) or_pack_utime (reply, * (DB_TIMESTAMP *) db_get_timestamp (&sys_timestamp));
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
#endif /* ENABLE_UNUSED_FUNCTION */
}
/*
* sserial_get_current_value -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sserial_get_current_value (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error_status = NO_ERROR;
DB_VALUE cur_val;
OID oid;
int cached_num;
int buffer_length;
char *buffer;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *p;
p = or_unpack_oid (request, &oid);
p = or_unpack_int (p, &cached_num);
error_status = xserial_get_current_value (thread_p, &cur_val, &oid, cached_num);
if (error_status != NO_ERROR)
{
assert (er_errid () != NO_ERROR);
error_status = er_errid ();
buffer_length = 0;
buffer = NULL;
}
else
{
buffer_length = or_db_value_size (&cur_val);
buffer = (char *) malloc (buffer_length);
if (buffer == NULL)
{
error_status = ER_OUT_OF_VIRTUAL_MEMORY;
buffer_length = 0;
}
}
p = or_pack_int (reply, buffer_length);
p = or_pack_int (p, error_status);
if (buffer == NULL)
{
(void) return_error_to_client (thread_p, rid);
buffer_length = 0;
}
else
{
(void) or_pack_value (buffer, &cur_val);
db_value_clear (&cur_val);
}
auto deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer,
buffer_length, std::move (deleter));
}
/*
* sserial_get_next_value -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sserial_get_next_value (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
DB_VALUE next_val;
OID oid;
char *buffer;
int cached_num, num_alloc, is_auto_increment;
int buffer_length, errid;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *p;
p = or_unpack_oid (request, &oid);
p = or_unpack_int (p, &cached_num);
p = or_unpack_int (p, &num_alloc);
p = or_unpack_int (p, &is_auto_increment);
/*
* If a client wants to generate AUTO_INCREMENT value during client-side
* insertion, a server should update LAST_INSERT_ID on a session.
*/
errid = xserial_get_next_value (thread_p, &next_val, &oid, cached_num, num_alloc, is_auto_increment, true);
if (errid != NO_ERROR)
{
buffer_length = 0;
buffer = NULL;
}
else
{
buffer_length = or_db_value_size (&next_val);
buffer = (char *) malloc (buffer_length);
if (buffer == NULL)
{
buffer_length = 0;
errid = ER_OUT_OF_VIRTUAL_MEMORY;
}
}
p = or_pack_int (reply, buffer_length);
p = or_pack_int (p, errid);
if (buffer == NULL)
{
(void) return_error_to_client (thread_p, rid);
}
else
{
(void) or_pack_value (buffer, &next_val);
db_value_clear (&next_val);
}
auto deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer,
buffer_length, std::move (deleter));
}
/*
* sserial_decache -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sserial_decache (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_oid (request, &oid);
xserial_decache (thread_p, &oid);
(void) or_pack_int (reply, NO_ERROR);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssynonym_remove_xasl_by_oid -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ssynonym_remove_xasl_by_oid (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID oid;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_oid (request, &oid);
xsynonym_remove_xasl_by_oid (thread_p, &oid);
(void) or_pack_int (reply, NO_ERROR);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* smnt_server_start_stats -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
smnt_server_start_stats (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
perfmon_start_watch (thread_p);
(void) or_pack_int (reply, NO_ERROR);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* smnt_server_stop_stats -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
smnt_server_stop_stats (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
perfmon_stop_watch (thread_p);
/* dummy reply message */
(void) or_pack_int (reply, 1);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* smnt_server_copy_stats -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
smnt_server_copy_stats (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *reply = NULL;
int nr_statistic_values;
UINT64 *stats = NULL;
nr_statistic_values = perfmon_get_number_of_statistic_values ();
stats = perfmon_allocate_values ();
if (stats == NULL)
{
ASSERT_ERROR ();
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
reply = perfmon_allocate_packed_values_buffer ();
if (reply == NULL)
{
ASSERT_ERROR ();
free_and_init (stats);
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
xperfmon_server_copy_stats (thread_p, stats, true);
perfmon_pack_stats (reply, stats);
css_send_data_to_client (thread_p->conn_entry, rid, reply, nr_statistic_values * sizeof (UINT64));
free_and_init (stats);
free_and_init (reply);
}
/*
* smnt_server_copy_global_stats -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
smnt_server_copy_global_stats (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *reply = NULL;
int nr_statistic_values;
UINT64 *stats = NULL;
nr_statistic_values = perfmon_get_number_of_statistic_values ();
stats = perfmon_allocate_values ();
if (stats == NULL)
{
ASSERT_ERROR ();
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
reply = perfmon_allocate_packed_values_buffer ();
if (reply == NULL)
{
ASSERT_ERROR ();
free_and_init (stats);
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
xperfmon_server_copy_global_stats (stats);
perfmon_pack_stats (reply, stats);
css_send_data_to_client (thread_p->conn_entry, rid, reply, nr_statistic_values * sizeof (UINT64));
free_and_init (stats);
free_and_init (reply);
}
/*
* sct_check_rep_dir -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sct_check_rep_dir (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID classoid;
OID rep_dir;
int success;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_OID_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_oid (request, &classoid);
OID_SET_NULL (&rep_dir); /* init */
success = xcatalog_check_rep_dir (thread_p, &classoid, &rep_dir);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
assert (success != NO_ERROR || !OID_ISNULL (&rep_dir));
ptr = or_pack_int (reply, (int) success);
ptr = or_pack_oid (ptr, &rep_dir);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* xs_receive_data_from_client -
*
* return:
*
* area(in):
* datasize(in):
*
* NOTE:
*/
int
xs_receive_data_from_client (THREAD_ENTRY *thread_p, char **area, int *datasize)
{
return xs_receive_data_from_client_with_timeout (thread_p, area, datasize, -1);
}
/*
* xs_receive_data_from_client_with_timeout -
*
* return:
*
* area(in):
* datasize(in):
* timeout (in):
*
* NOTE:
*/
int
xs_receive_data_from_client_with_timeout (THREAD_ENTRY *thread_p, char **area, int *datasize, int timeout)
{
unsigned int rid;
int rc = 0;
bool continue_checking = true;
if (*area)
{
free_and_init (*area);
}
rid = css_get_comm_request_id (thread_p);
rc = css_receive_data_from_client_with_timeout (thread_p->conn_entry, rid, area, (int *) datasize, timeout);
if (rc == TIMEDOUT_ON_QUEUE)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_DATA_RECEIVE_TIMEDOUT, 0);
return ER_NET_DATA_RECEIVE_TIMEDOUT;
}
else if (rc != 0)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
return ER_FAILED;
}
if (logtb_is_interrupted (thread_p, false, &continue_checking))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERRUPTED, 0);
return ER_FAILED;
}
return NO_ERROR;
}
/*
* slocator_assign_oid_batch -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_assign_oid_batch (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
LC_OIDSET *oidset = NULL;
/* skip over the word at the front reserved for the return code */
oidset = locator_unpack_oid_set_to_new (thread_p, request + OR_INT_SIZE);
if (oidset == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
success = xlocator_assign_oid_batch (thread_p, oidset);
/* the buffer we send back is identical in size to the buffer that was received so we can reuse it. */
/* first word is reserved for return code */
or_pack_int (request, success);
if (success == NO_ERROR)
{
if (locator_pack_oid_set (request + OR_INT_SIZE, oidset) == NULL)
{
/* trouble packing oidset for the return trip, severe error */
success = ER_FAILED;
or_pack_int (request, success);
}
}
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
css_send_data_to_client (thread_p->conn_entry, rid, request, reqlen);
locator_free_oid_set (thread_p, oidset);
}
/*
* slocator_find_lockhint_class_oids -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_find_lockhint_class_oids (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int num_classes;
char **many_classnames;
LOCK *many_locks = NULL;
int *many_need_subclasses = NULL;
OID *guessed_class_oids = NULL;
int *guessed_class_chns = NULL;
LC_PREFETCH_FLAGS *many_flags = NULL;
int quit_on_errors, lock_rr_tran;
LC_FIND_CLASSNAME allfind = LC_CLASSNAME_ERROR;
LC_LOCKHINT *found_lockhint;
LC_COPYAREA *copy_area;
char *desc_ptr = NULL;
int desc_size;
char *content_ptr;
int content_size;
char *ptr;
int num_objs = 0;
char *packed = NULL;
int packed_size;
int send_size = 0;
int i;
int malloc_size;
char *malloc_area;
OR_ALIGNED_BUF (NET_SENDRECV_BUFFSIZE + NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
found_lockhint = NULL;
copy_area = NULL;
ptr = or_unpack_int (request, &num_classes);
ptr = or_unpack_int (ptr, &quit_on_errors);
ptr = or_unpack_int (ptr, &lock_rr_tran);
malloc_size = ((sizeof (char *) + sizeof (LOCK) + sizeof (int) + sizeof (int) + sizeof (OID) + sizeof (int))
* num_classes);
malloc_area = (char *) db_private_alloc (thread_p, malloc_size);
if (malloc_area != NULL)
{
many_classnames = (char **) malloc_area;
many_locks = (LOCK *) ((char *) malloc_area + (sizeof (char *) * num_classes));
many_need_subclasses = (int *) ((char *) many_locks + (sizeof (LOCK) * num_classes));
many_flags = (LC_PREFETCH_FLAGS *) ((char *) many_need_subclasses + (sizeof (int) * num_classes));
guessed_class_oids = (OID *) ((char *) many_flags + (sizeof (int) * num_classes));
guessed_class_chns = (int *) ((char *) guessed_class_oids + (sizeof (OID) * num_classes));
for (i = 0; i < num_classes; i++)
{
ptr = or_unpack_string_nocopy (ptr, &many_classnames[i]);
ptr = or_unpack_lock (ptr, &many_locks[i]);
ptr = or_unpack_int (ptr, &many_need_subclasses[i]);
ptr = or_unpack_int (ptr, (int *) &many_flags[i]);
ptr = or_unpack_oid (ptr, &guessed_class_oids[i]);
ptr = or_unpack_int (ptr, &guessed_class_chns[i]);
}
allfind =
xlocator_find_lockhint_class_oids (thread_p, num_classes, (const char **) many_classnames, many_locks,
many_need_subclasses, many_flags, guessed_class_oids, guessed_class_chns,
quit_on_errors, &found_lockhint, ©_area);
}
if (allfind != LC_CLASSNAME_EXIST)
{
(void) return_error_to_client (thread_p, rid);
}
if ((LOCK) lock_rr_tran != NULL_LOCK)
{
/* lock the object common for RR transactions. This is used in ALTER TABLE ADD COLUMN NOT NULL scenarios */
if (xtran_lock_rep_read (thread_p, (LOCK) lock_rr_tran) != NO_ERROR)
{
allfind = LC_CLASSNAME_ERROR;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
(void) return_error_to_client (thread_p, rid);
}
}
if (found_lockhint != NULL && found_lockhint->length > 0)
{
send_size = locator_pack_lockhint (found_lockhint, true);
packed = found_lockhint->packed;
packed_size = found_lockhint->packed_size;
if (!packed)
{
(void) return_error_to_client (thread_p, rid);
allfind = LC_CLASSNAME_ERROR;
}
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
ptr = or_pack_int (reply, send_size);
ptr = or_pack_int (ptr, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, allfind);
if (copy_area == NULL && found_lockhint == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
else
{
auto deleter = [copy_area, found_lockhint, desc_ptr]() noexcept
{
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (found_lockhint)
{
locator_free_lockhint (found_lockhint);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_3_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), packed,
send_size, desc_ptr, desc_size, content_ptr, content_size, std::move (deleter));
}
if (malloc_area)
{
db_private_free_and_init (thread_p, malloc_area);
}
}
/*
* slocator_fetch_lockhint_classes -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_fetch_lockhint_classes (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
LC_COPYAREA *copy_area;
LC_LOCKHINT *lockhint;
OR_ALIGNED_BUF (NET_SENDRECV_BUFFSIZE + NET_COPY_AREA_SENDRECV_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *desc_ptr, *content_ptr;
int desc_size, content_size;
char *packed = NULL;
int packed_size;
char *ptr;
bool first_call;
int num_objs;
int send_size;
ptr = or_unpack_int (request, &packed_size);
if (packed_size == 0 || css_receive_data_from_client (thread_p->conn_entry, rid, &packed, (int *) &packed_size))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
if (packed)
{
thread_p->release_packet (packed);
}
return;
}
lockhint = locator_allocate_and_unpack_lockhint (packed, packed_size, true, false);
thread_p->release_packet (packed);
if ((lockhint == NULL) || (lockhint->length <= 0))
{
(void) return_error_to_client (thread_p, rid);
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, 0);
ptr = or_pack_int (ptr, ER_FAILED);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
first_call = true;
do
{
desc_ptr = NULL;
num_objs = 0;
copy_area = NULL;
success = xlocator_fetch_lockhint_classes (thread_p, lockhint, ©_area);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (copy_area != NULL)
{
num_objs = locator_send_copy_area (copy_area, &content_ptr, &content_size, &desc_ptr, &desc_size, true);
}
else
{
desc_ptr = NULL;
desc_size = 0;
content_ptr = NULL;
content_size = 0;
}
/* Send sizes of databuffer and copy area (descriptor + content) */
send_size = locator_pack_lockhint (lockhint, first_call);
packed = lockhint->packed;
packed_size = lockhint->packed_size;
ptr = or_pack_int (reply, send_size);
ptr = or_pack_int (ptr, num_objs);
ptr = or_pack_int (ptr, desc_size);
ptr = or_pack_int (ptr, content_size);
ptr = or_pack_int (ptr, success);
if (copy_area == NULL && lockhint == NULL)
{
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
else
{
auto deleter = [packed, packed_size, copy_area, desc_ptr]() noexcept
{
if (packed)
{
locator_free_packed (packed, packed_size);
}
if (copy_area)
{
locator_free_copy_area (copy_area);
}
if (desc_ptr)
{
free (desc_ptr);
}
};
css_send_reply_and_3_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), packed,
send_size, desc_ptr, desc_size, content_ptr, content_size, std::move (deleter));
/* packed area must not be shared */
lockhint->packed = NULL;
lockhint->packed_size = 0;
}
first_call = false;
}
while (copy_area && lockhint && ((lockhint->num_classes > lockhint->num_classes_processed)));
if (lockhint)
{
locator_free_lockhint (lockhint);
}
}
/*
* sthread_kill_tran_index -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sthread_kill_tran_index (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success;
int kill_tran_index;
int kill_pid;
char *kill_user;
char *kill_host;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &kill_tran_index);
ptr = or_unpack_string_nocopy (ptr, &kill_user);
ptr = or_unpack_string_nocopy (ptr, &kill_host);
ptr = or_unpack_int (ptr, &kill_pid);
success = (xlogtb_kill_tran_index (thread_p, kill_tran_index, kill_user, kill_host, kill_pid)
== NO_ERROR) ? NO_ERROR : ER_FAILED;
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sthread_kill_or_interrupt_tran -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sthread_kill_or_interrupt_tran (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success = NO_ERROR;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int i = 0;
int *tran_index_list;
int num_tran_index, interrupt_only;
int num_killed_tran = 0;
int is_dba_group_member = 0;
ptr = or_unpack_int (request, &is_dba_group_member);
ptr = or_unpack_int (ptr, &num_tran_index);
ptr = or_unpack_int_array (ptr, num_tran_index, &tran_index_list);
ptr = or_unpack_int (ptr, &interrupt_only);
for (i = 0; i < num_tran_index; i++)
{
success =
xlogtb_kill_or_interrupt_tran (thread_p, tran_index_list[i], (bool) is_dba_group_member, (bool) interrupt_only);
if (success == NO_ERROR)
{
num_killed_tran++;
}
else if (success == ER_KILL_TR_NOT_ALLOWED)
{
(void) return_error_to_client (thread_p, rid);
break;
}
else
{
/* error not related with authorization is ignored and keep running */
success = NO_ERROR;
}
}
ptr = or_pack_int (reply, success);
ptr = or_pack_int (ptr, num_killed_tran);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (tran_index_list)
{
db_private_free (NULL, tran_index_list);
}
}
/*
* sthread_dump_cs_stat -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sthread_dump_cs_stat (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (NULL, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("thread_cs_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (NULL, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
sync_dump_statistics (outfp, SYNC_TYPE_ALL);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (NULL, buffer);
}
/*
* slogtb_get_pack_tran_table -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*/
void
slogtb_get_pack_tran_table (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *buffer, *ptr;
int size;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int error;
int include_query_exec_info;
(void) or_unpack_int (request, &include_query_exec_info);
error = xlogtb_get_pack_tran_table (thread_p, &buffer, &size, include_query_exec_info);
if (error != NO_ERROR)
{
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
else
{
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
css_send_data_to_client (thread_p->conn_entry, rid, buffer, size);
free_and_init (buffer);
}
}
/*
* slogtb_dump_trantable -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*/
void
slogtb_dump_trantable (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("logtb_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xlogtb_dump_trantable (thread_p, outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* xcallback_console_print -
*
* return:
*
* print_str(in):
*/
int
xcallback_console_print (THREAD_ENTRY *thread_p, char *print_str)
{
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
unsigned int rid, rc;
int data_len, print_len;
char *ptr;
char *databuf;
rid = css_get_comm_request_id (thread_p);
data_len = or_packed_string_length (print_str, &print_len);
ptr = or_pack_int (reply, (int) CONSOLE_OUTPUT);
ptr = or_pack_int (ptr, NO_ERROR);
ptr = or_pack_int (ptr, data_len);
databuf = (char *) malloc (data_len);
if (databuf == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) data_len);
return ER_FAILED;
}
ptr = or_pack_string_with_length (databuf, print_str, print_len);
auto deleter = [buffer = databuf]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
rc =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), databuf,
data_len, std::move (deleter));
if (rc)
{
return ER_FAILED;
}
return NO_ERROR;
}
/*
* xio_send_user_prompt_to_client -
*
* return:
*
* prompt_id(in):
* prompt(in):
* failure_prompt(in):
* range_low(in):
* range_high(in):
* secondary_prompt(in):
* reprompt_value(in):
*
* NOTE:
* can be called only in the context of a net_client_callback
* that is waiting for the size of 3 integers to be returned.
* presently, on the client side that is bo_backup.
*/
int
xio_send_user_prompt_to_client (THREAD_ENTRY *thread_p, FILEIO_REMOTE_PROMPT_TYPE prompt_id, const char *prompt,
const char *failure_prompt, int range_low, int range_high, const char *secondary_prompt,
int reprompt_value)
{
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int prompt_length, strlen1, strlen2, strlen3;
unsigned int rid, rc;
char *ptr;
char *databuf;
rid = css_get_comm_request_id (thread_p);
/* need to know length of prompt string we are sending */
prompt_length = (or_packed_string_length (prompt, &strlen1) + or_packed_string_length (failure_prompt, &strlen2)
+ OR_INT_SIZE * 2 + or_packed_string_length (secondary_prompt, &strlen3) + OR_INT_SIZE);
/*
* Client side caller must be expecting a reply/callback followed
* by 2 ints, otherwise client will abort due to protocol error
* Prompt_length tells the receiver how big the followon message is.
*/
ptr = or_pack_int (reply, (int) ASYNC_OBTAIN_USER_INPUT);
ptr = or_pack_int (ptr, (int) prompt_id);
ptr = or_pack_int (ptr, prompt_length);
databuf = (char *) malloc (prompt_length);
if (databuf == NULL)
{
return ER_FAILED;
}
ptr = or_pack_string_with_length (databuf, prompt, strlen1);
ptr = or_pack_string_with_length (ptr, failure_prompt, strlen2);
ptr = or_pack_int (ptr, range_low);
ptr = or_pack_int (ptr, range_high);
ptr = or_pack_string_with_length (ptr, secondary_prompt, strlen3);
ptr = or_pack_int (ptr, reprompt_value);
auto deleter = [buffer = databuf]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
rc =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), databuf,
prompt_length, std::move (deleter));
if (rc)
{
return ER_FAILED;
}
return NO_ERROR;
}
/*
* xlog_send_log_pages_to_client -
*
* return:
* NOTE:
*/
int
xlog_send_log_pages_to_client (THREAD_ENTRY *thread_p, char *logpg_area, int area_size, LOGWR_MODE mode)
{
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
unsigned int rid, rc;
char *ptr;
rid = css_get_comm_request_id (thread_p);
/*
* Client side caller must be expecting a reply/callback followed
* by 2 ints, otherwise client will abort due to protocol error
* Prompt_length tells the receiver how big the followon message is.
*/
ptr = or_pack_int (reply, (int) GET_NEXT_LOG_PAGES);
ptr = or_pack_int (ptr, (int) area_size);
rc =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), logpg_area,
area_size, nullptr);
if (rc)
{
return ER_FAILED;
}
er_log_debug (ARG_FILE_LINE, "xlog_send_log_pages_to_client\n");
return NO_ERROR;
}
/*
* xlog_get_page_request_with_reply
*
* return:
* NOTE:
*/
int
xlog_get_page_request_with_reply (THREAD_ENTRY *thread_p, LOG_PAGEID *fpageid_ptr, LOGWR_MODE *mode_ptr, int timeout)
{
char *reply = NULL;
int reply_size;
LOG_PAGEID first_pageid;
int mode;
char *ptr;
int error;
int remote_error;
/* Obtain success message from the client, without blocking the server. */
error = xs_receive_data_from_client_with_timeout (thread_p, &reply, &reply_size, timeout);
if (error != NO_ERROR)
{
if (reply)
{
thread_p->release_packet (reply);
}
return error;
}
assert (reply != NULL);
ptr = or_unpack_int64 (reply, &first_pageid);
ptr = or_unpack_int (ptr, &mode);
ptr = or_unpack_int (ptr, &remote_error);
thread_p->release_packet (reply);
*fpageid_ptr = first_pageid;
*mode_ptr = (LOGWR_MODE) mode;
er_log_debug (ARG_FILE_LINE, "xlog_get_page_request_with_reply, " "fpageid(%lld), mode(%s)\n", first_pageid,
mode == LOGWR_MODE_SYNC ? "sync" : (mode == LOGWR_MODE_ASYNC ? "async" : "semisync"));
return (remote_error != NO_ERROR) ? remote_error : error;
}
/*
* shf_get_class_num_objs_and_pages -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_get_class_num_objs_and_pages (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
HFID hfid;
int success, approximation, nobjs, npages;
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_int (ptr, &approximation);
success = ((xheap_get_class_num_objects_pages (thread_p, &hfid, approximation, &nobjs, &npages) == NO_ERROR)
? NO_ERROR : ER_FAILED);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, (int) success);
ptr = or_pack_int (ptr, (int) nobjs);
ptr = or_pack_int (ptr, (int) npages);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sbtree_get_statistics -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sbtree_get_statistics (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTREE_STATS stat_info;
int success;
OR_ALIGNED_BUF (OR_INT_SIZE * 5) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_btid (request, &stat_info.btid);
assert_release (!BTID_IS_NULL (&stat_info.btid));
stat_info.keys = 0;
stat_info.pkeys_size = 0; /* do not request pkeys info */
stat_info.pkeys = NULL;
success = btree_get_stats (thread_p, &stat_info, STATS_WITH_SAMPLING);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
ptr = or_pack_int (ptr, stat_info.leafs);
ptr = or_pack_int (ptr, stat_info.pages);
ptr = or_pack_int (ptr, stat_info.height);
ptr = or_pack_int (ptr, stat_info.keys);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sbtree_get_key_type () - Obtains key type from index b-tree.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* int reqlen (in) :
*/
void
sbtree_get_key_type (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
BTID btid;
int error;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *reply_data = NULL;
char *ptr;
int reply_data_size;
TP_DOMAIN *key_type = NULL;
/* Unpack BTID */
ptr = or_unpack_btid (request, &btid);
assert_release (!BTID_IS_NULL (&btid));
/* Get key type */
error = xbtree_get_key_type (thread_p, btid, &key_type);
if (error != NO_ERROR && er_errid () != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
if (key_type != NULL)
{
/* Send key type to client */
reply_data_size = or_packed_domain_size (key_type, 0);
reply_data = (char *) malloc (reply_data_size);
if (reply_data == NULL)
{
error = ER_OUT_OF_VIRTUAL_MEMORY;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, (size_t) reply_data_size);
reply_data_size = 0;
}
else
{
(void) or_pack_domain (reply_data, key_type, 0, 0);
}
}
else
{
reply_data_size = 0;
reply_data = NULL;
error = (error == NO_ERROR) ? ER_FAILED : error;
}
ptr = or_pack_int (reply, reply_data_size);
ptr = or_pack_int (ptr, error);
auto deleter = [buffer = reply_data]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), reply_data,
reply_data_size, std::move (deleter));
}
/*
* sqp_get_server_info -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sqp_get_server_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
int success = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr, *buffer = NULL;
int buffer_length;
int server_info_bits;
DB_VALUE dt_dbval, ts_dbval; /* SI_SYS_DATETIME */
DB_VALUE lt_dbval; /* SI_LOCAL_TRANSACTION_ID */
ptr = or_unpack_int (request, &server_info_bits);
buffer_length = 0;
if (server_info_bits & SI_SYS_DATETIME)
{
success = db_sys_date_and_epoch_time (&dt_dbval, &ts_dbval);
if (success != NO_ERROR)
{
goto error_exit;
}
buffer_length += OR_VALUE_ALIGNED_SIZE (&dt_dbval);
buffer_length += OR_VALUE_ALIGNED_SIZE (&ts_dbval);
}
if (server_info_bits & SI_LOCAL_TRANSACTION_ID)
{
success = xtran_get_local_transaction_id (thread_p, <_dbval);
if (success != NO_ERROR)
{
goto error_exit;
}
buffer_length += OR_VALUE_ALIGNED_SIZE (<_dbval);
}
buffer = (char *) malloc (buffer_length);
if (buffer == NULL)
{
success = ER_OUT_OF_VIRTUAL_MEMORY;
goto error_exit;
}
ptr = buffer;
if (server_info_bits & SI_SYS_DATETIME)
{
ptr = or_pack_value (ptr, &dt_dbval);
ptr = or_pack_value (ptr, &ts_dbval);
}
if (server_info_bits & SI_LOCAL_TRANSACTION_ID)
{
ptr = or_pack_value (ptr, <_dbval);
}
#if !defined(NDEBUG)
/* suppress valgrind UMW error */
memset (ptr, 0, buffer_length - (ptr - buffer));
#endif
exit:
ptr = or_pack_int (reply, buffer_length);
ptr = or_pack_int (ptr, success);
deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer,
buffer_length, std::move (deleter));
return;
error_exit:
buffer_length = 0;
(void) return_error_to_client (thread_p, rid);
goto exit;
}
/*
* sprm_server_change_parameters () - Changes server's system parameter
* values.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
sprm_server_change_parameters (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
SYSPRM_ASSIGN_VALUE *assignments = NULL;
(void) sysprm_unpack_assign_values (request, &assignments);
xsysprm_change_server_parameters (assignments);
(void) or_pack_int (reply, PRM_ERR_NO_ERROR);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
sysprm_free_assign_values (&assignments);
}
/*
* sprm_server_get_force_parameters () - Obtains values for server's system
* parameters that are marked with
* PRM_FORCE_SERVER flag.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
sprm_server_get_force_parameters (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
SYSPRM_ASSIGN_VALUE *change_values;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int area_size;
char *area = NULL, *ptr = NULL;
change_values = xsysprm_get_force_server_parameters ();
if (change_values == NULL)
{
(void) return_error_to_client (thread_p, rid);
}
area_size = sysprm_packed_assign_values_length (change_values, 0);
area = (char *) malloc (area_size);
if (area == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) area_size);
(void) return_error_to_client (thread_p, rid);
area_size = 0;
}
ptr = or_pack_int (reply, area_size);
ptr = or_pack_int (ptr, er_errid ());
(void) sysprm_pack_assign_values (area, change_values);
auto deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area, area_size,
std::move (deleter));
sysprm_free_assign_values (&change_values);
}
/*
* sprm_server_obtain_parameters () - Obtains server's system parameter values
* for the requested parameters.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
sprm_server_obtain_parameters (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
SYSPRM_ERR rc = PRM_ERR_NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL, *reply_data = NULL;
int reply_data_size;
SYSPRM_ASSIGN_VALUE *prm_values = NULL;
(void) sysprm_unpack_assign_values (request, &prm_values);
xsysprm_obtain_server_parameters (prm_values);
reply_data_size = sysprm_packed_assign_values_length (prm_values, 0);
reply_data = (char *) malloc (reply_data_size);
if (reply_data == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) reply_data_size);
rc = PRM_ERR_NO_MEM_FOR_PRM;
reply_data_size = 0;
}
else
{
(void) sysprm_pack_assign_values (reply_data, prm_values);
}
ptr = or_pack_int (reply, reply_data_size);
ptr = or_pack_int (ptr, rc);
auto deleter = [buffer = reply_data]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), reply_data,
reply_data_size, std::move (deleter));
if (prm_values != NULL)
{
sysprm_free_assign_values (&prm_values);
}
}
/*
* sprm_server_dump_parameters -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*/
void
sprm_server_dump_parameters (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int in_flags, if_cond, out_flags, of_cond, old_style;
int send_size;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_int (request, &buffer_size);
ptr = or_unpack_int (ptr, &in_flags);
ptr = or_unpack_int (ptr, &if_cond);
ptr = or_unpack_int (ptr, &out_flags);
ptr = or_unpack_int (ptr, &of_cond);
ptr = or_unpack_int (ptr, &old_style);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("prm_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xsysprm_dump_server_parameters (outfp, (unsigned int) in_flags, (SYSPRM_DUMP_CONDITION) if_cond,
(unsigned int) out_flags, (SYSPRM_DUMP_CONDITION) of_cond, (bool) old_style);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* shf_has_instance -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
shf_has_instance (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
HFID hfid;
OID class_oid;
int r;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int has_visible_instance;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &has_visible_instance);
r = xheap_has_instance (thread_p, &hfid, &class_oid, has_visible_instance);
if (r == -1)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, (int) r);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* stran_get_local_transaction_id -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
stran_get_local_transaction_id (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
DB_VALUE val;
int success, trid;
success = (xtran_get_local_transaction_id (thread_p, &val) == NO_ERROR) ? NO_ERROR : ER_FAILED;
trid = db_get_int (&val);
ptr = or_pack_int (reply, success);
ptr = or_pack_int (ptr, trid);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* spl_get_server_port -
*
* return:
*
* rid(in):
*
* NOTE:
*/
void
spl_get_server_port (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_pack_int (reply, pl_server_port_from_info ());
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* srepl_set_info -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
srepl_set_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
REPL_INFO repl_info = { NULL, 0, false };
REPL_INFO_SBR repl_schema = { 0, NULL, NULL, NULL, NULL };
if (!LOG_CHECK_LOG_APPLIER (thread_p) && log_does_allow_replication () == true)
{
ptr = or_unpack_int (request, &repl_info.repl_info_type);
switch (repl_info.repl_info_type)
{
case REPL_INFO_TYPE_SBR:
{
ptr = or_unpack_int (ptr, &repl_schema.statement_type);
ptr = or_unpack_string_nocopy (ptr, &repl_schema.name);
ptr = or_unpack_string_nocopy (ptr, &repl_schema.stmt_text);
ptr = or_unpack_string_nocopy (ptr, &repl_schema.db_user);
ptr = or_unpack_string_nocopy (ptr, &repl_schema.sys_prm_context);
repl_info.info = (char *) &repl_schema;
break;
}
default:
success = ER_FAILED;
break;
}
if (success == NO_ERROR)
{
success = xrepl_set_info (thread_p, &repl_info);
}
}
(void) or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* srepl_log_get_append_lsa -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
srepl_log_get_append_lsa (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
LOG_LSA *lsa;
lsa = xrepl_log_get_append_lsa ();
reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_pack_log_lsa (reply, lsa);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_check_fk_validity -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_check_fk_validity (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OID class_oid;
HFID hfid;
OID pk_cls_oid;
BTID pk_btid;
int n_attrs, *attr_ids = NULL;
TP_DOMAIN *key_type;
char *fk_name = NULL;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_oid (request, &class_oid);
ptr = or_unpack_hfid (ptr, &hfid);
ptr = or_unpack_domain (ptr, &key_type, 0);
ptr = or_unpack_int (ptr, &n_attrs);
ptr = or_unpack_int_array (ptr, n_attrs, &attr_ids);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
goto end;
}
ptr = or_unpack_oid (ptr, &pk_cls_oid);
ptr = or_unpack_btid (ptr, &pk_btid);
ptr = or_unpack_string (ptr, &fk_name);
if (xlocator_check_fk_validity (thread_p, &class_oid, &hfid, key_type, n_attrs, attr_ids, &pk_cls_oid, &pk_btid,
fk_name) != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
end:
ptr = or_pack_int (reply, er_errid ());
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (attr_ids != NULL)
{
db_private_free_and_init (thread_p, attr_ids);
}
if (fk_name != NULL)
{
db_private_free_and_init (thread_p, fk_name);
}
}
/*
* slogwr_get_log_pages -
*
* return:
*
* thread_p(in):
* rid(in):
* request(in):
* reqlen(in):
*
* Note:
*/
void
slogwr_get_log_pages (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
LOG_PAGEID first_pageid;
LOGWR_MODE mode;
int m, error, remote_error;
ptr = or_unpack_int64 (request, &first_pageid);
ptr = or_unpack_int (ptr, &m);
mode = (LOGWR_MODE) m;
ptr = or_unpack_int (ptr, &remote_error);
error = xlogwr_get_log_pages (thread_p, first_pageid, mode);
if (error == ER_INTERRUPTED)
{
(void) return_error_to_client (thread_p, rid);
}
if (error == ER_NET_DATA_RECEIVE_TIMEDOUT)
{
css_end_server_request (thread_p->conn_entry);
}
else
{
ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, error);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
return;
}
/*
* sboot_compact_db -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_compact_db (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success, n_classes, reply_size, i;
char *reply = NULL;
OID *class_oids = NULL;
int *ids_repr = NULL;
char *ptr = NULL;
int space_to_process = 0, instance_lock_timeout = 0, delete_old_repr = 0;
int class_lock_timeout = 0;
OID last_processed_class_oid, last_processed_oid;
int *total_objects = NULL, *failed_objects = NULL;
int *modified_objects = NULL, *big_objects = NULL;
ptr = or_unpack_int (request, &n_classes);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_oid_array (ptr, n_classes, &class_oids);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int (ptr, &space_to_process);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int (ptr, &instance_lock_timeout);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int (ptr, &class_lock_timeout);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int (ptr, &delete_old_repr);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_oid (ptr, &last_processed_class_oid);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_oid (ptr, &last_processed_oid);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int_array (ptr, n_classes, &total_objects);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int_array (ptr, n_classes, &failed_objects);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int_array (ptr, n_classes, &modified_objects);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int_array (ptr, n_classes, &big_objects);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
ptr = or_unpack_int_array (ptr, n_classes, &ids_repr);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
success =
xboot_compact_db (thread_p, class_oids, n_classes, space_to_process, instance_lock_timeout, class_lock_timeout,
(bool) delete_old_repr, &last_processed_class_oid, &last_processed_oid, total_objects,
failed_objects, modified_objects, big_objects, ids_repr);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
reply_size = OR_OID_SIZE * 2 + OR_INT_SIZE * (5 * n_classes + 1);
reply = (char *) db_private_alloc (thread_p, reply_size);
if (reply == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, class_oids);
db_private_free_and_init (thread_p, ids_repr);
db_private_free_and_init (thread_p, failed_objects);
db_private_free_and_init (thread_p, modified_objects);
db_private_free_and_init (thread_p, big_objects);
db_private_free_and_init (thread_p, total_objects);
return;
}
ptr = or_pack_int (reply, success);
ptr = or_pack_oid (ptr, &last_processed_class_oid);
ptr = or_pack_oid (ptr, &last_processed_oid);
for (i = 0; i < n_classes; i++)
{
ptr = or_pack_int (ptr, total_objects[i]);
}
for (i = 0; i < n_classes; i++)
{
ptr = or_pack_int (ptr, failed_objects[i]);
}
for (i = 0; i < n_classes; i++)
{
ptr = or_pack_int (ptr, modified_objects[i]);
}
for (i = 0; i < n_classes; i++)
{
ptr = or_pack_int (ptr, big_objects[i]);
}
for (i = 0; i < n_classes; i++)
{
ptr = or_pack_int (ptr, ids_repr[i]);
}
if (css_send_data_to_client (thread_p->conn_entry, rid, reply, reply_size) != NO_ERROR)
{
boot_compact_stop (thread_p);
}
db_private_free_and_init (thread_p, class_oids);
db_private_free_and_init (thread_p, ids_repr);
db_private_free_and_init (thread_p, failed_objects);
db_private_free_and_init (thread_p, modified_objects);
db_private_free_and_init (thread_p, big_objects);
db_private_free_and_init (thread_p, total_objects);
db_private_free_and_init (thread_p, reply);
}
/*
* sboot_heap_compact -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_heap_compact (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int success;
OID class_oid;
ptr = or_unpack_oid (request, &class_oid);
if (ptr == NULL)
{
(void) return_error_to_client (thread_p, rid);
return;
}
success = xboot_heap_compact (thread_p, &class_oid);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, success);
if (css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply)) != NO_ERROR)
{
boot_compact_stop (thread_p);
}
}
/*
* sboot_compact_start -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_compact_start (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int success;
success = xboot_compact_start (thread_p);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_compact_stop -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sboot_compact_stop (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int success;
success = xboot_compact_stop (thread_p);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ses_posix_create_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_create_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *new_path;
int path_size = 0, ret;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
new_path = (char *) malloc (PATH_MAX);
ret = xes_posix_create_file (new_path);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
else
{
path_size = strlen (new_path) + 1;
}
ptr = or_pack_int (reply, path_size);
ptr = or_pack_int (ptr, ret);
auto deleter = [buffer = new_path]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), new_path,
path_size, std::move (deleter));
}
/*
* ses_posix_write_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_write_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *path;
void *buf = NULL;
off_t offset;
size_t count;
INT64 ret, tmp_int64;
int csserror, buf_size;
OR_ALIGNED_BUF (OR_INT64_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &path);
ptr = or_unpack_int64 (ptr, &tmp_int64);
offset = (off_t) tmp_int64;
ptr = or_unpack_int64 (ptr, &tmp_int64);
count = (size_t) tmp_int64;
csserror = css_receive_data_from_client (thread_p->conn_entry, rid, (char **) &buf, &buf_size);
if (csserror)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
}
else
{
ret = xes_posix_write_file (path, buf, count, offset);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int64 (reply, (INT64) ret);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
if (buf != NULL)
{
thread_p->release_packet (buf);
}
}
/*
* ses_posix_read_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_read_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *path;
void *buf;
off_t offset;
size_t count;
INT64 ret, tmp_int64;
OR_ALIGNED_BUF (OR_INT64_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &path);
ptr = or_unpack_int64 (ptr, &tmp_int64);
offset = (off_t) tmp_int64;
ptr = or_unpack_int64 (ptr, &tmp_int64);
count = (size_t) tmp_int64;
buf = (char *) malloc (count);
if (buf == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
}
else
{
ret = xes_posix_read_file (path, buf, count, offset);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int64 (reply, (INT64) ret);
auto deleter = [buffer = buf]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), (char *) buf,
(int) count, std::move (deleter));
}
}
/*
* ses_posix_delete_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_delete_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *path;
int ret;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &path);
ret = xes_posix_delete_file (path);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, ret);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ses_posix_copy_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_copy_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *src_path, *metaname, *new_path;
int path_size = 0, ret;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &src_path);
ptr = or_unpack_string_nocopy (ptr, &metaname);
new_path = (char *) malloc (PATH_MAX);
ret = xes_posix_copy_file (src_path, metaname, new_path);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
else
{
path_size = strlen (new_path) + 1;
}
ptr = or_pack_int (reply, path_size);
ptr = or_pack_int (ptr, ret);
auto deleter = [buffer = new_path]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), new_path,
path_size, std::move (deleter));
}
/*
* ses_posix_rename_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_rename_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *src_path, *metaname, *new_path;
int path_size = 0, ret;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &src_path);
ptr = or_unpack_string_nocopy (ptr, &metaname);
new_path = (char *) malloc (PATH_MAX);
ret = xes_posix_rename_file (src_path, metaname, new_path);
if (ret != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
else
{
path_size = strlen (new_path) + 1;
}
ptr = or_pack_int (reply, path_size);
ptr = or_pack_int (ptr, ret);
auto deleter = [buffer = new_path]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), new_path,
path_size, std::move (deleter));
}
/*
* ses_posix_read_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ses_posix_get_file_size (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *path;
off_t file_size;
OR_ALIGNED_BUF (OR_INT64_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_string_nocopy (request, &path);
file_size = xes_posix_get_file_size (path);
if (file_size < 0)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int64 (reply, (INT64) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_upgrade_instances_domain -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_upgrade_instances_domain (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
OID class_oid;
int attr_id;
int success;
ptr = request;
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &attr_id);
success = xlocator_upgrade_instances_domain (thread_p, &class_oid, attr_id);
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_find_or_create_session -
*
* return: void
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE: This function checks if a session is still active and creates a new
* one if needed
*/
void
ssession_find_or_create_session (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
SESSION_ID id = DB_EMPTY_SESSION;
int row_count = -1, area_size;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL, *area = NULL;
char *db_user = NULL, *host = NULL, *program_name = NULL;
char db_user_upper[DB_MAX_USER_LENGTH] = { '\0' };
char server_session_key[SERVER_SESSION_KEY_SIZE];
SESSION_PARAM *session_params = NULL;
int error = NO_ERROR, update_parameter_values = 0;
ptr = or_unpack_int (request, (int *) &id);
ptr = or_unpack_stream (ptr, server_session_key, SERVER_SESSION_KEY_SIZE);
ptr = sysprm_unpack_session_parameters (ptr, &session_params);
ptr = or_unpack_string_alloc (ptr, &db_user);
ptr = or_unpack_string_alloc (ptr, &host);
ptr = or_unpack_string_alloc (ptr, &program_name);
if (id == DB_EMPTY_SESSION
|| memcmp (server_session_key, xboot_get_server_session_key (), SERVER_SESSION_KEY_SIZE) != 0
|| (error = xsession_check_session (thread_p, id)) != NO_ERROR)
{
/* not an error yet */
er_clear ();
/* create new session */
error = xsession_create_new (thread_p, &id);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
}
else if (error == NO_ERROR)
{
xsession_set_is_keep_session (thread_p, false);
}
/* get row count */
xsession_get_row_count (thread_p, &row_count);
if (error == NO_ERROR)
{
error = sysprm_session_init_session_parameters (&session_params, &update_parameter_values);
if (error != NO_ERROR)
{
error = sysprm_set_error ((SYSPRM_ERR) error, NULL);
(void) return_error_to_client (thread_p, rid);
}
}
area_size = 0;
if (error == NO_ERROR)
{
/* key.id */
area_size = OR_INT_SIZE;
/* row_count */
area_size += OR_INT_SIZE;
/* server session key */
area_size += or_packed_stream_length (SERVER_SESSION_KEY_SIZE);
/* update_parameter_values */
area_size += OR_INT_SIZE;
if (update_parameter_values)
{
/* session params */
area_size += sysprm_packed_session_parameters_length (session_params, area_size);
}
area = (char *) malloc (area_size);
if (area != NULL)
{
ptr = or_pack_int (area, id);
ptr = or_pack_int (ptr, row_count);
ptr = or_pack_stream (ptr, xboot_get_server_session_key (), SERVER_SESSION_KEY_SIZE);
ptr = or_pack_int (ptr, update_parameter_values);
if (update_parameter_values)
{
ptr = sysprm_pack_session_parameters (ptr, session_params);
}
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) area_size);
error = ER_OUT_OF_VIRTUAL_MEMORY;
area_size = 0;
(void) return_error_to_client (thread_p, rid);
}
}
if (db_user != NULL)
{
assert (host != NULL);
assert (program_name != NULL);
intl_identifier_upper (db_user, db_user_upper);
css_set_user_access_status (db_user_upper, host, program_name);
logtb_set_current_user_name (thread_p, db_user_upper);
}
free_and_init (db_user);
free_and_init (host);
free_and_init (program_name);
ptr = or_pack_int (reply, area_size);
ptr = or_pack_int (ptr, error);
auto deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area, area_size,
std::move (deleter));
}
/*
* ssession_end_session -
*
* return: void
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE: This function ends the session with the id contained in the request
*/
void
ssession_end_session (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
int is_keep_session;
SESSION_ID id;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL;
ptr = or_unpack_int (request, (int *) &id);
ptr = or_unpack_int (ptr, &is_keep_session);
err = xsession_end_session (thread_p, id, (bool) is_keep_session);
ptr = or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_set_row_count - set the count of affected rows for a session
*
* return: void
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
ssession_set_row_count (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
int row_count = 0;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL;
(void) or_unpack_int (request, &row_count);
err = xsession_set_row_count (thread_p, row_count);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_get_row_count - get the count of affected rows for a session
* return: void
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_get_row_count (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
int row_count = 0;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL;
err = xsession_get_row_count (thread_p, &row_count);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, row_count);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_get_last_insert_id - get the value of the last update serial
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_get_last_insert_id (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
DB_VALUE lid;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *data_reply = NULL;
int data_size = 0;
char *ptr = NULL;
int update_last_insert_id;
(void) or_unpack_int (request, &update_last_insert_id);
err = xsession_get_last_insert_id (thread_p, &lid, (bool) update_last_insert_id);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
data_size = 0;
goto end;
}
data_size = OR_VALUE_ALIGNED_SIZE (&lid);
data_reply = (char *) malloc (data_size);
if (data_reply == NULL)
{
(void) return_error_to_client (thread_p, rid);
err = ER_FAILED;
data_size = 0;
goto end;
}
or_pack_value (data_reply, &lid);
end:
ptr = or_pack_int (reply, data_size);
ptr = or_pack_int (ptr, err);
auto deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply),
OR_ALIGNED_BUF_SIZE (a_reply), data_reply, data_size, std::move (deleter));
}
/*
* ssession_reset_cur_insert_id - reset the current insert id as NULL
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_reset_cur_insert_id (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = NULL;
err = xsession_reset_cur_insert_id (thread_p);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_create_prepared_statement - create a prepared statement
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_create_prepared_statement (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
/* request data */
char *name = NULL, *alias_print = NULL;
char *reply = NULL, *ptr = NULL;
char *data_request = NULL;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
int data_size = 0, err = 0;
char *info = NULL;
SHA1Hash alias_sha1 = SHA1_HASH_INITIALIZER;
reply = OR_ALIGNED_BUF_START (a_reply);
/* name */
ptr = or_unpack_string_alloc (request, &name);
/* alias_print */
ptr = or_unpack_string_alloc (ptr, &alias_print);
/* data_size */
ptr = or_unpack_int (ptr, &data_size);
if (data_size <= 0)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto error;
}
if (alias_print != NULL)
{
/* alias_sha1 */
ptr = or_unpack_sha1 (ptr, &alias_sha1);
}
err = css_receive_data_from_client (thread_p->conn_entry, rid, &data_request, &data_size);
if (err != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto error;
}
/* For prepared statements, on the server side, we only use the user OID, the statement name and the alias print.
* User OID and alias_print are needed as XASL cache key and the statement name is the identifier for the statement.
* The rest of the information will be kept unpacked and sent back to the client when requested */
info = (char *) malloc (data_size);
if (info == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) data_size);
goto error;
}
memcpy (info, data_request, data_size);
err = xsession_create_prepared_statement (thread_p, name, alias_print, &alias_sha1, info, data_size);
if (err != NO_ERROR)
{
goto error;
}
or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
if (data_request != NULL)
{
thread_p->release_packet (data_request);
}
return;
error:
(void) return_error_to_client (thread_p, rid);
or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
/* free data */
if (data_request != NULL)
{
thread_p->release_packet (data_request);
}
if (name != NULL)
{
free_and_init (name);
}
if (alias_print != NULL)
{
free_and_init (alias_print);
}
if (info != NULL)
{
free_and_init (info);
}
}
/*
* ssession_get_prepared_statement - create a prepared statement
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_get_prepared_statement (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
char *name = NULL, *stmt_info = NULL;
int info_len = 0;
char *reply = NULL, *ptr = NULL, *data_reply = NULL;
int err = NO_ERROR, reply_size = 0;
XASL_ID xasl_id;
/* return code + data length */
OR_ALIGNED_BUF (OR_INT_SIZE * 2 + OR_XASL_ID_SIZE) a_reply;
int get_xasl_header = 0;
XASL_NODE_HEADER xasl_header, *xasl_header_p = NULL;
/* unpack prepared statement name */
ptr = or_unpack_string (request, &name);
/* unpack get XASL node header boolean */
ptr = or_unpack_int (ptr, &get_xasl_header);
if (get_xasl_header)
{
/* need to get XASL node header too */
xasl_header_p = &xasl_header;
INIT_XASL_NODE_HEADER (xasl_header_p);
}
err = xsession_get_prepared_statement (thread_p, name, &stmt_info, &info_len, &xasl_id, xasl_header_p);
if (err != NO_ERROR)
{
goto error;
}
/* pack reply buffer */
reply_size = or_packed_stream_length (info_len); /* smt_info */
if (get_xasl_header)
{
reply_size += XASL_NODE_HEADER_SIZE; /* xasl node header */
}
data_reply = (char *) malloc (reply_size);
if (data_reply == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) reply_size);
err = ER_FAILED;
goto error;
}
ptr = or_pack_stream (data_reply, stmt_info, info_len);
if (get_xasl_header)
{
/* pack XASL node header */
OR_PACK_XASL_NODE_HEADER (ptr, xasl_header_p);
}
reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_pack_int (reply, reply_size);
ptr = or_pack_int (ptr, err);
OR_PACK_XASL_ID (ptr, &xasl_id);
deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
err =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply),
OR_ALIGNED_BUF_SIZE (a_reply), data_reply, reply_size, std::move (deleter));
goto cleanup;
error:
reply_size = 0;
if (data_reply != NULL)
{
free_and_init (data_reply);
}
ptr = OR_ALIGNED_BUF_START (a_reply);
ptr = or_pack_int (ptr, 0);
or_pack_int (ptr, err);
(void) return_error_to_client (thread_p, rid);
err =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply),
OR_ALIGNED_BUF_SIZE (a_reply), NULL, 0, []() noexcept { });
goto cleanup;
cleanup:
if (stmt_info != NULL)
{
free_and_init (stmt_info);
}
if (name != NULL)
{
db_private_free_and_init (thread_p, name);
}
}
/*
* ssession_delete_prepared_statement - get prepared statement info
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
* NOTE:
*/
void
ssession_delete_prepared_statement (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *name = NULL;
or_unpack_string_nocopy (request, &name);
if (name == NULL)
{
(void) return_error_to_client (thread_p, rid);
err = ER_FAILED;
}
else
{
err = xsession_delete_prepared_statement (thread_p, name);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
}
or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slogin_user - login user
* return: error code or NO_ERROR
* rid(in):
* request(in):
* reqlen(in):
*/
void
slogin_user (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *username = NULL;
or_unpack_string_nocopy (request, &username);
if (username == NULL)
{
(void) return_error_to_client (thread_p, rid);
err = ER_FAILED;
}
else
{
err = xlogin_user (thread_p, username);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
}
or_pack_int (reply, err);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_set_session_variables () - set session variables
* return :void
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
ssession_set_session_variables (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int count = 0, err = NO_ERROR, data_size = 0, i = 0;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = NULL, *ptr = NULL, *data_request = NULL;
DB_VALUE *values = NULL;
/* Unpack count of variables from request */
ptr = or_unpack_int (request, &count);
if (count <= 0)
{
goto cleanup;
}
/* fetch the values */
err = css_receive_data_from_client (thread_p->conn_entry, rid, &data_request, &data_size);
if (err != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto cleanup;
}
values = (DB_VALUE *) malloc (count * sizeof (DB_VALUE));
if (values == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, count * sizeof (DB_VALUE));
err = ER_FAILED;
goto cleanup;
}
ptr = data_request;
/* session variables are packed into an array containing DB_VALUE objects of the form name1, value1, name2, value2,
* name3, value 3... */
for (i = 0; i < count; i++)
{
ptr = or_unpack_db_value (ptr, &values[i]);
}
err = xsession_set_session_variables (thread_p, values, count);
cleanup:
if (values != NULL)
{
for (i = 0; i < count; i++)
{
pr_clear_value (&values[i]);
}
free_and_init (values);
}
if (data_request != NULL)
{
thread_p->release_packet (data_request);
}
reply = OR_ALIGNED_BUF_START (a_reply);
or_pack_int (reply, err);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
css_send_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply), OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_get_session_variable () - get the value of a session variable
* return : void
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
ssession_get_session_variable (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE * 2) a_reply;
char *reply = NULL, *ptr = NULL, *data_reply = NULL;
DB_VALUE result, name;
int size = 0;
db_make_null (&result);
db_make_null (&name);
reply = OR_ALIGNED_BUF_START (a_reply);
or_unpack_db_value (request, &name);
err = xsession_get_session_variable (thread_p, &name, &result);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
size = or_db_value_size (&result);
data_reply = (char *) malloc (size);
if (data_reply != NULL)
{
or_pack_db_value (data_reply, &result);
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) size);
(void) return_error_to_client (thread_p, rid);
size = 0;
err = ER_FAILED;
}
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, err);
auto deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), data_reply, size,
std::move (deleter));
pr_clear_value (&result);
pr_clear_value (&name);
}
/*
* svacuum () - Calls vacuum function.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
svacuum (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = NULL;
reply = OR_ALIGNED_BUF_START (a_reply);
/* Call vacuum */
err = xvacuum (thread_p);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
/* Send error code as reply */
(void) or_pack_int (reply, err);
/* For now no results are required, just fail/success */
css_send_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply), OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* svacuum_dump -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
svacuum_dump (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int file_size;
char *buffer;
int buffer_size;
int send_size;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_int (request, &buffer_size);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
auto[filename, outfp] = filesys::open_temp_file ("vacuum_dump_", "w+b");
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
filesys::auto_delete_file file_del (filename.c_str ());
xvacuum_dump (thread_p, outfp);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* slogtb_get_mvcc_snapshot () - Get MVCC Snapshot.
*
* return :
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
slogtb_get_mvcc_snapshot (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = NULL;
int err;
err = xlogtb_get_mvcc_snapshot (thread_p);
reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_pack_int (reply, err);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
css_send_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply), OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* ssession_drop_session_variables () - drop session variables
* return : void
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
ssession_drop_session_variables (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int count = 0, err = NO_ERROR, data_size = 0, i = 0;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = NULL, *ptr = NULL, *data_request = NULL;
DB_VALUE *values = NULL;
/* Unpack count of variables from request */
ptr = or_unpack_int (request, &count);
if (count <= 0)
{
goto cleanup;
}
/* fetch the values */
err = css_receive_data_from_client (thread_p->conn_entry, rid, &data_request, &data_size);
if (err != NO_ERROR)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_NET_SERVER_DATA_RECEIVE, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
goto cleanup;
}
values = (DB_VALUE *) malloc (count * sizeof (DB_VALUE));
if (values == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, count * sizeof (DB_VALUE));
err = ER_FAILED;
goto cleanup;
}
ptr = data_request;
for (i = 0; i < count; i++)
{
ptr = or_unpack_db_value (ptr, &values[i]);
}
err = xsession_drop_session_variables (thread_p, values, count);
cleanup:
if (values != NULL)
{
for (i = 0; i < count; i++)
{
pr_clear_value (&values[i]);
}
free_and_init (values);
}
if (data_request != NULL)
{
thread_p->release_packet (data_request);
}
reply = OR_ALIGNED_BUF_START (a_reply);
or_pack_int (reply, err);
if (err != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
css_send_data_to_client (thread_p->conn_entry, rid, OR_ALIGNED_BUF_START (a_reply), OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* sboot_get_locales_info () - get info about locales
* return : void
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
sboot_get_locales_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (2 * OR_INT_SIZE) a_reply;
char *reply = NULL, *ptr = NULL, *data_reply = NULL;
int size = 0, i;
int len_str;
const int collation_cnt = lang_collation_count ();
const int lang_cnt = lang_locales_count (false);
const int locales_cnt = lang_locales_count (true);
int found_coll = 0;
reply = OR_ALIGNED_BUF_START (a_reply);
/* compute size of packed information */
for (i = 0; i < LANG_MAX_COLLATIONS; i++)
{
LANG_COLLATION *lc = lang_get_collation (i);
assert (lc != NULL);
if (i != 0 && lc->coll.coll_id == LANG_COLL_DEFAULT)
{
/* iso88591 binary collation added only once */
continue;
}
found_coll++;
size += 2 * OR_INT_SIZE; /* collation id , codeset */
size += or_packed_string_length (lc->coll.coll_name, &len_str);
size += or_packed_string_length (lc->coll.checksum, &len_str);
}
assert (found_coll == collation_cnt);
for (i = 0; i < lang_cnt; i++)
{
const LANG_LOCALE_DATA *lld = lang_get_first_locale_for_lang (i);
assert (lld != NULL);
do
{
size += or_packed_string_length (lld->lang_name, &len_str);
size += OR_INT_SIZE; /* codeset */
size += or_packed_string_length (lld->checksum, &len_str);
lld = lld->next_lld;
}
while (lld != NULL);
}
size += 2 * OR_INT_SIZE; /* collation_cnt, locales_cnt */
data_reply = (char *) malloc (size);
if (data_reply != NULL)
{
ptr = or_pack_int (data_reply, collation_cnt);
ptr = or_pack_int (ptr, locales_cnt);
found_coll = 0;
/* pack collation information : */
for (i = 0; i < LANG_MAX_COLLATIONS; i++)
{
LANG_COLLATION *lc = lang_get_collation (i);
assert (lc != NULL);
if (i != 0 && lc->coll.coll_id == LANG_COLL_DEFAULT)
{
continue;
}
found_coll++;
ptr = or_pack_int (ptr, lc->coll.coll_id);
len_str = strlen (lc->coll.coll_name);
ptr = or_pack_string_with_length (ptr, lc->coll.coll_name, len_str);
ptr = or_pack_int (ptr, (int) lc->codeset);
len_str = strlen (lc->coll.checksum);
ptr = or_pack_string_with_length (ptr, lc->coll.checksum, len_str);
}
assert (found_coll == collation_cnt);
/* pack locale information : */
for (i = 0; i < lang_cnt; i++)
{
const LANG_LOCALE_DATA *lld = lang_get_first_locale_for_lang (i);
assert (lld != NULL);
do
{
len_str = strlen (lld->lang_name);
ptr = or_pack_string_with_length (ptr, lld->lang_name, len_str);
ptr = or_pack_int (ptr, lld->codeset);
len_str = strlen (lld->checksum);
ptr = or_pack_string_with_length (ptr, lld->checksum, len_str);
lld = lld->next_lld;
}
while (lld != NULL);
}
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) size);
(void) return_error_to_client (thread_p, rid);
size = 0;
err = ER_FAILED;
}
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, err);
auto deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), data_reply, size,
std::move (deleter));
}
/*
* sboot_get_timezone_checksum () - get the timezone library checksum
* return : void
* thread_p (in) :
* rid (in) :
* request (in) :
* reqlen (in) :
*/
void
sboot_get_timezone_checksum (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int err = NO_ERROR;
OR_ALIGNED_BUF (2 * OR_INT_SIZE) a_reply;
char *reply = NULL, *ptr = NULL, *data_reply = NULL;
int size = 0;
int len_str;
const TZ_DATA *tzd;
tzd = tz_get_data ();
assert (tzd != NULL);
reply = OR_ALIGNED_BUF_START (a_reply);
size += or_packed_string_length (tzd->checksum, &len_str);
data_reply = (char *) malloc (size);
if (data_reply != NULL)
{
len_str = strlen (tzd->checksum);
ptr = or_pack_string_with_length (data_reply, tzd->checksum, len_str);
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
(void) return_error_to_client (thread_p, rid);
size = 0;
err = ER_FAILED;
}
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, err);
auto deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), data_reply, size,
std::move (deleter));
}
/*
* schksum_insert_repl_log_and_demote_table_lock -
*
* return: error code
*
* NOTE: insert replication log and demote the read lock of the table
*/
void
schksum_insert_repl_log_and_demote_table_lock (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int success = NO_ERROR;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
OID class_oid;
REPL_INFO repl_info = { NULL, 0, false };
REPL_INFO_SBR repl_stmt = { 0, NULL, NULL, NULL, NULL };
ptr = or_unpack_oid (request, &class_oid);
ptr = or_unpack_int (ptr, &repl_info.repl_info_type);
switch (repl_info.repl_info_type)
{
case REPL_INFO_TYPE_SBR:
{
ptr = or_unpack_int (ptr, &repl_stmt.statement_type);
ptr = or_unpack_string_nocopy (ptr, &repl_stmt.name);
ptr = or_unpack_string_nocopy (ptr, &repl_stmt.stmt_text);
ptr = or_unpack_string_nocopy (ptr, &repl_stmt.db_user);
ptr = or_unpack_string_nocopy (ptr, &repl_stmt.sys_prm_context);
repl_info.info = (char *) &repl_stmt;
break;
}
default:
success = ER_FAILED;
break;
}
if (success == NO_ERROR)
{
success = xchksum_insert_repl_log_and_demote_table_lock (thread_p, &repl_info, &class_oid);
}
(void) or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slogtb_does_active_user_exist -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slogtb_does_active_user_exist (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *user_name;
bool existed;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_string_nocopy (request, &user_name);
existed = xlogtb_does_active_user_exist (thread_p, user_name);
(void) or_pack_int (reply, (int) existed);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* slocator_redistribute_partition_data () -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
slocator_redistribute_partition_data (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
OID *oid_list;
int nr_oids;
int success = NO_ERROR;
int i;
OID class_oid;
ptr = request;
ptr = or_unpack_oid (ptr, &class_oid);
ptr = or_unpack_int (ptr, &nr_oids);
if (nr_oids < 1)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_INVALID_PARTITION_REQUEST, 0);
(void) return_error_to_client (thread_p, rid);
success = ER_INVALID_PARTITION_REQUEST;
goto end;
}
oid_list = (OID *) malloc (nr_oids * sizeof (OID));
if (oid_list == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, nr_oids * sizeof (OID));
(void) return_error_to_client (thread_p, rid);
success = ER_OUT_OF_VIRTUAL_MEMORY;
goto end;
}
for (i = 0; i < nr_oids; i++)
{
ptr = or_unpack_oid (ptr, &oid_list[i]);
}
success = xlocator_redistribute_partition_data (thread_p, &class_oid, nr_oids, oid_list);
if (oid_list != NULL)
{
free_and_init (oid_list);
}
if (success != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
end:
ptr = or_pack_int (reply, success);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
/*
* netsr_spacedb () - server-side function to get database space info
*
* return : void
* thread_p (in) : thread entry
* rid (in) : request ID
* request (in) : request data
* reqlen (in) : request data length
*/
void
netsr_spacedb (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
SPACEDB_ALL all[SPACEDB_ALL_COUNT];
SPACEDB_ONEVOL *vols = NULL;
SPACEDB_FILES files[SPACEDB_FILE_COUNT];
int get_vols = 0;
int get_files = 0;
SPACEDB_ONEVOL **volsp = NULL;
SPACEDB_FILES *filesp = NULL;
OR_ALIGNED_BUF (2 * OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *data_reply = NULL;
int data_reply_length = 0;
char *ptr;
int error_code = NO_ERROR;
/* do we need space information on all volumes? */
ptr = or_unpack_int (request, &get_vols);
if (get_vols)
{
volsp = &vols;
}
/* do we need detailed file information? */
ptr = or_unpack_int (ptr, &get_files);
if (get_files)
{
filesp = files;
}
/* get info from disk manager */
error_code = disk_spacedb (thread_p, all, volsp);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
}
else if (get_files)
{
/* get info from file manager */
error_code = file_spacedb (thread_p, filesp);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
}
}
if (error_code == NO_ERROR)
{
/* success. pack space info */
data_reply_length = or_packed_spacedb_size (all, vols, filesp);
data_reply = (char *) malloc (data_reply_length);
ptr = or_pack_spacedb (data_reply, all, vols, filesp);
assert (ptr - data_reply == data_reply_length);
}
else
{
/* error */
(void) return_error_to_client (thread_p, rid);
}
/* send result to client */
ptr = or_pack_int (reply, data_reply_length);
ptr = or_pack_int (ptr, error_code);
auto deleter = [buffer = data_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), data_reply,
data_reply_length, std::move (deleter));
if (vols != NULL)
{
free_and_init (vols);
}
}
void
slocator_demote_class_lock (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
OID class_oid;
LOCK lock, ex_lock;
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
ptr = or_unpack_oid (request, &class_oid);
ptr = or_unpack_lock (ptr, &lock);
error = xlocator_demote_class_lock (thread_p, &class_oid, lock, &ex_lock);
if (error != NO_ERROR)
{
return_error_to_client (thread_p, rid);
}
ptr = or_pack_int (reply, error);
ptr = or_pack_lock (ptr, ex_lock);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
sloaddb_init (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
packing_unpacker unpacker (request, (size_t) reqlen);
cubload::load_args args;
args.unpack (unpacker);
load_session *session = new load_session (args);
session->set_client_type (thread_p->conn_entry->client_type);
int error_code = session_set_load_session (thread_p, session);
if (error_code != NO_ERROR)
{
delete session;
}
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
or_pack_int (reply, error_code);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
sloaddb_install_class (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
packing_unpacker unpacker (request, (size_t) reqlen);
bool is_ignored = false;
cubload::batch batch;
batch.unpack (unpacker);
load_session *session = NULL;
int error_code = session_get_load_session (thread_p, session);
std::string cls_name;
if (error_code == NO_ERROR)
{
assert (session != NULL);
error_code = session->install_class (*thread_p, batch, is_ignored, cls_name);
}
else
{
if (er_errid () == NO_ERROR || !er_has_error ())
{
error_code = ER_LDR_INVALID_STATE;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 0);
}
return_error_to_client (thread_p, rid);
}
// Error code and is_ignored.
OR_ALIGNED_BUF (3 * OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int buf_sz = (int) cls_name.length ();
ptr = or_pack_int (reply, buf_sz);
ptr = or_pack_int (ptr, error_code);
ptr = or_pack_int (ptr, (is_ignored ? 1 : 0));
char *mem_cls_name = NULL;
if (buf_sz > 0)
{
mem_cls_name = (char *) malloc (cls_name.length () + 1);
std::memcpy (mem_cls_name, (char *) cls_name.c_str (), cls_name.length () + 1);
}
auto deleter = [buffer = mem_cls_name]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply),
(char *) mem_cls_name, buf_sz, std::move (deleter));
}
void
sloaddb_load_batch (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
packing_unpacker unpacker (request, (size_t) reqlen);
cubload::batch *batch = NULL;
load_status status;
packing_packer packer;
cubmem::extensible_block eb;
char *reply_data = NULL;
int reply_data_size = 0;
bool use_temp_batch = false;
unpacker.unpack_bool (use_temp_batch);
if (!use_temp_batch)
{
batch = new cubload::batch ();
batch->unpack (unpacker);
}
bool is_batch_accepted = false;
load_session *session = NULL;
session_get_load_session (thread_p, session);
int error_code = session_get_load_session (thread_p, session);
if (error_code == NO_ERROR)
{
assert (session != NULL);
error_code = session->load_batch (*thread_p, batch, use_temp_batch, is_batch_accepted, status);
packer.set_buffer_and_pack_all (eb, status);
reply_data = eb.get_ptr ();
reply_data_size = (int) packer.get_current_size ();
}
else
{
if (er_errid () == NO_ERROR || !er_has_error ())
{
error_code = ER_LDR_INVALID_STATE;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 0);
}
return_error_to_client (thread_p, rid);
}
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = or_pack_int (reply, reply_data_size);
ptr = or_pack_int (ptr, error_code);
or_pack_int (ptr, (is_batch_accepted ? 1 : 0));
char *mem_reply = NULL;
if (reply_data_size > 0)
{
mem_reply = (char *) malloc (reply_data_size);
std::memcpy (mem_reply, reply_data, reply_data_size);
}
auto deleter = [buffer = mem_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), mem_reply,
reply_data_size, std::move (deleter));
}
void
sloaddb_fetch_status (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
packing_packer packer;
cubmem::extensible_block eb;
char *buffer = NULL;
int buffer_size = 0;
load_session *session = NULL;
int error_code = session_get_load_session (thread_p, session);
if (error_code == NO_ERROR)
{
assert (session != NULL);
load_status status;
session->fetch_status (status, false);
packer.set_buffer_and_pack_all (eb, status);
buffer = eb.get_ptr ();
buffer_size = (int) packer.get_current_size ();
}
else
{
if (er_errid () == NO_ERROR || !er_has_error ())
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_LDR_INVALID_STATE, 0);
}
return_error_to_client (thread_p, rid);
}
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *mem_buffer = NULL;
or_pack_int (reply, buffer_size);
if (buffer_size > 0)
{
mem_buffer = (char *) malloc (buffer_size);
std::memcpy (mem_buffer, buffer, buffer_size);
}
auto deleter = [buffer = mem_buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), mem_buffer,
buffer_size, std::move (deleter));
}
void
sloaddb_destroy (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
load_session *session = NULL;
int error_code = session_get_load_session (thread_p, session);
if (error_code == NO_ERROR)
{
assert (session != NULL);
session->wait_for_completion ();
delete session;
session_set_load_session (thread_p, NULL);
}
if (er_errid () != NO_ERROR || er_has_error ())
{
return_error_to_client (thread_p, rid);
}
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
or_pack_int (reply, error_code);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
sloaddb_interrupt (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
load_session *session = NULL;
int error_code = session_get_load_session (thread_p, session);
if (error_code == NO_ERROR)
{
assert (session != NULL);
session->interrupt ();
}
else
{
// what to do, what to do...
}
}
void
sloaddb_update_stats (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *buffer = NULL, *ptr = NULL;
int buffer_size = 0;
int oid_cnt = 0;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
load_session *session = NULL;
int error_code = session_get_load_session (thread_p, session);
std::vector < const cubload::class_entry * >class_entries;
if (error_code != NO_ERROR)
{
goto end;
}
assert (session != NULL);
/* check disable_statistics */
if (session->get_args ().disable_statistics || session->get_args ().syntax_check)
{
error_code = NO_ERROR;
goto end;
}
session->get_class_registry ().get_all_class_entries (class_entries);
for (const cubload::class_entry *class_entry:class_entries)
{
if (!class_entry->is_ignored ())
{
oid_cnt++;
}
}
/* start packing result */
/* buffer_size is (int:number of OIDs) + size of packed OIDs */
buffer_size = OR_INT_SIZE + (oid_cnt * sizeof (OID));
buffer = (char *) malloc (buffer_size);
if (buffer == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, buffer_size);
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto end;
}
ptr = or_pack_int (buffer, oid_cnt);
for (const cubload::class_entry *class_entry:class_entries)
{
if (!class_entry->is_ignored ())
{
OID *class_oid = const_cast < OID * > (&class_entry->get_class_oid ());
ptr = or_pack_oid (ptr, class_oid);
}
}
end:
char *ptr2 = or_pack_int (reply, buffer_size);
ptr2 = or_pack_int (ptr2, error_code);
auto deleter = [buffer]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer,
buffer_size, std::move (deleter));
}
void
ssession_stop_attached_threads (THREAD_ENTRY *thread_p, void *session)
{
session_stop_attached_threads (thread_p, session);
}
static bool
cdc_check_client_connection ()
{
if (css_check_conn (&cdc_Gl.conn) == NO_ERROR)
{
/* existing connection is alive */
return true;
}
else
{
return false;
}
}
void
spl_call (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error_code = NO_ERROR;
packing_unpacker unpacker (request, (size_t) reqlen);
DB_VALUE ret_value;
db_make_null (&ret_value);
/* 1) unpack arguments */
cubpl::pl_signature sig;
std::vector < DB_VALUE > args;
unpacker.unpack_all (sig, args);
std::vector < std::reference_wrapper < DB_VALUE >> ref_args (args.begin (), args.end ());
/* 2) invoke */
cubpl::executor executor (sig);
error_code = executor.fetch_args_peek (ref_args);
if (error_code == NO_ERROR)
{
error_code = executor.execute (ret_value);
}
packing_packer packer;
cubmem::extensible_block eb;
if (error_code == NO_ERROR)
{
/* 3) pack */
packer.set_buffer_and_pack_all (eb, ret_value, executor.get_out_args ());
}
else
{
std::string err_msg;
if (executor.get_stack ())
{
err_msg = executor.get_stack ()->get_error_message ();
}
if (err_msg.empty () && error_code != ER_SP_EXECUTE_ERROR)
{
err_msg.assign (er_msg ());
}
if (error_code !=
ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, err_msg.c_str ());
}
packer.set_buffer_and_pack_all (eb, er_errid (), err_msg);
(void) return_error_to_client (thread_p, rid);
}
char *reply_data = eb.get_ptr ();
int reply_data_size = (int) packer.get_current_size ();
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, reply_data_size);
ptr = or_pack_int (ptr, error_code);
// clear
//if (top_on_stack)
// {
// top_on_stack->reset (true);
// top_on_stack->end ();
// }
char *mem_reply = NULL;
if (reply_data_size > 0)
{
mem_reply = (char *) malloc (reply_data_size);
std::memcpy (mem_reply, reply_data, reply_data_size);
}
auto deleter = [buffer = mem_reply]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), mem_reply,
reply_data_size, std::move (deleter));
/*
if (top_on_stack)
{
rctx->pop_stack (thread_p, top_on_stack);
}
*/
pr_clear_value_vector (args);
db_value_clear (&ret_value);
}
#if 0
void
smethod_invoke_fold_constants (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
packing_unpacker unpacker (request, (size_t) reqlen);
/* 1) unpack arguments */
method_sig_list sig_list;
std::vector < DB_VALUE > args;
unpacker.unpack_all (sig_list, args);
std::vector < std::reference_wrapper < DB_VALUE >> ref_args (args.begin (), args.end ());
/* 2) invoke method */
DB_VALUE ret_value;
db_make_null (&ret_value);
int error_code = xmethod_invoke_fold_constants (thread_p, sig_list, ref_args, ret_value);
cubmethod::runtime_context *rctx = cubmethod::get_rctx (thread_p);
cubmethod::method_invoke_group *top_on_stack = NULL;
if (rctx)
{
top_on_stack = rctx->top_stack ();
}
if (rctx == NULL || top_on_stack == NULL)
{
/* might be interrupted and session is already freed */
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERRUPTED, 0);
error_code = ER_INTERRUPTED;
assert (false); // oops
}
packing_packer packer;
cubmem::extensible_block eb;
if (error_code == NO_ERROR)
{
/* 3) make out arguments */
method_sig_node *sig = sig_list.method_sig;
DB_VALUE dummy_null;
db_make_null (&dummy_null);
std::vector<std::reference_wrapper<DB_VALUE>> out_args (sig->num_method_args, dummy_null);
for (int i = 0; i < sig->num_method_args; i++)
{
if (sig->arg_info->arg_mode[i] == METHOD_ARG_MODE_IN)
{
continue;
}
int pos = sig->method_arg_pos[i];
out_args[pos] = std::ref (args[pos]);
}
/* 4) pack */
packer.set_buffer_and_pack_all (eb, ret_value, out_args);
}
else
{
if (rctx->is_interrupted ())
{
rctx->set_local_error_for_interrupt ();
}
else if (error_code !=
ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, top_on_stack->get_error_msg ().c_str ());
}
else
{
// error is already set
assert (er_errid () != NO_ERROR);
}
std::string err_msg;
if (er_errid () == ER_SP_EXECUTE_ERROR)
{
err_msg.assign (top_on_stack->get_error_msg ());
}
else if (er_msg ())
{
err_msg.assign (er_msg ());
}
if (er_has_error ())
{
error_code = er_errid ();
}
packer.set_buffer_and_pack_all (eb, er_errid (), err_msg);
(void) return_error_to_client (thread_p, rid);
}
char *reply_data = eb.get_ptr ();
int reply_data_size = (int) packer.get_current_size ();
OR_ALIGNED_BUF (OR_INT_SIZE * 3) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, reply_data_size);
ptr = or_pack_int (ptr, error_code);
// clear
if (top_on_stack)
{
top_on_stack->reset (true);
top_on_stack->end ();
}
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), reply_data,
reply_data_size);
if (top_on_stack)
{
rctx->pop_stack (thread_p, top_on_stack);
}
pr_clear_value_vector (args);
db_value_clear (&ret_value);
sig_list.freemem ();
}
#endif
void
scdc_start_session (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
int error_code;
int max_log_item, extraction_timeout, all_in_cond, num_extraction_user, num_extraction_class;
uint64_t *extraction_classoids = NULL;
char **extraction_user = NULL;
char *dummy_user = NULL;
if (prm_get_integer_value (PRM_ID_SUPPLEMENTAL_LOG) == 0)
{
error_code = ER_CDC_NOT_AVAILABLE;
er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_CDC_NOT_AVAILABLE, 0);
goto error;
}
/* scdc_start_session more than once without scdc_end_session */
if (cdc_Gl.conn.fd != -1)
{
if (thread_p->conn_entry->fd != cdc_Gl.conn.fd)
{
/* check if existing connection is alive */
if (cdc_check_client_connection ())
{
cdc_log ("%s : More than two clients attempt to connect", __func__);
error_code = ER_CDC_NOT_AVAILABLE;
er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_CDC_NOT_AVAILABLE, 0);
goto error;
}
}
/* if existing session is dead, then pause loginfo producer thread (cdc). */
if (cdc_Gl.producer.state != CDC_PRODUCER_STATE_WAIT)
{
cdc_pause_producer ();
}
LSA_SET_NULL (&cdc_Gl.consumer.next_lsa);
}
cdc_Gl.conn.fd = thread_p->conn_entry->fd;
cdc_Gl.conn.status = thread_p->conn_entry->status;
ptr = or_unpack_int (request, &max_log_item);
ptr = or_unpack_int (ptr, &extraction_timeout);
ptr = or_unpack_int (ptr, &all_in_cond);
ptr = or_unpack_int (ptr, &num_extraction_user);
if (num_extraction_user > 0)
{
extraction_user = (char **) malloc (sizeof (char *) * num_extraction_user);
if (extraction_user == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (char *) * num_extraction_user);
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto error;
}
for (int i = 0; i < num_extraction_user; i++)
{
ptr = or_unpack_string_nocopy (ptr, &dummy_user);
extraction_user[i] = strdup (dummy_user);
if (extraction_user[i] == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, strlen (dummy_user));
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto error;
}
}
}
ptr = or_unpack_int (ptr, &num_extraction_class);
if (num_extraction_class > 0)
{
extraction_classoids = (UINT64 *) malloc (sizeof (UINT64) * num_extraction_class);
if (extraction_classoids == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1,
sizeof (UINT64) * num_extraction_class);
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto error;
}
for (int i = 0; i < num_extraction_class; i++)
{
ptr = or_unpack_int64 (ptr, (INT64 *) & extraction_classoids[i]);
}
}
cdc_log
("%s : max_log_item (%d), extraction_timeout (%d), all_in_cond (%d), num_extraction_user (%d), num_extraction_class (%d)",
__func__, max_log_item, extraction_timeout, all_in_cond, num_extraction_user, num_extraction_class);
error_code =
cdc_set_configuration (max_log_item, extraction_timeout, all_in_cond, extraction_user, num_extraction_user,
extraction_classoids, num_extraction_class);
if (error_code != NO_ERROR)
{
goto error;
}
or_pack_int (reply, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
error:
if (extraction_user != NULL)
{
for (int i = 0; i < num_extraction_user; i++)
{
if (extraction_user[i] != NULL)
{
free_and_init (extraction_user[i]);
}
}
free_and_init (extraction_user);
}
if (extraction_classoids != NULL)
{
free_and_init (extraction_classoids);
}
or_pack_int (reply, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
void
scdc_find_lsa (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE + OR_LOG_LSA_ALIGNED_SIZE + OR_INT64_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
LOG_LSA start_lsa;
time_t input_time;
int error_code;
ptr = or_unpack_int64 (request, &input_time);
//if scdc_find_lsa() is called more than once, it should pause running cdc_loginfo_producer_execute() thread
cdc_log ("%s : input time (%lld)", __func__, input_time);
error_code = cdc_find_lsa (thread_p, &input_time, &start_lsa);
if (error_code == NO_ERROR || error_code == ER_CDC_ADJUSTED_LSA)
{
// check producer is sleep, and if not
// make producer sleep, and producer request consumer to be sleep
// if request is set to consumer to be sleep, go into spinlock
// checks request is set to none, then if it is none,
if (cdc_Gl.producer.state != CDC_PRODUCER_STATE_WAIT)
{
cdc_pause_producer ();
}
cdc_set_extraction_lsa (&start_lsa);
cdc_reinitialize_queue (&start_lsa);
cdc_wakeup_producer ();
ptr = or_pack_int (reply, error_code);
ptr = or_pack_log_lsa (ptr, &start_lsa);
or_pack_int64 (ptr, input_time);
cdc_log ("%s : reply contains start lsa (%lld|%d), output time (%lld)", __func__, LSA_AS_ARGS (&start_lsa),
input_time);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
else
{
goto error;
}
error:
or_pack_int (reply, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
scdc_get_loginfo_metadata (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE * 3 + OR_LOG_LSA_ALIGNED_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
LOG_LSA start_lsa;
LOG_LSA next_lsa;
int total_length;
char *log_info_list;
int error_code = NO_ERROR;
int num_log_info;
int rc;
or_unpack_log_lsa (request, &start_lsa);
cdc_log ("%s : request from client contains start_lsa (%lld|%d)", __func__, LSA_AS_ARGS (&start_lsa));
if (LSA_ISNULL (&cdc_Gl.consumer.next_lsa))
{
/* if server is restarted while cdc is running, and client immediately calls extraction without scdc_find_lsa() */
error_code = cdc_validate_lsa (thread_p, &start_lsa);
if (error_code != NO_ERROR)
{
goto error;
}
cdc_set_extraction_lsa (&start_lsa);
cdc_reinitialize_queue (&start_lsa);
cdc_wakeup_producer ();
}
if (LSA_EQ (&cdc_Gl.consumer.next_lsa, &start_lsa))
{
error_code = cdc_make_loginfo (thread_p, &start_lsa);
if (error_code != NO_ERROR)
{
goto error;
}
error_code = cdc_get_loginfo_metadata (&next_lsa, &total_length, &num_log_info);
if (error_code != NO_ERROR)
{
goto error;
}
}
else if (LSA_EQ (&cdc_Gl.consumer.start_lsa, &start_lsa))
{
/* Send again; only the case, where cdc client re-request loginfo metadata requested last time due to a problem like shutdown, will be dealt. */
error_code = cdc_get_loginfo_metadata (&next_lsa, &total_length, &num_log_info);
if (error_code != NO_ERROR)
{
goto error;
}
}
else
{
_er_log_debug (ARG_FILE_LINE,
"requested extract lsa is (%lld | %d) is not in a range of previously requested lsa (%lld | %d) and next lsa to extract (%lld | %d)",
LSA_AS_ARGS (&start_lsa), LSA_AS_ARGS (&cdc_Gl.consumer.start_lsa),
LSA_AS_ARGS (&cdc_Gl.consumer.next_lsa));
er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_CDC_INVALID_LOG_LSA, 1, LSA_AS_ARGS (&start_lsa));
error_code = ER_CDC_INVALID_LOG_LSA;
goto error;
}
ptr = or_pack_int (reply, error_code);
ptr = or_pack_log_lsa (ptr, &next_lsa);
ptr = or_pack_int (ptr, num_log_info);
ptr = or_pack_int (ptr, total_length);
cdc_log ("%s : reply contains next lsa (%lld|%d), num log info (%d), total length (%d)", __func__,
LSA_AS_ARGS (&next_lsa), num_log_info, total_length);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
error:
or_pack_int (reply, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
void
scdc_get_loginfo (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
cdc_log ("%s : size of log info is %d", __func__, cdc_Gl.consumer.log_info_size);
(void) css_send_data_to_client (thread_p->conn_entry, rid, cdc_Gl.consumer.log_info, cdc_Gl.consumer.log_info_size);
return;
}
void
scdc_end_session (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int error_code;
error_code = cdc_cleanup ();
cdc_log ("%s : clean up for cdc thread has done.", __func__);
cdc_Gl.conn.fd = -1;
cdc_Gl.conn.status = CONN_CLOSED;
or_pack_int (reply, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
void
sflashback_get_summary (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *area = NULL;
int area_size = 0;
int error_code = NO_ERROR;
char *ptr;
char *start_ptr;
char *num_ptr; //pointer in which 'number of summary' is located
int tmp_num = 0;
LC_FIND_CLASSNAME status;
FLASHBACK_SUMMARY_CONTEXT context = { LSA_INITIALIZER, LSA_INITIALIZER, NULL, 0, 0, };
time_t start_time = 0;
time_t end_time = 0;
char *classname = NULL;
error_code = flashback_initialize (thread_p);
if (error_code != NO_ERROR)
{
goto error;
}
ptr = or_unpack_int (request, &context.num_class);
for (int i = 0; i < context.num_class; i++)
{
OID classoid = OID_INITIALIZER;
ptr = or_unpack_string_nocopy (ptr, &classname);
status = xlocator_find_class_oid (thread_p, classname, &classoid, NULL_LOCK);
if (status != LC_CLASSNAME_EXIST)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_FLASHBACK_INVALID_CLASS, 1, classname);
error_code = ER_FLASHBACK_INVALID_CLASS;
goto error;
}
context.classoids.emplace_back (classoid);
}
ptr = or_unpack_string_nocopy (ptr, &context.user);
ptr = or_unpack_int64 (ptr, &start_time);
ptr = or_unpack_int64 (ptr, &end_time);
error_code = flashback_verify_time (thread_p, &start_time, &end_time, &context.start_lsa, &context.end_lsa);
if (error_code != NO_ERROR)
{
goto error;
}
assert (!LSA_ISNULL (&context.start_lsa));
flashback_set_min_log_pageid_to_keep (&context.start_lsa);
/* get summary list */
error_code = flashback_make_summary_list (thread_p, &context);
if (error_code != NO_ERROR)
{
goto error;
}
/* area : | class oid list | summary start time | summary end time | num summary | summary entry list |
* summary entry : | trid | user | start/end time | num insert/update/delete | num class | class oid list |
* OR_OID_SIZE * context.num_class means maximum class oid list size per summary entry */
area_size = OR_OID_SIZE * context.num_class + OR_INT64_SIZE + OR_INT64_SIZE + OR_INT_SIZE
+ (OR_SUMMARY_ENTRY_SIZE_WITHOUT_CLASS + OR_OID_SIZE * context.num_class) * context.num_summary;
area = (char *) malloc (area_size);
if (area == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, area_size);
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto error;
}
/* reply packing : error_code | area size */
ptr = or_pack_int (reply, area_size);
ptr = or_pack_int (ptr, error_code);
/* area packing : OID list | num summary | summary info list */
ptr = area;
for (auto iter : context.classoids)
{
ptr = or_pack_oid (ptr, &iter);
}
ptr = or_pack_int64 (ptr, start_time);
ptr = or_pack_int64 (ptr, end_time);
num_ptr = ptr;
ptr = or_pack_int (ptr, context.num_summary);
ptr = flashback_pack_summary_entry (ptr, context, &tmp_num);
if (context.num_summary != tmp_num)
{
or_pack_int (num_ptr, tmp_num);
}
deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
error_code =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
area_size, std::move (deleter));
if (error_code != NO_ERROR)
{
goto css_send_error;
}
return;
error:
if (error_code == ER_FLASHBACK_INVALID_CLASS)
{
ptr = or_pack_int (reply, strlen (classname));
or_pack_int (ptr, error_code);
char *mem_classname = (char *) malloc (strlen (classname) + 1);
std::memcpy (mem_classname, classname, strlen (classname) + 1);
deleter = [buffer = mem_classname]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), mem_classname,
strlen (classname), std::move (deleter));
}
else if (error_code == ER_FLASHBACK_INVALID_TIME)
{
area = (char *) malloc (OR_INT64_SIZE);
ptr = or_pack_int (reply, OR_INT64_SIZE);
or_pack_int (ptr, error_code);
or_pack_int64 (area, log_Gl.hdr.db_creation);
deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
OR_INT64_SIZE, std::move (deleter));
}
else
{
ptr = or_pack_int (reply, 0);
or_pack_int (ptr, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
if (error_code != ER_FLASHBACK_DUPLICATED_REQUEST)
{
/* if flashback variables are reset by duplicated request error,
* variables for existing connection (valid connection) can be reset */
flashback_reset ();
}
return;
css_send_error:
flashback_reset ();
return;
}
void
sflashback_get_loginfo (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
std::function<void ()> deleter;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *area = NULL;
int area_size = 0;
int error_code = NO_ERROR;
char *ptr;
char *start_ptr;
int threshold_to_remove_archive = 0;
FLASHBACK_LOGINFO_CONTEXT context = { -1, NULL, LSA_INITIALIZER, LSA_INITIALIZER, 0, 0, false, 0, OID_INITIALIZER, };
/* request : trid | user | num_class | table oid list | start_lsa | end_lsa | num_item | forward/backward */
ptr = or_unpack_int (request, &context.trid);
ptr = or_unpack_string_nocopy (ptr, &context.user);
ptr = or_unpack_int (ptr, &context.num_class);
for (int i = 0; i < context.num_class; i++)
{
OID classoid;
ptr = or_unpack_oid (ptr, &classoid);
context.classoid_set.emplace (classoid);
}
ptr = or_unpack_log_lsa (ptr, &context.start_lsa);
ptr = or_unpack_log_lsa (ptr, &context.end_lsa);
ptr = or_unpack_int (ptr, &context.num_loginfo);
ptr = or_unpack_int (ptr, &context.forward);
error_code = flashback_make_loginfo (thread_p, &context);
if (error_code != NO_ERROR)
{
goto error;
}
area_size = OR_LOG_LSA_ALIGNED_SIZE * 2 + OR_INT_SIZE;
/* log info entries are chunks of memory that already packed together, and they need to be aligned
* | lsa | lsa | num item | align | log info 1 | align | log info 2 | align | log info 3 | ..
* */
area_size += context.queue_size + context.num_loginfo * MAX_ALIGNMENT;
area = (char *) malloc (area_size);
if (area == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, area_size);
error_code = ER_OUT_OF_VIRTUAL_MEMORY;
goto error;
}
/* reply packing : area size | error_code */
ptr = or_pack_int (reply, area_size);
or_pack_int (ptr, error_code);
/* area packing : start lsa | end lsa | num item | item list */
ptr = or_pack_log_lsa (area, &context.start_lsa);
ptr = or_pack_log_lsa (ptr, &context.end_lsa);
ptr = or_pack_int (ptr, context.num_loginfo);
ptr = flashback_pack_loginfo (thread_p, ptr, context);
deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
error_code =
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
area_size, std::move (deleter));
if (error_code != NO_ERROR)
{
goto css_send_error;
}
if (flashback_is_loginfo_generation_finished (&context.start_lsa, &context.end_lsa))
{
flashback_reset ();
}
else
{
if (context.forward)
{
/* start_lsa is increased only if direction is forward */
flashback_set_min_log_pageid_to_keep (&context.start_lsa);
}
}
return;
error:
if (error_code == ER_FLASHBACK_SCHEMA_CHANGED)
{
area = (char *) malloc (OR_OID_SIZE);
ptr = or_pack_int (reply, OR_OID_SIZE);
or_pack_int (ptr, error_code);
or_pack_oid (area, &context.invalid_class);
deleter = [buffer = area]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), area,
OR_OID_SIZE, std::move (deleter));
}
else
{
ptr = or_pack_int (reply, 0);
or_pack_int (ptr, error_code);
(void) css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
flashback_reset ();
return;
css_send_error:
flashback_reset ();
return;
}
void
splcsql_transfer_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error = ER_FAILED;
PLCSQL_COMPILE_REQUEST compile_request;
packing_unpacker unpacker (request, (size_t) reqlen);
unpacker.unpack_all (compile_request);
cubmem::extensible_block ext_blk;
cubpl::compile_handler compile_handler;
error = compile_handler.compile (compile_request, ext_blk);
OR_ALIGNED_BUF (3 * OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr = or_pack_int (reply, (int) END_CALLBACK);
ptr = or_pack_int (ptr, ext_blk.get_size ());
ptr = or_pack_int (ptr, error);
char *mem_ext_blk = NULL;
if (ext_blk.get_size () > 0)
{
mem_ext_blk = (char *) malloc (ext_blk.get_size ());
std::memcpy (mem_ext_blk, ext_blk.get_ptr (), ext_blk.get_size ());
}
auto deleter = [buffer = mem_ext_blk]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply),
mem_ext_blk, ext_blk.get_size (), std::move (deleter));
}
/*
* smmon_get_server_info - get memory usage info from memory monitor
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*/
void
smmon_get_server_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *buffer_a = NULL, *buffer, *ptr;
int size = 0;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int error = NO_ERROR;
#if !defined(WINDOWS)
MMON_SERVER_INFO server_info;
if (mmon_is_memory_monitor_enabled ())
{
mmon_aggregate_server_info (server_info);
}
else
{
_er_log_debug (ARG_FILE_LINE, "Memory monitor is already disabled by cubrid memmon --disable-force.\n");
error = ER_FAILED;
goto end;
}
// Size of server name
size += or_packed_string_length (server_info.server_name, NULL);
size = size % MAX_ALIGNMENT ? size + INT_ALIGNMENT : size;
// Size of total_mem_usage
size += OR_INT64_SIZE;
// Size of total_metainfo_mem_usage
size += OR_INT64_SIZE;
// Size of num_stat
size += OR_INT_SIZE;
// Size of stat name and memory usage
for (const auto &s_info : server_info.stat_info)
{
// Size of filename
size += or_packed_string_length (s_info.first.c_str (), NULL);
size = size % MAX_ALIGNMENT ? size + INT_ALIGNMENT : size;
// Size of memory usage
size += OR_INT64_SIZE;
}
buffer_a = (char *) malloc (size + MAX_ALIGNMENT);
if (buffer_a == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, size);
error = ER_OUT_OF_VIRTUAL_MEMORY;
}
else
{
buffer = PTR_ALIGN (buffer_a, MAX_ALIGNMENT);
ptr = buffer;
ptr = or_pack_string (ptr, server_info.server_name);
ptr = or_pack_int64 (ptr, server_info.total_mem_usage);
ptr = or_pack_int64 (ptr, server_info.total_metainfo_mem_usage);
ptr = or_pack_int (ptr, server_info.num_stat);
for (const auto &s_info : server_info.stat_info)
{
ptr = or_pack_string (ptr, s_info.first.c_str ());
ptr = or_pack_int64 (ptr, s_info.second);
}
assert (size == (int) (ptr - buffer));
}
end:
if (error != NO_ERROR)
{
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
free (buffer_a);
}
else
{
ptr = or_pack_int (reply, size);
ptr = or_pack_int (ptr, error);
auto deleter = [buffer = buffer_a]() noexcept
{
if (buffer != NULL)
{
free (buffer);
}
};
css_send_reply_and_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply), buffer, size,
std::move (deleter));
}
#else // WINDOWS
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_SUPPORTED_OPERATION, 0);
error = ER_INTERFACE_NOT_SUPPORTED_OPERATION;
// send error
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
#endif // !WINDOWS
}
/*
* smmon_disable_force - disable memory_monitor forcely
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*/
void
smmon_disable_force (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE + OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
int error = NO_ERROR;
#if !defined(WINDOWS)
mmon_disabled = true;
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
#else // WINDOWS
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_INTERFACE_NOT_SUPPORTED_OPERATION, 0);
error = ER_INTERFACE_NOT_SUPPORTED_OPERATION;
// send error
ptr = or_pack_int (reply, 0);
ptr = or_pack_int (ptr, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
#endif // !WINDOWS
}
/*
* stdes_set_query_start_info - set the start time and sql text of the transaction
* thread_p(in): the thread pointer
* rid(in): the request id
* request(in): the request
* reqlen(in): the request length
*/
void
stdes_set_query_start_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *sql_user_text = NULL;
int tran_index = -1;
LOG_TDES *tdes_p;
or_unpack_string_nocopy (request, &sql_user_text);
tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
tdes_p = LOG_FIND_TDES (tran_index);
assert (tdes_p != NULL);
if (tdes_p)
{
tdes_p->query_start_time = log_get_clock_msec ();
if (tdes_p->tran_start_time == 0)
{
tdes_p->tran_start_time = tdes_p->query_start_time;
}
if (sql_user_text)
{
tdes_p->ddl_sql_user_text = strdup (sql_user_text);
}
}
css_send_data_to_client (thread_p->conn_entry, rid, NULL, 0);
}
/*
* stdes_reset_query_start_info - reset the query start time if the statement is a DDL statement
* thread_p(in): the thread pointer
* rid(in): the request id
* request(in): the request
* reqlen(in): the request length
*/
void
stdes_reset_query_start_info (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int tran_index = -1;
LOG_TDES *tdes_p;
tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
tdes_p = LOG_FIND_TDES (tran_index);
assert (tdes_p != NULL);
if (tdes_p)
{
tdes_p->query_start_time = 0;
if (tdes_p->ddl_sql_user_text != NULL)
{
free_and_init (tdes_p->ddl_sql_user_text);
}
}
css_send_data_to_client (thread_p->conn_entry, rid, NULL, 0);
}
/*
* slob_create_dir - Called when a request is sent from the client to the server.
* Invokes xlob_create_dir() to create the LOB directory
*
* thread_p(in): the thread pointer
* rid(in): the request id
* request(in): the request
* reqlen(in): the request length
*/
void
slob_create_dir (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
HFID hfid;
int *attrid_arr = NULL;
int attrid_arr_length = 0;
int error = NO_ERROR;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_int (ptr, &attrid_arr_length);
ptr = or_unpack_int_array (ptr, attrid_arr_length, &attrid_arr);
error = xlob_create_dir (thread_p, &hfid, attrid_arr, attrid_arr_length);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
db_private_free_and_init (thread_p, attrid_arr);
ptr = or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
/*
* slob_remove_dir - Called when a request is sent from the client to the server.
* Invokes xlob_remove_dir() to remove the LOB directory
*
* thread_p(in): the thread pointer
* rid(in): the request id
* request(in): the request
* reqlen(in): the request length
*/
void
slob_remove_dir (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
char *ptr;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
HFID hfid;
int attrid;
int error = NO_ERROR;
ptr = or_unpack_hfid (request, &hfid);
ptr = or_unpack_int (ptr, &attrid);
error = xlob_remove_dir (thread_p, &hfid, attrid);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
return;
}
/*
* sfile_tracker_dump_file_list -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sfile_tracker_dump_file_list (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
FILE *outfp;
int file_size;
char *buffer;
int buffer_size;
int send_size;
int invalid_only;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
ptr = or_unpack_int (request, &buffer_size);
ptr = or_unpack_int (ptr, &invalid_only);
buffer = (char *) db_private_alloc (thread_p, buffer_size);
if (buffer == NULL)
{
css_send_abort_to_client (thread_p->conn_entry, rid);
return;
}
outfp = tmpfile ();
if (outfp == NULL)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
db_private_free_and_init (thread_p, buffer);
return;
}
xfile_tracker_dump_file_list (thread_p, outfp, (bool) invalid_only);
file_size = ftell (outfp);
/*
* Send the file in pieces
*/
rewind (outfp);
(void) or_pack_int (reply, (int) file_size);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
while (file_size > 0)
{
if (file_size > buffer_size)
{
send_size = buffer_size;
}
else
{
send_size = file_size;
}
file_size -= send_size;
if (fread (buffer, 1, send_size, outfp) == 0)
{
er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
css_send_abort_to_client (thread_p->conn_entry, rid);
/*
* Continue sending the stuff that was prmoised to client. In this case
* junk (i.e., whatever it is in the buffers) is sent.
*/
}
css_send_data_to_client (thread_p->conn_entry, rid, buffer, send_size);
}
fclose (outfp);
db_private_free_and_init (thread_p, buffer);
}
/*
* sfile_tracker_clean_invalid_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sfile_tracker_clean_invalid_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int heap = 0, heap_ovf = 0, btree = 0, btree_ovf = 0;
int error;
OR_ALIGNED_BUF (OR_INT_SIZE * 5) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
char *ptr;
error = xfile_tracker_clean_invalid_file (thread_p, &heap, &heap_ovf, &btree, &btree_ovf);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
ptr = or_pack_errcode (reply, error);
ptr = or_pack_int (ptr, heap);
ptr = or_pack_int (ptr, heap_ovf);
ptr = or_pack_int (ptr, btree);
ptr = or_pack_int (ptr, btree_ovf);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
#if !defined(NDEBUG)
/*
* sfile_tracker_delete_target_file -
*
* return:
*
* rid(in):
* request(in):
* reqlen(in):
*
* NOTE:
*/
void
sfile_tracker_delete_target_file (THREAD_ENTRY *thread_p, unsigned int rid, char *request, int reqlen)
{
int error;
char *target_vfid_str;
OR_ALIGNED_BUF (OR_INT_SIZE) a_reply;
char *reply = OR_ALIGNED_BUF_START (a_reply);
(void) or_unpack_string_nocopy (request, &target_vfid_str);
error = xfile_tracker_delete_target_file (thread_p, target_vfid_str);
if (error != NO_ERROR)
{
(void) return_error_to_client (thread_p, rid);
}
(void) or_pack_errcode (reply, error);
css_send_data_to_client (thread_p->conn_entry, rid, reply, OR_ALIGNED_BUF_SIZE (a_reply));
}
#endif