summaryrefslogtreecommitdiff
path: root/db2/log/log_register.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/log/log_register.c')
-rw-r--r--db2/log/log_register.c199
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);
+}