mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
9.5 KiB
392 lines
9.5 KiB
#ifndef __CLASS_PTR_ARRAY_H
|
|
#define __CLASS_PTR_ARRAY_H
|
|
|
|
#include <memory>
|
|
#include <queue>
|
|
#include "proxysql.h"
|
|
#include "sqlite3db.h"
|
|
|
|
#define MIN_ARRAY_LEN 8
|
|
#define MIN_ARRAY_DELETE_RATIO 8
|
|
|
|
static unsigned int l_near_pow_2 (unsigned int n) {
|
|
unsigned int i = 1;
|
|
while (i < n) i <<= 1;
|
|
return i ? i : n;
|
|
}
|
|
|
|
|
|
#ifndef def_fastrand
|
|
inline int fastrand() {
|
|
g_seed = (214013*g_seed+2531011);
|
|
return (g_seed>>16)&0x7FFF;
|
|
}
|
|
#define def_fastrand
|
|
#endif
|
|
|
|
class PtrArray {
|
|
private:
|
|
void expand(unsigned int more) {
|
|
if ( (len+more) > size ) {
|
|
unsigned int new_size=l_near_pow_2(len+more);
|
|
void *new_pdata=malloc(new_size*sizeof(void *));
|
|
memset(new_pdata,0,new_size*sizeof(void *));
|
|
if (pdata) {
|
|
memcpy(new_pdata,pdata,size*sizeof(void *));
|
|
free(pdata);
|
|
}
|
|
size=new_size;
|
|
pdata=(void **)new_pdata;
|
|
}
|
|
}
|
|
void shrink() {
|
|
unsigned int new_size=l_near_pow_2(len+1);
|
|
pdata=(void **)realloc(pdata,new_size*sizeof(void *));
|
|
size=new_size;
|
|
}
|
|
public:
|
|
unsigned int len;
|
|
unsigned int size;
|
|
void **pdata;
|
|
PtrArray(unsigned int __size=0) {
|
|
len=0;
|
|
pdata=NULL;
|
|
size=0;
|
|
if (__size) {
|
|
expand(__size);
|
|
}
|
|
size=__size;
|
|
}
|
|
~PtrArray() {
|
|
if (pdata) ( free(pdata) );
|
|
pdata=NULL;
|
|
}
|
|
|
|
void reset() {
|
|
len=0;
|
|
if (pdata) ( free(pdata) );
|
|
pdata=NULL;
|
|
size=0;
|
|
}
|
|
|
|
void *index(unsigned int i) { return pdata[i];}
|
|
|
|
void add(void *p) {
|
|
if (len==size) {
|
|
expand(1);
|
|
}
|
|
pdata[len++]=p;
|
|
}
|
|
|
|
bool remove(void *p) {
|
|
unsigned int i;
|
|
for (i=0; i<len; i++) {
|
|
if (pdata[i]==p) {
|
|
remove_index(i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void * remove_index(unsigned int i) {
|
|
void *r=pdata[i];
|
|
if (i != (len-1)) {
|
|
memmove((void **)pdata+i,(void **)pdata+i+1,(len-i-1)*sizeof(void *));
|
|
}
|
|
len--;
|
|
if ( ( len>MIN_ARRAY_LEN ) && ( size > len*MIN_ARRAY_DELETE_RATIO ) ) {
|
|
shrink();
|
|
}
|
|
return r;
|
|
}
|
|
|
|
bool remove_fast(void *p) {
|
|
unsigned int i;
|
|
for (i=0; i<len; i++) {
|
|
if (pdata[i]==p) {
|
|
remove_index_fast(i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void * remove_index_fast(unsigned int i) {
|
|
void *r=pdata[i];
|
|
if (i != (len-1))
|
|
pdata[i]=pdata[len-1];
|
|
len--;
|
|
if ( ( len>MIN_ARRAY_LEN ) && ( size > len*MIN_ARRAY_DELETE_RATIO ) ) {
|
|
//shrink(); // FIXME: when shrink is called, is r invalid ??
|
|
}
|
|
return r;
|
|
}
|
|
};
|
|
|
|
|
|
class PtrSizeArray {
|
|
private:
|
|
void expand(unsigned int);
|
|
void shrink();
|
|
public:
|
|
void * operator new(size_t);
|
|
void operator delete(void *);
|
|
unsigned int len;
|
|
unsigned int size;
|
|
PtrSize_t *pdata;
|
|
PtrSizeArray(unsigned int __size=0);
|
|
~PtrSizeArray();
|
|
|
|
void add(void *p, unsigned int s) {
|
|
if (len==size) {
|
|
expand(1);
|
|
}
|
|
pdata[len].ptr=p;
|
|
pdata[len].size=s;
|
|
len++;
|
|
//#ifdef DEBUG
|
|
// mysql_hdr *m=(mysql_hdr *)p;
|
|
// fprintf(stderr,"%u %u\n", m->pkt_id, m->pkt_length);
|
|
//#endif /* DEBUG */
|
|
};
|
|
|
|
void remove_index(unsigned int i, PtrSize_t *ps) {
|
|
if (ps) {
|
|
ps->ptr=pdata[i].ptr;
|
|
ps->size=pdata[i].size;
|
|
}
|
|
if (i != (len-1)) {
|
|
memmove(pdata+i,pdata+i+1,(len-i-1)*sizeof(PtrSize_t));
|
|
}
|
|
len--;
|
|
};
|
|
|
|
void remove_index_range(unsigned int i, unsigned int s) {
|
|
if (i != (len-s)) {
|
|
memmove(pdata+i,pdata+i+s,(len-i-s)*sizeof(PtrSize_t));
|
|
}
|
|
len-=s;
|
|
};
|
|
|
|
void remove_index_fast(unsigned int, PtrSize_t *);
|
|
void copy_add(PtrSizeArray *, unsigned int, unsigned int);
|
|
|
|
PtrSize_t * index(unsigned int i) {
|
|
return &pdata[i];
|
|
}
|
|
unsigned int total_size(unsigned int _min_size=0) {
|
|
unsigned int intsize=0;
|
|
unsigned int i=0;
|
|
for (i = 0 ; i < len ; i++) {
|
|
PtrSize_t *pts = index(i);
|
|
if (pts->size > _min_size) {
|
|
intsize += pts->size;
|
|
} else {
|
|
intsize += _min_size;
|
|
}
|
|
}
|
|
return intsize;
|
|
}
|
|
};
|
|
|
|
struct buffer_t {
|
|
void * data = nullptr;
|
|
size_t len = 0;
|
|
size_t capacity = 0;
|
|
};
|
|
|
|
class FixedSizeQueue : public std::queue<buffer_t> {
|
|
private:
|
|
using std::queue<buffer_t>::push;
|
|
using std::queue<buffer_t>::emplace;
|
|
using std::queue<buffer_t>::swap;
|
|
size_t _max_size = 0;
|
|
|
|
public:
|
|
FixedSizeQueue() = default;
|
|
FixedSizeQueue(size_t max_size) : _max_size(max_size) {}
|
|
~FixedSizeQueue() {
|
|
while (empty() == false) {
|
|
auto& node = front();
|
|
l_free(node.len, node.data);
|
|
pop();
|
|
}
|
|
}
|
|
|
|
inline
|
|
size_t get_max_size() const {
|
|
return _max_size;
|
|
}
|
|
|
|
void set_max_size(size_t max_size) {
|
|
if (_max_size == max_size)
|
|
return;
|
|
|
|
_max_size = max_size;
|
|
|
|
if (size() > max_size) {
|
|
while (size() != max_size) {
|
|
auto& node = front();
|
|
l_free(node.len, node.data);
|
|
pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
// using template here to create compile-time separate definition of push, one for true and one for false
|
|
template<bool ALLOC_MEM = true>
|
|
void push(void* buff, size_t len) {
|
|
if (_max_size == 0) return;
|
|
assert(buff && len);
|
|
|
|
buffer_t mybuff;
|
|
|
|
if (size() == _max_size) {
|
|
mybuff = front();
|
|
pop();
|
|
}
|
|
|
|
if (ALLOC_MEM == true) {
|
|
if (mybuff.capacity < len) {
|
|
if (mybuff.data) free(mybuff.data);
|
|
|
|
mybuff.data = l_alloc(len);
|
|
mybuff.capacity = len;
|
|
}
|
|
|
|
memcpy(mybuff.data, buff, len);
|
|
mybuff.len = len;
|
|
|
|
} else {
|
|
if (mybuff.data) free(mybuff.data);
|
|
|
|
mybuff.data = buff;
|
|
mybuff.capacity = mybuff.len = len;
|
|
}
|
|
|
|
emplace(mybuff);
|
|
}
|
|
};
|
|
|
|
#endif /* __CLASS_PTR_ARRAY_H */
|
|
|
|
|
|
|
|
#ifndef __GEN_FUNCTIONS
|
|
#define __GEN_FUNCTIONS
|
|
|
|
#ifdef __APPLE__
|
|
#include <sys/types.h>
|
|
#include <sys/_types/_timespec.h>
|
|
#include <mach/mach.h>
|
|
#include <mach/clock.h>
|
|
#include <mach/mach_time.h>
|
|
|
|
#ifndef mach_time_h
|
|
#define mach_time_h
|
|
#ifndef CLOCK_MONOTONIC
|
|
#define CLOCK_MONOTONIC SYSTEM_CLOCK
|
|
#endif // CLOCK_MONOTONIC
|
|
|
|
static void clock_gettime(int clk_id, struct timespec *tp) {
|
|
clock_serv_t cclock;
|
|
mach_timespec_t mts;
|
|
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
|
//retval = clock_get_time(cclock, &mts);
|
|
mach_port_deallocate(mach_task_self(), cclock);
|
|
tp->tv_sec = mts.tv_sec;
|
|
tp->tv_nsec = mts.tv_nsec;
|
|
}
|
|
#endif /* mach_time_t */
|
|
#endif /* __APPLE__ */
|
|
|
|
|
|
inline unsigned long long monotonic_time() {
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return (((unsigned long long) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000);
|
|
}
|
|
|
|
inline unsigned long long realtime_time() {
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
return (((unsigned long long) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000);
|
|
}
|
|
|
|
template<int FACTOR, typename T>
|
|
inline T overflow_safe_multiply(T val) {
|
|
static_assert(std::is_integral<T>::value, "T must be an integer type.");
|
|
static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type.");
|
|
static_assert(FACTOR > 0, "Negative factors are not supported.");
|
|
|
|
if constexpr (FACTOR == 0) return 0;
|
|
if (val == 0) return 0;
|
|
if (val > std::numeric_limits<T>::max() / FACTOR) return std::numeric_limits<T>::max();
|
|
return (val * FACTOR);
|
|
}
|
|
|
|
/*
|
|
* @brief Reads and converts a big endian 32-bit unsigned integer from the provided packet buffer into the destination pointer.
|
|
*
|
|
* This function is used to extract the big endian 32-bit unsigned integer value at the specified position in a given
|
|
* packet buffer, and stores it in the destination pointer passed as an argument.
|
|
*
|
|
* @param[in] pkt A pointer to the start of the input packet buffer from which to read the 32-bit integer.
|
|
*
|
|
* @param[out] dst_p A pointer where the extracted big endian 32-bit unsigned integer value will be stored.
|
|
*/
|
|
inline bool get_uint32be(const unsigned char* pkt, uint32_t* dst_p) {
|
|
*dst_p = ((uint32_t)pkt[0] << 24) |
|
|
((uint32_t)pkt[1] << 16) |
|
|
((uint32_t)pkt[2] << 8) |
|
|
((uint32_t)pkt[3]);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Extracts a 16-bit unsigned integer from a packet and stores it in the provided destination pointer.
|
|
*
|
|
* This function reads two bytes from the packet `pkt` starting from the beginning, interprets them as a big-endian unsigned 16-bit integer,
|
|
* and stores the result into the memory location pointed to by `dst_p`. It consistently returns true to indicate successful execution.
|
|
*
|
|
* @param pkt Pointer to the packet data (array of unsigned chars) from which the 16-bit integer will be extracted.
|
|
* The caller must ensure this pointer is valid and points to at least two bytes of data.
|
|
* @param dst_p Pointer to a uint16_t variable where the extracted integer will be stored. The caller must ensure that
|
|
* this pointer is valid and points to a uint16_t variable.
|
|
*
|
|
* @return Always returns true to indicate success.
|
|
*
|
|
* @note This function uses big-endian byte order (network byte order) for interpreting the packet data.
|
|
* It is assumed that the packet buffer `pkt` contains at least two bytes (the size of a uint16_t).
|
|
* The function uses post-increment to move the reading position after extracting each byte.
|
|
*/
|
|
inline bool get_uint16be(const unsigned char* pkt, uint16_t* dst_p) {
|
|
*dst_p = ((uint16_t)pkt[0] << 8) |
|
|
((uint16_t)pkt[1]);
|
|
return true;
|
|
}
|
|
|
|
#endif /* __GEN_FUNCTIONS */
|
|
|
|
bool Proxy_file_exists(const char *);
|
|
bool Proxy_file_regular(const char *);
|
|
|
|
char *escape_string_single_quotes(char *input, bool free_it);
|
|
int remove_spaces(const char *);
|
|
char *trim_spaces_in_place(char *str);
|
|
char *trim_spaces_and_quotes_in_place(char *str);
|
|
bool mywildcmp(const char *p, const char *str);
|
|
std::string trim(const std::string& s);
|
|
char* escape_string_single_quotes_and_backslashes(char* input, bool free_it);
|
|
const char* escape_string_backslash_spaces(const char* input);
|
|
|
|
/**
|
|
* @brief Helper function that converts a MYSQL_RES into a 'SQLite3_result'.
|
|
* @param resultset The resultset to be converted into a 'SQLite3_result'.
|
|
* @return An 'unique_ptr' holding the resulting 'SQLite3_result'.
|
|
*/
|
|
std::unique_ptr<SQLite3_result> get_SQLite3_resulset(MYSQL_RES* resultset);
|
|
|
|
std::vector<std::string> split_string(const std::string& str, char delimiter);
|