diff options
Diffstat (limited to 'src/db')
-rw-r--r-- | src/db/sysdb_init.c | 134 | ||||
-rw-r--r-- | src/db/sysdb_private.h | 24 |
2 files changed, 158 insertions, 0 deletions
diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c index cfe6e86fb..b2b845317 100644 --- a/src/db/sysdb_init.c +++ b/src/db/sysdb_init.c @@ -297,6 +297,17 @@ static errno_t sysdb_cache_create_empty(struct ldb_context *ldb, return EOK; } +static errno_t sysdb_ts_cache_upgrade(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + struct ldb_context *ldb, + struct sss_domain_info *domain, + const char *cur_version, + const char **_new_version) +{ + /* Currently the sysdb cache only has one version */ + return EFAULT; +} + static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct ldb_context *ldb, @@ -609,6 +620,114 @@ done: return ret; } +static int sysdb_timestamp_cache_connect(struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + bool allow_upgrade) +{ + errno_t ret; + const char *version; + TALLOC_CTX *tmp_ctx; + struct ldb_context *ldb; + + if (sysdb->ldb_ts_file == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, "No timestamp cache for %s\n", domain->name); + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sysdb_cache_connect(tmp_ctx, domain, + sysdb->ldb_ts_file, LDB_FLG_NOSYNC, + SYSDB_TS_VERSION, SYSDB_TS_BASE_LDIF, + &ldb, &version); + switch (ret) { + case ERR_SYSDB_VERSION_TOO_OLD: + if (allow_upgrade == false) { + DEBUG(SSSDBG_FATAL_FAILURE, + "DB version too old [%s], expected [%s] for domain %s!\n", + version, SYSDB_VERSION, domain->name); + break; + } + + ret = sysdb_ts_cache_upgrade(tmp_ctx, sysdb, ldb, domain, version, + &version); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not upgrade the timestamp ldb file (%d) (%s)\n", + ret, sss_strerror(ret)); + break; + } + + /* The version should now match SYSDB_VERSION. + * If not, it means we didn't match any of the + * known older versions. The DB might be + * corrupt or generated by a newer version of + * SSSD. + */ + ret = sysdb_version_check(SYSDB_TS_VERSION, version); + if (ret == EOK) { + /* The cache has been upgraded. + * We need to reopen the LDB to ensure that + * any changes made above take effect. + */ + ret = sysdb_ldb_reconnect(tmp_ctx, + sysdb->ldb_ts_file, + LDB_FLG_NOSYNC, + &ldb); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not reopen the timestamp ldb file (%d) (%s)\n", + ret, sss_strerror(ret)); + } + } + break; + case ERR_SYSDB_VERSION_TOO_NEW: + DEBUG(SSSDBG_MINOR_FAILURE, + "DB version too new [%s], expected [%s] for domain %s!\n", + version, SYSDB_TS_VERSION, domain->name); + break; + default: + break; + } + + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "The timestamps cache could not be opened. " + "Throwing away the database and opening a new one\n"); + + ret = unlink(sysdb->ldb_ts_file); + if (ret != EOK && errno != ENOENT) { + ret = errno; + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not delete the timestamp ldb file (%d) (%s)\n", + ret, sss_strerror(ret)); + return ret; + } + + /* Now the connect must succeed because the previous cache doesn't + * exist anymore. + */ + ret = sysdb_cache_connect(tmp_ctx, domain, + sysdb->ldb_ts_file, LDB_FLG_NOSYNC, + SYSDB_TS_VERSION, SYSDB_TS_BASE_LDIF, + &ldb, &version); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not delete the timestamp ldb file (%d) (%s)\n", + ret, sss_strerror(ret)); + } + } + + if (ret == EOK) { + sysdb->ldb_ts = talloc_steal(sysdb, ldb); + } + talloc_free(tmp_ctx); + return ret; +} + int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *db_path, @@ -640,6 +759,21 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, "DB File for %s: %s\n", domain->name, sysdb->ldb_file); ret = sysdb_domain_cache_connect(sysdb, domain, allow_upgrade); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not open the sysdb cache [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + ret = sysdb_timestamp_cache_connect(sysdb, domain, allow_upgrade); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not open the timestamp cache [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + done: if (ret == EOK) { *_ctx = talloc_steal(mem_ctx, sysdb); diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h index a78a9be2f..5f7a1ed6f 100644 --- a/src/db/sysdb_private.h +++ b/src/db/sysdb_private.h @@ -84,11 +84,35 @@ "cn: ranges\n" \ "\n" +/* The timestamp cache has its own versioning */ +#define SYSDB_TS_VERSION_0_1 "0.1" + +#define SYSDB_TS_VERSION SYSDB_TS_VERSION_0_1 + +#define SYSDB_TS_BASE_LDIF \ + "dn: @ATTRIBUTES\n" \ + "dn: CASE_INSENSITIVE\n" \ + "\n" \ + "dn: @INDEXLIST\n" \ + "@IDXATTR: lastUpdate\n" \ + "@IDXATTR: dataExpireTimestamp\n" \ + "@IDXONE: 1\n" \ + "\n" \ + "dn: cn=sysdb\n" \ + "cn: sysdb\n" \ + "version: " SYSDB_TS_VERSION "\n" \ + "description: base object\n" \ + "\n" \ + #include "db/sysdb.h" struct sysdb_ctx { struct ldb_context *ldb; char *ldb_file; + + struct ldb_context *ldb_ts; + char *ldb_ts_file; + int transaction_nesting; }; |