trigger type 2

This commit is contained in:
2023-02-23 07:59:34 +08:00
parent 64d4e3dd9a
commit 84105347fc
16 changed files with 197 additions and 48 deletions
+7
View File
@@ -148,7 +148,14 @@ struct StoredProcedurePayload {
Context* cxt;
};
struct StoredProcedurePayloadCond {
StoredProcedure *condition;
StoredProcedure *action;
Context* cxt;
};
int execTriggerPayload(void*);
int execTriggerPayloadCond(void*);
#ifdef _WIN32
#define __DLLEXPORT__ __declspec(dllexport) __stdcall
+69 -6
View File
@@ -136,6 +136,7 @@ void Server::exec(const char* q){
bool Server::haserror(){
if (last_error){
puts(last_error);
last_error = nullptr;
return true;
}
@@ -218,6 +219,50 @@ void* Server::getCol(int col_idx){
return nullptr;
}
#define AQ_MONETDB_FETCH(X) case monetdbe_##X: \
return (long long)((X *)(_ret_col->data))[0];
long long Server::getFirstElement() {
if(!this->haserror() && res) {
auto _res = static_cast<monetdbe_result*>(this->res);
auto err_msg = monetdbe_result_fetch(_res,
reinterpret_cast<monetdbe_column**>(&ret_col), 0);
if(err_msg == nullptr)
{
auto _ret_col = static_cast<monetdbe_column*>(this->ret_col);
cnt = _ret_col->count;
if(cnt > 0) {
switch(_ret_col->type) {
AQ_MONETDB_FETCH(bool)
AQ_MONETDB_FETCH(int8_t)
AQ_MONETDB_FETCH(int16_t)
AQ_MONETDB_FETCH(int32_t)
AQ_MONETDB_FETCH(int64_t)
#ifdef HAVE_HGE
case monetdbe_int128_t:
return (long long)((__int128_t *)(_ret_col->data))[0];
#endif
AQ_MONETDB_FETCH(size_t)
AQ_MONETDB_FETCH(float)
AQ_MONETDB_FETCH(double)
case monetdbe_str:
return ((const char **)(_ret_col->data))[0][0] == '\0';
default:
printf("Error, non-primitive result: Getting col %s, type: %s\n",
_ret_col->name, monetdbe_type_str[_ret_col->type]);
return 0;
}
}
}
else {
printf("Error fetching result: %s\n", err_msg);
}
}
else {
puts("Error: No result.");
}
return 0;
}
Server::~Server(){
close();
}
@@ -233,19 +278,23 @@ bool Server::havehge() {
}
void ExecuteStoredProcedureEx(const StoredProcedure *p, Context* cxt){
int ExecuteStoredProcedureEx(const StoredProcedure *p, Context* cxt){
auto server = static_cast<Server*>(cxt->alt_server);
int ret = 0;
bool return_from_procedure = false;
void* handle = nullptr;
uint32_t procedure_module_cursor = 0;
for(uint32_t i = 0; i < p->cnt; ++i) {
switch(p->queries[i][0]){
puts(p->queries[i]);
case 'Q': {
server->exec(p->queries[i]);
server->exec(p->queries[i] + 1);
ret = int(server->getFirstElement());
}
break;
case 'P': {
auto c = code_snippet(dlsym(handle, p->queries[i]+1));
c(cxt);
auto c = code_snippet(dlsym(handle, p->queries[i] + 1));
ret = c(cxt);
}
break;
case 'N': {
@@ -266,11 +315,25 @@ void ExecuteStoredProcedureEx(const StoredProcedure *p, Context* cxt){
i, p->queries[i][0]);
}
}
return ret;
}
int execTriggerPayload(void* args) {
auto spp = (StoredProcedurePayload*)(args);
ExecuteStoredProcedureEx(spp->p, spp->cxt);
puts("exec trigger");
auto ret = ExecuteStoredProcedureEx(spp->p, spp->cxt);
delete spp;
return 0;
return ret;
}
int execTriggerPayloadCond(void* args) {
int ret = 0;
auto spp = (StoredProcedurePayloadCond*)(args);
if(ExecuteStoredProcedureEx(spp->condition, spp->cxt) != 0)
ret = ExecuteStoredProcedureEx(spp->action, spp->cxt);
free(spp->condition);
free(spp->action);
delete spp;
return ret;
}
+1
View File
@@ -19,6 +19,7 @@ struct Server{
void connect(Context* cxt);
void exec(const char* q);
void *getCol(int col_idx);
long long getFirstElement();
void close();
bool haserror();
static bool havehge();
+28 -6
View File
@@ -94,8 +94,8 @@ have_hge() {
return false;
#endif
}
__AQEXPORT__(StoredProcedure)
Context* _g_cxt;
StoredProcedure
get_procedure(Context* cxt, const char* name) {
auto res = cxt->stored_proc.find(name);
if (res == cxt->stored_proc.end())
@@ -107,7 +107,10 @@ get_procedure(Context* cxt, const char* name) {
};
return res->second;
}
__AQEXPORT__(StoredProcedure)
get_procedure_ex(const char* name){
return get_procedure(_g_cxt, name);
}
using prt_fn_t = char* (*)(void*, char*);
// This function contains heap allocations, free after use
@@ -490,7 +493,7 @@ start:
puts(p.queries[j-1]);
}
fclose(fp);
p.__rt_loaded_modules = 0;
p.__rt_loaded_modules = nullptr;
return load_modules(p);
};
switch(n_recvd[i][1]){
@@ -561,6 +564,7 @@ start:
break;
case 'T': // triggers
{
puts(n_recvd[i]);
switch(n_recvd[i][1]){
case 'I': // register interval based trigger
{
@@ -578,6 +582,23 @@ start:
}
break;
case 'C': // activate callback based trigger
{
const char* query_name = n_recvd[i] + 2;
const char* action_name = query_name;
while(*action_name++);
if(auto q = get_procedure(cxt, query_name),
a = get_procedure(cxt, action_name);
q.name == nullptr || a.name == nullptr
)
printf("Warning: Invalid query or action name: %s %s",
query_name, action_name);
else{
auto query = AQ_DupObject(&q);
auto action = AQ_DupObject(&a);
cxt->ct_host->execute_trigger(query, action);
}
}
break;
case 'R': // remove trigger
{
@@ -656,14 +677,15 @@ extern "C" int __DLLEXPORT__ main(int argc, char** argv) {
#endif
// puts("running");
Context* cxt = new Context();
_g_cxt = cxt;
cxt->aquery_root_path = to_lpstr(std::filesystem::current_path().string());
// cxt->log("%d %s\n", argc, argv[1]);
#ifdef THREADING
auto tp = new ThreadPool();
cxt->thread_pool = tp;
cxt->it_host = new IntervalBasedTriggerHost(tp);
cxt->ct_host = new CallbackBasedTriggerHost(tp);
cxt->it_host = new IntervalBasedTriggerHost(tp, cxt);
cxt->ct_host = new CallbackBasedTriggerHost(tp, cxt);
#endif
const char* shmname;
+35 -13
View File
@@ -154,11 +154,14 @@ bool ThreadPool::busy(){
return true;
}
IntervalBasedTriggerHost::IntervalBasedTriggerHost(ThreadPool* tp){
IntervalBasedTriggerHost::IntervalBasedTriggerHost(ThreadPool* tp, Context* cxt){
this->cxt = cxt;
this->tp = tp;
this->triggers = new aq_map<std::string, IntervalBasedTrigger>;
trigger_queue_lock = new mutex();
this->now = std::chrono::high_resolution_clock::now().time_since_epoch().count();
this->running = true;
this->handle = new thread(&IntervalBasedTriggerHost::tick, this);
}
void IntervalBasedTriggerHost::add_trigger(const char* name, StoredProcedure *p, uint32_t interval) {
@@ -171,21 +174,28 @@ void IntervalBasedTriggerHost::add_trigger(const char* name, StoredProcedure *p,
}
void IntervalBasedTriggerHost::tick() {
const auto current_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
const auto delta_t = static_cast<uint32_t>((current_time - now) / 1000000); // miliseconds precision
auto current_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
auto delta_t = static_cast<uint32_t>((current_time - now) / 1000000); // miliseconds precision
now = current_time;
auto vt_triggers = static_cast<aq_map<std::string, IntervalBasedTrigger> *>(this->triggers);
trigger_queue_lock->lock();
for(auto& [_, t] : vt_triggers->values()) {
if(t.tick(delta_t)) {
payload_t payload;
payload.f = execTriggerPayload;
payload.args = static_cast<void*>(new StoredProcedurePayload {t.sp, cxt});
fflush(stdout);
while(this->running) {
std::this_thread::sleep_for(50ms);
current_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
delta_t = static_cast<uint32_t>((current_time - now) / 1000000); // miliseconds precision
now = current_time;
trigger_queue_lock->lock();
for(auto& [_, t] : vt_triggers->values()) {
if(t.tick(delta_t)) {
payload_t payload;
payload.f = execTriggerPayload;
payload.args = static_cast<void*>(new StoredProcedurePayload {t.sp, cxt});
tp->enqueue_task(payload);
tp->enqueue_task(payload);
}
}
trigger_queue_lock->unlock();
}
trigger_queue_lock->unlock();
}
void IntervalBasedTriggerHost::remove_trigger(const char* name) {
@@ -199,6 +209,7 @@ void IntervalBasedTrigger::reset() {
bool IntervalBasedTrigger::tick(uint32_t delta_t) {
bool ret = false;
// printf("%d %d\n",delta_t, time_remaining);
if (time_remaining <= delta_t)
ret = true;
if (auto curr_dt = delta_t % interval; time_remaining <= curr_dt)
@@ -208,8 +219,19 @@ bool IntervalBasedTrigger::tick(uint32_t delta_t) {
return ret;
}
CallbackBasedTriggerHost::CallbackBasedTriggerHost(ThreadPool *tp) {
CallbackBasedTriggerHost::CallbackBasedTriggerHost(ThreadPool *tp, Context *cxt) {
this->tp = tp;
this->cxt = cxt;
}
void CallbackBasedTriggerHost::tick() {}
void CallbackBasedTriggerHost::execute_trigger(StoredProcedure* query, StoredProcedure* action) {
payload_t payload;
payload.f = execTriggerPayloadCond;
payload.args = static_cast<void*>(
new StoredProcedurePayloadCond {query, action, cxt}
);
this->tp->enqueue_task(payload);
}
void CallbackBasedTriggerHost::tick() {}
+4 -3
View File
@@ -71,18 +71,19 @@ struct IntervalBasedTrigger : Trigger {
class IntervalBasedTriggerHost : public TriggerHost {
public:
explicit IntervalBasedTriggerHost(ThreadPool *tp);
explicit IntervalBasedTriggerHost(ThreadPool *tp, Context* cxt);
void add_trigger(const char* name, StoredProcedure* stored_procedure, uint32_t interval);
void remove_trigger(const char* name);
private:
unsigned long long now;
bool running;
void tick() override;
};
class CallbackBasedTriggerHost : public TriggerHost {
public:
explicit CallbackBasedTriggerHost(ThreadPool *tp);
void add_trigger();
explicit CallbackBasedTriggerHost(ThreadPool *tp, Context *cxt);
void execute_trigger(StoredProcedure* query, StoredProcedure* action);
private:
void tick() override;
};
+1 -1
View File
@@ -11,7 +11,7 @@ constexpr static bool cpp_17 = false;
#endif
template <class T>
inline const char* str(const T& v) {
inline const char* str([[maybe_unused]] const T& v) {
return "";
}