diff --git a/lib/records/P_RecCore.cc b/lib/records/P_RecCore.cc index 4e073772d09..11d800cd91e 100644 --- a/lib/records/P_RecCore.cc +++ b/lib/records/P_RecCore.cc @@ -34,6 +34,8 @@ #include "P_RecMessage.h" #include "P_RecCore.h" +#include + RecModeT g_mode_type = RECM_NULL; //------------------------------------------------------------------------- @@ -491,6 +493,27 @@ RecSetRecordCounter(const char *name, RecCounter rec_counter, RecSourceT source, return RecSetRecord(RECT_NULL, name, RECD_COUNTER, &data, nullptr, source, lock, inc_version); } +// check the version of the snap file to remove records.snap or not +static void +CheckSnapFileVersion(const char *path) +{ + std::ifstream f(path, std::ios::binary); + if (f.good()) { + // get version, compare and remove + char data[VERSION_HDR_SIZE]; + if (!f.read(data, VERSION_HDR_SIZE)) { + return; + } + if (data[0] != 'V' || data[1] != PACKAGE_VERSION[0] || data[2] != PACKAGE_VERSION[2] || data[3] != PACKAGE_VERSION[4] || + data[4] != '\0') { + // not the right version found + if (remove(path) != 0) { + ink_warning("unable to remove incompatible snap file '%s'", path); + } + } + } +} + //------------------------------------------------------------------------- // RecReadStatsFile //------------------------------------------------------------------------- @@ -506,6 +529,8 @@ RecReadStatsFile() // lock our hash table ink_rwlock_wrlock(&g_records_rwlock); + CheckSnapFileVersion(snap_fpath); + if ((m = RecMessageReadFromDisk(snap_fpath)) != nullptr) { if (RecMessageUnmarshalFirst(m, &itr, &r) != REC_ERR_FAIL) { do { diff --git a/lib/records/P_RecFile.h b/lib/records/P_RecFile.h index a47448dd91e..93c0c402663 100644 --- a/lib/records/P_RecFile.h +++ b/lib/records/P_RecFile.h @@ -30,6 +30,7 @@ #define REC_HANDLE_INVALID -1 typedef int RecHandle; +static constexpr unsigned VERSION_HDR_SIZE = 5; //------------------------------------------------------------------------- // RecFile //------------------------------------------------------------------------- @@ -38,7 +39,9 @@ RecHandle RecFileOpenR(const char *file); RecHandle RecFileOpenW(const char *file); int RecFileClose(RecHandle h_file); int RecFileRead(RecHandle h_file, char *buf, int size, int *bytes_read); +int RecSnapFileRead(RecHandle h_file, char *buf, int size, int *bytes_read); int RecFileWrite(RecHandle h_file, char *buf, int size, int *bytes_written); +int RecSnapFileWrite(RecHandle h_file, char *buf, int size, int *bytes_written); int RecFileGetSize(RecHandle h_file); int RecFileExists(const char *file); int RecFileSync(RecHandle h_file); diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index aa2557a9b5f..2a7b3c038f6 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -47,7 +47,7 @@ register_record(RecT rec_type, const char *name, RecDataT data_type, RecData dat RecRecord *r = nullptr; // Metrics are restored from persistence before they are registered. In this case, when the registration arrives, we - // might find that they yave changed. For example, a metric might change it's type due to a software upgrade. Records + // might find that they have changed. For example, a metric might change it's type due to a software upgrade. Records // must not flip between config and metrics, but changing within those classes is OK. if (ink_hash_table_lookup(g_records_ht, name, (void **)&r)) { if (REC_TYPE_IS_STAT(rec_type)) { diff --git a/lib/records/RecFile.cc b/lib/records/RecFile.cc index 466864b2690..99a518904c8 100644 --- a/lib/records/RecFile.cc +++ b/lib/records/RecFile.cc @@ -27,6 +27,8 @@ #include "P_RecDefs.h" #include "P_RecUtils.h" +#include + //------------------------------------------------------------------------- // RecFileOpenR //------------------------------------------------------------------------- @@ -74,6 +76,20 @@ RecFileClose(RecHandle h_file) return (close(h_file) == 0) ? REC_ERR_OKAY : REC_ERR_FAIL; } +//------------------------------------------------------------------------- +// RecSnapFileRead +//------------------------------------------------------------------------- + +int +RecSnapFileRead(RecHandle h_file, char *buf, int size, int *bytes_read) +{ + if ((*bytes_read = ::pread(h_file, buf, size, VERSION_HDR_SIZE)) <= 0) { + *bytes_read = 0; + return REC_ERR_FAIL; + } + return REC_ERR_OKAY; +} + //------------------------------------------------------------------------- // RecFileRead //------------------------------------------------------------------------- @@ -88,6 +104,26 @@ RecFileRead(RecHandle h_file, char *buf, int size, int *bytes_read) return REC_ERR_OKAY; } +//------------------------------------------------------------------------- +// RecSnapFileWrite +//------------------------------------------------------------------------- + +int +RecSnapFileWrite(RecHandle h_file, char *buf, int size, int *bytes_written) +{ + // First write the version byes for snap file + std::array VERSION_HDR{{'V', PACKAGE_VERSION[0], PACKAGE_VERSION[2], PACKAGE_VERSION[4], '\0'}}; + if (::write(h_file, VERSION_HDR.data(), VERSION_HDR_SIZE) < 0) { + return REC_ERR_FAIL; + } + + if ((*bytes_written = ::pwrite(h_file, buf, size, VERSION_HDR_SIZE)) < 0) { + *bytes_written = 0; + return REC_ERR_FAIL; + } + return REC_ERR_OKAY; +} + //------------------------------------------------------------------------- // RecFileWrite //------------------------------------------------------------------------- diff --git a/lib/records/RecMessage.cc b/lib/records/RecMessage.cc index bcb35cf211a..e863636859b 100644 --- a/lib/records/RecMessage.cc +++ b/lib/records/RecMessage.cc @@ -266,12 +266,12 @@ RecMessageReadFromDisk(const char *fpath) if ((h_file = RecFileOpenR(fpath)) == REC_HANDLE_INVALID) { goto Lerror; } - if (RecFileRead(h_file, (char *)(&msg_hdr), sizeof(RecMessageHdr), &bytes_read) == REC_ERR_FAIL) { + if (RecSnapFileRead(h_file, (char *)(&msg_hdr), sizeof(RecMessageHdr), &bytes_read) == REC_ERR_FAIL) { goto Lerror; } msg = (RecMessage *)ats_malloc((msg_hdr.o_end - msg_hdr.o_start) + sizeof(RecMessageHdr)); memcpy(msg, &msg_hdr, sizeof(RecMessageHdr)); - if (RecFileRead(h_file, (char *)(msg) + msg_hdr.o_start, msg_hdr.o_end - msg_hdr.o_start, &bytes_read) == REC_ERR_FAIL) { + if (RecSnapFileRead(h_file, (char *)(msg) + msg_hdr.o_start, msg_hdr.o_end - msg_hdr.o_start, &bytes_read) == REC_ERR_FAIL) { goto Lerror; } @@ -307,7 +307,7 @@ RecMessageWriteToDisk(RecMessage *msg, const char *fpath) msg_size = sizeof(RecMessageHdr) + (msg->o_write - msg->o_start); if ((h_file = RecFileOpenW(fpath)) != REC_HANDLE_INVALID) { - if (RecFileWrite(h_file, (char *)msg, msg_size, &bytes_written) == REC_ERR_FAIL) { + if (RecSnapFileWrite(h_file, (char *)msg, msg_size, &bytes_written) == REC_ERR_FAIL) { RecFileClose(h_file); return REC_ERR_FAIL; }