-
Notifications
You must be signed in to change notification settings - Fork 0
/
plmruby_env.c
113 lines (90 loc) · 2.28 KB
/
plmruby_env.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <postgres.h>
#include <miscadmin.h>
#include <utils/memutils.h>
#include <mruby.h>
#include "plmruby_env.h"
#define INITIAL_LEN 16
typedef struct {
plmruby_global_env *env;
Oid user_id;
} env_entry;
static env_entry *envs = NULL;
static int envs_max_len = 0;
static int envs_len = 0;
static plmruby_exec_env *exec_env_head;
static plmruby_global_env *new_env(void);
static void extend_envs(int new_len);
static void append_env(plmruby_global_env *env, Oid user_id);
void
init_plmruby_env_cache(void)
{
envs_max_len = INITIAL_LEN;
envs = MemoryContextAlloc(TopMemoryContext, sizeof(env_entry) * envs_max_len);
}
plmruby_global_env*
get_plmruby_global_env(void)
{
Oid user_id = GetUserId();
for (int i = 0; i < envs_len; ++i)
{
if (envs[i].user_id == user_id)
return envs[i].env;
}
plmruby_global_env *env = new_env();
append_env(env, user_id);
return env;
}
plmruby_exec_env *
create_plmruby_exec_env(struct RClass *proc_class)
{
plmruby_global_env *env = get_plmruby_global_env();
plmruby_exec_env *xenv = (plmruby_exec_env *) MemoryContextAllocZero(TopTransactionContext, sizeof(plmruby_exec_env));
xenv->ai = mrb_gc_arena_save(env->mrb);
xenv->mrb = env->mrb;
xenv->mid = mrb_intern_cstr(env->mrb, "call");
xenv->nil = mrb_nil_value();
xenv->proc = mrb_obj_new(env->mrb, proc_class, 0, NULL);
xenv->next = exec_env_head;
exec_env_head = xenv;
return xenv;
}
void
cleanup_plmruby_exec_env(void)
{
plmruby_exec_env *xenv = exec_env_head;
while (xenv != NULL)
{
mrb_gc_arena_restore(xenv->mrb, xenv->ai);
xenv = xenv->next;
}
exec_env_head = NULL;
}
static plmruby_global_env *
new_env(void)
{
plmruby_global_env *env = MemoryContextAlloc(TopMemoryContext, sizeof(plmruby_global_env));
env->mrb = mrb_open();
env->cxt = mrbc_context_new(env->mrb);
env->cxt->capture_errors = TRUE;
return env;
}
static void
extend_envs(int new_len)
{
if (new_len == envs_max_len)
{
envs_max_len = envs_max_len * 2;
MemoryContext old_context = MemoryContextSwitchTo(TopMemoryContext);
repalloc(envs, sizeof(env_entry) * envs_max_len);
MemoryContextSwitchTo(old_context);
}
}
static void
append_env(plmruby_global_env *env, Oid user_id)
{
int new_len = envs_len + 1;
extend_envs(new_len);
envs[envs_len].env = env;
envs[envs_len].user_id = user_id;
envs_len = new_len;
}