00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #include <stdlib.h>
00015 #include <time.h>
00016 #include <unistd.h>
00017 #include <fcntl.h>
00018 #include <u/libu.h>
00019 #include <klone/session.h>
00020 #include <klone/request.h>
00021 #include <klone/context.h>
00022 #include <klone/response.h>
00023 #include <klone/vars.h>
00024 #include <klone/utils.h>
00025 #include <klone/atom.h>
00026 #include <klone/ses_prv.h>
00027 #include <klone/ppc.h>
00028 #include <klone/ppc_cmd.h>
00029
00030 enum { SESSION_FILENAME_MAX_LENGTH = 256 };
00031
00032 struct enc_ses_mem_s
00033 {
00034 time_t mtime;
00035 char filename[SESSION_FILENAME_MAX_LENGTH];
00036 size_t size;
00037 char data[1];
00038 };
00039
00040 typedef struct enc_ses_mem_s enc_ses_mem_t;
00041
00042 static int so_atom_delete_oldest(session_opt_t *so)
00043 {
00044 atom_t *atom, *oldest;
00045 size_t count, i;
00046
00047 dbg_err_if (so == NULL);
00048
00049 count = atoms_count(so->atoms);
00050 nop_err_if(count == 0);
00051
00052 dbg_err_if(atoms_getn(so->atoms, 0, &oldest));
00053 for(i = 1; i < count; ++i)
00054 {
00055 dbg_err_if(atoms_getn(so->atoms, i, &atom));
00056
00057
00058 if(atom->arg <= oldest->arg)
00059 oldest = atom;
00060 }
00061
00062 dbg_err_if(atoms_remove(so->atoms, oldest));
00063
00064 return 0;
00065 err:
00066 return ~0;
00067 }
00068
00069 static int session_delete_oldest(session_opt_t *so)
00070 {
00071 ppc_t *ppc;
00072
00073 dbg_err_if (so == NULL);
00074
00075 if(ctx->pipc)
00076 {
00077 ppc = server_get_ppc(ctx->server);
00078 dbg_err_if(ppc == NULL);
00079
00080 dbg_err_if(ppc_write(ppc, ctx->pipc, PPC_CMD_MSES_DELOLD, "", 1) < 0);
00081
00082
00083 dbg_err_if(so_atom_delete_oldest(so));
00084 } else {
00085
00086 dbg_err_if(so_atom_delete_oldest(so));
00087 }
00088
00089 return 0;
00090 err:
00091 return ~0;
00092 }
00093
00094 static int so_atom_remove(session_opt_t *so, const char *id)
00095 {
00096 atom_t *atom = NULL;
00097
00098 dbg_err_if (so == NULL);
00099 dbg_err_if (id == NULL);
00100
00101
00102 if(atoms_get(so->atoms, id, &atom))
00103 return 0;
00104
00105
00106 dbg_err_if(atoms_remove(so->atoms, atom));
00107
00108 atom_free(atom);
00109
00110 return 0;
00111 err:
00112 return ~0;
00113 }
00114
00115
00116 static int so_atom_add(session_opt_t *so, const char *id, char *buf,
00117 size_t size, void *arg)
00118 {
00119 atom_t *atom = NULL, *old = NULL;
00120 size_t new_size, old_found = 0;
00121
00122 dbg_err_if (so == NULL);
00123 dbg_err_if (id == NULL);
00124 dbg_err_if (buf == NULL);
00125
00126
00127 if(!atoms_get(so->atoms, id, &old))
00128 old_found = 1;
00129
00130
00131 if(so->max_count && atoms_count(so->atoms) - old_found >= so->max_count)
00132 dbg_err_if(session_delete_oldest(so));
00133
00134
00135 if(so->mem_limit)
00136 {
00137 warn_err_ifm(size > so->mem_limit,
00138 "session size is bigger the memory.limit, save aborted...");
00139 for(;;)
00140 {
00141
00142
00143 new_size = atoms_size(so->atoms) + size - (old ? old->size : 0);
00144 if(atoms_count(so->atoms) && new_size > so->mem_limit)
00145 dbg_err_if(session_delete_oldest(so));
00146 else
00147 break;
00148 }
00149 }
00150
00151
00152 dbg_err_if(atom_create(id, buf, size, arg, &atom));
00153
00154
00155 dbg_err_if(atoms_add(so->atoms, atom));
00156
00157
00158 if(old)
00159 {
00160 dbg_err_if(atoms_remove(so->atoms, old));
00161 atom_free(old);
00162 }
00163
00164 return 0;
00165 err:
00166 if(atom)
00167 atom_free(atom);
00168 return ~0;
00169 }
00170
00171
00172
00173 static int session_cmd_remove(ppc_t *ppc, int fd, unsigned char cmd,
00174 char *data, size_t size, void *vso)
00175 {
00176 session_opt_t *so = vso;
00177
00178 u_unused_args(ppc, fd, cmd, size);
00179
00180 dbg_err_if (data == NULL);
00181 dbg_err_if (vso == NULL);
00182
00183 dbg_err_if(so_atom_remove(so, data ));
00184
00185 return 0;
00186 err:
00187 return ~0;
00188 }
00189
00190
00191 static int session_cmd_delold(ppc_t *ppc, int fd, unsigned char cmd,
00192 char *data, size_t size, void *vso)
00193 {
00194 session_opt_t *so = vso;
00195
00196 u_unused_args(ppc, fd, cmd, data, size);
00197
00198 dbg_err_if (vso == NULL);
00199
00200 dbg_err_if (so_atom_delete_oldest(so));
00201
00202 return 0;
00203 err:
00204 return ~0;
00205 }
00206
00207
00208 static int session_cmd_save(ppc_t *ppc, int fd, unsigned char cmd, char *data,
00209 size_t size, void *vso)
00210 {
00211 session_opt_t *so = vso;
00212 enc_ses_mem_t *esm = (enc_ses_mem_t*)data;
00213
00214 u_unused_args(ppc, fd, cmd, size);
00215
00216 dbg_err_if (vso == NULL);
00217 dbg_err_if (data == NULL);
00218
00219 dbg_err_if(so_atom_add(so, esm->filename, esm->data, esm->size,
00220 (void*)esm->mtime));
00221
00222 return 0;
00223 err:
00224 return ~0;
00225 }
00226
00227
00228 static int session_cmd_get(ppc_t *ppc, int fd, unsigned char cmd, char *data,
00229 size_t size, void *vso)
00230 {
00231 enum { BUFSZ = 4096 };
00232 session_opt_t *so = vso;
00233 enc_ses_mem_t *esm = NULL;
00234 atom_t *atom = NULL;
00235 char buf[BUFSZ];
00236 size_t esm_size;
00237
00238 u_unused_args(cmd, size);
00239
00240 dbg_err_if (ppc == NULL);
00241 dbg_err_if (vso == NULL);
00242 dbg_err_if (data == NULL);
00243 dbg_err_if (strlen(data) > SESSION_FILENAME_MAX_LENGTH);
00244
00245
00246 nop_err_if(atoms_get(so->atoms, data, &atom));
00247
00248
00249
00250 if((esm_size = sizeof(enc_ses_mem_t) + atom->size) > BUFSZ)
00251 {
00252 esm = u_malloc(1 + esm_size);
00253 dbg_err_if(esm == NULL);
00254 } else
00255 esm = (enc_ses_mem_t*)buf;
00256
00257
00258 esm->mtime = (time_t)atom->arg;
00259 u_strlcpy(esm->filename, data, sizeof esm->filename);
00260 esm->size = atom->size;
00261 memcpy(esm->data, atom->data, atom->size);
00262
00263 dbg_err_if(ppc_write(ppc, fd, PPC_CMD_RESPONSE_OK, (char*)esm,
00264 esm_size) <= 0);
00265
00266 if(esm && esm != (void*)buf)
00267 U_FREE(esm);
00268
00269 return 0;
00270 err:
00271 if(ppc)
00272 ppc_write(ppc, fd, PPC_CMD_RESPONSE_ERROR, (char *)"", 1);
00273 if(esm && esm != (void *)buf)
00274 U_FREE(esm);
00275 return ~0;
00276 }
00277
00278
00279 static int session_mem_add(session_opt_t *so, const char *filename, char *buf,
00280 size_t size, time_t mtime)
00281 {
00282 atom_t *atom = NULL;
00283 enc_ses_mem_t *esm = NULL;
00284 ppc_t *ppc;
00285 size_t esize;
00286
00287 dbg_err_if (so == NULL);
00288 dbg_err_if (filename == NULL);
00289 dbg_err_if (buf == NULL);
00290
00291 if(ctx->pipc)
00292 {
00293 ppc = server_get_ppc(ctx->server);
00294 dbg_err_if(ppc == NULL);
00295
00296
00297 esize = size + sizeof(enc_ses_mem_t);
00298 esm = (enc_ses_mem_t*)u_malloc(esize);
00299 dbg_err_if(esm == NULL);
00300
00301
00302 esm->mtime = time(0);
00303 esm->size = size;
00304 dbg_err_if(strlen(filename) > SESSION_FILENAME_MAX_LENGTH);
00305 u_strlcpy(esm->filename, filename, sizeof esm->filename);
00306 memcpy(esm->data, buf, size);
00307
00308
00309 dbg_err_if(ppc_write(ppc, ctx->pipc, PPC_CMD_MSES_SAVE,
00310 (char*)esm, esize) < 0);
00311
00312 U_FREE(esm);
00313
00314
00315 dbg_err_if(so_atom_add(so, filename, buf, size, (void*)mtime));
00316
00317 } else {
00318
00319 dbg_err_if(so_atom_add(so, filename, buf, size, (void*)mtime));
00320 }
00321
00322 return 0;
00323 err:
00324 U_FREE(esm);
00325 if(atom)
00326 atom_free(atom);
00327 return ~0;
00328 }
00329
00330
00331 static int session_mem_save(session_t *ss)
00332 {
00333 char *buf = NULL;
00334 size_t sz;
00335
00336 dbg_err_if (ss == NULL);
00337
00338
00339 dbg_err_if(session_prv_save_to_buf(ss, &buf, &sz));
00340
00341
00342 dbg_err_if(session_mem_add(ss->so, ss->filename, buf, sz, time(0)));
00343
00344 U_FREE(buf);
00345
00346 return 0;
00347 err:
00348 U_FREE(buf);
00349 return ~0;
00350 }
00351
00352 static int session_mem_load(session_t *ss)
00353 {
00354 enum { BUFSZ = 4096 };
00355 atom_t *atom;
00356 char buf[BUFSZ];
00357 size_t size;
00358 enc_ses_mem_t *esm;
00359 ppc_t *ppc;
00360 unsigned char cmd;
00361
00362 dbg_err_if (ss == NULL);
00363 nop_err_if (ss->filename == NULL || strlen(ss->filename) == 0);
00364
00365
00366
00367
00368 if(ctx->backend && ctx->backend->model == SERVER_MODEL_PREFORK)
00369 {
00370 ppc = server_get_ppc(ctx->server);
00371 dbg_err_if(ppc == NULL);
00372
00373
00374 dbg_err_if(ppc_write(ppc, ctx->pipc, PPC_CMD_MSES_GET, ss->filename,
00375 strlen(ss->filename) + 1) < 0);
00376
00377
00378 dbg_err_if((size = ppc_read(ppc, ctx->pipc, &cmd, buf, BUFSZ)) <= 0);
00379
00380 nop_err_if(cmd != PPC_CMD_RESPONSE_OK);
00381
00382
00383 esm = (enc_ses_mem_t*)buf;
00384 ss->mtime = esm->mtime;
00385 dbg_err_if(session_prv_load_from_buf(ss, esm->data, esm->size));
00386
00387 } else {
00388
00389 if(atoms_get(ss->so->atoms, ss->filename, &atom))
00390 return ~0;
00391
00392
00393 ss->mtime = (time_t)atom->arg;
00394
00395
00396 dbg_err_if(session_prv_load_from_buf(ss, atom->data, atom->size));
00397 }
00398
00399 return 0;
00400 err:
00401 return ~0;
00402 }
00403
00404 static int session_mem_remove(session_t *ss)
00405 {
00406 ppc_t *ppc;
00407
00408 dbg_err_if (ss == NULL);
00409
00410 if(ctx->pipc)
00411 {
00412 ppc = server_get_ppc(ctx->server);
00413 dbg_err_if(ppc == NULL);
00414
00415 dbg_err_if(ppc_write(ppc, ctx->pipc, PPC_CMD_MSES_REMOVE, ss->filename,
00416 strlen(ss->filename) + 1) < 0);
00417
00418
00419 dbg_err_if(so_atom_remove(ss->so, ss->filename));
00420 } else {
00421
00422 dbg_err_if(so_atom_remove(ss->so, ss->filename));
00423 }
00424
00425 return 0;
00426 err:
00427 return ~0;
00428 }
00429
00430 static int session_mem_term(session_t *ss)
00431 {
00432
00433 u_unused_args(ss);
00434 return 0;
00435 }
00436
00437 int session_mem_create(session_opt_t *so, request_t *rq, response_t *rs,
00438 session_t **pss)
00439 {
00440 session_t *ss = NULL;
00441
00442 dbg_err_if (so == NULL);
00443 dbg_err_if (rq == NULL);
00444 dbg_err_if (rs == NULL);
00445 dbg_err_if (pss == NULL);
00446
00447 ss = u_zalloc(sizeof(session_t));
00448 dbg_err_if(ss == NULL);
00449
00450 ss->load = session_mem_load;
00451 ss->save = session_mem_save;
00452 ss->remove = session_mem_remove;
00453 ss->term = session_mem_term;
00454 ss->mtime = time(0);
00455 ss->so = so;
00456
00457 dbg_err_if(session_prv_init(ss, rq, rs));
00458
00459 *pss = ss;
00460
00461 return 0;
00462 err:
00463 if(ss)
00464 session_free(ss);
00465 return ~0;
00466 }
00467
00468
00469 int session_mem_module_init(u_config_t *config, session_opt_t *so)
00470 {
00471 ppc_t *ppc;
00472 u_config_t *c;
00473 const char *v;
00474
00475
00476 dbg_err_if (so == NULL);
00477
00478
00479 so->max_count = 0;
00480 so->mem_limit = 0;
00481
00482 if(config && u_config_get_subkey(config, "memory", &c) == 0)
00483 {
00484 if((v = u_config_get_subkey_value(c, "max_count")) != NULL)
00485 so->max_count = atoi(v);
00486
00487 if((v = u_config_get_subkey_value(c, "limit")) != NULL)
00488 so->mem_limit = atoi(v);
00489 }
00490
00491
00492 ppc = server_get_ppc(ctx->server);
00493 dbg_err_if(ppc == NULL);
00494
00495
00496 dbg_err_if(atoms_create(&so->atoms));
00497
00498
00499 dbg_err_if(ppc_register(ppc, PPC_CMD_MSES_SAVE, session_cmd_save, so));
00500 dbg_err_if(ppc_register(ppc, PPC_CMD_MSES_GET, session_cmd_get, so));
00501 dbg_err_if(ppc_register(ppc, PPC_CMD_MSES_DELOLD, session_cmd_delold, so));
00502 dbg_err_if(ppc_register(ppc, PPC_CMD_MSES_REMOVE, session_cmd_remove, so));
00503
00504 return 0;
00505 err:
00506 return ~0;
00507 }
00508