Skip to content
Snippets Groups Projects
Commit 4c262172 authored by Eric Cano's avatar Eric Cano
Browse files

Created a linked mock remote file and remote NS access to allow proper...

Created a linked mock remote file and remote NS access to allow proper environment in unit test involving migrations.
Added missing file.
parent 8831f0c5
No related branches found
No related tags found
No related merge requests found
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MockRemoteFullFS.hpp"
#include "common/exception/Errnum.hpp"
#include <fcntl.h>
namespace cta {
MockRemoteFullFS::MockRemoteFullFS() {
char path[] = "/tmp/MockRemoteFullFS_XXXXXX";
exception::Errnum::throwOnNull(mkdtemp(path), "In MockRemoteFullFS::MockRemoteFullFS(): failed to create the temporary directory");
m_basePath = path;
std::string regex = std::string("file://") + path + "(/.+)";
m_pathRegex.reset(new castor::tape::utils::Regex(regex.c_str()));
}
std::string MockRemoteFullFS::createFullURL(const std::string& relativePath) {
if (relativePath[0] == '/')
return std::string ("file://") + m_basePath + relativePath;
else
return std::string ("file://") + m_basePath + "/" + relativePath;
}
void MockRemoteFullFS::createFile(const std::string& URL, size_t size) {
auto match = m_pathRegex->exec(URL);
if (match.empty())
throw exception::Exception("In MockRemoteFullFS::createFile(): invalid path");
std::string path = m_basePath + "/" + match.at(1);
// Create the file
int randomFd = ::open("/dev/urandom", 0);
exception::Errnum::throwOnMinusOne(randomFd, "Error opening /dev/urandom");
int fd = ::open(path.c_str(), O_CREAT | O_EXCL | O_WRONLY);
exception::Errnum::throwOnMinusOne(fd, "Error creating a file");
char * buff = NULL;
try {
buff = new char[size];
if(!buff) { throw exception::Exception("Failed to allocate memory to read /dev/urandom"); }
exception::Errnum::throwOnMinusOne(read(randomFd, buff, size));
exception::Errnum::throwOnMinusOne(write(fd, buff, size));
//m_checksum = adler32(0L, Z_NULL, 0);
//m_checksum = adler32(m_checksum, (const Bytef *)buff, size);
close(randomFd);
close(fd);
exception::Errnum::throwOnNonZero(::chmod(path.c_str(), 0777));
delete[] buff;
} catch (...) {
delete[] buff;
unlink(path.c_str());
throw;
}
}
std::string MockRemoteFullFS::getFilename(const RemotePath& remoteFile) const {
auto match = m_pathRegex->exec(remoteFile.getRaw());
if (match.size())
return match.at(1);
throw exception::Exception("In MockRemoteFullFS::getFilename(): invalid path");
}
void MockRemoteFullFS::rename(const RemotePath& remoteFile, const RemotePath& newRemoteFile) {
auto srcMatch = m_pathRegex->exec(remoteFile.getRaw());
auto dstMatch = m_pathRegex->exec(newRemoteFile.getRaw());
if (srcMatch.empty() || dstMatch.empty())
throw exception::Exception("In MockRemoteFullFS::rename(): invalid path");
std::string srcPath = m_basePath + srcMatch.at(1);
std::string dstPath = m_basePath + dstMatch.at(1);
exception::Errnum::throwOnNonZero(::rename(srcPath.c_str(), dstPath.c_str()));
}
std::unique_ptr<RemoteFileStatus> MockRemoteFullFS::statFile(const RemotePath& path) const {
std::unique_ptr<RemoteFileStatus> ret (new RemoteFileStatus);
auto pathMatch = m_pathRegex->exec(path.getRaw());
if (pathMatch.empty())
throw exception::Exception("In MockRemoteFullFS::statFile(): invalid path");
std::string realPath = m_basePath + pathMatch.at(1);
struct ::stat statBuff;
exception::Errnum::throwOnNonZero(::stat(realPath.c_str(), &statBuff));
ret->mode = statBuff.st_mode;
ret->owner.uid = statBuff.st_uid;
ret->owner.gid = statBuff.st_gid;
ret->size = statBuff.st_size;
return ret;
}
int MockRemoteFullFS::deleteFileOrDirectory(const char* fpath,
const struct ::stat* sb, int tflag, struct ::FTW * ftwbuf) {
switch (tflag) {
case FTW_D:
case FTW_DNR:
case FTW_DP:
rmdir(fpath);
break;
default:
unlink(fpath);
break;
}
return 0;
}
MockRemoteFullFS::~MockRemoteFullFS() throw() {
// Delete the created directories recursively
nftw(m_basePath.c_str(), deleteFileOrDirectory, 100, FTW_DEPTH);
}
} // end of namespace cta
\ No newline at end of file
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/remoteFS/RemoteFileStatus.hpp"
#include "remotens/RemoteNS.hpp"
#include "tapeserver/castor/tape/tapeserver/utils/Regex.hpp"
#include <sys/stat.h>
#include <ftw.h>
namespace cta {
/**
* A mock proxy class for the namespace of a remote storage system, backed
* by a real local temporary file system. This mock namespace also generates
* valid URLs in order for the tape server to be able to actually transfer
* data.
*/
class MockRemoteFullFS: public RemoteNS {
public:
/**
* Destructor.
*/
~MockRemoteFullFS() throw();
/**
* Constructor.
*/
MockRemoteFullFS();
/**
* Returns the status of the specified file or directory within the remote
* storage system or NULL if the fil eor directory does not exist.
*
* @param path The absolute path of the file or directory.
* @return The status of the file or directory or NULL if the file or
* directory does not exist.
*/
std::unique_ptr<RemoteFileStatus> statFile(const RemotePath &path) const;
/**
* Renames the specified remote file to the specified new name.
*
* @param remoteFile The current path.
* @param newRemoteFile The new path.
*/
void rename(const RemotePath &remoteFile,
const RemotePath &newRemoteFile);
/**
* Parses the specified remote file and returns the file name.
*
* @param path The absolute path of the file.
* @return The file name.
*/
std::string getFilename(const RemotePath &remoteFile) const;
/**
* Get a real URL that will be compatible with both remoteNS interface for
* metadata access and tape server's file access (via a file:// URL).
*/
std::string createFullURL(const std::string & relativePath);
/**
* Create a file with random content
*/
void createFile(const std::string & URL, size_t size);
private:
std::string m_basePath; ///< The path to the directory within which all the URLs will be created
std::unique_ptr<castor::tape::utils::Regex> m_pathRegex; ///< A regex alloging validation of the path in calls
/** Utility function to delete a directory in depth */
static int deleteFileOrDirectory(const char* fpath,
const struct ::stat* sb, int tflag, struct ::FTW * ftwbuf);
}; // class MockRemoteNS
} // namespace cta
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment