27 */ |
27 */ |
28 |
28 |
29 #include "resourcepool.h" |
29 #include "resourcepool.h" |
30 #include "request.h" |
30 #include "request.h" |
31 #include "session.h" |
31 #include "session.h" |
|
32 #include "../public/nsapi.h" |
|
33 |
|
34 #define RESOURCE_POOL_MAX_DEFAULT 32 |
|
35 |
|
36 #define RESOURCE_POOL_MAX_ALLOC 268435455 |
|
37 |
|
38 static UcxMap *resource_pool_types; |
|
39 |
|
40 int init_resource_pools(void) { |
|
41 resource_pool_types = ucx_map_new(4); |
|
42 return resource_pool_types ? 0 : 1; |
|
43 } |
|
44 |
|
45 |
|
46 |
|
47 int resourcepool_new(ServerConfiguration *cfg, scstr_t type, scstr_t name, ConfigNode *node) { |
|
48 ResourceType *restype = ucx_map_sstr_get(resource_pool_types, type); |
|
49 if(!restype) { |
|
50 log_ereport(LOG_MISCONFIG, "Unknown resource pool type: %s", type.ptr); |
|
51 return 1; |
|
52 } |
|
53 |
|
54 // convert ConfigNode to pblock |
|
55 // no sub-objects allowed for this specific ConfigNode, therefore |
|
56 // it can be represented as key-value-pairs |
|
57 pblock *param = config_obj2pblock(cfg->pool, node); |
|
58 if(!param) { |
|
59 log_ereport(LOG_FAILURE, "resourcepool_new: OOM"); |
|
60 return 1; |
|
61 } |
|
62 |
|
63 ResourcePool *respool = pool_malloc(cfg->pool, sizeof(ResourcePool)); |
|
64 if(!respool) { |
|
65 log_ereport(LOG_FAILURE, "resourcepool_new: OOM"); |
|
66 return 1; |
|
67 } |
|
68 respool->pool = cfg->pool; |
|
69 |
|
70 void *respool_data = restype->init(cfg->pool, param); |
|
71 if(!respool_data) { |
|
72 log_ereport(LOG_FAILURE, "Cannot create resource pool data: pool: %s type: %s", name.ptr, type.ptr); |
|
73 return 1; |
|
74 } |
|
75 |
|
76 respool->type = restype; |
|
77 respool->data = respool_data; |
|
78 respool->min = 0; // TODO: get from node |
|
79 respool->max = RESOURCE_POOL_MAX_DEFAULT; // TODO: get from node |
|
80 |
|
81 // don't allow too large resource pools |
|
82 // this prevents the need to check malloc integer overflows |
|
83 if(respool->max > RESOURCE_POOL_MAX_ALLOC) { |
|
84 respool->max = RESOURCE_POOL_MAX_ALLOC; |
|
85 log_ereport(LOG_WARN, "Resource pool %s: limit max to %d", name.ptr, respool->max); |
|
86 } |
|
87 |
|
88 respool->resalloc = respool->max; |
|
89 respool->resources = pool_malloc(cfg->pool, respool->resalloc * sizeof(void*)); |
|
90 |
|
91 if(!respool->resources || ucx_map_sstr_put(cfg->resources, name, respool)) { |
|
92 log_ereport(LOG_FAILURE, "Cannot add resource pool: OOM"); |
|
93 // the only cleanup we have to do |
|
94 restype->destroy(respool_data); |
|
95 return 1; |
|
96 } |
|
97 |
|
98 pthread_mutex_init(&respool->lock, NULL); |
|
99 pthread_cond_init(&respool->available, NULL); |
|
100 |
|
101 if(resourcepool_create_resources(respool, respool->max)) { |
|
102 log_ereport(LOG_FAILURE, "Resource pool %s: Cannot create resources", name.ptr); |
|
103 resourcepool_destroy(respool); |
|
104 return 1; |
|
105 } |
|
106 |
|
107 return 0; |
|
108 } |
|
109 |
|
110 int resourcepool_create_resources(ResourcePool *pool, int num_res) { |
|
111 if(num_res > pool->resalloc) { |
|
112 num_res = pool->resalloc; |
|
113 } |
|
114 |
|
115 for(int i=pool->numresources;i<num_res;i++) { |
|
116 void *resource = pool->type->createresource(pool->data); |
|
117 if(resource) { |
|
118 pool->resources[pool->numresources++] = resource; |
|
119 } else { |
|
120 return 1; // error |
|
121 } |
|
122 } |
|
123 |
|
124 return 0; |
|
125 } |
32 |
126 |
33 ResourceData* resourcepool_lookup(Session *sn, Request *rq, const char *name, int flags) { |
127 ResourceData* resourcepool_lookup(Session *sn, Request *rq, const char *name, int flags) { |
34 NSAPIRequest *request = (NSAPIRequest*)rq; |
128 NSAPIRequest *request = (NSAPIRequest*)rq; |
35 NSAPISession *session = (NSAPISession*)sn; |
129 NSAPISession *session = (NSAPISession*)sn; |
36 ServerConfiguration *cfg = session->config; |
130 ServerConfiguration *cfg = session->config; |