int
db_dirdelete(struct db_i *dbip, struct directory *dp)
{
    struct directory *findp;
    struct directory **headp;

    RT_CK_DBI(dbip);
    RT_CK_DIR(dp);

    headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]);

    if (dp->d_flags & RT_DIR_INMEM) {
	if (dp->d_un.ptr != NULL)
	    bu_free(dp->d_un.ptr, "db_dirdelete() inmem ptr");
    }

    if (*headp == dp) {
	RT_DIR_FREE_NAMEP(dp);	/* frees d_namep */
	*headp = dp->d_forw;

	/* Put 'dp' back on the freelist */
	dp->d_forw = rt_uniresource.re_directory_hd;
	rt_uniresource.re_directory_hd = dp;
	return 0;
    }
    for (findp = *headp; findp != RT_DIR_NULL; findp = findp->d_forw) {
	if (findp->d_forw != dp)
	    continue;
	RT_DIR_FREE_NAMEP(dp);	/* frees d_namep */
	findp->d_forw = dp->d_forw;

	/* Put 'dp' back on the freelist */
	dp->d_forw = rt_uniresource.re_directory_hd;
	rt_uniresource.re_directory_hd = dp;
	return 0;
    }
    return -1;
}
int
db_rename(struct db_i *dbip, struct directory *dp, const char *newname)
{
    struct directory *findp;
    struct directory **headp;

    RT_CK_DBI(dbip);
    RT_CK_DIR(dp);

    /* Remove from linked list */
    headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]);
    if (*headp == dp) {
	/* Was first on list, dequeue */
	*headp = dp->d_forw;
    } else {
	for (findp = *headp; findp != RT_DIR_NULL; findp = findp->d_forw) {
	    if (findp->d_forw != dp)
		continue;
	    /* Dequeue */
	    findp->d_forw = dp->d_forw;
	    goto out;
	}
	return -1;		/* ERROR: can't find */
    }

out:
    /* Effect new name */
    RT_DIR_FREE_NAMEP(dp);			/* frees d_namep */
    RT_DIR_SET_NAMEP(dp, newname);	/* sets d_namep */

    /* Add to new linked list */
    headp = &(dbip->dbi_Head[db_dirhash(newname)]);
    dp->d_forw = *headp;
    *headp = dp;
    return 0;
}
Esempio n. 3
0
void
db_close(register struct db_i *dbip)
{
    register int i;
    register struct directory *dp, *nextdp;

    if (!dbip)
	return;

    RT_CK_DBI(dbip);
    if (RT_G_DEBUG&DEBUG_DB) bu_log("db_close(%s) %p uses=%d\n",
				    dbip->dbi_filename, (void *)dbip, dbip->dbi_uses);

    bu_semaphore_acquire(BU_SEM_LISTS);
    if ((--dbip->dbi_uses) > 0) {
	bu_semaphore_release(BU_SEM_LISTS);
	/* others are still using this database */
	return;
    }
    bu_semaphore_release(BU_SEM_LISTS);

    /* ready to free the database -- use count is now zero */

    /* free up any mapped files */
    if (dbip->dbi_mf) {
	/*
	 * We're using an instance of a memory mapped file.
	 * We have two choices:
	 * Either dissociate from the memory mapped file
	 * by clearing dbi_mf->apbuf, or
	 * keeping our already-scanned dbip ready for
	 * further use, with our dbi_uses counter at 0.
	 * For speed of re-open, at the price of some address space,
	 * the second choice is taken.
	 */
	bu_close_mapped_file(dbip->dbi_mf);
	bu_free_mapped_files(0);
	dbip->dbi_mf = (struct bu_mapped_file *)NULL;
    }

    /* try to ensure/encourage that the file is written out */
    db_sync(dbip);

    if (dbip->dbi_fp) {
	fclose(dbip->dbi_fp);
    }

    if (dbip->dbi_title)
	bu_free(dbip->dbi_title, "dbi_title");
    if (dbip->dbi_filename)
	bu_free(dbip->dbi_filename, "dbi_filename");

    db_free_anim(dbip);
    rt_color_free();		/* Free MaterHead list */

    /* Release map of database holes */
    rt_mempurge(&(dbip->dbi_freep));
    rt_memclose();

    dbip->dbi_inmem = NULL;		/* sanity */

    bu_ptbl_free(&dbip->dbi_clients);

    /* Free all directory entries */
    for (i = 0; i < RT_DBNHASH; i++) {
	for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL;) {
	    RT_CK_DIR(dp);
	    nextdp = dp->d_forw;
	    RT_DIR_FREE_NAMEP(dp);	/* frees d_namep */

	    if ((dp->d_flags & RT_DIR_INMEM) && (dp->d_un.ptr != NULL)) {
		bu_free(dp->d_un.ptr, "db_close d_un.ptr");
		dp->d_un.ptr = NULL;
		dp->d_len    = 0;
	    }

	    /* Put 'dp' back on the freelist */
	    dp->d_forw = rt_uniresource.re_directory_hd;
	    rt_uniresource.re_directory_hd = dp;

	    /* null'ing the forward pointer here is a huge
	     * memory leak as it causes the loss of all
	     * nodes on the freelist except the first.
	     * (so don't do it)
	     */

	    dp = nextdp;
	}
	dbip->dbi_Head[i] = RT_DIR_NULL;	/* sanity*/
    }

    if (dbip->dbi_filepath != NULL) {
	bu_free_argv(2, dbip->dbi_filepath);
	dbip->dbi_filepath = NULL; /* sanity */
    }

    bu_free((char *)dbip, "struct db_i");
}