Ejemplo n.º 1
0
static int
write_db_file(const char *reason)
{
    Objid oid;
    Objid max_oid = db_last_used_objid();
    Verbdef *v;
    Var user_list;
    int i;
    volatile int nprogs = 0;
    volatile int success = 1;

    for (oid = 0; oid <= max_oid; oid++) {
        if (valid(oid))
            for (v = dbpriv_find_object(oid)->verbdefs; v; v = v->next)
                if (v->program)
                    nprogs++;
    }

    user_list = db_all_users();

    TRY {
        dbio_printf(header_format_string, current_db_version);
        dbio_printf("%d\n%d\n%d\n%d\n",
        max_oid + 1, nprogs, 0, user_list.v.list[0].v.num);
        for (i = 1; i <= user_list.v.list[0].v.num; i++)
            dbio_write_objid(user_list.v.list[i].v.obj);
        oklog("%s: Writing %d objects...\n", reason, max_oid + 1);
        for (oid = 0; oid <= max_oid; oid++) {
            write_object(oid);
            if (oid == max_oid || log_report_progress())
                oklog("%s: Done writing %d objects...\n", reason, oid + 1);
        }
        oklog("%s: Writing %d MOO verb programs...\n", reason, nprogs);
        for (i = 0, oid = 0; oid <= max_oid; oid++)
            if (valid(oid)) {
                int vcount = 0;

                for (v = dbpriv_find_object(oid)->verbdefs; v; v = v->next) {
                    if (v->program) {
                        dbio_printf("#%d:%d\n", oid, vcount);
                        dbio_write_program(v->program);
                        if (++i == nprogs || log_report_progress())
                            oklog("%s: Done writing %d verb programs...\n",
                            reason, i);
                    }
                    vcount++;
                }
            }
        oklog("%s: Writing forked and suspended tasks...\n", reason);
        write_task_queue();
        oklog("%s: Writing list of formerly active connections...\n", reason);
        write_active_connections();
    }
    EXCEPT(dbpriv_dbio_failed)
    success = 0;
    ENDTRY;

    return success;
}
Ejemplo n.º 2
0
static int
validate_hierarchies()
{
    Objid oid, log_oid;
    Objid size = db_last_used_objid() + 1;
    int broken = 0;
    int fixed_nexts = 0;

    oklog("VALIDATING the object hierarchies ...\n");

#   define PROGRESS_INTERVAL 10000
#   define MAYBE_LOG_PROGRESS					\
    {								\
        if (oid == log_oid) {					\
	    log_oid += PROGRESS_INTERVAL;			\
	    oklog("VALIDATE: Done through #%d ...\n", oid);	\
	}							\
    }

    oklog("VALIDATE: Phase 1: Check for invalid objects ...\n");
    for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
	Object *o = dbpriv_find_object(oid);

	MAYBE_LOG_PROGRESS;
	if (o) {
	    if (o->location == NOTHING && o->next != NOTHING) {
		o->next = NOTHING;
		fixed_nexts++;
	    }
#	    define CHECK(field, name) 					\
	    {								\
	        if (o->field != NOTHING					\
		    && !dbpriv_find_object(o->field)) {			\
		    errlog("VALIDATE: #%d.%s = #%d <invalid> ... fixed.\n", \
			   oid, name, o->field);			\
		    o->field = NOTHING;				  	\
		}							\
	    }

	    CHECK(parent, "parent");
	    CHECK(child, "child");
	    CHECK(sibling, "sibling");
	    CHECK(location, "location");
	    CHECK(contents, "contents");
	    CHECK(next, "next");

#	    undef CHECK
	}
    }

    if (fixed_nexts != 0)
	errlog("VALIDATE: Fixed %d should-be-null next pointer(s) ...\n",
	       fixed_nexts);

    /*
     * The next two phases are only done if the moo is launched with -r
     * and can be used with DBs that have broken hierarchies.
     */
    if (recovery_mode) {
    oklog("EMERGENCY REBUILD PHASE 1: Removing old contents and child lists ...\n");
    for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);
        
        MAYBE_LOG_PROGRESS;
        if (o) {
           o->contents = NOTHING;
           o->next = NOTHING;
           o->child = NOTHING;
           o->sibling = NOTHING;
        }
    }

    oklog("EMERGENCY REBUILD PHASE 2: Rebuilding contents and child lists ...\n");
    for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);

        MAYBE_LOG_PROGRESS;
        if (o) {
            /* find this obj's parent & loc */
         
            Objid parent = o->parent;
            Objid location = o->location;

            if (parent != NOTHING) {
              Object *po = dbpriv_find_object(parent);
              Objid lastchild = po->lastchild;
              
              if (lastchild != NOTHING) {
                 Object *co = dbpriv_find_object(lastchild);

                 co->sibling = oid;
                 po->lastchild = oid;
              }
              else {
                 po->child = oid;
                 po->lastchild = oid;
              }
           }
        
            if (location != NOTHING) {
              Object *lo = dbpriv_find_object(location);
              Objid lastcontents = lo->lastcontents;

              if (lastcontents != NOTHING) {
                 Object *co = dbpriv_find_object(lastcontents);

                 co->next = oid;
                 lo->lastcontents = oid;
              }
              else {
                 lo->contents = oid;
                 lo->lastcontents = oid;
              }
           }
         
        } /* endif o */
    } /* for oid */              
    } /* recovery_mode */ 

    oklog("VALIDATE: Phase 2: Check for cycles ...\n");
    for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
	Object *o = dbpriv_find_object(oid);
	Objid list_end;

	MAYBE_LOG_PROGRESS;
	if (o) {

#	    define CHECK(start, field, name)				\
	    {								\
	        Objid	oid2 = start;					\
		int	count = 0;					\
	        for (; oid2 != NOTHING					\
		     ; oid2 = dbpriv_find_object(oid2)->field) {	\
		    if (++count > size)	{				\
			errlog("VALIDATE: Cycle in `%s' chain of #%d\n",\
			       name, oid);				\
			broken = 1;					\
			break;						\
		    }							\
		    list_end = oid2;					\
		}							\
	    }

	    CHECK(o->parent, parent, "parent");

	    list_end = NOTHING;
	    CHECK(o->child, sibling, "child");
	    o->lastchild = list_end;

	    CHECK(o->location, location, "location");

	    list_end = NOTHING;
	    CHECK(o->contents, next, "contents");
	    o->lastcontents = list_end;

#	    undef CHECK
	}
    }

    if (broken)			/* Can't continue if cycles found */
	return 0;

    oklog("VALIDATING the object hierarchies ... finished.\n");
    return !broken;
}
Ejemplo n.º 3
0
static int
read_object(void)
{
    Objid oid;
    Object *o;
    char s[20];
    int i;
    Verbdef *v, **prevv;
    int nprops;

    if (dbio_scanf("#%d", &oid) != 1 || oid != db_last_used_objid() + 1)
	return 0;
    dbio_read_line(s, sizeof(s));

    if (strcmp(s, " recycled\n") == 0) {
	dbpriv_new_recycled_object();
	return 1;
    } else if (strcmp(s, "\n") != 0)
	return 0;

    o = dbpriv_new_object();
    o->name = dbio_read_string_intern();
    (void) dbio_read_string();	/* discard old handles string */
    o->flags = dbio_read_num();

    o->owner = dbio_read_objid();

    o->location = dbio_read_objid();
    o->contents = dbio_read_objid();
    o->next = dbio_read_objid();
    o->lastcontents = NOTHING;

    o->parent = dbio_read_objid();
    o->child = dbio_read_objid();
    o->sibling = dbio_read_objid();
    o->lastchild = NOTHING;

    o->verbdefs = 0;
    prevv = &(o->verbdefs);
    for (i = dbio_read_num(); i > 0; i--) {
	v = mymalloc(sizeof(Verbdef), M_VERBDEF);
	read_verbdef(v);
	*prevv = v;
	prevv = &(v->next);
    }

    o->propdefs.cur_length = 0;
    o->propdefs.max_length = 0;
    o->propdefs.l = 0;
    if ((i = dbio_read_num()) != 0) {
	o->propdefs.l = mymalloc(i * sizeof(Propdef), M_PROPDEF);
	o->propdefs.cur_length = i;
	o->propdefs.max_length = i;
	for (i = 0; i < o->propdefs.cur_length; i++)
	    o->propdefs.l[i] = read_propdef();
    }
    nprops = dbio_read_num();
    if (nprops)
	o->propval = mymalloc(nprops * sizeof(Pval), M_PVAL);
    else
	o->propval = 0;

    for (i = 0; i < nprops; i++) {
	read_propval(o->propval + i);
    }

    return 1;
}
Ejemplo n.º 4
0
static int
validate_hierarchies()
{
    Objid oid;
    Objid size = db_last_used_objid() + 1;
    int broken = 0;
    int fixed_nexts = 0;

    oklog("VALIDATING the object hierarchies ...\n");

#   define MAYBE_LOG_PROGRESS					\
    {								\
        if (log_report_progress()) {				\
	    oklog("VALIDATE: Done through #%d ...\n", oid);	\
	}							\
    }

    oklog("VALIDATE: Phase 1: Check for invalid objects ...\n");
    for (oid = 0; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);

        MAYBE_LOG_PROGRESS;
        if (o) {
            if (o->location == NOTHING && o->next != NOTHING) {
                o->next = NOTHING;
                fixed_nexts++;
            }
#	    define CHECK(field, name) 					\
	    {								\
	        if (o->field != NOTHING					\
		    && !dbpriv_find_object(o->field)) {			\
		    errlog("VALIDATE: #%d.%s = #%d <invalid> ... fixed.\n", \
			   oid, name, o->field);			\
		    o->field = NOTHING;				  	\
		}							\
	    }

            CHECK(parent, "parent");
            CHECK(child, "child");
            CHECK(sibling, "sibling");
            CHECK(location, "location");
            CHECK(contents, "contents");
            CHECK(next, "next");

#	    undef CHECK
        }
    }

    if (fixed_nexts != 0)
        errlog("VALIDATE: Fixed %d should-be-null next pointer(s) ...\n",
               fixed_nexts);

    oklog("VALIDATE: Phase 2: Check for cycles ...\n");
    for (oid = 0; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);

        MAYBE_LOG_PROGRESS;
        if (o) {
#	    define CHECK(start, field, name)			\
	    {							\
		Objid slower = start;				\
		Objid faster = slower;				\
		while (faster != NOTHING) {			\
		    faster = dbpriv_find_object(faster)->field;	\
		    if (faster == NOTHING)			\
			break;					\
		    faster = dbpriv_find_object(faster)->field;	\
		    slower = dbpriv_find_object(slower)->field;	\
		    if (faster == slower) {			\
			errlog("VALIDATE: Cycle in `%s' chain of #%d\n", \
			       name, oid);			\
			broken = 1;				\
			break;					\
		    }						\
		}						\
	    }

            CHECK(o->parent, parent, "parent");
            CHECK(o->child, sibling, "child");
            CHECK(o->location, location, "location");
            CHECK(o->contents, next, "contents");

#	    undef CHECK

            /* setup for phase 3:  set two temp flags on every object */
            o->flags |= (3<<FLAG_FIRST_TEMP);
        }
    }

    if (broken)			/* Can't continue if cycles found */
        return 0;

    oklog("VALIDATE: Phase 3a: Finding delusional parents ...\n");
    for (oid = 0; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);

        MAYBE_LOG_PROGRESS;
        if (o) {
#	    define CHECK(up, down, down_name, across, FLAG)	\
	    {							\
		Objid	oidkid;					\
		Object *okid;					\
								\
		for (oidkid = o->down;				\
		     oidkid != NOTHING;				\
		     oidkid = okid->across) {			\
								\
		    okid = dbpriv_find_object(oidkid);		\
		    if (okid->up != oid) {			\
			errlog(					\
			    "VALIDATE: #%d erroneously on #%d's %s list.\n", \
			    oidkid, oid, down_name);		\
			broken = 1;				\
		    }						\
		    else {					\
			/* mark okid as properly claimed */	\
			okid->flags &= ~(1<<(FLAG));		\
		    }						\
		}						\
	    }

            CHECK(parent,   child,    "child",    sibling, FLAG_FIRST_TEMP);
            CHECK(location, contents, "contents", next,    FLAG_FIRST_TEMP+1);

#	    undef CHECK
        }
    }

    oklog("VALIDATE: Phase 3b: Finding delusional children ...\n");
    for (oid = 0; oid < size; oid++) {
        Object *o = dbpriv_find_object(oid);

        MAYBE_LOG_PROGRESS;
        if (o) {
#	    define CHECK(up, up_name, down_name, FLAG)			\
	    {								\
		/* If oid is unclaimed, up must be NOTHING */		\
		if ((o->flags & (1<<(FLAG))) && o->up != NOTHING) {	\
		    errlog("VALIDATE: #%d not in %s (#%d)'s %s list.\n", \
			   oid, up_name, o->up, down_name);		\
		    broken = 1;						\
		}							\
	    }

            CHECK(parent,   "parent",   "child",    FLAG_FIRST_TEMP);
            CHECK(location, "location", "contents", FLAG_FIRST_TEMP+1);

            /* clear temp flags */
            o->flags &= ~(3<<FLAG_FIRST_TEMP);

#	    undef CHECK
        }
    }

    oklog("VALIDATING the object hierarchies ... finished.\n");
    return !broken;
}