Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor for simplification and unique responsability for some classes Add OS support for macOS and Windows #22360

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 115 additions & 19 deletions src/shared_modules/utils/rocksDBWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,20 +492,91 @@ namespace Utils
*/
void deleteAll() override
{
// Delete from all family columns
for (const auto& columnHandle : m_columnsHandles)
auto it = m_columnsHandles.begin();
std::vector<std::string> columnsNames;
sebasfalcone marked this conversation as resolved.
Show resolved Hide resolved

while (it != m_columnsHandles.end())
{
rocksdb::WriteBatch batch;
std::unique_ptr<rocksdb::Iterator> it(m_db->NewIterator(rocksdb::ReadOptions(), columnHandle));
for (it->SeekToFirst(); it->Valid(); it->Next())
if ((*it)->GetName() != rocksdb::kDefaultColumnFamilyName)
{
batch.Delete(it->key());
auto status = m_db->DropColumnFamily(*it);
if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
}
columnsNames.push_back((*it)->GetName());
sebasfalcone marked this conversation as resolved.
Show resolved Hide resolved

status = m_db->DestroyColumnFamilyHandle(*it);
if (!status.ok())
{
std::cerr << "Failed to free RocksDB column family: " + std::string {status.getState()}
<< std::endl;
}

it = m_columnsHandles.erase(it);
sebasfalcone marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
rocksdb::WriteBatch batch;
std::unique_ptr<rocksdb::Iterator> itDefault(m_db->NewIterator(rocksdb::ReadOptions(), *it));
for (itDefault->SeekToFirst(); itDefault->Valid(); itDefault->Next())
{
batch.Delete(*it, itDefault->key());
}

auto status = m_db->Write(rocksdb::WriteOptions(), &batch);
if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
}

++it;
}
}

rocksdb::WriteOptions writeOptions;
writeOptions.disableWAL = true;
for (const auto& columnName : columnsNames)
{
createColumn(columnName);
}
}

const auto status {m_db->Write(writeOptions, &batch)};
/**
* @brief Delete all key-value pairs from specified column.
* @param column The column to delete from.
*/
void deleteAll(const std::string& columnName)
{
// Delete all data from the specified column
const auto columnHandle = getColumnFamilyHandle(columnName);
if (columnHandle->GetName() != rocksdb::kDefaultColumnFamilyName)
{
auto status = m_db->DropColumnFamily(columnHandle);
if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
}

status = m_db->DestroyColumnFamilyHandle(columnHandle);
if (!status.ok())
{
std::cerr << "Failed to free RocksDB column family: " + std::string {status.getState()}
<< std::endl;
}

m_columnsHandles.erase(std::remove(m_columnsHandles.begin(), m_columnsHandles.end(), columnHandle),
m_columnsHandles.end());
createColumn(columnName);
}
else
{
rocksdb::WriteBatch batch;
std::unique_ptr<rocksdb::Iterator> itDefault(m_db->NewIterator(rocksdb::ReadOptions(), columnHandle));
for (itDefault->SeekToFirst(); itDefault->Valid(); itDefault->Next())
{
batch.Delete(columnHandle, itDefault->key());
}

auto status = m_db->Write(rocksdb::WriteOptions(), &batch);
if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
Expand All @@ -529,8 +600,6 @@ namespace Utils
// Delete data from all family columns
for (const auto& columnHandle : m_columnsHandles)
{
rocksdb::WriteBatch batch;

// Create an iterator for the current column family
std::unique_ptr<rocksdb::Iterator> it(m_db->NewIterator(rocksdb::ReadOptions(), columnHandle));

Expand All @@ -542,18 +611,45 @@ namespace Utils

callback(keyStr, valueStr);

// Mark the key for deletion in the batch
batch.Delete(keyStr);
auto status = m_db->Delete(rocksdb::WriteOptions(), columnHandle, it->key());

if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
}
}
}
}

/**
* @brief Delete all key-value pairs from the database.
*
* This method deletes all key-value pairs stored in the database for a specific column family.
* Uses a provided callback function to handle each deleted key. After deletion, it commits the changes
* to the database.
*
* @param callback A callback function that takes a string reference representing the deleted key.
* @param columnName The column name to delete from.
*
* @throws std::runtime_error if an error occurs during data deletion.
*/
void deleteAll(const std::function<void(std::string&, std::string&)>& callback, const std::string& columnName)
{
// Get the column family handle
const auto columnHandle = getColumnFamilyHandle(columnName);

// Create an iterator for the current column family
std::unique_ptr<rocksdb::Iterator> it(m_db->NewIterator(rocksdb::ReadOptions(), columnHandle));

for (it->SeekToFirst(); it->Valid(); it->Next())
{
auto keyStr = std::string(it->key().data(), it->key().size());
auto valueStr = it->value().ToString();

// Configure write options to disable write-ahead-logging (WAL)
rocksdb::WriteOptions writeOptions;
writeOptions.disableWAL = true;
callback(keyStr, valueStr);

// Write the batch changes to the database
const auto status = m_db->Write(writeOptions, &batch);
auto status = m_db->Delete(rocksdb::WriteOptions(), columnHandle, it->key());

// Check for errors and throw an exception if necessary
if (!status.ok())
{
throw std::runtime_error("Error deleting data: " + status.ToString());
Expand Down
39 changes: 30 additions & 9 deletions src/shared_modules/utils/socketDBWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
#include <condition_variable>
#include <mutex>
#include <string>
#include <utility>

auto constexpr DB_WRAPPER_QUERY_WAIT_TIME {500};
auto constexpr DB_WRAPPER_QUERY_WAIT_TIME {5000};

char constexpr DB_WRAPPER_OK[] = {"ok"};
char constexpr DB_WRAPPER_ERROR[] = {"err"};
Expand All @@ -33,18 +34,19 @@ class SocketDBWrapper final
nlohmann::json m_response;
nlohmann::json m_responsePartial;
std::string m_exceptionStr;
std::mutex m_mutex;
std::mutex m_mutexMessage;
std::mutex m_mutexResponse;
std::condition_variable m_conditionVariable;
std::string m_socketPath;

public:
explicit SocketDBWrapper(const std::string& socketPath)
: m_dbSocket {
std::make_unique<SocketClient<Socket<OSPrimitives, SizeHeaderProtocol>, EpollWrapper>>(socketPath)}
void initializeSocket()
{
m_dbSocket =
std::make_unique<SocketClient<Socket<OSPrimitives, SizeHeaderProtocol>, EpollWrapper>>(m_socketPath);
m_dbSocket->connect(
[&](const char* body, uint32_t bodySize, const char* header, uint32_t headerSize)
{
std::lock_guard<std::mutex> lock {m_mutex};
std::lock_guard<std::mutex> lock {m_mutexResponse};
std::string responsePacket(body, bodySize);

if (0 == responsePacket.compare(0, sizeof(DB_WRAPPER_DUE) - 1, DB_WRAPPER_DUE))
Expand Down Expand Up @@ -116,20 +118,39 @@ class SocketDBWrapper final
});
}

public:
explicit SocketDBWrapper(std::string socketPath)
: m_socketPath(std::move(socketPath))
{
initializeSocket();
}

void query(const std::string& query, nlohmann::json& response)
{
// Acquire lock to avoid multiple threads sending queries at the same time
std::lock_guard<std::mutex> lockMessage {m_mutexMessage};

// Acquire lock before clearing the response
std::unique_lock<std::mutex> lock {m_mutex};
std::unique_lock<std::mutex> lockResponse {m_mutexResponse};

if (!m_dbSocket)
{
initializeSocket();
}

m_response.clear();
m_responsePartial.clear();
m_exceptionStr.clear();

m_dbSocket->send(query.c_str(), query.size());
const auto res = m_conditionVariable.wait_for(lock, std::chrono::milliseconds(DB_WRAPPER_QUERY_WAIT_TIME));
const auto res =
m_conditionVariable.wait_for(lockResponse, std::chrono::milliseconds(DB_WRAPPER_QUERY_WAIT_TIME));

if (res == std::cv_status::timeout)
{
// Restart the socket connection to avoid the reception of old messages
m_dbSocket->stop();
initializeSocket();
throw std::runtime_error("Timeout waiting for DB response");
}

Expand Down
16 changes: 14 additions & 2 deletions src/shared_modules/utils/tests/rocksDBWrapper_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@ TEST_F(RocksDBWrapperTest, TestDeleteAll)
EXPECT_FALSE(db_wrapper->get("key7", value)); // The key should have been deleted
}

/**
* @brief Tests the deleteAll function with column family
*/
TEST_F(RocksDBWrapperTest, TestDeleteAllColumnFamily)
{
db_wrapper->createColumn("column_A");
db_wrapper->put("key6", "value6", "column_A");
db_wrapper->put("key7", "value7", "column_A");
EXPECT_NO_THROW(db_wrapper->deleteAll());
std::string value {};
EXPECT_FALSE(db_wrapper->get("key6", value, "column_A")); // The key should have been deleted
EXPECT_FALSE(db_wrapper->get("key7", value, "column_A")); // The key should have been deleted
}

/**
* @brief Tests the deleteAll function with an empty database
*/
Expand Down Expand Up @@ -428,8 +442,6 @@ TEST_F(RocksDBWrapperTest, CreateMultipleColumns)
constexpr auto COLUMN_NAME_B {"column_B"};
constexpr auto COLUMN_NAME_C {"column_C"};

EXPECT_NO_THROW(db_wrapper->createColumn(COLUMN_NAME_A));
EXPECT_NO_THROW(db_wrapper->createColumn(COLUMN_NAME_B));
EXPECT_NO_THROW(db_wrapper->createColumn(COLUMN_NAME_C));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ constexpr auto TRANSLATIONS_COLUMN {"translations"};
constexpr auto DESCRIPTIONS_COLUMN {"descriptions"};
constexpr auto VENDOR_MAP_COLUMN {"vendor_map"};
constexpr auto OS_CPE_RULES_COLUMN {"oscpe_rules"};
constexpr auto LOCALFILE_MQ {"1"};

/**
* @brief VulnerabilityScanner class.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
"Deleting package agent key: test_node_name_001_ec465b7eb5fa011a336e95614072e4c7f1a65a53"
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"agent_info": {
"agent_id": "001",
"node_name": "test_node_name"
},
"data_type": "dbsync_packages",
"data": {
"architecture": "amd64",
"checksum": "1e6ce14f97f57d1bbd46ff8e5d3e133171a1bbce",
"description": "system and service manager",
"format": "deb",
"groups": "libs",
"item_id": "ec465b7eb5fa011a336e95614072e4c7f1a65a53",
"multiarch": "same",
"name": "systemd",
"priority": "optional",
"scan_time": "2023/08/04 19:56:11",
"size": 72,
"source": "systemd",
"vendor": "Debian vendor",
"version": "247.3-7+deb11u4"
},
"operation": "DELETED"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Loading
Loading