From e124b3654eec9cac66792e0fe77cbde0ad99f059 Mon Sep 17 00:00:00 2001
From: Keerthana K <keerthanak@vmware.com>
Date: Fri, 23 Nov 2018 07:11:23 +0000
Subject: [PATCH] Support for Libsolv caching of metadata
This change includes the support of libsolv caching of metadata which is a .solv file.
When the cache is created, tdnf creates a metadata cache file (*.solv)
in cache directory (/var/cache/tdnf/REPO-NAME/solvcache/). This is consumed by tdnf in
subsequent tdnf operations till the refresh timer expires. Solv cache file improves the
time consumed by tdnf operation which results in quicker results.
Change-Id: I42894260b8e9a110188c38027fc480dd83bfdc10
---
diff --git a/client/defines.h b/client/defines.h
index c112074..e604c49 100644
--- a/client/defines.h
+++ b/client/defines.h
@@ -139,6 +139,7 @@
#define TDNF_DEFAULT_DISTROARCHPKG "x86_64"
#define TDNF_RPM_CACHE_DIR_NAME "rpms"
#define TDNF_REPODATA_DIR_NAME "repodata"
+#define TDNF_SOLVCACHE_DIR_NAME "solvcache"
#define TDNF_REPO_DEFAULT_METADATA_EXPIRE "8294400"//48 hours in seconds
#define TDNF_REPO_METADATA_EXPIRE_NEVER "never"
//var names
@@ -177,6 +178,10 @@
{ERROR_TDNF_SOLV_VALIDATION, "ERROR_TDNF_SOLV_VALIDATION", "Solv - validation check failed"}, \
{ERROR_TDNF_SOLV_NO_SOLUTION, "ERROR_TDNF_SOLV_NO_SOLUTION", "Solv - goal found no solutions"}, \
{ERROR_TDNF_SOLV_NO_CAPABILITY, "ERROR_TDNF_SOLV_NO_CAPABILITY", "Solv - the capability was not available"}, \
+ {ERROR_TDNF_SOLV_CHKSUM, "ERROR_TDNF_SOLV_CHKSUM", "Solv - Checksum creation failed"}, \
+ {ERROR_TDNF_REPO_WRITE, "ERROR_TDNF_REPO_WRITE", "Solv - Failed to write repo"}, \
+ {ERROR_TDNF_SOLV_CACHE_NOT_CREATED, "ERROR_TDNF_SOLV_CACHE_NOT_CREATED", "Solv - Solv cache not found"}, \
+ {ERROR_TDNF_ADD_SOLV, "ERROR_TDNF_ADD_SOLV", "Solv - Failed to add solv"}, \
{ERROR_TDNF_REPO_BASE, "ERROR_TDNF_REPO_BASE", "Repo error base"}, \
{ERROR_TDNF_REPO_PERFORM, "ERROR_TDNF_REPO_PERFORM", "Error during repo handle execution"}, \
{ERROR_TDNF_REPO_GETINFO, "ERROR_TDNF_REPO_GETINFO", "Repo during repo result getinfo"}, \
diff --git a/client/init.c b/client/init.c
index 493bf7e..8823599 100644
--- a/client/init.c
+++ b/client/init.c
@@ -226,6 +226,13 @@
dwError = 0;//Ignore non existent folders
}
BAIL_ON_TDNF_ERROR(dwError);
+
+ dwError = TDNFRemoveSolvCache(pTdnf, pTempRepo->pszId);
+ if(dwError == ERROR_TDNF_FILE_NOT_FOUND)
+ {
+ dwError = 0;//Ignore non existent folders
+ }
+ BAIL_ON_TDNF_ERROR(dwError);
}
if(pSack)
diff --git a/client/prototypes.h b/client/prototypes.h
index 7bfb714..87e8dfe 100644
--- a/client/prototypes.h
+++ b/client/prototypes.h
@@ -125,6 +125,12 @@
);
uint32_t
+TDNFRemoveSolvCache(
+ PTDNF pTdnf,
+ const char* pszRepoId
+ );
+
+uint32_t
TDNFRepoApplyProxySettings(
PTDNF_CONF pConf,
CURL *pCurl
@@ -424,7 +430,7 @@
//repo.c
uint32_t
TDNFInitRepoFromMetadata(
- PSolvSack pSack,
+ Repo *pRepo,
const char* pszRepoName,
PTDNF_REPO_METADATA pRepoMD
);
@@ -768,11 +774,6 @@
uint32_t
TDNFUtilsMakeDir(
- const char* pszPath
- );
-
-uint32_t
-TDNFUtilsMakeDirs(
const char* pszPath
);
diff --git a/client/repo.c b/client/repo.c
index 01b1f8f..5967689 100644
--- a/client/repo.c
+++ b/client/repo.c
@@ -34,14 +34,19 @@
char* pszLastRefreshMarker = NULL;
PTDNF_REPO_METADATA pRepoMD = NULL;
PTDNF_CONF pConf = NULL;
+ Repo* pRepo = NULL;
+ Pool* pPool = NULL;;
+ int nUseMetaDataCache = 0;
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo = NULL;
- if(!pTdnf || !pTdnf->pConf || !pRepoData || !pSack)
+ if(!pTdnf || !pTdnf->pConf || !pRepoData || !pSack || !pSack->pPool)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pConf = pTdnf->pConf;
+ pPool = pSack->pPool;
dwError = TDNFAllocateStringPrintf(
&pszRepoCacheDir,
@@ -63,8 +68,38 @@
&pRepoMD);
BAIL_ON_TDNF_ERROR(dwError);
- dwError = TDNFInitRepoFromMetadata(pSack, pRepoData->pszId, pRepoMD);
+ dwError = TDNFAllocateMemory(
+ 1,
+ sizeof(SOLV_REPO_INFO_INTERNAL),
+ (void**)&pSolvRepoInfo);
BAIL_ON_TDNF_ERROR(dwError);
+
+ pRepo = repo_create(pPool, pRepoData->pszId);
+
+ if (!pRepo)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_ERROR(dwError);
+ }
+ pSolvRepoInfo->pRepo = pRepo;
+ pRepo->appdata = pSolvRepoInfo;
+
+ dwError = SolvCalculateCookieForRepoMD(pRepoMD->pszRepoMD, pSolvRepoInfo->cookie);
+ BAIL_ON_TDNF_ERROR(dwError);
+
+ pSolvRepoInfo->nCookieSet = 1;
+ dwError = SolvUseMetaDataCache(pSack, pSolvRepoInfo, &nUseMetaDataCache);
+ BAIL_ON_TDNF_ERROR(dwError);
+
+ if (nUseMetaDataCache == 0)
+ {
+ dwError = TDNFInitRepoFromMetadata(pSolvRepoInfo->pRepo, pRepoData->pszId, pRepoMD);
+ BAIL_ON_TDNF_ERROR(dwError);
+
+ dwError = SolvCreateMetaDataCache(pSack, pSolvRepoInfo);
+ BAIL_ON_TDNF_ERROR(dwError);
+ }
+ pool_createwhatprovides(pPool);
dwError = TDNFAllocateStringPrintf(
&pszLastRefreshMarker,
@@ -81,9 +116,13 @@
TDNF_SAFE_FREE_MEMORY(pszLastRefreshMarker);
TDNF_SAFE_FREE_MEMORY(pszRepoDataDir);
TDNF_SAFE_FREE_MEMORY(pszRepoCacheDir);
+ TDNF_SAFE_FREE_MEMORY(pSolvRepoInfo);
return dwError;
-
error:
+ if(pRepo)
+ {
+ repo_free(pRepo, 1);
+ }
//If there is an error during init, log the error
//remove any cache data that could be potentially corrupt.
if(pRepoData)
@@ -101,23 +140,22 @@
}
goto cleanup;
}
-
uint32_t
TDNFInitRepoFromMetadata(
- PSolvSack pSack,
+ Repo *pRepo,
const char* pszRepoName,
PTDNF_REPO_METADATA pRepoMD
)
{
uint32_t dwError = 0;
- if(!pSack || !pRepoMD || IsNullOrEmptyString(pszRepoName))
+ if(!pRepo || !pRepoMD || IsNullOrEmptyString(pszRepoName))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
- dwError = SolvReadYumRepo(pSack,
+ dwError = SolvReadYumRepo(pRepo,
pszRepoName,
pRepoMD->pszRepoMD,
pRepoMD->pszPrimary,
diff --git a/client/repoutils.c b/client/repoutils.c
index 179ad96..63040ea 100644
--- a/client/repoutils.c
+++ b/client/repoutils.c
@@ -277,6 +277,87 @@
}
uint32_t
+TDNFRemoveSolvCache(
+ PTDNF pTdnf,
+ const char* pszRepoId
+ )
+{
+ uint32_t dwError = 0;
+ char* pszSolvCacheDir = NULL;
+ char* pszFilePath = NULL;
+ DIR *pDir = NULL;
+ struct dirent *pEnt = NULL;
+
+ if(!pTdnf || !pTdnf->pConf || IsNullOrEmptyString(pszRepoId))
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_ERROR(dwError);
+ }
+
+ dwError = TDNFAllocateStringPrintf(
+ &pszSolvCacheDir,
+ "%s/%s/%s",
+ pTdnf->pConf->pszCacheDir,
+ pszRepoId,
+ TDNF_SOLVCACHE_DIR_NAME);
+ BAIL_ON_TDNF_ERROR(dwError);
+
+ pDir = opendir(pszSolvCacheDir);
+ if(pDir == NULL)
+ {
+ dwError = errno;
+ BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
+ }
+
+ while ((pEnt = readdir (pDir)) != NULL )
+ {
+ if (!strcmp(pEnt->d_name, ".") || !strcmp(pEnt->d_name, ".."))
+ {
+ continue;
+ }
+
+ dwError = TDNFAllocateStringPrintf(
+ &pszFilePath,
+ "%s/%s",
+ pszSolvCacheDir,
+ pEnt->d_name);
+ BAIL_ON_TDNF_ERROR(dwError);
+ if(pszFilePath)
+ {
+ if(unlink(pszFilePath))
+ {
+ dwError = errno;
+ BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
+ }
+ TDNF_SAFE_FREE_MEMORY(pszFilePath);
+ pszFilePath = NULL;
+ }
+ else
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_ERROR(dwError);
+ }
+ }
+ if(rmdir(pszSolvCacheDir))
+ {
+ dwError = errno;
+ BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
+ }
+
+cleanup:
+ TDNF_SAFE_FREE_MEMORY(pszFilePath);
+ TDNF_SAFE_FREE_MEMORY(pszSolvCacheDir);
+ if(pDir)
+ {
+ closedir(pDir);
+ }
+ return dwError;
+
+error:
+ goto cleanup;
+}
+
+uint32_t
TDNFRepoApplyProxySettings(
PTDNF_CONF pConf,
CURL *pCurl
diff --git a/common/prototypes.h b/common/prototypes.h
index 9508dc1..50cd00f 100644
--- a/common/prototypes.h
+++ b/common/prototypes.h
@@ -136,3 +136,8 @@
TDNFFreePackageInfoContents(
PTDNF_PKG_INFO pPkgInfo
);
+
+uint32_t
+TDNFUtilsMakeDirs(
+ const char* pszPath
+ );
diff --git a/include/tdnferror.h b/include/tdnferror.h
index 9033efc..1be2b0f 100644
--- a/include/tdnferror.h
+++ b/include/tdnferror.h
@@ -92,6 +92,14 @@
#define ERROR_TDNF_SOLV_NO_SOLUTION (ERROR_TDNF_SOLV_BASE + 10)
// the capability was not available
#define ERROR_TDNF_SOLV_NO_CAPABILITY (ERROR_TDNF_SOLV_BASE + 11)
+// Solv Checksum Error
+#define ERROR_TDNF_SOLV_CHKSUM (ERROR_TDNF_SOLV_BASE + 12)
+// Solv file write failed
+#define ERROR_TDNF_REPO_WRITE (ERROR_TDNF_SOLV_BASE + 13)
+// Solv File not created
+#define ERROR_TDNF_SOLV_CACHE_NOT_CREATED (ERROR_TDNF_SOLV_BASE + 14)
+// Add solv file to repo failed
+#define ERROR_TDNF_ADD_SOLV (ERROR_TDNF_SOLV_BASE + 15)
//Repo errors 1400 to 1469
#define ERROR_TDNF_REPO_BASE 1400
diff --git a/solv/defines.h b/solv/defines.h
index 2796d56..79a5444 100644
--- a/solv/defines.h
+++ b/solv/defines.h
@@ -1,5 +1,8 @@
#define SYSTEM_REPO_NAME "@System"
#define CMDLINE_REPO_NAME "@commandline"
+#define SOLV_COOKIE_IDENT "tdnf"
+#define TDNF_SOLVCACHE_DIR_NAME "solvcache"
+#define SOLV_COOKIE_LEN 32
#define BAIL_ON_TDNF_LIBSOLV_ERROR(dwError) \
do { \
diff --git a/solv/includes.h b/solv/includes.h
index 6e26b66..d2f0903 100644
--- a/solv/includes.h
+++ b/solv/includes.h
@@ -3,6 +3,8 @@
#include <sys/utsname.h>
#include <stdlib.h>
#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
// libsolv
#include <solv/evr.h>
#include <solv/pool.h>
@@ -20,6 +22,7 @@
#include <solv/selection.h>
#include <solv/solverdebug.h>
#include <solv/testcase.h>
+#include <solv/chksum.h>
#include <tdnf.h>
#include "defines.h"
diff --git a/solv/prototypes.h b/solv/prototypes.h
index 2484649..d8a3f41 100644
--- a/solv/prototypes.h
+++ b/solv/prototypes.h
@@ -36,6 +36,13 @@
Queue queuePackages;
} SolvPackageList, *PSolvPackageList;
+typedef struct _SOLV_REPO_INFO_INTERNAL_
+{
+ Repo* pRepo;
+ unsigned char cookie[SOLV_COOKIE_LEN];
+ int nCookieSet;
+}SOLV_REPO_INFO_INTERNAL, *PSOLV_REPO_INFO_INTERNAL;
+
// tdnfpackage.c
uint32_t
SolvGetPkgInfoFromId(
@@ -412,7 +419,7 @@
// tdnfrepo.c
uint32_t
SolvReadYumRepo(
- PSolvSack pSack,
+ Repo *pRepo,
const char *pszRepoName,
const char *pszRepomd,
const char *pszPrimary,
@@ -479,6 +486,39 @@
SolvIsGlob(
const char* pszString
);
+
+uint32_t
+SolvCalculateCookieForRepoMD(
+ char* pszRepoMD,
+ unsigned char* pszCookie
+ );
+
+uint32_t
+SolvGetMetaDataCachePath(
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ PSolvSack pSack,
+ char** ppszCachePath
+ );
+
+uint32_t
+SolvAddSolvMetaData(
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ char *pszTempSolvFile
+ );
+
+uint32_t
+SolvCreateMetaDataCache(
+ PSolvSack pSack,
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo
+ );
+
+uint32_t
+SolvUseMetaDataCache(
+ PSolvSack pSack,
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ int *nUseMetaDataCache
+ );
+
#ifdef __cplusplus
}
#endif
diff --git a/solv/tdnfrepo.c b/solv/tdnfrepo.c
index 76b8b62..b243c36 100644
--- a/solv/tdnfrepo.c
+++ b/solv/tdnfrepo.c
@@ -152,7 +152,7 @@
uint32_t
SolvReadYumRepo(
- PSolvSack pSack,
+ Repo *pRepo,
const char *pszRepoName,
const char *pszRepomd,
const char *pszPrimary,
@@ -161,21 +161,12 @@
)
{
uint32_t dwError = 0;
- Repo* pRepo = NULL;
- Pool* pPool = NULL;
- if(!pSack || !pSack->pPool || !pszRepoName || !pszRepomd || !pszPrimary)
+ if(!pRepo || !pszRepoName || !pszRepomd || !pszPrimary)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
}
- pPool = pSack->pPool;
- pRepo = repo_create(pPool, pszRepoName);
- if( !pRepo )
- {
- dwError = ERROR_TDNF_INVALID_PARAMETER;
- BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
- }
dwError = SolvLoadRepomd(pRepo, pszRepomd);
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
@@ -196,17 +187,12 @@
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
}
- pool_createwhatprovides(pPool);
cleanup:
return dwError;
error:
- if(pRepo)
- {
- repo_free(pRepo, 1);
- }
goto cleanup;
}
@@ -288,4 +274,329 @@
repo_free(pRepo, 1);
}
goto cleanup;
-}
\ No newline at end of file
+}
+
+uint32_t
+SolvCalculateCookieForRepoMD(
+ char* pszRepoMD,
+ unsigned char* pszCookie
+ )
+{
+ uint32_t dwError = 0;
+ FILE *fp = NULL;
+ Chksum *pChkSum = NULL;
+ int nLen = 0;
+ char buf[4096];
+
+ if (!pszRepoMD)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ fp = fopen(pszRepoMD, "r");
+ if (fp == NULL)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ pChkSum = solv_chksum_create(REPOKEY_TYPE_SHA256);
+ if (!pChkSum)
+ {
+ dwError = ERROR_TDNF_SOLV_CHKSUM;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ solv_chksum_add(pChkSum, SOLV_COOKIE_IDENT, strlen(SOLV_COOKIE_IDENT));
+
+ while ((nLen = fread(buf, 1, sizeof(buf), fp)) > 0)
+ {
+ solv_chksum_add(pChkSum, buf, nLen);
+ }
+ solv_chksum_free(pChkSum, pszCookie);
+
+cleanup:
+ if (fp != NULL)
+ {
+ fclose(fp);
+ }
+ return dwError;
+error:
+ goto cleanup;
+}
+
+uint32_t
+SolvGetMetaDataCachePath(
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ PSolvSack pSack,
+ char** ppszCachePath
+ )
+{
+ char *pszCachePath = NULL;
+ uint32_t dwError = 0;
+ Repo *pRepo = NULL;
+
+ if (!pSolvRepoInfo || !pSack || !pSolvRepoInfo->pRepo || !ppszCachePath)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ pRepo = pSolvRepoInfo->pRepo;
+ if (!IsNullOrEmptyString(pRepo->name))
+ {
+ dwError = TDNFAllocateStringPrintf(
+ &pszCachePath,
+ "%s/%s/%s/%s.solv",
+ pSack->pszCacheDir,
+ pRepo->name,
+ TDNF_SOLVCACHE_DIR_NAME,
+ pRepo->name);
+ BAIL_ON_TDNF_ERROR(dwError);
+ }
+ *ppszCachePath = pszCachePath;
+cleanup:
+ return dwError;
+error:
+ TDNF_SAFE_FREE_MEMORY(pszCachePath);
+ goto cleanup;
+}
+
+uint32_t
+SolvAddSolvMetaData(
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ char *pszTempSolvFile
+ )
+{
+ uint32_t dwError = 0;
+ Repo *pRepo = NULL;
+ FILE *fp = NULL;
+ int i = 0;
+
+ if (!pSolvRepoInfo || !pSolvRepoInfo->pRepo || !pszTempSolvFile)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ pRepo = pSolvRepoInfo->pRepo;
+ if (!pRepo->pool)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ for (i = pRepo->start; i < pRepo->end; i++)
+ {
+ if (pRepo->pool->solvables[i].repo != pRepo)
+ {
+ break;
+ }
+ }
+ if (i < pRepo->end)
+ {
+ goto cleanup;
+ }
+ fp = fopen (pszTempSolvFile, "r");
+ if (fp == NULL)
+ {
+ dwError = errno;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ repo_empty(pRepo, 1);
+ if (repo_add_solv(pRepo, fp, SOLV_ADD_NO_STUBS))
+ {
+ dwError = ERROR_TDNF_ADD_SOLV;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+cleanup:
+ if (fp != NULL)
+ {
+ fclose(fp);
+ }
+ return dwError;
+error:
+ goto cleanup;
+}
+
+uint32_t
+SolvUseMetaDataCache(
+ PSolvSack pSack,
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo,
+ int *nUseMetaDataCache
+ )
+{
+ uint32_t dwError = 0;
+ FILE *fp = NULL;
+ Repo *pRepo = NULL;
+ unsigned char *pszCookie = NULL;
+ unsigned char pszTempCookie[32];
+ char *pszCacheFilePath = NULL;
+
+ if (!pSack || !pSolvRepoInfo || !pSolvRepoInfo->pRepo)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ pRepo = pSolvRepoInfo->pRepo;
+ pszCookie = pSolvRepoInfo->nCookieSet ? pSolvRepoInfo->cookie : 0;
+
+ dwError = SolvGetMetaDataCachePath(pSolvRepoInfo, pSack, &pszCacheFilePath);
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+
+ if (IsNullOrEmptyString(pszCacheFilePath))
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ fp = fopen(pszCacheFilePath, "r");
+ if (fp == NULL)
+ {
+ dwError = ERROR_TDNF_SOLV_CACHE_NOT_CREATED;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ // Reading the cookie from cached Solv File
+ if (fseek (fp, -sizeof(pszTempCookie), SEEK_END) || fread (pszTempCookie, sizeof(pszTempCookie), 1, fp) != 1)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ // compare the calculated cookie with the one read from Solv file
+ if (pszCookie && memcmp (pszCookie, pszTempCookie, sizeof(pszTempCookie)) != 0)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ rewind(fp);
+ if (repo_add_solv(pRepo, fp, 0))
+ {
+ dwError = ERROR_TDNF_ADD_SOLV;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ *nUseMetaDataCache = 1;
+
+cleanup:
+ if (fp != NULL)
+ {
+ fclose(fp);
+ }
+ TDNF_SAFE_FREE_MEMORY(pszCacheFilePath);
+ return dwError;
+error:
+ if (dwError == ERROR_TDNF_SOLV_CACHE_NOT_CREATED)
+ {
+ dwError = 0;
+ }
+ goto cleanup;
+}
+
+uint32_t
+SolvCreateMetaDataCache(
+ PSolvSack pSack,
+ PSOLV_REPO_INFO_INTERNAL pSolvRepoInfo
+ )
+{
+ uint32_t dwError = 0;
+ Repo *pRepo = NULL;
+ FILE *fp = NULL;
+ int fd = 0;
+ char *pszSolvCacheDir = NULL;
+ char *pszTempSolvFile = NULL;
+ char *pszCacheFilePath = NULL;
+
+ if (!pSack || !pSolvRepoInfo|| !pSolvRepoInfo->nCookieSet)
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ pRepo = pSolvRepoInfo->pRepo;
+ dwError = TDNFAllocateStringPrintf(
+ &pszSolvCacheDir,
+ "%s/%s/%s",
+ pSack->pszCacheDir,
+ pRepo->name,
+ TDNF_SOLVCACHE_DIR_NAME);
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+
+ if (access(pszSolvCacheDir, W_OK| X_OK) != 0)
+ {
+ if(errno != ENOENT)
+ {
+ dwError = errno;
+ }
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+
+ dwError = TDNFUtilsMakeDirs(pszSolvCacheDir);
+ if (dwError == ERROR_TDNF_ALREADY_EXISTS)
+ {
+ dwError = 0;
+ }
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ pszTempSolvFile = solv_dupjoin(pszSolvCacheDir, "/", ".newsolv-XXXXXX");
+ fd = mkstemp(pszTempSolvFile);
+ if (fd < 0)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ fchmod (fd, 0444);
+ fp = fdopen(fd, "w");
+ if (fp == NULL)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ if (repo_write(pRepo, fp))
+ {
+ dwError = ERROR_TDNF_REPO_WRITE;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ if (fwrite(pSolvRepoInfo->cookie, SOLV_COOKIE_LEN, 1, fp) != 1)
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ if (fclose(fp))
+ {
+ dwError = ERROR_TDNF_SOLV_IO;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ fp = NULL;
+ dwError = SolvAddSolvMetaData(pSolvRepoInfo, pszTempSolvFile);
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+
+ dwError = SolvGetMetaDataCachePath(pSolvRepoInfo, pSack, &pszCacheFilePath);
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+
+ if (IsNullOrEmptyString(pszCacheFilePath))
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+
+ if (rename (pszTempSolvFile, pszCacheFilePath))
+ {
+ dwError = ERROR_TDNF_INVALID_PARAMETER;
+ BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
+ }
+ unlink(pszTempSolvFile);
+cleanup:
+ TDNF_SAFE_FREE_MEMORY(pszTempSolvFile);
+ TDNF_SAFE_FREE_MEMORY(pszSolvCacheDir);
+ TDNF_SAFE_FREE_MEMORY(pszCacheFilePath);
+ return dwError;
+error:
+ if (fp != NULL)
+ {
+ fclose(fp);
+ unlink(pszTempSolvFile);
+ }
+ else if (fd > 0)
+ {
+ close(fd);
+ unlink(pszTempSolvFile);
+ }
+ goto cleanup;
+}