mdstypes: write inode_t::compare() function

This compares one inode_t against another, seeing which version is newer
and checking that differences in the data members make sense given that.

Signed-off-by: Greg Farnum <greg@inktank.com>
This commit is contained in:
Greg Farnum 2014-09-30 18:07:30 -07:00 committed by Greg Farnum
parent 7795a4e113
commit 4743f28b26
2 changed files with 84 additions and 0 deletions

View File

@ -390,6 +390,70 @@ void inode_t::generate_test_instances(list<inode_t*>& ls)
// i am lazy.
}
int inode_t::compare(const inode_t &other, bool *divergent) const
{
assert(ino == other.ino);
if (version == other.version) {
if (rdev != other.rdev ||
ctime != other.ctime ||
mode != other.mode ||
uid != other.uid ||
gid != other.gid ||
nlink != other.nlink ||
memcmp(&dir_layout, &other.dir_layout, sizeof(dir_layout)) ||
memcmp(&layout, &other.layout, sizeof(layout)) ||
old_pools != other.old_pools ||
size != other.size ||
max_size_ever != other.max_size_ever ||
truncate_seq != other.truncate_seq ||
truncate_size != other.truncate_size ||
truncate_from != other.truncate_from ||
truncate_pending != other.truncate_pending ||
mtime != other.mtime ||
atime != other.atime ||
time_warp_seq != other.time_warp_seq ||
!(*const_cast<bufferlist*>(&inline_data) ==
*const_cast<bufferlist*>(&other.inline_data)) ||
inline_version != other.inline_version ||
client_ranges != other.client_ranges ||
!(dirstat == other.dirstat) ||
!(rstat == other.rstat) ||
!(accounted_rstat == other.accounted_rstat) ||
file_data_version != other.file_data_version ||
xattr_version != other.xattr_version ||
backtrace_version != other.backtrace_version) {
*divergent = true;
}
return 0;
} else if (version > other.version) {
*divergent = !older_is_consistent(other);
return 1;
} else {
assert(version < other.version);
*divergent = !other.older_is_consistent(*this);
return -1;
}
assert(0 == "can't have reached this point");
*divergent = true;
return 0;
}
bool inode_t::older_is_consistent(const inode_t &other) const
{
if (max_size_ever < other.max_size_ever ||
truncate_seq < other.truncate_seq ||
time_warp_seq < other.time_warp_seq ||
inline_version < other.inline_version ||
dirstat.version < other.dirstat.version ||
rstat.version < other.rstat.version ||
accounted_rstat.version < other.accounted_rstat.version ||
file_data_version < other.file_data_version ||
xattr_version < other.xattr_version ||
backtrace_version < other.backtrace_version) {
return false;
}
return true;
}
/*
* old_inode_t

View File

@ -308,6 +308,11 @@ inline bool operator==(const client_writeable_range_t& l,
* inode_t
*/
struct inode_t {
/**
* ***************
* Do not forget to add any new fields to the compare() function.
* ***************
*/
// base (immutable)
inodeno_t ino;
uint32_t rdev; // if special file
@ -447,6 +452,21 @@ struct inode_t {
void decode(bufferlist::iterator& bl);
void dump(Formatter *f) const;
static void generate_test_instances(list<inode_t*>& ls);
/**
* Compare this inode_t with another that represent *the same inode*
* at different points in time.
* @pre The inodes are the same ino
*
* @param other The inode_t to compare ourselves with
* @param divergent A bool pointer which will be set to true
* if the values are different in a way that can't be explained
* by one being a newer version than the other.
*
* @returns 1 if we are newer than the other, 0 if equal, -1 if older.
*/
int compare(const inode_t &other, bool *divergent) const;
private:
bool older_is_consistent(const inode_t &other) const;
};
WRITE_CLASS_ENCODER(inode_t)