Cache: Add TesterStorage class
A class dedicated for performing basic testing of Storages.
This commit is contained in:
219
server/modules/filter/cache/test/testerstorage.cc
vendored
Normal file
219
server/modules/filter/cache/test/testerstorage.cc
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include "testerstorage.hh"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include "storage.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// class TesterStorage::HitTask
|
||||
//
|
||||
|
||||
TesterStorage::HitTask::HitTask(ostream* pOut,
|
||||
Storage* pStorage,
|
||||
const CacheItems* pCache_items)
|
||||
: Tester::Task(pOut)
|
||||
, m_storage(*pStorage)
|
||||
, m_cache_items(*pCache_items)
|
||||
, m_puts(0)
|
||||
, m_gets(0)
|
||||
, m_dels(0)
|
||||
, m_misses(0)
|
||||
{
|
||||
ss_dassert(m_cache_items.size() > 0);
|
||||
}
|
||||
|
||||
int TesterStorage::HitTask::run()
|
||||
{
|
||||
int rv = EXIT_SUCCESS;
|
||||
|
||||
size_t n = m_cache_items.size();
|
||||
size_t i = 0;
|
||||
|
||||
while (!should_terminate())
|
||||
{
|
||||
if (i >= n)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
const CacheItems::value_type& cache_item = m_cache_items[i];
|
||||
|
||||
storage_action_t action = TesterStorage::get_random_action();
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case STORAGE_PUT:
|
||||
{
|
||||
cache_result_t result = m_storage.put_value(cache_item.first, cache_item.second);
|
||||
if (result == CACHE_RESULT_OK)
|
||||
{
|
||||
++m_puts;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(!true);
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STORAGE_GET:
|
||||
{
|
||||
GWBUF* pQuery;
|
||||
cache_result_t result = m_storage.get_value(cache_item.first, 0, &pQuery);
|
||||
|
||||
if (result == CACHE_RESULT_OK)
|
||||
{
|
||||
ss_dassert(GWBUF_LENGTH(pQuery) == GWBUF_LENGTH(cache_item.second));
|
||||
ss_dassert(memcmp(GWBUF_DATA(pQuery), GWBUF_DATA(cache_item.second),
|
||||
GWBUF_LENGTH(pQuery)) == 0);
|
||||
|
||||
gwbuf_free(pQuery);
|
||||
++m_gets;
|
||||
}
|
||||
else if (result == CACHE_RESULT_NOT_FOUND)
|
||||
{
|
||||
++m_misses;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(!true);
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STORAGE_DEL:
|
||||
{
|
||||
cache_result_t result = m_storage.del_value(cache_item.first);
|
||||
|
||||
if (result == CACHE_RESULT_OK)
|
||||
{
|
||||
++m_dels;
|
||||
}
|
||||
else if (result == CACHE_RESULT_NOT_FOUND)
|
||||
{
|
||||
++m_misses;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(!true);
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ss_dassert(!true);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
stringstream ss;
|
||||
ss << "HitTask ending: "
|
||||
<< m_gets << ", " << m_puts << ", " << m_dels << ", " << m_misses << "\n";
|
||||
|
||||
out() << ss.str() << flush;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// class TesterStorage
|
||||
//
|
||||
|
||||
TesterStorage::TesterStorage(std::ostream* pOut, StorageFactory* pFactory)
|
||||
: Tester(pOut)
|
||||
, m_factory(*pFactory)
|
||||
{
|
||||
}
|
||||
|
||||
int TesterStorage::run(size_t n_threads, size_t n_seconds, std::istream& in)
|
||||
{
|
||||
int rv = EXIT_FAILURE;
|
||||
|
||||
Storage* pStorage = get_storage();
|
||||
|
||||
if (pStorage)
|
||||
{
|
||||
size_t n_items = get_n_items(n_threads, n_seconds);
|
||||
|
||||
CacheItems cache_items;
|
||||
|
||||
if (get_cache_items(in, n_items, *pStorage, &cache_items))
|
||||
{
|
||||
rv = run(n_threads, n_seconds, cache_items, *pStorage);
|
||||
}
|
||||
|
||||
delete pStorage;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int TesterStorage::run(size_t n_threads,
|
||||
size_t n_seconds,
|
||||
const CacheItems& cache_items,
|
||||
Storage& storage)
|
||||
{
|
||||
return run_hit_task(n_threads, n_seconds, cache_items, storage);
|
||||
}
|
||||
|
||||
int TesterStorage::run_hit_task(size_t n_threads,
|
||||
size_t n_seconds,
|
||||
const CacheItems& cache_items,
|
||||
Storage& storage)
|
||||
{
|
||||
int rv = EXIT_FAILURE;
|
||||
|
||||
Tasks tasks;
|
||||
|
||||
for (size_t i = 0; i < n_threads; ++i)
|
||||
{
|
||||
tasks.push_back(new HitTask(&out(), &storage, &cache_items));
|
||||
}
|
||||
|
||||
rv = Tester::run(out(), n_seconds, tasks);
|
||||
|
||||
for_each(tasks.begin(), tasks.end(), Task::free);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// static
|
||||
TesterStorage::storage_action_t TesterStorage::get_random_action()
|
||||
{
|
||||
storage_action_t action;
|
||||
long l = random();
|
||||
|
||||
if (l < RAND_MAX / 3)
|
||||
{
|
||||
action = STORAGE_PUT;
|
||||
}
|
||||
else if (l < 2 * (RAND_MAX / 3))
|
||||
{
|
||||
action = STORAGE_GET;
|
||||
}
|
||||
else
|
||||
{
|
||||
action = STORAGE_DEL;
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
152
server/modules/filter/cache/test/testerstorage.hh
vendored
Normal file
152
server/modules/filter/cache/test/testerstorage.hh
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include "tester.hh"
|
||||
|
||||
class StorageFactory;
|
||||
|
||||
class TesterStorage : public Tester
|
||||
{
|
||||
public:
|
||||
enum storage_action_t
|
||||
{
|
||||
STORAGE_PUT, /*< Put an item to the storage. */
|
||||
STORAGE_GET, /*< Get an item from the storage. */
|
||||
STORAGE_DEL /*< Delete an item from the storage. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class HitTask
|
||||
*
|
||||
* A task whose sole purpose is to hit a Storage continuously
|
||||
* and intensly.
|
||||
*/
|
||||
class HitTask : public Tester::Task
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pOut The stream to use for (user) output.
|
||||
* @param pStorage The storage to hit.
|
||||
* @param pCache_items The cache items to use when hitting the storage.
|
||||
*/
|
||||
HitTask(std::ostream* pOut,
|
||||
Storage* pStorage,
|
||||
const CacheItems* pCache_items);
|
||||
|
||||
/**
|
||||
* Runs continuously until the task is terminated.
|
||||
*
|
||||
* @return EXIT_SUCCESS or EXIT_FAILURE
|
||||
*/
|
||||
int run();
|
||||
|
||||
private:
|
||||
HitTask(const HitTask&);
|
||||
HitTask& operator = (const HitTask&);
|
||||
|
||||
private:
|
||||
Storage& m_storage; /*< The storage that is hit. */
|
||||
const CacheItems& m_cache_items; /*< The cache items that are used. */
|
||||
size_t m_puts; /*< How many puts. */
|
||||
size_t m_gets; /*< How many gets. */
|
||||
size_t m_dels; /*< How many deletes. */
|
||||
size_t m_misses; /*< How many misses. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads statements from the provided stream, converts them to cache items and
|
||||
* runs all storage tasks using as many threads as specified for the specified
|
||||
* number of seconds.
|
||||
*
|
||||
* @param n_threads How many threads to use.
|
||||
* @param n_seconds For how many seconds to run the test.
|
||||
* @param in Stream, assumed to refer to a file containing statements.
|
||||
*
|
||||
* @return EXIT_SUCCESS or EXIT_FAILURE.
|
||||
*/
|
||||
virtual int run(size_t n_threads, size_t n_seconds, std::istream& in);
|
||||
|
||||
/**
|
||||
* Runs all storage tasks using as many threads as specified, for the specified
|
||||
* number of seconds.
|
||||
*
|
||||
* @param n_threads How many threads to use.
|
||||
* @param n_seconds For how many seconds to run the test.
|
||||
* @param cache_items The cache items to use. Assumed to have been created using
|
||||
* @c storage.
|
||||
* @param storage The storage items to use.
|
||||
*
|
||||
* @return EXIT_SUCCESS or EXIT_FAILURE.
|
||||
*/
|
||||
virtual int run(size_t n_threads, size_t n_seconds, const CacheItems& cache_items, Storage& storage);
|
||||
|
||||
/**
|
||||
* Runs the HitTask using as many threads as specified, for the specified
|
||||
* number of seconds.
|
||||
*
|
||||
* @param n_threads How many threads to use.
|
||||
* @param n_seconds For how many seconds to run the test.
|
||||
* @param cache_items The cache items to use. Assumed to have been created using
|
||||
* @c storage.
|
||||
* @param storage The storage items to use.
|
||||
*
|
||||
* @return EXIT_SUCCESS or EXIT_FAILURE.
|
||||
*/
|
||||
virtual int run_hit_task(size_t n_threads,
|
||||
size_t n_seconds,
|
||||
const CacheItems& cache_items,
|
||||
Storage& storage);
|
||||
|
||||
/**
|
||||
* Get a random action.
|
||||
*
|
||||
* @return Some storage action.
|
||||
*/
|
||||
static storage_action_t get_random_action();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pOut Pointer to the stream to be used for (user) output.
|
||||
* @param pFactory Pointer to factory to be used.
|
||||
*/
|
||||
TesterStorage(std::ostream* pOut, StorageFactory* pFactory);
|
||||
|
||||
/**
|
||||
* Return a storage instance. The ownership is transferred to the caller.
|
||||
*
|
||||
* @return A storage instance or NULL.
|
||||
*/
|
||||
virtual Storage* get_storage() = 0;
|
||||
|
||||
/**
|
||||
* Return the desired number of cache items to be used in the tests.
|
||||
*
|
||||
* @param n_threads How many threads are used.
|
||||
* @param n_seconds For how many seconds the tests will be run.
|
||||
*
|
||||
* @return The desired number of items to use.
|
||||
*/
|
||||
virtual size_t get_n_items(size_t n_threads, size_t n_seconds) = 0;
|
||||
|
||||
protected:
|
||||
StorageFactory& m_factory; /*< The storage factory that is used. */
|
||||
|
||||
private:
|
||||
TesterStorage(const TesterStorage&);
|
||||
TesterStorage& operator = (const TesterStorage&);
|
||||
};
|
Reference in New Issue
Block a user