mirror of
https://review.haiku-os.org/haiku
synced 2024-11-23 07:18:40 +01:00
RAMFS: Lock attribute iterators separate from entry iterators.
And clean up the code style while at it.
This commit is contained in:
parent
e2e7d84d21
commit
bab3f64413
@ -2,11 +2,15 @@
|
|||||||
* Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* All rights reserved. Distributed under the terms of the MIT license.
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AttributeIterator.h"
|
#include "AttributeIterator.h"
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
// constructor
|
|
||||||
AttributeIterator::AttributeIterator(Node *node)
|
AttributeIterator::AttributeIterator(Node *node)
|
||||||
: fNode(node),
|
: fNode(node),
|
||||||
fAttribute(NULL),
|
fAttribute(NULL),
|
||||||
@ -16,34 +20,36 @@ AttributeIterator::AttributeIterator(Node *node)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
|
||||||
AttributeIterator::~AttributeIterator()
|
AttributeIterator::~AttributeIterator()
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTo
|
|
||||||
status_t
|
status_t
|
||||||
AttributeIterator::SetTo(Node *node)
|
AttributeIterator::SetTo(Node *node)
|
||||||
{
|
{
|
||||||
Unset();
|
Unset();
|
||||||
status_t error = (node ? B_OK : B_BAD_VALUE);
|
|
||||||
if (error == B_OK) {
|
if (node == NULL)
|
||||||
fNode = node;
|
return B_BAD_VALUE;
|
||||||
fAttribute = NULL;
|
|
||||||
fSuspended = false;
|
fNode = node;
|
||||||
fIsNext = false;
|
fAttribute = NULL;
|
||||||
fDone = false;
|
fSuspended = false;
|
||||||
}
|
fIsNext = false;
|
||||||
return error;
|
fDone = false;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unset
|
|
||||||
void
|
void
|
||||||
AttributeIterator::Unset()
|
AttributeIterator::Unset()
|
||||||
{
|
{
|
||||||
if (fNode && fSuspended)
|
if (fNode && fSuspended)
|
||||||
Resume();
|
Resume();
|
||||||
|
|
||||||
fNode = NULL;
|
fNode = NULL;
|
||||||
fAttribute = NULL;
|
fAttribute = NULL;
|
||||||
fSuspended = false;
|
fSuspended = false;
|
||||||
@ -51,51 +57,57 @@ AttributeIterator::Unset()
|
|||||||
fDone = false;
|
fDone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suspend
|
|
||||||
status_t
|
status_t
|
||||||
AttributeIterator::Suspend()
|
AttributeIterator::Suspend()
|
||||||
{
|
{
|
||||||
status_t error = (fNode ? B_OK : B_ERROR);
|
if (fNode == NULL)
|
||||||
if (error == B_OK) {
|
return B_ERROR;
|
||||||
if (fNode->GetVolume()->IteratorLock()) {
|
|
||||||
if (!fSuspended) {
|
RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
|
||||||
if (fAttribute)
|
if (!locker.IsLocked())
|
||||||
fAttribute->AttachAttributeIterator(this);
|
return B_ERROR;
|
||||||
fNode->GetVolume()->IteratorUnlock();
|
|
||||||
fSuspended = true;
|
if (fSuspended)
|
||||||
} else
|
return B_ERROR;
|
||||||
error = B_ERROR;
|
|
||||||
} else
|
if (fAttribute)
|
||||||
error = B_ERROR;
|
fAttribute->AttachAttributeIterator(this);
|
||||||
}
|
fSuspended = true;
|
||||||
return error;
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resume
|
|
||||||
status_t
|
status_t
|
||||||
AttributeIterator::Resume()
|
AttributeIterator::Resume()
|
||||||
{
|
{
|
||||||
status_t error = (fNode ? B_OK : B_ERROR);
|
if (fNode == NULL)
|
||||||
if (error == B_OK) {
|
return B_ERROR;
|
||||||
if (fNode->GetVolume()->IteratorLock()) {
|
|
||||||
if (fSuspended) {
|
RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
|
||||||
if (fAttribute)
|
if (!locker.IsLocked())
|
||||||
fAttribute->DetachAttributeIterator(this);
|
return B_ERROR;
|
||||||
fSuspended = false;
|
|
||||||
}
|
if (!fSuspended)
|
||||||
fNode->GetVolume()->IteratorUnlock();
|
return B_ERROR;
|
||||||
} else
|
|
||||||
error = B_ERROR;
|
if (fAttribute)
|
||||||
}
|
fAttribute->DetachAttributeIterator(this);
|
||||||
return error;
|
fSuspended = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNext
|
|
||||||
status_t
|
status_t
|
||||||
AttributeIterator::GetNext(Attribute **attribute)
|
AttributeIterator::GetNext(Attribute **attribute)
|
||||||
{
|
{
|
||||||
|
if (attribute == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
status_t error = B_ENTRY_NOT_FOUND;
|
status_t error = B_ENTRY_NOT_FOUND;
|
||||||
if (!fDone && fNode && attribute) {
|
if (!fDone && fNode != NULL) {
|
||||||
if (fIsNext) {
|
if (fIsNext) {
|
||||||
fIsNext = false;
|
fIsNext = false;
|
||||||
if (fAttribute)
|
if (fAttribute)
|
||||||
@ -108,26 +120,26 @@ AttributeIterator::GetNext(Attribute **attribute)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewind
|
|
||||||
status_t
|
status_t
|
||||||
AttributeIterator::Rewind()
|
AttributeIterator::Rewind()
|
||||||
{
|
{
|
||||||
status_t error = (fNode ? B_OK : B_ERROR);
|
if (fNode == NULL)
|
||||||
if (error == B_OK) {
|
return B_ERROR;
|
||||||
if (fNode->GetVolume()->IteratorLock()) {
|
|
||||||
if (fSuspended && fAttribute)
|
RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
|
||||||
fAttribute->DetachAttributeIterator(this);
|
if (!locker.IsLocked())
|
||||||
fAttribute = NULL;
|
return B_ERROR;
|
||||||
fIsNext = false;
|
|
||||||
fDone = false;
|
if (fSuspended && fAttribute)
|
||||||
fNode->GetVolume()->IteratorUnlock();
|
fAttribute->DetachAttributeIterator(this);
|
||||||
} else
|
fAttribute = NULL;
|
||||||
error = B_ERROR;
|
fIsNext = false;
|
||||||
}
|
fDone = false;
|
||||||
return error;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCurrent
|
|
||||||
void
|
void
|
||||||
AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
|
AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
|
||||||
{
|
{
|
||||||
@ -135,4 +147,3 @@ AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
|
|||||||
fAttribute = attribute;
|
fAttribute = attribute;
|
||||||
fDone = !fAttribute;
|
fDone = !fAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,14 @@
|
|||||||
* All rights reserved. Distributed under the terms of the MIT license.
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include "AllocationInfo.h"
|
#include "AllocationInfo.h"
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
#include "EntryIterator.h"
|
#include "EntryIterator.h"
|
||||||
#include "LastModifiedIndex.h"
|
#include "LastModifiedIndex.h"
|
||||||
#include "Node.h"
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
@ -191,40 +194,39 @@ Node::AddAttribute(Attribute *attribute)
|
|||||||
status_t
|
status_t
|
||||||
Node::RemoveAttribute(Attribute *attribute)
|
Node::RemoveAttribute(Attribute *attribute)
|
||||||
{
|
{
|
||||||
status_t error = (attribute && attribute->GetNode() == this
|
if (attribute == NULL || attribute->GetNode() != this)
|
||||||
? B_OK : B_BAD_VALUE);
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
RecursiveLocker locker(GetVolume()->AttributeIteratorLocker());
|
||||||
|
if (!locker.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// move all iterators pointing to the attribute to the next attribute
|
||||||
|
Attribute *nextAttr = fAttributes.GetNext(attribute);
|
||||||
|
DoublyLinkedList<AttributeIterator> *iterators
|
||||||
|
= attribute->GetAttributeIteratorList();
|
||||||
|
for (AttributeIterator *iterator = iterators->First();
|
||||||
|
iterator != NULL; iterator = iterators->GetNext(iterator)) {
|
||||||
|
iterator->SetCurrent(nextAttr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the iterators from one list to the other, or just remove
|
||||||
|
// them, if there is no next attribute.
|
||||||
|
if (nextAttr != NULL) {
|
||||||
|
DoublyLinkedList<AttributeIterator> *nextIterators
|
||||||
|
= nextAttr->GetAttributeIteratorList();
|
||||||
|
nextIterators->MoveFrom(iterators);
|
||||||
|
} else
|
||||||
|
iterators->RemoveAll();
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
// remove the attribute
|
||||||
|
status_t error = GetVolume()->NodeAttributeRemoved(GetID(), attribute);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
// move all iterators pointing to the attribute to the next attribute
|
fAttributes.Remove(attribute);
|
||||||
if (GetVolume()->IteratorLock()) {
|
attribute->SetNode(NULL);
|
||||||
// set the iterators' current entry
|
MarkModified(B_STAT_MODIFICATION_TIME);
|
||||||
Attribute *nextAttr = fAttributes.GetNext(attribute);
|
|
||||||
DoublyLinkedList<AttributeIterator> *iterators
|
|
||||||
= attribute->GetAttributeIteratorList();
|
|
||||||
for (AttributeIterator *iterator = iterators->First();
|
|
||||||
iterator;
|
|
||||||
iterator = iterators->GetNext(iterator)) {
|
|
||||||
iterator->SetCurrent(nextAttr, true);
|
|
||||||
}
|
|
||||||
// Move the iterators from one list to the other, or just remove
|
|
||||||
// them, if there is no next attribute.
|
|
||||||
if (nextAttr) {
|
|
||||||
DoublyLinkedList<AttributeIterator> *nextIterators
|
|
||||||
= nextAttr->GetAttributeIteratorList();
|
|
||||||
nextIterators->MoveFrom(iterators);
|
|
||||||
} else
|
|
||||||
iterators->RemoveAll();
|
|
||||||
GetVolume()->IteratorUnlock();
|
|
||||||
} else
|
|
||||||
error = B_ERROR;
|
|
||||||
// remove the attribute
|
|
||||||
if (error == B_OK) {
|
|
||||||
error = GetVolume()->NodeAttributeRemoved(GetID(), attribute);
|
|
||||||
if (error == B_OK) {
|
|
||||||
fAttributes.Remove(attribute);
|
|
||||||
attribute->SetNode(NULL);
|
|
||||||
MarkModified(B_STAT_MODIFICATION_TIME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,7 @@ Volume::Volume(fs_volume* volume)
|
|||||||
{
|
{
|
||||||
rw_lock_init(&fLocker, "ramfs volume");
|
rw_lock_init(&fLocker, "ramfs volume");
|
||||||
recursive_lock_init(&fIteratorLocker, "ramfs iterators");
|
recursive_lock_init(&fIteratorLocker, "ramfs iterators");
|
||||||
|
recursive_lock_init(&fAttributeIteratorLocker, "ramfs attribute iterators");
|
||||||
recursive_lock_init(&fQueryLocker, "ramfs queries");
|
recursive_lock_init(&fQueryLocker, "ramfs queries");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +150,7 @@ Volume::~Volume()
|
|||||||
{
|
{
|
||||||
Unmount();
|
Unmount();
|
||||||
|
|
||||||
|
recursive_lock_destroy(&fAttributeIteratorLocker);
|
||||||
recursive_lock_destroy(&fIteratorLocker);
|
recursive_lock_destroy(&fIteratorLocker);
|
||||||
recursive_lock_destroy(&fQueryLocker);
|
recursive_lock_destroy(&fQueryLocker);
|
||||||
rw_lock_destroy(&fLocker);
|
rw_lock_destroy(&fLocker);
|
||||||
@ -777,4 +779,3 @@ Volume::IteratorUnlock()
|
|||||||
{
|
{
|
||||||
recursive_lock_unlock(&fIteratorLocker);
|
recursive_lock_unlock(&fIteratorLocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +167,8 @@ public:
|
|||||||
bool IteratorLock();
|
bool IteratorLock();
|
||||||
void IteratorUnlock();
|
void IteratorUnlock();
|
||||||
|
|
||||||
|
recursive_lock& AttributeIteratorLocker() { return fAttributeIteratorLocker; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
fs_volume* fVolume;
|
fs_volume* fVolume;
|
||||||
|
|
||||||
@ -186,6 +188,7 @@ private:
|
|||||||
EntryListenerList fAnyEntryListeners;
|
EntryListenerList fAnyEntryListeners;
|
||||||
|
|
||||||
recursive_lock fIteratorLocker;
|
recursive_lock fIteratorLocker;
|
||||||
|
recursive_lock fAttributeIteratorLocker;
|
||||||
|
|
||||||
recursive_lock fQueryLocker;
|
recursive_lock fQueryLocker;
|
||||||
QueryList fQueries;
|
QueryList fQueries;
|
||||||
|
Loading…
Reference in New Issue
Block a user