diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp b/src/add-ons/kernel/file_systems/bfs/Query.cpp index b910cd8b3d..2d3bab70e3 100644 --- a/src/add-ons/kernel/file_systems/bfs/Query.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp @@ -1661,3 +1661,31 @@ Query::LiveUpdate(Inode* inode, const char* attribute, int32 type, } } + +void +Query::LiveUpdateRenameMove(Inode* inode, ino_t oldDirectoryID, + const char* oldName, size_t oldLength, ino_t newDirectoryID, + const char* newName, size_t newLength) +{ + if (fPort < 0 || fExpression == NULL) + return; + + // TODO: check if the attribute is part of the query at all... + + status_t oldStatus = fExpression->Root()->Match(inode, "name", + B_STRING_TYPE, (const uint8*)oldName, oldLength); + status_t newStatus = fExpression->Root()->Match(inode, "name", + B_STRING_TYPE, (const uint8*)newName, newLength); + + if (oldStatus != MATCH_OK || oldStatus != newStatus) + return; + + // The entry stays in the query, notify query listeners about the rename + // or move + + notify_query_entry_removed(fPort, fToken, fVolume->ID(), + oldDirectoryID, oldName, inode->ID()); + + notify_query_entry_created(fPort, fToken, fVolume->ID(), + newDirectoryID, newName, inode->ID()); +} diff --git a/src/add-ons/kernel/file_systems/bfs/Query.h b/src/add-ons/kernel/file_systems/bfs/Query.h index 0ba38cf429..fe75cf7612 100644 --- a/src/add-ons/kernel/file_systems/bfs/Query.h +++ b/src/add-ons/kernel/file_systems/bfs/Query.h @@ -56,6 +56,10 @@ public: int32 type, const uint8* oldKey, size_t oldLength, const uint8* newKey, size_t newLength); + void LiveUpdateRenameMove(Inode* inode, + ino_t oldDirectoryID, const char* oldName, + size_t oldLength, ino_t newDirectoryID, + const char* newName, size_t newLength); Expression* GetExpression() const { return fExpression; } diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp b/src/add-ons/kernel/file_systems/bfs/Volume.cpp index c59c41a818..f1ba489c62 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp @@ -535,6 +535,24 @@ Volume::UpdateLiveQueries(Inode* inode, const char* attribute, int32 type, } +void +Volume::UpdateLiveQueriesRenameMove(Inode* inode, ino_t oldDirectoryID, + const char* oldName, ino_t newDirectoryID, const char* newName) +{ + MutexLocker _(fQueryLock); + + size_t oldLength = strlen(oldName); + size_t newLength = strlen(newName); + + SinglyLinkedList::Iterator iterator = fQueries.GetIterator(); + while (iterator.HasNext()) { + Query* query = iterator.Next(); + query->LiveUpdateRenameMove(inode, oldDirectoryID, oldName, oldLength, + newDirectoryID, newName, newLength); + } +} + + /*! Checks if there is a live query whose results depend on the presence or value of the specified attribute. Don't use it if you already have all the data together to evaluate diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.h b/src/add-ons/kernel/file_systems/bfs/Volume.h index 37e1a5a928..c8c1ec5cb6 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.h +++ b/src/add-ons/kernel/file_systems/bfs/Volume.h @@ -117,6 +117,10 @@ public: const char* attribute, int32 type, const uint8* oldKey, size_t oldLength, const uint8* newKey, size_t newLength); + void UpdateLiveQueriesRenameMove(Inode* inode, + ino_t oldDirectoryID, const char* oldName, + ino_t newDirectoryID, const char* newName); + bool CheckForLiveQuery(const char* attribute); void AddQuery(Query* query); void RemoveQuery(Query* query); diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 856459d8ca..aa206a3ec7 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -1156,6 +1156,9 @@ bfs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char* oldName, inode->WriteLockInTransaction(transaction); + volume->UpdateLiveQueriesRenameMove(inode, oldDirectory->ID(), oldName, + newDirectory->ID(), newName); + // update the name only when they differ bool nameUpdated = false; if (strcmp(oldName, newName)) {