Skip to content

Commit 2c397b5

Browse files
authored
Merge pull request #20 from CESNET/hutak-tsnapshot-copy
Template manager: introduce fds_snapshot_{eq,deep_copy,destroy} functions
2 parents dbb95db + 7278594 commit 2c397b5

3 files changed

Lines changed: 314 additions & 0 deletions

File tree

include/libfds/template_mgr.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,42 @@ typedef bool (*fds_tsnapshot_for_cb)(const struct fds_template *tmplt, void *dat
450450
FDS_API void
451451
fds_tsnapshot_for(const fds_tsnapshot_t *snap, fds_tsnapshot_for_cb cb, void *data);
452452

453+
/**
454+
* \brief Check if two snapshots are equal
455+
*
456+
* Only raw templates are compared i.e. everything is ignored except Template ID
457+
* and template fields (Information Element ID, Private Enterprise Number and length).
458+
* \param[in] lhs Template snapshot
459+
* \param[in] rhs Template snapshot
460+
* \return Non-zero value if the snapshots are the same. Otherwise returns zero.
461+
*/
462+
FDS_API int
463+
fds_tsnapshot_eq(const fds_tsnapshot_t *lhs, const fds_tsnapshot_t *rhs);
464+
465+
/**
466+
* \brief Create a deep copy of the given template snapshot.
467+
*
468+
* The newly created snapshot is not a part of any template manager and it MUST be
469+
* later destroyed using fds_tsnapshot_destroy() function.
470+
*
471+
* Keep on mind that all Templates will preseve their references to definition of
472+
* Information Elements stored inside an external IE Manager.
473+
* \param[in] snap Template snapshot to copy
474+
* \return Pointer or NULL (i.e. memory allocation error)
475+
*/
476+
FDS_API fds_tsnapshot_t *
477+
fds_tsnapshot_deep_copy(const fds_tsnapshot_t *snap);
478+
479+
/**
480+
* \brief Destroy a template snapshot.
481+
*
482+
* The function should be called only on a Template snapshot previously created
483+
* by fds_tsnapshot_deep_copy() as it will also destroy all referenced Templates.
484+
* \param[in] snap Template snapshot to destory
485+
*/
486+
FDS_API void
487+
fds_tsnapshot_destroy(fds_tsnapshot_t *snap);
488+
453489
/**
454490
* @}
455491
*/

src/template_mgr/template_manager.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,112 @@ fds_tsnapshot_for(const fds_tsnapshot_t *snap, fds_tsnapshot_for_cb cb, void *da
18441844
snapshot_rec_for(snap_orig, &tsnapshot_cb_aux, &for_data);
18451845
}
18461846

1847+
/// Auxiliary internal data structure for template snapshot comparison
1848+
struct tsnapshot_eq_data {
1849+
/// Right-hand side parameter of comparision function
1850+
const fds_tsnapshot_t *rhs;
1851+
/// Result of comparison
1852+
int result;
1853+
};
1854+
1855+
static bool
1856+
fds_tsnapshot_eq_cb(const struct fds_template *lhs_tmplt, void *data)
1857+
{
1858+
struct tsnapshot_eq_data *cmp_data = (struct tsnapshot_eq_data *) data;
1859+
const struct fds_template *rhs_tmplt;
1860+
1861+
rhs_tmplt = fds_tsnapshot_template_get(cmp_data->rhs, lhs_tmplt->id);
1862+
if (!rhs_tmplt) {
1863+
cmp_data->result = 0; // Template not found
1864+
return false;
1865+
}
1866+
1867+
if (fds_template_cmp(lhs_tmplt, rhs_tmplt) != 0) {
1868+
cmp_data->result = 0; // Template is different
1869+
return false;
1870+
}
1871+
1872+
return true;
1873+
}
1874+
1875+
int
1876+
fds_tsnapshot_eq(const fds_tsnapshot_t *lhs, const fds_tsnapshot_t *rhs)
1877+
{
1878+
struct tsnapshot_eq_data eq_data = {rhs, 1};
1879+
1880+
if (lhs == rhs)
1881+
return 1;
1882+
1883+
if (lhs->rec_cnt != rhs->rec_cnt) {
1884+
return 0;
1885+
}
1886+
1887+
fds_tsnapshot_for(lhs, &fds_tsnapshot_eq_cb, &eq_data);
1888+
return eq_data.result;
1889+
}
1890+
1891+
/// Auxiliary internal data structure for deep copy of a template snapshot
1892+
struct tsnapshot_deep_copy_data {
1893+
/// Snapshot where to insert copied templates
1894+
fds_tsnapshot_t *snapshot;
1895+
/// Result of deep copy
1896+
int failed;
1897+
};
1898+
1899+
static bool
1900+
fds_tsnapshot_deep_copy_cb(const struct fds_template *tmplt, void *data)
1901+
{
1902+
struct tsnapshot_deep_copy_data *dc_data = (struct tsnapshot_deep_copy_data *) data;
1903+
const int tmplt_flags = SNAPSHOT_TF_CREATE | SNAPSHOT_TF_DESTROY;
1904+
struct fds_template *tmplt_copy;
1905+
int ret;
1906+
1907+
tmplt_copy = fds_template_copy(tmplt);
1908+
if (!tmplt_copy) {
1909+
dc_data->failed = 1;
1910+
return false;
1911+
}
1912+
1913+
ret = mgr_snap_template_add_ref(dc_data->snapshot, tmplt_copy, tmplt_flags);
1914+
if (ret != FDS_OK) {
1915+
fds_template_destroy(tmplt_copy);
1916+
dc_data->failed = 1;
1917+
return false;
1918+
}
1919+
1920+
return true;
1921+
}
1922+
1923+
fds_tsnapshot_t *
1924+
fds_tsnapshot_deep_copy(const fds_tsnapshot_t *snap)
1925+
{
1926+
struct tsnapshot_deep_copy_data dc_data = {0};
1927+
fds_tsnapshot_t *result;
1928+
1929+
result = snapshot_create();
1930+
if (!result) {
1931+
return NULL;
1932+
}
1933+
1934+
result->start_time = snap->start_time;
1935+
dc_data.snapshot = result;
1936+
1937+
fds_tsnapshot_for(snap, &fds_tsnapshot_deep_copy_cb, &dc_data);
1938+
1939+
if (dc_data.failed) {
1940+
mgr_snap_destroy(result);
1941+
return NULL;
1942+
}
1943+
1944+
return result;
1945+
}
1946+
1947+
void
1948+
fds_tsnapshot_destroy(fds_tsnapshot_t *snap)
1949+
{
1950+
mgr_snap_destroy(snap);
1951+
}
1952+
18471953
int
18481954
fds_tmgr_template_get(fds_tmgr_t *tmgr, uint16_t id, const struct fds_template **tmplt)
18491955
{

tests/unit_tests/templates/tmgr_common.cpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,178 @@ TEST_P(Common, snapshotIterator)
847847
}
848848
}
849849

850+
// Auxiliary callback function for counting number of templates in a snapshot
851+
bool snapshot_iterator_count_cb(const struct fds_template *tmplt, void *data)
852+
{
853+
(void) tmplt;
854+
855+
size_t *count = reinterpret_cast<size_t *>(data);
856+
(*count)++;
857+
858+
return true;
859+
}
860+
861+
// Try to create a deep copy of a Template snapshot
862+
TEST_P(Common, snapshotDeepCopy)
863+
{
864+
const struct fds_template *tmplt;
865+
const fds_tsnapshot_t *snap = nullptr;
866+
fds_tsnapshot_t *snap_copy = nullptr;
867+
size_t count;
868+
869+
// Create an IE manager and load definitions
870+
fds_iemgr_t *iemgr = fds_iemgr_create();
871+
ASSERT_NE(iemgr, nullptr);
872+
ASSERT_EQ(fds_iemgr_read_file(iemgr, "./data/iana.xml", false), FDS_OK);
873+
fds_tmgr_set_iemgr(tmgr, iemgr);
874+
875+
// Create a copy of an empty snapshot
876+
EXPECT_EQ(fds_tmgr_set_time(tmgr, 10000), FDS_OK);
877+
ASSERT_EQ(fds_tmgr_snapshot_get(tmgr, &snap), FDS_OK);
878+
ASSERT_NE(snap, nullptr);
879+
snap_copy = fds_tsnapshot_deep_copy(snap);
880+
ASSERT_NE(snap_copy, nullptr);
881+
EXPECT_TRUE(fds_tsnapshot_eq(snap, snap_copy));
882+
883+
count = 0;
884+
fds_tsnapshot_for(snap_copy, &snapshot_iterator_count_cb, &count);
885+
ASSERT_EQ(count, 0U);
886+
887+
fds_tsnapshot_destroy(snap_copy);
888+
889+
// Create a copy of a snapshot with some templates
890+
const uint16_t tid1 = 1234;
891+
const uint16_t tid2 = 2000;
892+
const uint16_t tid3 = 256;
893+
struct fds_template *t1 = TMock::create(TMock::type::DATA_BASIC_FLOW, tid1);
894+
struct fds_template *t2 = TMock::create(TMock::type::OPTS_ERPOC_RSTAT, tid2);
895+
struct fds_template *t3 = TMock::create(TMock::type::DATA_BASIC_BIFLOW, tid3);
896+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t1), FDS_OK);
897+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t2), FDS_OK);
898+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t3), FDS_OK);
899+
900+
ASSERT_EQ(fds_tmgr_snapshot_get(tmgr, &snap), FDS_OK);
901+
ASSERT_NE(snap, nullptr);
902+
snap_copy = fds_tsnapshot_deep_copy(snap);
903+
ASSERT_NE(snap_copy, nullptr);
904+
EXPECT_TRUE(fds_tsnapshot_eq(snap, snap_copy));
905+
906+
/*
907+
* Destroy the template manager
908+
* (the templates in deeply copied snapshot should be still accessible)
909+
*/
910+
fds_tmgr_destroy(tmgr);
911+
tmgr = nullptr;
912+
913+
// Try to access the templates in the copied snapshop
914+
count = 0;
915+
fds_tsnapshot_for(snap_copy, &snapshot_iterator_count_cb, &count);
916+
ASSERT_EQ(count, 3U);
917+
918+
tmplt = fds_tsnapshot_template_get(snap_copy, tid1); // TID 1
919+
ASSERT_NE(tmplt, nullptr);
920+
EXPECT_NE(tmplt->raw.data, nullptr);
921+
EXPECT_EQ(tmplt->fields_rev, nullptr);
922+
923+
for (uint16_t i = 0; i < tmplt->fields_cnt_total; ++i) {
924+
const struct fds_tfield *field = &tmplt->fields[i];
925+
926+
// Just try to touch a memory of template and IE manager
927+
EXPECT_NE(field->id, 0U);
928+
if (field->def) {
929+
EXPECT_EQ(field->id, field->def->id);
930+
}
931+
}
932+
933+
tmplt = fds_tsnapshot_template_get(snap_copy, tid3); // TID 3
934+
ASSERT_NE(tmplt, nullptr);
935+
EXPECT_NE(tmplt->raw.data, nullptr);
936+
ASSERT_NE(tmplt->fields_rev, nullptr);
937+
938+
for (uint16_t i = 0; i < tmplt->fields_cnt_total; ++i) {
939+
const struct fds_tfield *field = &tmplt->fields[i];
940+
const struct fds_tfield *field_rev = &tmplt->fields_rev[i];
941+
942+
// Just try to touch a memory of template and IE manager
943+
EXPECT_NE(field->id, 0U);
944+
945+
if (field->def) {
946+
EXPECT_EQ(field->id, field->def->id);
947+
}
948+
949+
EXPECT_NE(field_rev->id, 0U);
950+
951+
if (field_rev->def) {
952+
EXPECT_EQ(field_rev->id, field_rev->def->id);
953+
}
954+
}
955+
956+
fds_tsnapshot_destroy(snap_copy);
957+
fds_iemgr_destroy(iemgr);
958+
}
959+
960+
// Try to compare two independent snapshots with the same Templates
961+
TEST_P(Common, snapshotEq)
962+
{
963+
// Create an IE manager and load definitions
964+
fds_iemgr_t *iemgr = fds_iemgr_create();
965+
ASSERT_NE(iemgr, nullptr);
966+
ASSERT_EQ(fds_iemgr_read_file(iemgr, "./data/iana.xml", false), FDS_OK);
967+
968+
// Create a secondary independent Template manager with the IE manager
969+
fds_tmgr_t *tmgr2 = fds_tmgr_create(GetParam());
970+
ASSERT_NE(tmgr2, nullptr);
971+
ASSERT_EQ(fds_tmgr_set_iemgr(tmgr2, iemgr), FDS_OK);
972+
973+
// Set different export time
974+
const uint32_t time1 = 2147483647;
975+
const uint32_t time2 = 2147483657;
976+
EXPECT_EQ(fds_tmgr_set_time(tmgr, time1), FDS_OK);
977+
EXPECT_EQ(fds_tmgr_set_time(tmgr2, time2), FDS_OK);
978+
979+
// Fill the primary Template manager with Templates
980+
const uint16_t tid1 = 1234;
981+
const uint16_t tid2 = 1235;
982+
const uint16_t tid3 = 12222;
983+
struct fds_template *t1 = TMock::create(TMock::type::DATA_BASIC_FLOW, tid1);
984+
struct fds_template *t2 = TMock::create(TMock::type::OPTS_MPROC_STAT, tid2);
985+
struct fds_template *t3 = TMock::create(TMock::type::OPTS_FKEY, tid3);
986+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t1), FDS_OK);
987+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t2), FDS_OK);
988+
EXPECT_EQ(fds_tmgr_template_add(tmgr, t3), FDS_OK);
989+
990+
const fds_tsnapshot_t *snap = nullptr;
991+
EXPECT_EQ(fds_tmgr_snapshot_get(tmgr, &snap), FDS_OK);
992+
EXPECT_TRUE(fds_tsnapshot_eq(snap, snap));
993+
994+
const fds_tsnapshot_t *snap2 = nullptr;
995+
EXPECT_EQ(fds_tmgr_snapshot_get(tmgr2, &snap2), FDS_OK);
996+
997+
// Compare the primary (filled) with secondary (empty) snapshot
998+
EXPECT_FALSE(fds_tsnapshot_eq(snap, snap2));
999+
1000+
// Fill the secondary Template manager
1001+
t1 = TMock::create(TMock::type::DATA_BASIC_FLOW, tid1);
1002+
t2 = TMock::create(TMock::type::OPTS_MPROC_STAT, tid2);
1003+
t3 = TMock::create(TMock::type::OPTS_FKEY, tid3);
1004+
EXPECT_EQ(fds_tmgr_template_add(tmgr2, t1), FDS_OK);
1005+
EXPECT_EQ(fds_tmgr_template_add(tmgr2, t2), FDS_OK);
1006+
EXPECT_EQ(fds_tmgr_template_add(tmgr2, t3), FDS_OK);
1007+
1008+
// Compare the primary with the secondary snapshot
1009+
EXPECT_EQ(fds_tmgr_snapshot_get(tmgr2, &snap2), FDS_OK);
1010+
EXPECT_TRUE(fds_tsnapshot_eq(snap, snap2));
1011+
1012+
// Slightly modify secondary template manager so it is different
1013+
struct fds_template *t4 = TMock::create(TMock::type::DATA_BASIC_BIFLOW, 1236);
1014+
EXPECT_EQ(fds_tmgr_template_add(tmgr2, t4), FDS_OK);
1015+
1016+
EXPECT_EQ(fds_tmgr_snapshot_get(tmgr2, &snap2), FDS_OK);
1017+
EXPECT_FALSE(fds_tsnapshot_eq(snap, snap2));
1018+
1019+
fds_tmgr_destroy(tmgr2);
1020+
fds_iemgr_destroy(iemgr);
1021+
}
8501022

8511023
// TODO: Multiple updates of the same template at the same time + cleanup
8521024

0 commit comments

Comments
 (0)