You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-12-15 12:09:09 +03:00
Got a basic unit test to work for IOC::read()
This commit is contained in:
Submodule libmarias3 updated: aef6eaca14...fa4c00da11
@@ -85,7 +85,7 @@ Cache::Cache() : currentCacheSize(0)
|
|||||||
}
|
}
|
||||||
catch (exception &e)
|
catch (exception &e)
|
||||||
{
|
{
|
||||||
syslog(LOG_CRIT, "Failed to create %s, got: %s", prefix.string().c_str(), e.what());
|
logger->log(LOG_CRIT, "Failed to create %s, got: %s", prefix.string().c_str(), e.what());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
//cout << "Cache got prefix " << prefix << endl;
|
//cout << "Cache got prefix " << prefix << endl;
|
||||||
@@ -209,7 +209,8 @@ void Cache::read(const vector<string> &keys)
|
|||||||
if (mit != m_lru.end())
|
if (mit != m_lru.end())
|
||||||
{
|
{
|
||||||
lru.splice(lru.end(), lru, mit->lit);
|
lru.splice(lru.end(), lru, mit->lit);
|
||||||
removeFromDNE(lru.end());
|
LRU_t::iterator lit = lru.end();
|
||||||
|
removeFromDNE(--lit);
|
||||||
}
|
}
|
||||||
else if (dl_errnos[i] == 0) // successful download
|
else if (dl_errnos[i] == 0) // successful download
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ IOCoordinator::IOCoordinator()
|
|||||||
cerr << "ObjectStorage/object_size must be set to a numeric value" << endl;
|
cerr << "ObjectStorage/object_size must be set to a numeric value" << endl;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
cachePath = cache->getCachePath();
|
cachePath = cache->getCachePath();
|
||||||
journalPath = cache->getJournalPath();
|
journalPath = cache->getJournalPath();
|
||||||
}
|
}
|
||||||
@@ -93,6 +94,7 @@ int IOCoordinator::loadObject(int fd, uint8_t *data, off_t offset, size_t length
|
|||||||
}
|
}
|
||||||
count += err;
|
count += err;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IOCoordinator::loadObjectAndJournal(const char *objFilename, const char *journalFilename,
|
int IOCoordinator::loadObjectAndJournal(const char *objFilename, const char *journalFilename,
|
||||||
@@ -126,7 +128,14 @@ int IOCoordinator::read(const char *filename, uint8_t *data, off_t offset, size_
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ScopedReadLock fileLock(this, filename);
|
ScopedReadLock fileLock(this, filename);
|
||||||
MetadataFile meta(filename);
|
MetadataFile meta(filename, MetadataFile::no_create_t());
|
||||||
|
|
||||||
|
if (!meta.exists())
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
vector<metadataObject> relevants = meta.metadataRead(offset, length);
|
vector<metadataObject> relevants = meta.metadataRead(offset, length);
|
||||||
map<string, int> journalFDs, objectFDs;
|
map<string, int> journalFDs, objectFDs;
|
||||||
map<string, string> keyToJournalName, keyToObjectName;
|
map<string, string> keyToJournalName, keyToObjectName;
|
||||||
@@ -153,10 +162,10 @@ int IOCoordinator::read(const char *filename, uint8_t *data, off_t offset, size_
|
|||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
keyToJournalName[key] = filename;
|
keyToJournalName[key] = filename;
|
||||||
journalFDs[filename] = fd;
|
journalFDs[key] = fd;
|
||||||
fdMinders.push_back(SharedCloser(fd));
|
fdMinders.push_back(SharedCloser(fd));
|
||||||
}
|
}
|
||||||
else if (errno != EEXIST)
|
else if (errno != ENOENT)
|
||||||
{
|
{
|
||||||
int l_errno = errno;
|
int l_errno = errno;
|
||||||
logger->log(LOG_CRIT, "IOCoordinator::read(): Got an unexpected error opening %s, error was '%s'",
|
logger->log(LOG_CRIT, "IOCoordinator::read(): Got an unexpected error opening %s, error was '%s'",
|
||||||
|
|||||||
@@ -47,18 +47,19 @@ MetadataFile::MetadataFile()
|
|||||||
mpLogger->log(LOG_CRIT, "ObjectStorage/metadata_path is not set");
|
mpLogger->log(LOG_CRIT, "ObjectStorage/metadata_path is not set");
|
||||||
throw runtime_error("Please set ObjectStorage/metadata_path in the storagemanager.cnf file");
|
throw runtime_error("Please set ObjectStorage/metadata_path in the storagemanager.cnf file");
|
||||||
}
|
}
|
||||||
boost::filesystem::create_directories(msMetadataPath);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
boost::filesystem::create_directories(msMetadataPath);
|
boost::filesystem::create_directories(msMetadataPath);
|
||||||
}
|
}
|
||||||
catch (exception &e)
|
catch (exception &e)
|
||||||
{
|
{
|
||||||
syslog(LOG_CRIT, "Failed to create %s, got: %s", msMetadataPath.c_str(), e.what());
|
mpLogger->log(LOG_CRIT, "Failed to create %s, got: %s", msMetadataPath.c_str(), e.what());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
mVersion=1;
|
mVersion=1;
|
||||||
mRevision=1;
|
mRevision=1;
|
||||||
|
_exists = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@ MetadataFile::MetadataFile(const char* filename)
|
|||||||
mpConfig = Config::get();
|
mpConfig = Config::get();
|
||||||
mpLogger = SMLogging::get();
|
mpLogger = SMLogging::get();
|
||||||
mObjectSize = 5 * (1<<20);
|
mObjectSize = 5 * (1<<20);
|
||||||
|
_exists = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mObjectSize = stoul(mpConfig->getValue("ObjectStorage", "object_size"));
|
mObjectSize = stoul(mpConfig->getValue("ObjectStorage", "object_size"));
|
||||||
@@ -122,11 +124,77 @@ MetadataFile::MetadataFile(const char* filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetadataFile::MetadataFile(const char* filename, no_create_t)
|
||||||
|
{
|
||||||
|
mpConfig = Config::get();
|
||||||
|
mpLogger = SMLogging::get();
|
||||||
|
mObjectSize = 5 * (1<<20);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mObjectSize = stoul(mpConfig->getValue("ObjectStorage", "object_size"));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
cerr << "ObjectStorage/object_size must be set to a numeric value" << endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
msMetadataPath = mpConfig->getValue("ObjectStorage", "metadata_path");
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
mpLogger->log(LOG_CRIT, "Could not load metadata_path from storagemanger.cnf file.");
|
||||||
|
throw runtime_error("Please set ObjectStorage/metadata_path in the storagemanager.cnf file");
|
||||||
|
}
|
||||||
|
boost::filesystem::create_directories(msMetadataPath);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::filesystem::create_directories(msMetadataPath);
|
||||||
|
}
|
||||||
|
catch (exception &e)
|
||||||
|
{
|
||||||
|
syslog(LOG_CRIT, "Failed to create %s, got: %s", msMetadataPath.c_str(), e.what());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
string metadataFilename = msMetadataPath + "/" + string(filename) + ".meta";
|
||||||
|
if (boost::filesystem::exists(metadataFilename))
|
||||||
|
{
|
||||||
|
_exists = true;
|
||||||
|
boost::property_tree::ptree jsontree;
|
||||||
|
boost::property_tree::read_json(metadataFilename, jsontree);
|
||||||
|
metadataObject newObject;
|
||||||
|
//try catch
|
||||||
|
mVersion = jsontree.get<int>("version");
|
||||||
|
mRevision = jsontree.get<int>("revision");
|
||||||
|
|
||||||
|
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, jsontree.get_child("objects"))
|
||||||
|
{
|
||||||
|
metadataObject newObject;
|
||||||
|
newObject.offset = v.second.get<uint64_t>("offset");
|
||||||
|
newObject.length = v.second.get<uint64_t>("length");
|
||||||
|
newObject.key = v.second.get<string>("key");
|
||||||
|
mObjects.insert(newObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mVersion = 1;
|
||||||
|
mRevision = 1;
|
||||||
|
_exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetadataFile::~MetadataFile()
|
MetadataFile::~MetadataFile()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MetadataFile::exists()
|
||||||
|
{
|
||||||
|
return _exists;
|
||||||
|
}
|
||||||
|
|
||||||
vector<metadataObject> MetadataFile::metadataRead(off_t offset, size_t length)
|
vector<metadataObject> MetadataFile::metadataRead(off_t offset, size_t length)
|
||||||
{
|
{
|
||||||
// this version assumes mObjects is sorted by offset, and there are no gaps between objects
|
// this version assumes mObjects is sorted by offset, and there are no gaps between objects
|
||||||
@@ -224,6 +292,7 @@ int MetadataFile::writeMetadata(const char *filename)
|
|||||||
}
|
}
|
||||||
jsontree.add_child("objects", objs);
|
jsontree.add_child("objects", objs);
|
||||||
write_json(metadataFilename, jsontree);
|
write_json(metadataFilename, jsontree);
|
||||||
|
_exists = true;
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,13 @@ struct metadataObject {
|
|||||||
class MetadataFile
|
class MetadataFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct no_create_t {};
|
||||||
MetadataFile();
|
MetadataFile();
|
||||||
MetadataFile(const char* filename);
|
MetadataFile(const char* filename);
|
||||||
|
MetadataFile(const char* filename, no_create_t); // this one won't create it if it doesn't exist
|
||||||
~MetadataFile();
|
~MetadataFile();
|
||||||
|
|
||||||
|
bool exists();
|
||||||
void printObjects();
|
void printObjects();
|
||||||
// returns the objects needed to update
|
// returns the objects needed to update
|
||||||
std::vector<metadataObject> metadataRead(off_t offset, size_t length);
|
std::vector<metadataObject> metadataRead(off_t offset, size_t length);
|
||||||
@@ -59,6 +62,7 @@ class MetadataFile
|
|||||||
size_t mObjectSize;
|
size_t mObjectSize;
|
||||||
std::string msMetadataPath;
|
std::string msMetadataPath;
|
||||||
std::set<metadataObject> mObjects;
|
std::set<metadataObject> mObjects;
|
||||||
|
bool _exists;
|
||||||
//vector<metadataObject> mObjects;
|
//vector<metadataObject> mObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
namespace storagemanager
|
namespace storagemanager
|
||||||
{
|
{
|
||||||
|
|
||||||
ScopedReadLock::ScopedReadLock(IOCoordinator *i, const std::string &k) : ioc(i), key(k)
|
ScopedReadLock::ScopedReadLock(IOCoordinator *i, const std::string &k) : ioc(i), key(k), locked(false)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ void ScopedReadLock::unlock()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedWriteLock::ScopedWriteLock(IOCoordinator *i, const std::string &k) : ioc(i), key(k)
|
ScopedWriteLock::ScopedWriteLock(IOCoordinator *i, const std::string &k) : ioc(i), key(k), locked(false)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -638,6 +638,7 @@ bool cacheTest1()
|
|||||||
cout << "cache test 1 OK" << endl;
|
cout << "cache test 1 OK" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (ints) 0 1 2 3 ... 2048
|
||||||
void makeTestObject(const char *dest)
|
void makeTestObject(const char *dest)
|
||||||
{
|
{
|
||||||
int objFD = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
int objFD = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
@@ -665,7 +666,8 @@ void makeTestJournal(const char *dest)
|
|||||||
assert(write(journalFD, &i, 4) == 4);
|
assert(write(journalFD, &i, 4) == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *testObjKey = "12345_0_8192_test-object";
|
const char *testObjKey = "12345_0_8192_test-file";
|
||||||
|
const char *testFile = "test-file";
|
||||||
|
|
||||||
void makeTestMetadata(const char *dest)
|
void makeTestMetadata(const char *dest)
|
||||||
{
|
{
|
||||||
@@ -964,6 +966,86 @@ void s3storageTest1()
|
|||||||
cout << "S3Storage Test 1 OK" << endl;
|
cout << "S3Storage Test 1 OK" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOCReadTest1()
|
||||||
|
{
|
||||||
|
/* Generate the test object & metadata
|
||||||
|
read it, verify result
|
||||||
|
|
||||||
|
Generate the journal object
|
||||||
|
read it, verify the merged result
|
||||||
|
|
||||||
|
TODO: do partial reads with an offset similar to what the mergeJournal tests do
|
||||||
|
TODO: some error path testing
|
||||||
|
*/
|
||||||
|
Cache *cache = Cache::get();
|
||||||
|
CloudStorage *cs = CloudStorage::get();
|
||||||
|
IOCoordinator *ioc = IOCoordinator::get();
|
||||||
|
Config *config = Config::get();
|
||||||
|
LocalStorage *ls = dynamic_cast<LocalStorage *>(cs);
|
||||||
|
if (!ls)
|
||||||
|
{
|
||||||
|
cout << "IOC read test 1 requires LocalStorage for now." << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bf::path storagePath = ls->getPrefix();
|
||||||
|
bf::path cachePath = cache->getCachePath();
|
||||||
|
bf::path journalPath = cache->getJournalPath();
|
||||||
|
bf::path metaPath = config->getValue("ObjectStorage", "metadata_path");
|
||||||
|
assert(!metaPath.empty());
|
||||||
|
bf::create_directories(metaPath);
|
||||||
|
|
||||||
|
string objFilename = (storagePath/testObjKey).string();
|
||||||
|
string journalFilename = (journalPath/testObjKey).string() + ".journal";
|
||||||
|
string metaFilename = (metaPath/testFile).string() + ".meta";
|
||||||
|
|
||||||
|
cache->reset();
|
||||||
|
bf::remove(objFilename);
|
||||||
|
bf::remove(journalFilename);
|
||||||
|
bf::remove(metaFilename);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
boost::scoped_array<uint8_t> data(new uint8_t[1<<20]);
|
||||||
|
memset(data.get(), 0, 1<<20);
|
||||||
|
err = ioc->read(testFile, data.get(), 0, 1<<20);
|
||||||
|
assert(err < 0);
|
||||||
|
assert(errno == ENOENT);
|
||||||
|
|
||||||
|
makeTestObject(objFilename.c_str());
|
||||||
|
makeTestMetadata(metaFilename.c_str());
|
||||||
|
size_t objSize = bf::file_size(objFilename);
|
||||||
|
err = ioc->read(testFile, data.get(), 0, 1<<20);
|
||||||
|
assert(err == objSize);
|
||||||
|
|
||||||
|
// verify the data
|
||||||
|
int *data32 = (int *) data.get();
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 2048; i++)
|
||||||
|
assert(data32[i] == i);
|
||||||
|
for (; i < (1<<20)/4; i++)
|
||||||
|
assert(data32[i] == 0);
|
||||||
|
|
||||||
|
makeTestJournal(journalFilename.c_str());
|
||||||
|
|
||||||
|
err = ioc->read(testFile, data.get(), 0, 1<<20);
|
||||||
|
assert(err == objSize);
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
assert(data32[i] == i);
|
||||||
|
for (; i < 10; i++)
|
||||||
|
assert(data32[i] == i-5);
|
||||||
|
for (; i < 2048; i++)
|
||||||
|
assert(data32[i] == i);
|
||||||
|
for (; i < (1<<20)/4; i++)
|
||||||
|
assert(data32[i] == 0);
|
||||||
|
|
||||||
|
cache->reset();
|
||||||
|
bf::remove(objFilename);
|
||||||
|
bf::remove(journalFilename);
|
||||||
|
bf::remove(metaFilename);
|
||||||
|
|
||||||
|
cout << "IOC read test 1 OK" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::size_t sizeKB = 1024;
|
std::size_t sizeKB = 1024;
|
||||||
@@ -1003,6 +1085,7 @@ int main()
|
|||||||
syncTest1();
|
syncTest1();
|
||||||
|
|
||||||
s3storageTest1();
|
s3storageTest1();
|
||||||
|
IOCReadTest1();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user