BFS: Fix handling of the last_modified index.

Its values must be shifted before comparing against them.
Also handle the last-modified times correctly in NodeGetLastModifiedTime.

Fixes an issue noticed in #19080 which was a regression from
the query refactor earlier this year.

Also while at it, remove a needless lock in EntryGetName;
Inode::GetName acquires this lock for us.
This commit is contained in:
Augustin Cavalier 2024-11-21 22:38:10 -05:00
parent 1abf2059a7
commit 783b77b14f

View File

@ -27,19 +27,25 @@ struct Query::QueryPolicy {
typedef ::Inode Node; typedef ::Inode Node;
struct Index : ::Index { struct Index : ::Index {
bool isSpecialTime;
Index(Context* context) Index(Context* context)
: :
::Index(context->fVolume) ::Index(context->fVolume),
isSpecialTime(false)
{ {
} }
}; };
struct IndexIterator : TreeIterator { struct IndexIterator : TreeIterator {
off_t offset; off_t offset;
bool isSpecialTime;
IndexIterator(BPlusTree* tree) IndexIterator(BPlusTree* tree)
: :
TreeIterator(tree) TreeIterator(tree),
offset(0),
isSpecialTime(false)
{ {
} }
}; };
@ -71,7 +77,6 @@ struct Query::QueryPolicy {
static ssize_t EntryGetName(Inode* inode, void* buffer, size_t bufferSize) static ssize_t EntryGetName(Inode* inode, void* buffer, size_t bufferSize)
{ {
RecursiveLocker locker(&inode->SmallDataLock());
status_t status = inode->GetName((char*)buffer, bufferSize); status_t status = inode->GetName((char*)buffer, bufferSize);
if (status != B_OK) if (status != B_OK)
return status; return status;
@ -99,7 +104,17 @@ struct Query::QueryPolicy {
static status_t IndexSetTo(Index& index, const char* attribute) static status_t IndexSetTo(Index& index, const char* attribute)
{ {
return index.SetTo(attribute); status_t status = index.SetTo(attribute);
if (status == B_OK) {
// The special time flag is set if the time values are shifted
// 64-bit values to reduce the number of duplicates.
// We have to be able to compare them against unshifted values
// later. The only index which needs this is the last_modified
// index, but we may want to open that feature for other indices,
// too one day.
index.isSpecialTime = (strcmp(attribute, "last_modified") == 0);
}
return status;
} }
static void IndexUnset(Index& index) static void IndexUnset(Index& index)
@ -132,6 +147,7 @@ struct Query::QueryPolicy {
if (iterator == NULL) if (iterator == NULL)
return NULL; return NULL;
iterator->isSpecialTime = index.isSpecialTime;
return iterator; return iterator;
} }
@ -145,6 +161,13 @@ struct Query::QueryPolicy {
static status_t IndexIteratorFind(IndexIterator* iterator, static status_t IndexIteratorFind(IndexIterator* iterator,
const void* value, size_t size) const void* value, size_t size)
{ {
int64 shiftedTime;
if (iterator->isSpecialTime) {
// int64 time index; convert value.
shiftedTime = *(int64*)value << INODE_TIME_SHIFT;
value = &shiftedTime;
}
return iterator->Find((const uint8*)value, size); return iterator->Find((const uint8*)value, size);
} }
@ -158,6 +181,11 @@ struct Query::QueryPolicy {
if (status != B_OK) if (status != B_OK)
return status; return status;
if (iterator->isSpecialTime) {
// int64 time index; convert value.
*(int64*)indexValue >>= INODE_TIME_SHIFT;
}
*_keyLength = keyLength; *_keyLength = keyLength;
*_duplicate = duplicate; *_duplicate = duplicate;
return B_OK; return B_OK;
@ -203,7 +231,7 @@ struct Query::QueryPolicy {
static time_t NodeGetLastModifiedTime(Inode* inode) static time_t NodeGetLastModifiedTime(Inode* inode)
{ {
return inode->Node().LastModifiedTime(); return bfs_inode::ToSecs(inode->Node().LastModifiedTime());
} }
static status_t NodeGetAttribute(NodeHolder& holder, Inode* inode, static status_t NodeGetAttribute(NodeHolder& holder, Inode* inode,