Пример #1
0
/*
 * Swap out an object. Only the program is swapped, not the 'object_t'.
 *
 * marion - the swap seems to corrupt the function table
 */
int swap(object_t *  ob)
{
    /* the simuls[] table uses pointers to the functions so the simul_efun
     * program cannot be relocated.  locate_in() could be changed to
     * correct this or simuls[] could use offsets, but it doesn't seem
     * worth it just to get the simul_efun object to swap.  Maybe later.
     *
     * Ditto the master object and master_applies[].  Mudlibs that have
     * a period TIME_TO_SWAP between successive master applies must be
     * extremely rare ...
     */
    if (ob == simul_efun_ob || ob == master_ob) return 0;
    if (ob->flags & O_DESTRUCTED)
	return 0;
    debug(d_flag, ("Swap object /%s (ref %d)", ob->name, ob->ref));

    if (ob->prog->line_info)
	swap_line_numbers(ob->prog);	/* not always done before we get here */
    if ((ob->flags & O_HEART_BEAT) || (ob->flags & O_CLONE)) {
	debug(d_flag, ("  object not swapped - heart beat or cloned."));
	return 0;
    }
    if (ob->prog->ref > 1 || ob->interactive) {
	debug(d_flag, ("  object not swapped - inherited or interactive or in apply_low() cache."));

	return 0;
    }
    if (ob->prog->func_ref > 0) {
	debug(d_flag, ("  object not swapped - referenced by functions."));

	return 0;
    }
    locate_out(ob->prog);	/* relocate the internal pointers */
    if (swap_out((char *) ob->prog, ob->prog->total_size, (int *) &ob->swap_num)) {
	num_swapped++;
	free_prog(ob->prog, 0);	/* Do not free the strings */
	ob->prog = 0;
	ob->flags |= O_SWAPPED;
	return 1;
    } else {
	locate_in(ob->prog);
	return 0;
    }
}
Пример #2
0
/*
 * Despite the name, this routine takes care of several things.
 * It will run once every 15 minutes.
 *
 * . It will attempt to reconnect to the address server if the connection has
 *   been lost.
 * . It will loop through all objects.
 *
 *   . If an object is found in a state of not having done reset, and the
 *     delay to next reset has passed, then reset() will be done.
 *
 *   . If the object has a existed more than the time limit given for swapping,
 *     then 'clean_up' will first be called in the object, after which it will
 *     be swapped out if it still exists.
 *
 * There are some problems if the object self-destructs in clean_up, so
 * special care has to be taken of how the linked list is used.
*/
static void look_for_objects_to_swap()
{
    static int next_time;
#ifndef NO_IP_DEMON
    extern int no_ip_demon;
    static int next_server_time;
#endif
    object_t *ob;
    VOLATILE object_t *next_ob;
    error_context_t econ;

#ifndef NO_IP_DEMON
    if (current_time >= next_server_time) {
	/* initialize the address server.  if it is already initialized, then
	 * this is a nop.  this will cause the driver to reattempt connecting
	 * to the address server once every 15 minutes in the event that it
	 * has gone down.
	 */
	if (!no_ip_demon && next_server_time)
	    init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT);
	next_server_time = current_time + 15 * 60;
    }
#endif

    if (current_time < next_time)
	return;			/* Not time to look yet */
    next_time = current_time + 15 * 60;	/* Next time is in 15 minutes */

    /*
     * Objects object can be destructed, which means that next object to
     * investigate is saved in next_ob. If very unlucky, that object can be
     * destructed too. In that case, the loop is simply restarted.
     */
    next_ob = obj_list;
    save_context(&econ);
    if (SETJMP(econ.context))
	restore_context(&econ);
    
    while ((ob = (object_t *)next_ob)) {
	int ready_for_swap = 0;
	int ready_for_clean_up = 0;

	eval_cost = max_cost;

	if (ob->flags & O_DESTRUCTED)
	    ob = obj_list;	/* restart */
	next_ob = ob->next_all;

	/*
	 * Check reference time before reset() is called.
	 */
	if (current_time - ob->time_of_ref > time_to_swap)
	    ready_for_swap = 1;
	if (current_time - ob->time_of_ref > time_to_clean_up)
	    ready_for_clean_up = 1;
#if !defined(NO_RESETS) && !defined(LAZY_RESETS)
	/*
	 * Should this object have reset(1) called ?
	 */
	if ((ob->flags & O_WILL_RESET) && (ob->next_reset < current_time)
	    && !(ob->flags & O_RESET_STATE)) {
	    debug(d_flag, ("RESET /%s\n", ob->name));
	    reset_object(ob);
	    if (ob->flags & O_DESTRUCTED)
		continue;
	}
#endif
	if (time_to_clean_up > 0) {
	    /*
	     * Has enough time passed, to give the object a chance to
	     * self-destruct ? Save the O_RESET_STATE, which will be cleared.
	     * 
	     * Only call clean_up in objects that has defined such a function.
	     * 
	     * Only if the clean_up returns a non-zero value, will it be called
	     * again.
	     */

	    if (ready_for_clean_up && (ob->flags & O_WILL_CLEAN_UP)) {
		int save_reset_state = ob->flags & O_RESET_STATE;
		svalue_t *svp;

		debug(d_flag, ("clean up /%s\n", ob->name));

		/*
		 * Supply a flag to the object that says if this program is
		 * inherited by other objects. Cloned objects might as well
		 * believe they are not inherited. Swapped objects will not
		 * have a ref count > 1 (and will have an invalid ob->prog
		 * pointer).
		 *
		 * Note that if it is in the apply_low cache, it will also
		 * get a flag of 1, which may cause the mudlib not to clean
		 * up the object.  This isn't bad because:
		 * (1) one expects it is rare for objects that have untouched
		 * long enough to clean_up to still be in the cache, especially
		 * on busy MUDs.
		 * (2) the ones that are are the more heavily used ones, so
		 * keeping them around seems justified.
		 */

		push_number(ob->flags & (O_CLONE | O_SWAPPED) ? 0 : ob->prog->ref);
		svp = apply(APPLY_CLEAN_UP, ob, 1, ORIGIN_DRIVER);
		if (ob->flags & O_DESTRUCTED)
		    continue;
		if (!svp || (svp->type == T_NUMBER && svp->u.number == 0))
		    ob->flags &= ~O_WILL_CLEAN_UP;
		ob->flags |= save_reset_state;
	    }
	}
	if (time_to_swap > 0) {
	    /*
	     * At last, there is a possibility that the object can be swapped
	     * out.  Always swap out line number information.  If already
	     * swapped, not time yet, or the object has a heart_beat, don't
	     * swap.
	     */

	    if (ob->prog && ob->prog->line_info)
		swap_line_numbers(ob->prog);
	    if (ob->flags & O_SWAPPED || !ready_for_swap)
		continue;
	    if (ob->flags & O_HEART_BEAT)
		continue;

	    debug(d_flag, ("swap /%s\n", ob->name));
	    swap(ob);		/* See if it is possible to swap out to disk */
	}
    }
    pop_context(&econ);
}				/* look_for_objects_to_swap() */