term_t bif_embedded_module1(term_t Mod, process_t *ctx) { xmod_bin_t *mp, *me; cstr_t *s; if (!is_atom(Mod)) return A_BADARG; s = atoms_get(proc_atoms(ctx), index(Mod)); mp = (xmod_bin_t *)module_bins->elts; me = mp + module_bins->nelts; while (mp < me) { if (scomp(mp->name, s)) { term_t bin = make_binary(intnum(mp->size), mp->data, proc_gc_pool(ctx)); result(make_tuple3(A_OK, bin, bool(mp->is_preloaded), proc_gc_pool(ctx))); return AI_OK; } mp++; } result(A_FALSE); return AI_OK; }
static int so_atom_add(session_opt_t *so, const char *id, char *buf, size_t size, void *arg) { atom_t *atom = NULL, *old = NULL; size_t new_size, old_found = 0; dbg_err_if (so == NULL); dbg_err_if (id == NULL); dbg_err_if (buf == NULL); /* get the old atom associated to this id */ if(!atoms_get(so->atoms, id, &old)) old_found = 1; /* delete the oldest session if there are already max_count sessions */ if(so->max_count && atoms_count(so->atoms) - old_found >= so->max_count) dbg_err_if(session_delete_oldest(so)); /* delete the oldest session(s) if we are using already mem_limit bytes */ if(so->mem_limit) { warn_err_ifm(size > so->mem_limit, "session size is bigger the memory.limit, save aborted..."); for(;;) { /* new_size = size of all atoms + size of the atom we're going to add - the size of the atom (if found) we're going to remove */ new_size = atoms_size(so->atoms) + size - (old ? old->size : 0); if(atoms_count(so->atoms) && new_size > so->mem_limit) dbg_err_if(session_delete_oldest(so)); else break; } } /* create a new atom */ dbg_err_if(atom_create(id, buf, size, arg, &atom)); /* add it to the list */ dbg_err_if(atoms_add(so->atoms, atom)); /* remove the old atom associated to this id */ if(old) { dbg_err_if(atoms_remove(so->atoms, old)); atom_free(old); } return 0; err: if(atom) atom_free(atom); return ~0; }
static int session_mem_load(session_t *ss) { enum { BUFSZ = 4096 }; atom_t *atom; char buf[BUFSZ]; size_t size; enc_ses_mem_t *esm; ppc_t *ppc; unsigned char cmd; dbg_err_if (ss == NULL); nop_err_if (ss->filename == NULL || strlen(ss->filename) == 0); /* in fork and iterative model we can get the session from the current address space, in prefork we must ask the parent for a fresh copy of the session */ if(ctx->backend && ctx->backend->model == SERVER_MODEL_PREFORK) { /* get the session data through ppc */ ppc = server_get_ppc(ctx->server); dbg_err_if(ppc == NULL); /* send a get request */ dbg_err_if(ppc_write(ppc, ctx->pipc, PPC_CMD_MSES_GET, ss->filename, strlen(ss->filename) + 1) < 0); /* get the response from the parent */ dbg_err_if((size = ppc_read(ppc, ctx->pipc, &cmd, buf, BUFSZ)) <= 0); nop_err_if(cmd != PPC_CMD_RESPONSE_OK); /* load session from esm */ esm = (enc_ses_mem_t*)buf; ss->mtime = esm->mtime; dbg_err_if(session_prv_load_from_buf(ss, esm->data, esm->size)); } else { /* find the file into the atom list */ if(atoms_get(ss->so->atoms, ss->filename, &atom)) return ~0; /* not found */ /* copy stored mtime */ ss->mtime = (time_t)atom->arg; /* load session from atom->data */ dbg_err_if(session_prv_load_from_buf(ss, atom->data, atom->size)); } return 0; err: return ~0; }
/* [parent] get session data */ static int session_cmd_get(ppc_t *ppc, int fd, unsigned char cmd, char *data, size_t size, void *vso) { enum { BUFSZ = 4096 }; session_opt_t *so = vso; enc_ses_mem_t *esm = NULL; atom_t *atom = NULL; char buf[BUFSZ]; size_t esm_size; u_unused_args(cmd, size); dbg_err_if (ppc == NULL); dbg_err_if (vso == NULL); dbg_err_if (data == NULL); dbg_err_if (strlen(data) > SESSION_FILENAME_MAX_LENGTH); /* find the atom whose name is stored into 'data' buffer */ nop_err_if(atoms_get(so->atoms, data, &atom)); /* if the buffer on the stack is big enough use it, otherwise alloc a bigger one on the heap */ if((esm_size = sizeof(enc_ses_mem_t) + atom->size) > BUFSZ) { esm = u_malloc(1 + esm_size); dbg_err_if(esm == NULL); } else esm = (enc_ses_mem_t*)buf; /* fill the enc_ses_mem_t struct */ esm->mtime = (time_t)atom->arg; u_strlcpy(esm->filename, data, sizeof esm->filename); esm->size = atom->size; memcpy(esm->data, atom->data, atom->size); dbg_err_if(ppc_write(ppc, fd, PPC_CMD_RESPONSE_OK, (char*)esm, esm_size) <= 0); if(esm && esm != (void*)buf) U_FREE(esm); return 0; err: if(ppc) ppc_write(ppc, fd, PPC_CMD_RESPONSE_ERROR, (char *)"", 1); if(esm && esm != (void *)buf) U_FREE(esm); return ~0; }
static int so_atom_remove(session_opt_t *so, const char *id) { atom_t *atom = NULL; dbg_err_if (so == NULL); dbg_err_if (id == NULL); /* find the atom bound to this session */ if(atoms_get(so->atoms, id, &atom)) return 0; /* remove it from the list */ dbg_err_if(atoms_remove(so->atoms, atom)); atom_free(atom); return 0; err: return ~0; }
int is_term_smaller(term_t a, term_t b) { if (a == b) return 0; if (are_both_immed(a, b)) { if (are_both_int(a, b)) return int_value(a) < int_value(b); if (is_int(a)) // !is_int(b) return 1; if (is_nil(a)) // !is_nil(b) return 0; if (is_nil(b)) // !is_nil(a) return 1; if (is_atom(a)) { if (is_int(b)) return 0; else if (is_atom(b)) { uint8_t *print1 = atoms_get(atom_index(a)); uint8_t *print2 = atoms_get(atom_index(b)); int short_len = (print1[0] < print2[0]) ? print1[0] : print2[0]; int d = memcmp(print1+1, print2+1, short_len); if (d == 0) return print1[0] < print2[0]; return d < 0; } else return 1; } else if (is_short_oid(a)) { if (is_int(b) || is_atom(b)) return 0; else if (is_short_oid(b)) return short_oid_id(a) < short_oid_id(b); else return 1; } else if (is_short_pid(a)) { if (is_int(b) || is_atom(b) || is_short_oid(b)) return 0; else { assert(is_short_pid(b)); return short_pid_id(a) < short_pid_id(b); } } } //TODO: comparison of bignum and float: docs mention the // number 9007199254740992.0 and a loss of transitivity if (!is_immed(a) && !is_immed(b) && primary_tag(a) == primary_tag(b)) { if (is_cons(a)) return is_term_smaller_1(a, b); else if (is_tuple(a)) return is_term_smaller_2(a, b); else { assert(is_boxed(a) && is_boxed(b)); uint32_t *adata = peel_boxed(a); uint32_t *bdata = peel_boxed(b); if (boxed_tag(adata) == boxed_tag(bdata) || (is_binary(adata) && is_binary(bdata)) || (is_bignum(adata) && is_bignum(bdata))) { switch(boxed_tag(adata)) { case SUBTAG_POS_BIGNUM: case SUBTAG_NEG_BIGNUM: return bignum_compare((bignum_t *)adata, (bignum_t *)bdata) < 0; case SUBTAG_FUN: return fun_compare((t_fun_t *)adata, (t_fun_t *)bdata) < 0; case SUBTAG_EXPORT: return export_compare((t_export_t *)adata, (t_export_t *)bdata) < 0; case SUBTAG_PID: return pid_compare((t_long_pid_t *)adata, (t_long_pid_t *)bdata) < 0; case SUBTAG_OID: return oid_compare((t_long_oid_t *)adata, (t_long_oid_t *)bdata) < 0; case SUBTAG_REF: return ref_compare((t_long_ref_t *)adata, (t_long_ref_t *)bdata) < 0; case SUBTAG_PROC_BIN: case SUBTAG_HEAP_BIN: case SUBTAG_MATCH_CTX: case SUBTAG_SUB_BIN: return is_term_smaller_3(adata, bdata); default: assert(boxed_tag(adata) == SUBTAG_FLOAT); return float_value(adata) < float_value(bdata); } } } } // Number comparison with (mandatory) coercion // int use_float = (is_boxed(a) && boxed_tag(peel_boxed(a)) == SUBTAG_FLOAT) || (is_boxed(b) && boxed_tag(peel_boxed(b)) == SUBTAG_FLOAT); if (use_float) { if (is_int(a)) // b is always float return (double)int_value(a) < float_value(peel_boxed(b)); else if (is_boxed(a)) { uint32_t *adata = peel_boxed(a); if (is_bignum(adata)) // b is always float return bignum_to_double((bignum_t *)adata) < float_value(peel_boxed(b)); if (boxed_tag(adata) == SUBTAG_FLOAT) { if (is_int(b)) return float_value(adata) < (double)int_value(b); if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) return float_value(adata) < bignum_to_double((bignum_t *)bdata); } } } } else // use integer { if (is_int(a)) { if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) { bignum_t *bbn = (bignum_t *)bdata; return !bignum_is_neg(bbn); } assert(boxed_tag(bdata) != SUBTAG_FLOAT); } } else if (is_boxed(a)) { uint32_t *adata = peel_boxed(a); if (is_bignum(adata)) { bignum_t *abn = (bignum_t *)adata; if (is_int(b)) return bignum_is_neg(abn); if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) return bignum_compare(abn, (bignum_t *)bdata); assert(boxed_tag(bdata) != SUBTAG_FLOAT); } } assert(boxed_tag(adata) != SUBTAG_FLOAT); } } // a and b are quaranteed to have different types // return term_order(a) < term_order(b); }