Fixed queries a bit more (maybe even completely...). In several situations,
the old attribute value wasn't evaluated at all. Also, Index::Update() got a type code of zero, instead of the real value in situations where this didn't make any sense. Minor cleanup in kernel_interface.cpp. New method Volume::CheckForLiveQuery() that checks if there is a live query depending on the specified attribute - not yet implemented, but already used; always returns "true" right now, which doesn't cause any harm but reducing the speed lightly. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3394 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
cca15c0166
commit
8ea8d0c2bb
@ -226,12 +226,15 @@ Index::Update(Transaction *transaction, const char *name, int32 type, const uint
|
|||||||
if (type == B_MIME_STRING_TYPE)
|
if (type == B_MIME_STRING_TYPE)
|
||||||
type = B_STRING_TYPE;
|
type = B_STRING_TYPE;
|
||||||
|
|
||||||
// if the two keys are identical, don't do anything
|
// If the two keys are identical, don't do anything - only compare if the
|
||||||
|
// type has been set, until we have a real type code, we can't do much
|
||||||
|
// about the comparison here
|
||||||
if (type != 0 && !compareKeys(type, oldKey, oldLength, newKey, newLength))
|
if (type != 0 && !compareKeys(type, oldKey, oldLength, newKey, newLength))
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// update all live queries about the change, if they have an index or not
|
// update all live queries about the change, if they have an index or not
|
||||||
fVolume->UpdateLiveQueries(inode, name, type, oldKey, oldLength, newKey, newLength);
|
if (type != 0)
|
||||||
|
fVolume->UpdateLiveQueries(inode, name, type, oldKey, oldLength, newKey, newLength);
|
||||||
|
|
||||||
status_t status;
|
status_t status;
|
||||||
if (((name != fName || strcmp(name, fName)) && (status = SetTo(name)) < B_OK)
|
if (((name != fName || strcmp(name, fName)) && (status = SetTo(name)) < B_OK)
|
||||||
@ -242,6 +245,10 @@ Index::Update(Transaction *transaction, const char *name, int32 type, const uint
|
|||||||
if (type == 0 && !compareKeys(Type(), oldKey, oldLength, newKey, newLength))
|
if (type == 0 && !compareKeys(Type(), oldKey, oldLength, newKey, newLength))
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
// same for the live query update
|
||||||
|
if (type == 0)
|
||||||
|
fVolume->UpdateLiveQueries(inode, name, Type(), oldKey, oldLength, newKey, newLength);
|
||||||
|
|
||||||
BPlusTree *tree;
|
BPlusTree *tree;
|
||||||
if ((status = Node()->GetTree(&tree)) < B_OK)
|
if ((status = Node()->GetTree(&tree)) < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
@ -548,12 +548,12 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
|
|||||||
// correctly terminate the small_data section
|
// correctly terminate the small_data section
|
||||||
item = item->Next();
|
item = item->Next();
|
||||||
if (!item->IsLast(Node()))
|
if (!item->IsLast(Node()))
|
||||||
memset(item,0,(uint8 *)Node() + fVolume->InodeSize() - (uint8 *)item);
|
memset(item, 0, (uint8 *)Node() + fVolume->InodeSize() - (uint8 *)item);
|
||||||
|
|
||||||
// update all current iterators
|
// update all current iterators
|
||||||
AttributeIterator *iterator = NULL;
|
AttributeIterator *iterator = NULL;
|
||||||
while ((iterator = fIterators.Next(iterator)) != NULL)
|
while ((iterator = fIterators.Next(iterator)) != NULL)
|
||||||
iterator->Update(index,1);
|
iterator->Update(index, 1);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -733,30 +733,28 @@ Inode::WriteAttribute(Transaction *transaction, const char *name, int32 type, of
|
|||||||
uint8 oldBuffer[BPLUSTREE_MAX_KEY_LENGTH], *oldData = NULL;
|
uint8 oldBuffer[BPLUSTREE_MAX_KEY_LENGTH], *oldData = NULL;
|
||||||
size_t oldLength = 0;
|
size_t oldLength = 0;
|
||||||
|
|
||||||
// ToDo: we actually depend on that the contents of "buffer" are constant
|
// ToDo: we actually depend on that the contents of "buffer" are constant.
|
||||||
// if they get changed during the write (hey, user programs), we may mess
|
// If they get changed during the write (hey, user programs), we may mess
|
||||||
// up our index trees!
|
// up our index trees!
|
||||||
|
|
||||||
Index index(fVolume);
|
Index index(fVolume);
|
||||||
bool hasIndex = index.SetTo(name) == B_OK;
|
index.SetTo(name);
|
||||||
|
|
||||||
Inode *attribute = NULL;
|
Inode *attribute = NULL;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (GetAttribute(name, &attribute) < B_OK) {
|
if (GetAttribute(name, &attribute) < B_OK) {
|
||||||
// save the old attribute data
|
// save the old attribute data
|
||||||
if (hasIndex) {
|
fSmallDataLock.Lock();
|
||||||
fSmallDataLock.Lock();
|
|
||||||
|
|
||||||
small_data *smallData = FindSmallData(name);
|
small_data *smallData = FindSmallData(name);
|
||||||
if (smallData != NULL) {
|
if (smallData != NULL) {
|
||||||
oldLength = smallData->data_size;
|
oldLength = smallData->data_size;
|
||||||
if (oldLength > BPLUSTREE_MAX_KEY_LENGTH)
|
if (oldLength > BPLUSTREE_MAX_KEY_LENGTH)
|
||||||
oldLength = BPLUSTREE_MAX_KEY_LENGTH;
|
oldLength = BPLUSTREE_MAX_KEY_LENGTH;
|
||||||
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
|
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
|
||||||
}
|
|
||||||
fSmallDataLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
fSmallDataLock.Unlock();
|
||||||
|
|
||||||
// if the attribute doesn't exist yet (as a file), try to put it in the
|
// if the attribute doesn't exist yet (as a file), try to put it in the
|
||||||
// small_data section first - if that fails (due to insufficent space),
|
// small_data section first - if that fails (due to insufficent space),
|
||||||
@ -773,7 +771,7 @@ Inode::WriteAttribute(Transaction *transaction, const char *name, int32 type, of
|
|||||||
if (attribute != NULL) {
|
if (attribute != NULL) {
|
||||||
if (attribute->Lock().LockWrite() == B_OK) {
|
if (attribute->Lock().LockWrite() == B_OK) {
|
||||||
// save the old attribute data (if this fails, oldLength will reflect it)
|
// save the old attribute data (if this fails, oldLength will reflect it)
|
||||||
if (hasIndex) {
|
if (fVolume->CheckForLiveQuery(name)) {
|
||||||
oldLength = BPLUSTREE_MAX_KEY_LENGTH;
|
oldLength = BPLUSTREE_MAX_KEY_LENGTH;
|
||||||
if (attribute->ReadAt(0, oldBuffer, &oldLength) == B_OK)
|
if (attribute->ReadAt(0, oldBuffer, &oldLength) == B_OK)
|
||||||
oldData = oldBuffer;
|
oldData = oldBuffer;
|
||||||
@ -817,7 +815,7 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
|
|||||||
bool hasIndex = index.SetTo(name) == B_OK;
|
bool hasIndex = index.SetTo(name) == B_OK;
|
||||||
|
|
||||||
// update index for attributes in the small_data section
|
// update index for attributes in the small_data section
|
||||||
if (hasIndex) {
|
{
|
||||||
fSmallDataLock.Lock();
|
fSmallDataLock.Lock();
|
||||||
|
|
||||||
small_data *smallData = FindSmallData(name);
|
small_data *smallData = FindSmallData(name);
|
||||||
@ -825,7 +823,7 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
|
|||||||
uint32 length = smallData->data_size;
|
uint32 length = smallData->data_size;
|
||||||
if (length > BPLUSTREE_MAX_KEY_LENGTH)
|
if (length > BPLUSTREE_MAX_KEY_LENGTH)
|
||||||
length = BPLUSTREE_MAX_KEY_LENGTH;
|
length = BPLUSTREE_MAX_KEY_LENGTH;
|
||||||
index.Update(transaction, name, 0, smallData->Data(), length, NULL, 0, this);
|
index.Update(transaction, name, smallData->type, smallData->Data(), length, NULL, 0, this);
|
||||||
}
|
}
|
||||||
fSmallDataLock.Unlock();
|
fSmallDataLock.Unlock();
|
||||||
}
|
}
|
||||||
@ -842,11 +840,12 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
|
|||||||
|
|
||||||
// update index
|
// update index
|
||||||
Inode *attribute;
|
Inode *attribute;
|
||||||
if (hasIndex && GetAttribute(name, &attribute) == B_OK) {
|
if ((hasIndex || fVolume->CheckForLiveQuery(name))
|
||||||
|
&& GetAttribute(name, &attribute) == B_OK) {
|
||||||
uint8 data[BPLUSTREE_MAX_KEY_LENGTH];
|
uint8 data[BPLUSTREE_MAX_KEY_LENGTH];
|
||||||
size_t length = BPLUSTREE_MAX_KEY_LENGTH;
|
size_t length = BPLUSTREE_MAX_KEY_LENGTH;
|
||||||
if (attribute->ReadAt(0, data, &length) == B_OK)
|
if (attribute->ReadAt(0, data, &length) == B_OK)
|
||||||
index.Update(transaction, name, 0, data, length, NULL, 0, this);
|
index.Update(transaction, name, attribute->Type(), data, length, NULL, 0, this);
|
||||||
|
|
||||||
ReleaseAttribute(attribute);
|
ReleaseAttribute(attribute);
|
||||||
}
|
}
|
||||||
@ -2023,7 +2022,7 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m
|
|||||||
// Everything worked well until this point, we have a fully
|
// Everything worked well until this point, we have a fully
|
||||||
// initialized inode, and we want to keep it
|
// initialized inode, and we want to keep it
|
||||||
allocator.Keep();
|
allocator.Keep();
|
||||||
|
|
||||||
if (_id != NULL)
|
if (_id != NULL)
|
||||||
*_id = inode->ID();
|
*_id = inode->ID();
|
||||||
if (_inode != NULL)
|
if (_inode != NULL)
|
||||||
|
@ -98,6 +98,7 @@ class Inode : public CachedBlock {
|
|||||||
SimpleLock &SmallDataLock() { return fSmallDataLock; }
|
SimpleLock &SmallDataLock() { return fSmallDataLock; }
|
||||||
|
|
||||||
mode_t Mode() const { return Node()->mode; }
|
mode_t Mode() const { return Node()->mode; }
|
||||||
|
uint32 Type() const { return Node()->type; }
|
||||||
int32 Flags() const { return Node()->flags; }
|
int32 Flags() const { return Node()->flags; }
|
||||||
bool IsContainer() const { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); }
|
bool IsContainer() const { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); }
|
||||||
// note, that this test will also be true for S_IFBLK (not that it's used in the fs :)
|
// note, that this test will also be true for S_IFBLK (not that it's used in the fs :)
|
||||||
|
@ -54,11 +54,13 @@ Inode
|
|||||||
Indices
|
Indices
|
||||||
|
|
||||||
- consider Index::UpdateLastModified() writing back the updated inode
|
- consider Index::UpdateLastModified() writing back the updated inode
|
||||||
|
- clearing up Index::Update() and live query update (seems to be a bit confusing right now)
|
||||||
|
|
||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
|
|
||||||
- Inode::WriteAttribute() doesn't check if the attribute data may fit into the small_data region if there already is that attribute as an attribute file
|
- Inode::WriteAttribute() doesn't check if the attribute data may fit into the small_data region if there already is that attribute as an attribute file
|
||||||
|
- for indices, we could get the old data from there when doing a query update
|
||||||
|
|
||||||
|
|
||||||
Volume
|
Volume
|
||||||
|
@ -277,6 +277,20 @@ Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
* the queries - it wouldn't safe you anything in this case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Volume::CheckForLiveQuery(const char *attribute)
|
||||||
|
{
|
||||||
|
// ToDo: check for a live query that depends on the specified attribute
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Volume::AddQuery(Query *query)
|
Volume::AddQuery(Query *query)
|
||||||
{
|
{
|
||||||
|
@ -99,6 +99,7 @@ class Volume {
|
|||||||
void UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
|
void UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
|
||||||
const uint8 *oldKey, size_t oldLength,
|
const uint8 *oldKey, size_t oldLength,
|
||||||
const uint8 *newKey, size_t newLength);
|
const uint8 *newKey, size_t newLength);
|
||||||
|
bool CheckForLiveQuery(const char *attribute);
|
||||||
void AddQuery(Query *query);
|
void AddQuery(Query *query);
|
||||||
void RemoveQuery(Query *query);
|
void RemoveQuery(Query *query);
|
||||||
|
|
||||||
|
@ -1701,7 +1701,7 @@ bfs_read_attrdir(void *_ns, void *node, void *_cookie, long *num, struct dirent
|
|||||||
int
|
int
|
||||||
bfs_remove_attr(void *_ns, void *_node, const char *name)
|
bfs_remove_attr(void *_ns, void *_node, const char *name)
|
||||||
{
|
{
|
||||||
FUNCTION_START(("name = \"%s\"\n",name));
|
FUNCTION_START(("name = \"%s\"\n", name));
|
||||||
|
|
||||||
if (_ns == NULL || _node == NULL || name == NULL)
|
if (_ns == NULL || _node == NULL || name == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@ -1746,7 +1746,8 @@ bfs_stat_attr(void *ns, void *_node, const char *name, struct attr_info *attrInf
|
|||||||
Inode *inode = (Inode *)_node;
|
Inode *inode = (Inode *)_node;
|
||||||
if (inode == NULL || inode->Node() == NULL)
|
if (inode == NULL || inode->Node() == NULL)
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
|
|
||||||
|
// first, try to find it in the small data region
|
||||||
small_data *smallData = NULL;
|
small_data *smallData = NULL;
|
||||||
if (inode->SmallDataLock().Lock() == B_OK)
|
if (inode->SmallDataLock().Lock() == B_OK)
|
||||||
{
|
{
|
||||||
@ -1759,12 +1760,12 @@ bfs_stat_attr(void *ns, void *_node, const char *name, struct attr_info *attrInf
|
|||||||
if (smallData != NULL)
|
if (smallData != NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// search in the attribute directory
|
// then, search in the attribute directory
|
||||||
Inode *attribute;
|
Inode *attribute;
|
||||||
status_t status = inode->GetAttribute(name, &attribute);
|
status_t status = inode->GetAttribute(name, &attribute);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
attrInfo->type = attribute->Node()->type;
|
attrInfo->type = attribute->Type();
|
||||||
attrInfo->size = attribute->Node()->data.size;
|
attrInfo->size = attribute->Size();
|
||||||
|
|
||||||
inode->ReleaseAttribute(attribute);
|
inode->ReleaseAttribute(attribute);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@ -1786,10 +1787,12 @@ bfs_write_attr(void *_ns, void *_node, const char *name, int type, const void *b
|
|||||||
// Writing the name attribute using this function is not allowed,
|
// Writing the name attribute using this function is not allowed,
|
||||||
// also using the reserved indices name, last_modified, and size
|
// also using the reserved indices name, last_modified, and size
|
||||||
// shouldn't be allowed.
|
// shouldn't be allowed.
|
||||||
|
// ToDo: we might think about allowing to update those values, but
|
||||||
|
// really change their corresponding values in the bfs_inode structure
|
||||||
if (name[0] == FILE_NAME_NAME && name[1] == '\0'
|
if (name[0] == FILE_NAME_NAME && name[1] == '\0'
|
||||||
|| !strcmp(name,"name")
|
|| !strcmp(name, "name")
|
||||||
|| !strcmp(name,"last_modified")
|
|| !strcmp(name, "last_modified")
|
||||||
|| !strcmp(name,"size"))
|
|| !strcmp(name, "size"))
|
||||||
RETURN_ERROR(B_NOT_ALLOWED);
|
RETURN_ERROR(B_NOT_ALLOWED);
|
||||||
|
|
||||||
Volume *volume = (Volume *)_ns;
|
Volume *volume = (Volume *)_ns;
|
||||||
|
Loading…
Reference in New Issue
Block a user