summaryrefslogtreecommitdiff
path: root/src/persistence_client_library_backup_filelist.c
diff options
context:
space:
mode:
authorIngo Huerner <ingo.huerner@xse.de>2014-01-24 14:33:15 +0100
committerIngo Huerner <ingo.huerner@xse.de>2014-01-24 14:33:15 +0100
commita756aac7ed08de6ab876fbfe88a46b07360a8922 (patch)
tree89a878740546cf464cfeaf8094fe364df7c3366d /src/persistence_client_library_backup_filelist.c
parentbdca9b7b7fabd6f6a6506a33b39c1a6d1a667703 (diff)
downloadpersistence-client-library-a756aac7ed08de6ab876fbfe88a46b07360a8922.tar.gz
File backups on seperate partition; Fixed bug 146; created performance benchmark; minor optimization; disabled PAS interface by default, to enable use configure --enable-pasinterface
Diffstat (limited to 'src/persistence_client_library_backup_filelist.c')
-rw-r--r--src/persistence_client_library_backup_filelist.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/persistence_client_library_backup_filelist.c b/src/persistence_client_library_backup_filelist.c
index 24cf12b..168f30c 100644
--- a/src/persistence_client_library_backup_filelist.c
+++ b/src/persistence_client_library_backup_filelist.c
@@ -17,6 +17,7 @@
*/
#include "persistence_client_library_backup_filelist.h"
+#include "persistence_client_library_handle.h"
#include "rbtree.h"
#include "../include_protected/crc32.h"
#include "../include_protected/persistence_client_library_data_organization.h"
@@ -317,3 +318,459 @@ void key_val_rel(void *p )
}
+int pclCreateFile(const char* path)
+{
+ const char* delimiters = "/\n"; // search for blank and end of line
+ char* tokenArray[24];
+ char* thePath = (char*)path;
+ int numTokens = 0, i = 0, validPath = 1;
+ int handle = 0;
+
+ tokenArray[numTokens++] = strtok(thePath, delimiters);
+ while(tokenArray[numTokens-1] != NULL )
+ {
+ tokenArray[numTokens] = strtok(NULL, delimiters);
+ if(tokenArray[numTokens] != NULL)
+ {
+ numTokens++;
+ if(numTokens >= 24)
+ {
+ validPath = 0;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(validPath == 1)
+ {
+ char createPath[DbPathMaxLen] = {0};
+ snprintf(createPath, DbPathMaxLen, "/%s",tokenArray[0] );
+ for(i=1; i<numTokens-1; i++)
+ {
+ // create folders
+ strncat(createPath, "/", DbPathMaxLen-1);
+ strncat(createPath, tokenArray[i], DbPathMaxLen-1);
+ mkdir(createPath, 0744);
+ }
+ // finally create the file
+ strncat(createPath, "/", DbPathMaxLen-1);
+ strncat(createPath, tokenArray[i], DbPathMaxLen-1);
+ handle = open(createPath, O_CREAT|O_RDWR |O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if(handle != -1)
+ {
+ if(handle < MaxPersHandle)
+ {
+ __sync_fetch_and_add(&gOpenFdArray[handle], FileOpen); // set open flag
+ }
+ else
+ {
+ close(handle);
+ handle = EPERS_MAXHANDLE;
+ }
+ }
+ }
+ else
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateFile ==> no valid path to create: "), DLT_STRING(path) );
+ }
+
+ return handle;
+}
+
+
+int pclVerifyConsistency(const char* origPath, const char* backupPath, const char* csumPath, int openFlags)
+{
+ int handle = 0, readSize = 0;
+ int backupAvail = 0, csumAvail = 0;
+ int fdCsum = 0, fdBackup = 0;
+
+ char origCsumBuf[ChecksumBufSize] = {0};
+ char backCsumBuf[ChecksumBufSize] = {0};
+ char csumBuf[ChecksumBufSize] = {0};
+
+ // check if we have a backup and checksum file
+ backupAvail = access(backupPath, F_OK);
+ csumAvail = access(csumPath, F_OK);
+
+ // *************************************************
+ // there is a backup file and a checksum
+ // *************************************************
+ if( (backupAvail == 0) && (csumAvail == 0) )
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is a backup file AND a checksum"));
+ // calculate checksum form backup file
+ fdBackup = open(backupPath, O_RDONLY);
+ if(fdBackup != -1)
+ {
+ pclCalcCrc32Csum(fdBackup, backCsumBuf);
+
+ fdCsum = open(csumPath, O_RDONLY);
+ if(fdCsum != -1)
+ {
+ readSize = read(fdCsum, csumBuf, ChecksumBufSize);
+ if(readSize > 0)
+ {
+ if(strcmp(csumBuf, backCsumBuf) == 0)
+ {
+ // checksum matches ==> replace with original file
+ handle = pclRecoverFromBackup(fdBackup, origPath);
+ }
+ else
+ {
+ // checksum does not match, check checksum with original file
+ handle = open(origPath, openFlags);
+ if(handle != -1)
+ {
+ pclCalcCrc32Csum(handle, origCsumBuf);
+ if(strcmp(csumBuf, origCsumBuf) != 0)
+ {
+ close(handle);
+ handle = -1; // error: file corrupt
+ }
+ // else case: checksum matches ==> keep original file ==> nothing to do
+
+ }
+ else
+ {
+ close(handle);
+ handle = -1; // error: file corrupt
+ }
+ }
+ }
+ close(fdCsum);
+ }
+ else
+ {
+ close(fdCsum);
+ handle = -1; // error: file corrupt
+ }
+ }
+ else
+ {
+ handle = -1;
+ }
+ close(fdBackup);
+ }
+ // *************************************************
+ // there is ONLY a checksum file
+ // *************************************************
+ else if(csumAvail == 0)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is ONLY a checksum file"));
+
+ fdCsum = open(csumPath, O_RDONLY);
+ if(fdCsum != -1)
+ {
+ readSize = read(fdCsum, csumBuf, ChecksumBufSize);
+ if(readSize <= 0)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclVerifyConsistency => read checksum: invalid readSize"));
+ }
+ close(fdCsum);
+
+ // calculate the checksum form the original file to see if it matches
+ handle = open(origPath, openFlags);
+ if(handle != -1)
+ {
+ pclCalcCrc32Csum(handle, origCsumBuf);
+
+ if(strcmp(csumBuf, origCsumBuf) != 0)
+ {
+ close(handle);
+ handle = -1; // checksum does NOT match ==> error: file corrupt
+ }
+ // else case: checksum matches ==> keep original file ==> nothing to do
+ }
+ else
+ {
+ close(handle);
+ handle = -1; // error: file corrupt
+ }
+ }
+ else
+ {
+ close(fdCsum);
+ handle = -1; // error: file corrupt
+ }
+ }
+ // *************************************************
+ // there is ONLY a backup file
+ // *************************************************
+ else if(backupAvail == 0)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is ONLY a backup file"));
+
+ // calculate checksum form backup file
+ fdBackup = open(backupPath, O_RDONLY);
+ if(fdBackup != -1)
+ {
+ pclCalcCrc32Csum(fdBackup, backCsumBuf);
+ close(fdBackup);
+
+ // calculate the checksum form the original file to see if it matches
+ handle = open(origPath, openFlags);
+ if(handle != -1)
+ {
+ pclCalcCrc32Csum(handle, origCsumBuf);
+
+ if(strcmp(backCsumBuf, origCsumBuf) != 0)
+ {
+ close(handle);
+ handle = -1; // checksum does NOT match ==> error: file corrupt
+ }
+ // else case: checksum matches ==> keep original file ==> nothing to do
+
+ }
+ else
+ {
+ close(handle);
+ handle = -1; // error: file corrupt
+ }
+ }
+ else
+ {
+ close(fdBackup);
+ handle = -1; // error: file corrupt
+ }
+ }
+ // for else case: nothing to do
+
+
+ // if we are in an inconsistent state: delete file, backup and checksum
+ if(handle == -1)
+ {
+ remove(origPath);
+ remove(backupPath);
+ remove(csumPath);
+ }
+
+ return handle;
+}
+
+
+
+int pclRecoverFromBackup(int backupFd, const char* original)
+{
+ int handle = 0;
+ int readSize = 0;
+ char buffer[RDRWBufferSize];
+
+ handle = open(original, O_TRUNC | O_RDWR);
+ if(handle != -1)
+ {
+ // copy data from one file to another
+ while((readSize = read(backupFd, buffer, RDRWBufferSize)) > 0)
+ {
+ if(write(handle, buffer, readSize) != readSize)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclRecoverFromBackup => couldn't write whole buffer"));
+ break;
+ }
+ }
+
+ }
+
+ return handle;
+}
+
+
+
+int pclCreateBackup(const char* dstPath, int srcfd, const char* csumPath, const char* csumBuf)
+{
+ int dstFd = 0, csfd = 0;
+ int readSize = -1;
+ char buffer[RDRWBufferSize];
+
+ if(access(dstPath, F_OK) != 0)
+ {
+ char pathToCreate[DbPathMaxLen] = {0};
+ strncpy(pathToCreate, dstPath, DbPathMaxLen);
+ pclCreateFileAndPath(pathToCreate);
+ }
+
+ // create checksum file and and write checksum
+ csfd = open(csumPath, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if(csfd != -1)
+ {
+ int csumSize = strlen(csumBuf);
+ if(write(csfd, csumBuf, csumSize) != csumSize)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to write checksum to file"));
+ }
+ close(csfd);
+ }
+ else
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to create checksum file:"), DLT_STRING(strerror(errno)) );
+ }
+
+ // create backup file, user and group has read/write permission, others have read permission
+ dstFd = open(dstPath, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ if(dstFd != -1)
+ {
+ off_t curPos = 0;
+ // remember the current position
+ curPos = lseek(srcfd, 0, SEEK_CUR);
+
+ // copy data from one file to another
+ while((readSize = read(srcfd, buffer, RDRWBufferSize)) > 0)
+ {
+ if(write(dstFd, buffer, readSize) != readSize)
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => couldn't write whole buffer"));
+ break;
+ }
+ }
+
+ if(readSize == -1)
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pcl_create_backup => error copying file"));
+
+ if((readSize = close(dstFd)) == -1)
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pcl_create_backup => error closing fd"));
+
+ // set back to the position
+ lseek(srcfd, curPos, SEEK_SET);
+ }
+ else
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to open backup file"),
+ DLT_STRING(dstPath), DLT_STRING(strerror(errno)));
+ }
+
+ return readSize;
+}
+
+
+
+int pclCalcCrc32Csum(int fd, char crc32sum[])
+{
+ int rval = 1;
+
+ if(crc32sum != 0)
+ {
+ char* buf;
+ struct stat statBuf;
+
+ fstat(fd, &statBuf);
+ buf = malloc((unsigned int)statBuf.st_size);
+
+ if(buf != 0)
+ {
+ off_t curPos = 0;
+ // remember the current position
+ curPos = lseek(fd, 0, SEEK_CUR);
+
+ if(curPos != 0)
+ {
+ // set to beginning of the file
+ lseek(fd, 0, SEEK_SET);
+ }
+
+ while((rval = read(fd, buf, statBuf.st_size)) > 0)
+ {
+ unsigned int crc = 0;
+ crc = pclCrc32(crc, (unsigned char*)buf, statBuf.st_size);
+ snprintf(crc32sum, ChecksumBufSize-1, "%x", crc);
+ }
+
+ // set back to the position
+ lseek(fd, curPos, SEEK_SET);
+
+ free(buf);
+ }
+ }
+ return rval;
+}
+
+
+
+int pclBackupNeeded(const char* path)
+{
+ return need_backup_key(pclCrc32(0, (const unsigned char*)path, strlen(path)));
+}
+
+
+
+int pclCreateFileAndPath(const char* path)
+{
+ const char* delimiters = "/\n"; // search for blank and end of line
+ char* tokenArray[24];
+ char* thePath = (char*)path;
+ char createPath[DbPathMaxLen] = {0};
+ int numTokens = 0, i = 0, validPath = 1;
+ int rval = -1;
+
+ tokenArray[numTokens++] = strtok(thePath, delimiters);
+ while(tokenArray[numTokens-1] != NULL )
+ {
+ tokenArray[numTokens] = strtok(NULL, delimiters);
+ if(tokenArray[numTokens] != NULL)
+ {
+ numTokens++;
+ if(numTokens >= 24)
+ {
+ validPath = 0;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if(validPath == 1)
+ {
+ snprintf(createPath, DbPathMaxLen, "/%s",tokenArray[0] );
+ for(i=1; i<numTokens-1; i++)
+ {
+ // create folders
+ strncat(createPath, "/", DbPathMaxLen-1);
+ strncat(createPath, tokenArray[i], DbPathMaxLen-1);
+ mkdir(createPath, 0744);
+ }
+ // finally create the file
+ strncat(createPath, "/", DbPathMaxLen-1);
+ strncat(createPath, tokenArray[i], DbPathMaxLen-1);
+ rval = open(createPath, O_CREAT|O_RDWR |O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ close(rval);
+ }
+ else
+ {
+ DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateFileAndPath ==> no valid path to create:"), DLT_STRING(path));
+ }
+
+ return rval;
+}
+
+
+
+int pclGetPosixPermission(PersistencePermission_e permission)
+{
+ int posixPerm = 0;
+
+ switch( (int)permission)
+ {
+ case PersistencePermission_ReadWrite:
+ posixPerm = O_RDWR;
+ break;
+ case PersistencePermission_ReadOnly:
+ posixPerm = O_RDONLY;
+ break;
+ case PersistencePermission_WriteOnly:
+ posixPerm = O_WRONLY;
+ break;
+ default:
+ posixPerm = O_RDONLY;
+ break;
+ }
+
+ return posixPerm;
+}
+
+
+