Exemple #1
0
int
svcond_destroy(svcond_t *cond)
{
	int ret = 0;

	if (svsem_wait(cond->blocked_lock) == -1) {
		AMSG("");
		return -1;
	}
	if (svsem_trywait(cond->unblock_lock) != 0) {
		AMSG("");
		svsem_post(cond->blocked_lock);
		return -1;
	}

	if (cond) {
		if (cond->blocked_lock) {
			ret += pool_release(cond->sempool, cond->blocked_lock);
			if (cond->block_queue) {
				ret += pool_release(cond->sempool, cond->block_queue);
				if (cond->unblock_lock) {
					ret += pool_release(cond->sempool, cond->unblock_lock);
					cond->unblock_lock = NULL;
				}
				cond->block_queue = NULL;
			}
			cond->blocked_lock = NULL;
		}
	}

	return ret ? -1 : 0;
}
void bacstack_session_dl_receive_thread_handler(void *state)
{
  info("session receive thread started");
  bacstack_session_t *session = (bacstack_session_t*)state;
  uint8_t port_id;
  bacdl_msg_t msg;
  bacstack_message_t *stack_msg;

  while(!session->disposing) {
    if(bacdl_server_receive_msg(&session->dl_server, &msg, &port_id)) {
      switch(msg.code) {
        case BACDL_MSG_CODE_PORT_ID:
          debug("Port %i port_id message: %i", port_id, msg.port_id.port_id);
          break;
        case BACDL_MSG_CODE_TEXT:
          debug("Port %i text message: %s", port_id, msg.text.text);
          break;
        case BACDL_MSG_CODE_DATAGRAM:
          debug("Port %i datagram message", port_id);

          if(pool_acquire(&session->message_pool, (void**)&stack_msg)) {
            stack_msg->datagram.port_id = port_id;

            bacstack_mac_init(
                &stack_msg->datagram.source_mac,
                msg.datagram.source_mac,
                msg.datagram.source_mac_length);

            bacstack_mac_init(
                &stack_msg->datagram.dest_mac,
                msg.datagram.dest_mac,
                msg.datagram.dest_mac_length);

            stack_msg->raw_length = msg.datagram.datagram_length;
            memcpy(stack_msg->raw, msg.datagram.datagram, msg.datagram.datagram_length);
            buffer_init(&stack_msg->buf, stack_msg->raw, stack_msg->raw_length);            

            if(!pool_release(&session->proc_pool, stack_msg)) {
              warn("failed to release bacstack message to proc pool");
              pool_release(&session->message_pool, &stack_msg);
            }
          }
          else
            warn("failed to acquire bacstack_message from pool");
        
          break;
      }
      bacdl_msg_destroy(&msg);
    }
  }
}
Exemple #3
0
static void
pet_test(void)
{
#define NODES	1000000
    node_t *pool, *root;
    struct timeval tv, tv2;
    time_t sec;
    suseconds_t msec;
    int i, j;

    pool = pool_new(NODES);
    j = NODES / 2;
    gettimeofday(&tv, NULL);
    root = alloc_node(pool);
    root = make_node(root, 0);
    for (i = 1; i < NODES; i++, j = (j + 17) % NODES)
        root = insert(root, alloc_node(pool), j);
    while (root)
        root = delete_min(root);
    gettimeofday(&tv2, NULL);
    sec = tv2.tv_sec - tv.tv_sec;
    msec = tv2.tv_usec - tv.tv_usec;
    msec += sec * 1000000;
    printf("%d nodes add/remove: %lu msec\n", NODES, msec);

    pool_release(pool);
}
void bacstack_session_msg_proc_thread_handler(void *state)
{
  info("message proc thread started");
  bacstack_session_t *session = (bacstack_session_t*)state;
  bacstack_message_t *message = NULL;

  while(!session->disposing) {
    if(pool_acquire(&session->proc_pool, (void**)&message) && message != NULL) {  
      debug("processor thread received datagram");

      // hand the message off to the network processing functionality
      if(!bacstack_proc_npdu(session, message)) {
        error("failed to process network message");
        goto release;
      }

      if(!(message->npdu_header.control & BACSTACK_NPDU_NETWORK_MESSAGE_MASK)) {
        debug("bacstack received an apdu");
      }

release:
      if(!bacstack_message_reset(message)) {
        warn("error while resetting processed bacstack message");
      }

      if(!pool_release(&session->message_pool, message)) {
        error("failure releasing processed message back to message pool");
      }
    }
  }
}
VOID CL_ThreadUnix::ExecRun()
{
#if defined (_FOR_ANDROID_) || defined (_FOR_APPLE_) || defined (_LINUX)
    m_dwThreadID = GetCurrentThreadId();
#else
    m_dwThreadID = (DWORD)m_tid;
#endif

#if defined(_LINUX)
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);            // 允许退出线程
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,   NULL);     // 设置立即取消
#endif

    SetPriorityNormal();
    SetThreadName();

    CL_Printf("<<<< Thread [%s] run (%lu, 0x%x) prio: %d, TC: %lu.", m_szThreadName, m_dwThreadID, m_dwThreadID, GetPriorityExt(), ::GetTickCount());

#ifdef _FOR_APPLE_
    m_pPool = NULL;
    pool_alloc(&m_pPool);
#endif

    m_pThreadIF->Run();

#ifdef _FOR_APPLE_
    pool_release(&m_pPool);
#endif

    CL_Printf("<<<< Thread [%s] quit (%lu, 0x%x) TC: %lu.", m_szThreadName, m_dwThreadID, m_dwThreadID, ::GetTickCount());

    m_isAlive = CL_FALSE;
    m_dwThreadID = 0;
}
int bacstack_session_put_message(bacstack_session_t *session, bacstack_message_t *message)
{
  if(!bacstack_message_reset(message)) {
    warn("failed to reset a message");
  }

  return pool_release(&session->message_pool, (void*)message);
}
Exemple #7
0
int
PoolExercise(int verbose, struct cfg *cfg, char *args[])
{
    void *data;
    int rate, i;
    struct linkedlist *l;
    struct pool *p;
    cfg = NULL;
    args[0] = NULL;

    if ((p = pool_new(EXERCISE_SM_COUNT,
                      (new_fn)allocator_alloc,
                      allocator_free,
                      NULL,
                      NULL, BUFFER_SIZE_SM, 0, NULL)) == NULL ||
            (l = linkedlist_new(0, NULL)) == NULL) {
        PMNO(errno);
        return 1;
    }

    rate = EXERCISE_R0;
    for (i = 0; i < EXERCISE_SM_COUNT; i++) {
        if (i == EXERCISE_SM_P1) {
            rate = EXERCISE_R1;
        } else if (i == EXERCISE_SM_P2) {
            rate = EXERCISE_R2;
        } else if (i == EXERCISE_SM_P3) {
            rate = EXERCISE_R3;
        }

        if (rand() % 10 < rate) {
            if (pool_size(p) == EXERCISE_SM_COUNT && pool_unused(p) == 0) {
                continue;
            } else if ((data = pool_get(p)) == NULL) {
                AMSG("");
                return -1;
            } else if (linkedlist_add(l, data) == -1) {
                AMSG("%04d %p s=%d,u=%d\n", i, data, pool_size(p), pool_unused(p));
                return -1;
            }
            tcase_printf(verbose, "%04d get %p s=%d,u=%d\n", i, data, pool_size(p), pool_unused(p));
        } else if ((data = linkedlist_remove(l, 0))) {
            if (data == NULL || pool_release(p, data) == -1) {
                AMSG("%04d %p s=%d,u=%d\n", i, data, pool_size(p), pool_unused(p));
                return -1;
            }
            tcase_printf(verbose, "%04d rel %p s=%d,u=%d\n", i, data, pool_size(p), pool_unused(p));
        } else {
            tcase_printf(verbose, "%04d nothing to release\n", i);
        }
    }

    linkedlist_del(l, NULL, NULL);
    pool_del(p);

    return 0;
}
Exemple #8
0
struct sproto *
sproto_create(const void * proto, size_t sz) {
	struct pool mem;
	pool_init(&mem);
	struct sproto * s = pool_alloc(&mem, sizeof(*s));
	if (s == NULL)
		return NULL;
	memset(s, 0, sizeof(*s));
	s->memory = mem;
	if (create_from_bundle(s, proto, sz) == NULL) {
		pool_release(&s->memory);
		return NULL;
	}
	return s;
}
Exemple #9
0
static intnat pool_sweep(struct caml_heap_state* local, pool** plist, sizeclass sz) {
  pool* a = *plist;
  if (!a) return 0;
  *plist = a->next;

  value* p = (value*)((char*)a + POOL_HEADER_SZ);
  value* end = (value*)a + POOL_WSIZE;
  mlsize_t wh = wsize_sizeclass[sz];
  int all_free = 1, all_used = 1;
  struct heap_stats* s = &local->stats;

  while (p + wh <= end) {
    header_t hd = (header_t)*p;
    if (hd == 0) {
      /* already on freelist */
      all_used = 0;
    } else if (Has_status_hd(hd, global.GARBAGE)) {
      Assert(Whsize_hd(hd) <= wh);
      /* add to freelist */
      p[0] = 0;
      p[1] = (value)a->next_obj;
      Assert(Is_block((value)p));
      a->next_obj = p;
      all_used = 0;
      /* update stats */
      s->pool_live_blocks--;
      s->pool_live_words -= Whsize_hd(hd);
      s->pool_frag_words -= (wh - Whsize_hd(hd));
    } else {
      /* still live */
      all_free = 0;
    }
    p += wh;
  }

  if (all_free) {
    pool_release(local, a, sz);
  } else {
    pool** list = all_used ? &local->full_pools[sz] : &local->avail_pools[sz];
    a->next = *list;
    *list = a;
  }

  return POOL_WSIZE;
}
Exemple #10
0
void test_mempool()
{
    MemPool       *block = pool_create(bsz,1);
    clock_t       start, end;
    int i , j ;


    start = clock();
    for( j = 0 ;j < runtimes; ++j)
    for ( i = 0 ; i < times; ++i)
    {
       void *f = m_malloc(block);
       m_free(block,&f);
    }
    end = clock();
    fprintf(stdout,"Block Pool Time Ellapsed:%d\n",end-start);
    pool_release(block);
}
Exemple #11
0
static void
delete_test(void)
{
    node_t *pool, *root, *node;

    pool = pool_new(10);
    root = make_node(alloc_node(pool), 1);
    root = insert(root, alloc_node(pool), 5);
    root = insert(root, alloc_node(pool), 8);
    root = insert(root, alloc_node(pool), 10);
    root = insert(root, alloc_node(pool), 2);
    root = insert(root, alloc_node(pool), 4);
    root = insert(root, alloc_node(pool), 6);
    node = alloc_node(pool);
    root = insert(root, node, 3);

    delete(root, node);

    pool_release(pool);
}
Exemple #12
0
void test_pool()
{
    MemPool *pool = pool_create(128,10);
    char    *cp;
    int     i = 0;
    for ( ; i < 15; ++i )
    {
        char *c = (char*)m_malloc(pool);

        sprintf(c,"%d\tThis Is My Pool\n",i+1);
        printf(c);
    }

    cp = m_malloc(pool);
    m_free(pool,&cp);
    m_free(pool,&cp);

    cp = m_malloc(pool);

    pool_release(pool);
}
Exemple #13
0
static void
delete_min_test(void)
{
    node_t *pool, *root;

    pool = pool_new(10);
    root = make_node(alloc_node(pool), 1);
    root = insert(root, alloc_node(pool), 5);
    root = insert(root, alloc_node(pool), 8);
    root = insert(root, alloc_node(pool), 10);
    root = insert(root, alloc_node(pool), 2);
    root = insert(root, alloc_node(pool), 4);
    root = insert(root, alloc_node(pool), 6);
    root = insert(root, alloc_node(pool), 3);

    while (root) {
        printf("delete key: %lu\n", root->key);
        root = delete_min(root);
    }

    pool_release(pool);
}
Exemple #14
0
/*
 * 	Call the function_name inside the module
 * 	Store all vps in hashes %RAD_CHECK %RAD_REPLY %RAD_REQUEST
 *
 */
static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
{

	PERL_INST	*inst = instance;
	VALUE_PAIR	*vp;
	int		exitstatus=0, count;
	STRLEN		n_a;

	HV		*rad_reply_hv;
	HV		*rad_check_hv;
	HV		*rad_request_hv;
	HV		*rad_request_proxy_hv;
	HV		*rad_request_proxy_reply_hv;

#ifdef USE_ITHREADS
	POOL_HANDLE	*handle;

	if ((handle = pool_pop(instance)) == NULL) {
		return RLM_MODULE_FAIL;
	}

	radlog(L_DBG,"found interpetator at address 0x%lx",(unsigned long) handle->clone);
	{
	dTHXa(handle->clone);
	PERL_SET_CONTEXT(handle->clone);
	}
#else
	PERL_SET_CONTEXT(inst->perl);
	radlog(L_DBG,"Using perl at 0x%lx",(unsigned long) inst->perl);
#endif
	{
	dSP;

	ENTER;
	SAVETMPS;


	/*
	 *	Radius has told us to call this function, but none
	 *	is defined.
	 */
	if (!function_name) {
		return RLM_MODULE_FAIL;
	}

	rad_reply_hv = get_hv("RAD_REPLY",1);
	rad_check_hv = get_hv("RAD_CHECK",1);
	rad_request_hv = get_hv("RAD_REQUEST",1);
	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);


	perl_store_vps(request->reply->vps, rad_reply_hv);
	perl_store_vps(request->config_items, rad_check_hv);
	perl_store_vps(request->packet->vps, rad_request_hv);
	
	if (request->proxy != NULL) {
		perl_store_vps(request->proxy->vps, rad_request_proxy_hv);
	} else {
		hv_undef(rad_request_proxy_hv);
	}

	if (request->proxy_reply !=NULL) {
		perl_store_vps(request->proxy_reply->vps, rad_request_proxy_reply_hv);
	} else {
		hv_undef(rad_request_proxy_reply_hv);
	}	
	
	vp = NULL;


	PUSHMARK(SP);
	/*
	* This way %RAD_xx can be pushed onto stack as sub parameters.
	* XPUSHs( newRV_noinc((SV *)rad_request_hv) );
	* XPUSHs( newRV_noinc((SV *)rad_reply_hv) );
	* XPUSHs( newRV_noinc((SV *)rad_check_hv) );
	* PUTBACK;
	*/

	count = call_pv(function_name, G_SCALAR | G_EVAL | G_NOARGS);

	SPAGAIN;

	if (SvTRUE(ERRSV)) {
		radlog(L_ERR, "rlm_perl: perl_embed:: module = %s , func = %s exit status= %s\n",
		       inst->module,
		       function_name, SvPV(ERRSV,n_a));
		POPs;
	}

	if (count == 1) {
		exitstatus = POPi;
		if (exitstatus >= 100 || exitstatus < 0) {
			exitstatus = RLM_MODULE_FAIL;
		}
	}
	

	PUTBACK;
	FREETMPS;
	LEAVE;


	if ((get_hv_content(rad_reply_hv, &vp)) > 0 ) {
		pairmove(&request->reply->vps, &vp);
		pairfree(&vp);
	}

	if ((get_hv_content(rad_check_hv, &vp)) > 0 ) {
		pairmove(&request->config_items, &vp);
		pairfree(&vp);
	}
	
	if ((get_hv_content(rad_request_proxy_reply_hv, &vp)) > 0 && request->proxy_reply != NULL) {
		pairfree(&request->proxy_reply->vps);
		pairmove(&request->proxy_reply->vps, &vp);
		pairfree(&vp);
	}
	}
#ifdef USE_ITHREADS
	pool_release(handle,instance);
	radlog(L_DBG,"Unreserve perl at address 0x%lx", (unsigned long) handle->clone);
#endif

	return exitstatus;
}
Exemple #15
0
void
sproto_release(struct sproto * s) {
	if (s == NULL)
		return;
	pool_release(&s->memory);
}
int bacstack_session_init(bacstack_session_t *session)
{
  int ret = 1;
  memset(session, 0, sizeof(*session));

  /* this setting sets the range that is used
   * as the network numbers of directly attached netork.
   * For example, if this value is set to 1000, then
   * the network out of port 0 will be assigned
   * network number 1000. The network out of port
   * 100 would be assigned network number 1100. This
   * number must be chosen to not conflict with
   * existing network numbers on the BACnet network */
  session->local_networks_origin = 65535 - 255;


  if(!rwlock_init(&session->routetable_lock)) {
    ret = 0;
    goto done;
  }
  
  if(!bacstack_routetable_init(&session->routetable, 2048)) {
    ret = 0;
    goto done;
  }

  if(!pool_init(&session->message_pool, BACSTACK_SESSION_MESSAGE_POOL_CAPACITY)) {
    ret = 0;
    goto done;
  }

  for(int i = 0; i < BACSTACK_SESSION_MESSAGE_POOL_CAPACITY; i++) {
    bacstack_message_t *message = malloc(sizeof(bacstack_message_t));
    if(message == NULL || !bacstack_message_init(message)) {
      ret = 0;
      goto done;
    }

    if(!pool_release(&session->message_pool, message)) {
      ret = 0;
      goto done;
    }
  }

  if(!pool_init(&session->proc_pool, BACSTACK_SESSION_MESSAGE_POOL_CAPACITY)) {
    ret = 0;
    goto done;
  }

  if(!bacdl_server_init(&session->dl_server, 54321)) {
    ret = 0;
    goto done;
  }

  if(!thread_init(&session->msg_proc_thread, bacstack_session_msg_proc_thread_handler, session)) {
    ret = 0;
    goto done;
  }

  if(!thread_init(&session->dl_accept_thread, bacstack_session_dl_accept_thread_handler, session)) {
    ret = 0;
    goto done;
  }

  if(!thread_init(&session->dl_receive_thread, bacstack_session_dl_receive_thread_handler, session)) {
    ret = 0;
    goto done;
  }

done:
  if(!ret){
    rwlock_destroy(&session->routetable_lock);
    bacstack_routetable_destroy(&session->routetable);
    pool_destroy(&session->message_pool);
    pool_destroy(&session->proc_pool);
    bacdl_server_destroy(&session->dl_server);
    thread_destroy(&session->msg_proc_thread);
    thread_destroy(&session->dl_accept_thread);
    thread_destroy(&session->dl_receive_thread);
  }
  return ret;
}
Exemple #17
0
static void release(IQueue *queue) {
	Queue* q = itos(queue);
	mutex_release(q->mutex);
	pool_release(q->pool);
	free(q);
}
Exemple #18
0
/*
 * The xlat function
 */
static int perl_xlat(void *instance, REQUEST *request, char *fmt, char * out,
		     size_t freespace, RADIUS_ESCAPE_STRING func)
{

	PERL_INST	*inst= (PERL_INST *) instance;
	PerlInterpreter *perl;
	char		params[1024], *ptr, *tmp;
	int		count, ret=0;
	STRLEN		n_a;

	/*
	 * Do an xlat on the provided string (nice recursive operation).
	*/
	if (!radius_xlat(params, sizeof(params), fmt, request, func)) {
		radlog(L_ERR, "rlm_perl: xlat failed.");
		return 0;
	}
#ifndef USE_ITHREADS
	perl = inst->perl;
#endif
#ifdef USE_ITHREADS
	POOL_HANDLE	*handle;

	if ((handle = pool_pop(instance)) == NULL) {
		return 0;
	}

	perl = handle->clone;

	radlog(L_DBG,"Found a interpetator 0x%lx",(unsigned long) perl);
	{
	dTHXa(perl);
	}
#endif
	PERL_SET_CONTEXT(perl);
	{
	dSP;
	ENTER;SAVETMPS;

	ptr = strtok(params, " ");

	PUSHMARK(SP);

	while (ptr != NULL) {
		XPUSHs(sv_2mortal(newSVpv(ptr,0)));
		ptr = strtok(NULL, " ");
	}

	PUTBACK;

	count = call_pv(inst->func_xlat, G_SCALAR | G_EVAL);

	SPAGAIN;
	if (SvTRUE(ERRSV)) {
		radlog(L_ERR, "rlm_perl: perl_xlat exit %s\n",
		       SvPV(ERRSV,n_a));
		POPs ;
	} else if (count > 0) {
		tmp = POPp;
		ret = strlen(tmp);
		strncpy(out,tmp,ret);

		radlog(L_DBG,"rlm_perl: Len is %d , out is %s freespace is %d",
		       ret, out,freespace);
	}

	PUTBACK ;
	FREETMPS ;
	LEAVE ;

	}
#ifdef USE_ITHREADS
	pool_release(handle, instance);
#endif
	return ret;
}
Exemple #19
0
/**
 *  @note	The disposition parameter marks whether or not the signature is currently marked as junk.
 *  		So training the signature means that it will toggle its status.
 *  @param	usernum			the numerical id of the user making the spam training request.
 *  @param	disposition		if 0, dspam will mark the signature as junk; otherwise, mark as OK.
 *  @param	signature		a managed string containing the spam signature to be trained.
 *  @return	true on success or false on failure.
 */
bool_t dspam_train(uint64_t usernum, int_t disposition, stringer_t *signature) {

	int_t ret;
	DSPAM_CTX *ctx;
	chr_t unum[20];
	stringer_t *tmpdir;
	uint32_t connection;
	struct _mysql_drv_dbh dbh;
	struct _ds_spam_signature sig;

	// Generate a string version of the dispatch number.
	if (snprintf(unum, 20, "%lu", usernum) <= 0 || !(tmpdir = spool_path(MAGMA_SPOOL_DATA))) {
		log_pedantic("Context setup error.");
		return false;
	}
	// Initialize the DSPAM context.
	else if (!(ctx = dspam_create_d(unum, NULL, st_char_get(tmpdir), DSM_PROCESS, DSF_SIGNATURE | DSF_NOISE | DSF_WHITELIST))) {
		log_pedantic("An error occurred inside the DSPAM library. {dspam_create = NULL}");
		st_free(tmpdir);
		return false;
 	}

	st_free(tmpdir);

	// Get a DB connection.
	if (pool_pull(sql_pool, &connection) != PL_RESERVED) {
		log_info("Unable to get an available connection for the query.");
		dspam_destroy_d(ctx);
		return false;
	}
	else if (sql_ping(connection) < 0 || !stmt_rebuild(connection)) {
		log_info("The database connection has been lost and the reconnection attempt failed.");
		dspam_destroy_d(ctx);
		return false;
	}

	// Setup the database handle in a structure format.
	dbh.dbh_read = pool_get_obj(sql_pool, connection);
	dbh.dbh_write = pool_get_obj(sql_pool, connection);

	if ((ret = dspam_attach_d(ctx, &dbh))) {

		if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}

		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while attaching to the statistical database. {dspam_attach = %i}", ret);
		dspam_destroy_d(ctx);
		return false;
	}

	// Tokenization method and statistical algorithm.
	ctx->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
	ctx->tokenizer = DSZ_CHAIN;

	// Setup the classification as opposite of what the original was.
	ctx->classification = disposition ? DSR_ISINNOCENT : DSR_ISSPAM;

	// Set up the context for error correction.
	ctx->source = DSS_ERROR;

	// Setup the signature.
	sig.length = st_length_get(signature);
	sig.data = st_char_get(signature);
	ctx->signature = &sig;

	// Call DSPAM, and then destroy the context.
	ret = dspam_process_d(ctx, NULL);
	dspam_detach_d(ctx);
	dspam_destroy_d(ctx);
	pool_release(sql_pool, connection);

	if (ret) {
		log_pedantic("An error occurred while training message signature. {dspam_process = %i}", ret);
		return false;
	}

	return true;
}
Exemple #20
0
/// HIGH: Return a result structure with the disposition, confidence, probability and signature data. Then store the analysis result with the message. Either in the DB or
/// by adding a custom header to the message. Return codes should become 0 for success, or a negative integer for errors. Add statistical updates to check and train functions.
/// Result: result=\"%s\"; class=\"%s\"; probability=%01.4f; confidence=%02.2f; signature=%lu; key=%lu;
/// Layman's terms: How spammy is this message
int_t dspam_check(uint64_t usernum, stringer_t *message, stringer_t **signature) {

	DSPAM_CTX *ctx;
	chr_t unum[20];
	uint32_t connection;
	int_t result = 2, ret;
	struct _mysql_drv_dbh dbh;
	stringer_t *tmpdir, *output;

	// Generate a string version of the dispatch number.
	if (snprintf(unum, 20, "%lu", usernum) <= 0 || !(tmpdir = spool_path(MAGMA_SPOOL_DATA))) {
		log_pedantic("Context setup error.");
		return -1;
	}
	// Initialize the DSPAM context.
	else if (!(ctx = dspam_create_d(unum, NULL, st_char_get(tmpdir), DSM_PROCESS, DSF_SIGNATURE | DSF_NOISE | DSF_WHITELIST))) {
		log_pedantic("An error occurred inside the DSPAM library. {dspam_create = NULL}");
		st_free(tmpdir);
    return -1;
 	}

	st_free(tmpdir);

	if (pool_pull(sql_pool, &connection) != PL_RESERVED) {
		log_info("Unable to get an available connection for the query.");
		dspam_destroy_d(ctx);
		return -1;
	}
	else if (sql_ping(connection) < 0 || !stmt_rebuild(connection)) {
		log_info("The database connection has been lost and the reconnection attempt failed.");
		dspam_destroy_d(ctx);
		return -1;
	}

	// Setup the database handle in a structure format.
	dbh.dbh_read = pool_get_obj(sql_pool, connection);
	dbh.dbh_write = pool_get_obj(sql_pool, connection);

	if ((ret = dspam_attach_d(ctx, &dbh))) {
   	if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}
		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while attaching to the statistical database. {dspam_attach = %i}", ret);
		dspam_destroy_d(ctx);
		return -1;
  }

	// Tokenization method and statistical algorithm.
	ctx->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
	ctx->tokenizer = DSZ_CHAIN;

	// To prevent the message tokens from being stored in the database we disable training.
	ctx->training_mode = DST_NOTRAIN;

	// This actually processes the message.
	if ((ret = dspam_process_d(ctx, st_char_get(message)))) {
		if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}
		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while analyzing an email with DSPAM. {dspam_process = %i}", ret);
		dspam_destroy_d(ctx);
    return -1;
	}

	// We assume that the SQL connection will no longer be needed.
	if ((ret = dspam_detach_d(ctx))) {
		log_pedantic("Could not detach the DB connection. {dspam_detach = %i}", ret);
		pool_release(sql_pool, connection);
		dspam_destroy_d(ctx);
    return -1;
	}

	// Return the connection to our pool.
	pool_release(sql_pool, connection);

	// Check to see if the message is junk mail.
	if (ctx->result == DSR_ISSPAM) {
		result = -2;
	}
	else {
		result = 1;
	}

	//log_pedantic("Probability: %2.4f Confidence: %2.4f, Result: %s", ctx->probability, ctx->confidence,
 	//	(ctx->result == DSR_ISSPAM) ? "JUNK" : "INNOCENT");

	// See what happens if we don't get a signature back.
	if (ctx->signature == NULL) {
		log_error("DSPAM did not return a signature. {ctx->signature = NULL}");
		dspam_destroy_d(ctx);
    return result;
  }

	// Copy over the signature.
	if (!(output = st_import(ctx->signature->data, ctx->signature->length))) {
		log_pedantic("Could not import the statistical signature. {length = %lu}", ctx->signature->length);
		dspam_destroy_d(ctx);
		return result;
  }

	if (signature) {
		*signature = output;
	}

	// Destroy the context and return the result.
	dspam_destroy_d(ctx);
	return result;
}
void net_packet_release(net_socket_t s, net_packet_t p)
{
	pool_release(s->poolPackets, p);
}