diff options
Diffstat (limited to 'db2/log/log_register.c')
-rw-r--r-- | db2/log/log_register.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/db2/log/log_register.c b/db2/log/log_register.c new file mode 100644 index 0000000000..582eab9408 --- /dev/null +++ b/db2/log/log_register.c @@ -0,0 +1,199 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 1997 + * Sleepycat Software. All rights reserved. + */ +#include "config.h" + +#ifndef lint +static const char sccsid[] = "@(#)log_register.c 10.10 (Sleepycat) 8/20/97"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#endif + +#include "db_int.h" +#include "shqueue.h" +#include "log.h" +#include "common_ext.h" + +/* + * log_register -- + * Register a file name. + */ +int +log_register(dblp, dbp, name, type, idp) + DB_LOG *dblp; + DB *dbp; + const char *name; + DBTYPE type; + u_int32_t *idp; +{ + DBT r_name; + DBT fid_dbt; + DB_LSN r_unused; + FNAME *fnp; + size_t len; + u_int32_t fid; + int inserted, ret; + char *fullname; + void *fidp, *namep; + + fid = 0; + inserted = 0; + fullname = NULL; + fnp = fidp = namep = NULL; + + /* Check the arguments. */ + if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) { + __db_err(dblp->dbenv, "log_register: unknown DB file type"); + return (EINVAL); + } + + /* Get the log file id. */ + if ((ret = __db_appname(dblp->dbenv, + DB_APP_DATA, NULL, name, NULL, &fullname)) != 0) + return (ret); + + LOCK_LOGREGION(dblp); + + /* + * See if we've already got this file in the log, finding the + * next-to-lowest file id currently in use as we do it. + */ + for (fid = 1, fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); + fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { + if (fid <= fnp->id) + fid = fnp->id + 1; + if (!memcmp(dbp->lock.fileid, + ADDR(dblp, fnp->fileid_off), DB_FILE_ID_LEN)) { + ++fnp->ref; + fid = fnp->id; + if (!F_ISSET(dblp, DB_AM_RECOVER) && + (ret = __log_add_logid(dblp, dbp, fid) != 0)) + goto err; + goto ret1; + } + } + + /* Allocate a new file name structure. */ + if ((ret = __db_shalloc(dblp->addr, sizeof(FNAME), 0, &fnp)) != 0) + goto err; + fnp->ref = 1; + fnp->id = fid; + fnp->s_type = type; + + if ((ret = __db_shalloc(dblp->addr, DB_FILE_ID_LEN, 0, &fidp)) != 0) + goto err; + /* + * XXX Now that uids are fixed size, we can put them in the fnp + * structure. + */ + fnp->fileid_off = OFFSET(dblp, fidp); + memcpy(fidp, dbp->lock.fileid, DB_FILE_ID_LEN); + + len = strlen(name) + 1; + if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0) + goto err; + fnp->name_off = OFFSET(dblp, namep); + memcpy(namep, name, len); + + SH_TAILQ_INSERT_HEAD(&dblp->lp->fq, fnp, q, __fname); + inserted = 1; + + /* Log the registry. */ + if (!F_ISSET(dblp, DB_AM_RECOVER)) { + r_name.data = (void *)name; /* XXX: Yuck! */ + r_name.size = strlen(name) + 1; + memset(&fid_dbt, 0, sizeof(fid_dbt)); + fid_dbt.data = dbp->lock.fileid; + fid_dbt.size = DB_FILE_ID_LEN; + if ((ret = __log_register_log(dblp, NULL, &r_unused, + 0, &r_name, &fid_dbt, fid, type)) != 0) + goto err; + if ((ret = __log_add_logid(dblp, dbp, fid)) != 0) + goto err; + } + + if (0) { +err: /* + * XXX + * We should grow the region. + */ + if (inserted) + SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname); + if (namep != NULL) + __db_shalloc_free(dblp->addr, namep); + if (fidp != NULL) + __db_shalloc_free(dblp->addr, fidp); + if (fnp != NULL) + __db_shalloc_free(dblp->addr, fnp); + } + +ret1: UNLOCK_LOGREGION(dblp); + + if (fullname != NULL) + FREES(fullname); + + if (idp != NULL) + *idp = fid; + return (ret); +} + +/* + * log_unregister -- + * Discard a registered file name. + */ +int +log_unregister(dblp, fid) + DB_LOG *dblp; + u_int32_t fid; +{ + DB_LSN r_unused; + FNAME *fnp; + int ret; + + ret = 0; + LOCK_LOGREGION(dblp); + + /* Unlog the registry. */ + if (!F_ISSET(dblp, DB_AM_RECOVER) && + (ret = __log_unregister_log(dblp, NULL, &r_unused, 0, fid)) != 0) + return (ret); + + /* Find the entry in the log. */ + for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); + fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) + if (fid == fnp->id) + break; + if (fnp == NULL) { + __db_err(dblp->dbenv, "log_unregister: non-existent file id"); + ret = EINVAL; + goto ret1; + } + + /* If more than 1 reference, decrement the reference and return. */ + if (fnp->ref > 1) { + --fnp->ref; + goto ret1; + } + + /* Free the unique file information, name and structure. */ + __db_shalloc_free(dblp->addr, ADDR(dblp, fnp->fileid_off)); + __db_shalloc_free(dblp->addr, ADDR(dblp, fnp->name_off)); + SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname); + __db_shalloc_free(dblp->addr, fnp); + + /* Remove from the process local table. */ + __log_rem_logid(dblp, fid); + +ret1: UNLOCK_LOGREGION(dblp); + + return (ret); +} |