2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
7 #include "PackageLinkDirectory.h"
11 #include <NodeMonitor.h>
13 #include <AutoDeleter.h>
15 #include "AutoPackageAttributeDirectoryCookie.h"
16 #include "DebugSupport.h"
17 #include "PackageLinksListener.h"
18 #include "StringConstants.h"
24 PackageLinkDirectory::PackageLinkDirectory()
27 // the ID needs to be assigned later, when added to a volume
31 get_real_time(fModifiedTime
);
35 PackageLinkDirectory::~PackageLinkDirectory()
37 if (fSelfLink
!= NULL
)
38 fSelfLink
->ReleaseReference();
39 if (fSettingsLink
!= NULL
)
40 fSettingsLink
->ReleaseReference();
42 while (DependencyLink
* link
= fDependencyLinks
.RemoveHead())
43 link
->ReleaseReference();
48 PackageLinkDirectory::Init(Directory
* parent
, Package
* package
)
50 // init the directory/node
51 status_t error
= Init(parent
, package
->VersionedName());
56 AddPackage(package
, NULL
);
63 PackageLinkDirectory::Init(Directory
* parent
, const String
& name
)
65 return Directory::Init(parent
, name
);
70 PackageLinkDirectory::ModifiedTime() const
77 PackageLinkDirectory::OpenAttributeDirectory(AttributeDirectoryCookie
*& _cookie
)
79 Package
* package
= fPackages
.Head();
81 return B_ENTRY_NOT_FOUND
;
83 AutoPackageAttributeDirectoryCookie
* cookie
= new(std::nothrow
)
84 AutoPackageAttributeDirectoryCookie();
94 PackageLinkDirectory::OpenAttribute(const StringKey
& name
, int openMode
,
95 AttributeCookie
*& _cookie
)
97 Package
* package
= fPackages
.Head();
99 return B_ENTRY_NOT_FOUND
;
101 return AutoPackageAttributes::OpenCookie(package
, name
, openMode
, _cookie
);
106 PackageLinkDirectory::AddPackage(Package
* package
,
107 PackageLinksListener
* listener
)
109 NodeWriteLocker
writeLocker(this);
111 // Find the insertion point in the list. We sort by mount type -- the more
112 // specific the higher the priority.
113 MountType mountType
= package
->Volume()->MountType();
114 Package
* otherPackage
= NULL
;
115 for (PackageList::Iterator it
= fPackages
.GetIterator();
116 (otherPackage
= it
.Next()) != NULL
;) {
117 if (otherPackage
->Volume()->MountType() <= mountType
)
121 fPackages
.InsertBefore(otherPackage
, package
);
122 package
->SetLinkDirectory(this);
124 if (package
== fPackages
.Head())
130 PackageLinkDirectory::RemovePackage(Package
* package
,
131 PackageLinksListener
* listener
)
133 ASSERT(package
->LinkDirectory() == this);
135 NodeWriteLocker
writeLocker(this);
137 bool firstPackage
= package
== fPackages
.Head();
139 package
->SetLinkDirectory(NULL
);
140 fPackages
.Remove(package
);
148 PackageLinkDirectory::UpdatePackageDependencies(Package
* package
,
149 PackageLinksListener
* listener
)
151 ASSERT(package
->LinkDirectory() == this);
153 NodeWriteLocker
writeLocker(this);
155 // We only need to update, if that head package is affected.
156 if (package
!= fPackages
.Head())
159 _UpdateDependencies(listener
);
164 PackageLinkDirectory::_Update(PackageLinksListener
* listener
)
166 // Always remove all dependency links -- if there's still a package, they
167 // will be re-created below.
168 while (DependencyLink
* link
= fDependencyLinks
.RemoveHead())
169 _RemoveLink(link
, listener
);
172 Package
* package
= fPackages
.Head();
173 if (package
== NULL
) {
174 // remove self and settings link
175 _RemoveLink(fSelfLink
, listener
);
178 _RemoveLink(fSettingsLink
, listener
);
179 fSettingsLink
= NULL
;
184 // create/update self and settings link
185 status_t error
= _CreateOrUpdateLink(fSelfLink
, package
,
186 Link::TYPE_INSTALLATION_LOCATION
, StringConstants::Get().kSelfLinkName
,
191 error
= _CreateOrUpdateLink(fSettingsLink
, package
, Link::TYPE_SETTINGS
,
192 StringConstants::Get().kSettingsLinkName
, listener
);
196 // update the dependency links
197 return _UpdateDependencies(listener
);
202 PackageLinkDirectory::_UpdateDependencies(PackageLinksListener
* listener
)
204 Package
* package
= fPackages
.Head();
208 // Iterate through the package's dependencies
209 for (DependencyList::ConstIterator it
210 = package
->Dependencies().GetIterator();
211 Dependency
* dependency
= it
.Next();) {
212 Resolvable
* resolvable
= dependency
->Resolvable();
213 Package
* resolvablePackage
= resolvable
!= NULL
214 ? resolvable
->Package() : NULL
;
216 Node
* node
= FindChild(dependency
->FileName());
218 // link already exists -- update
219 DependencyLink
* link
= static_cast<DependencyLink
*>(node
);
221 NodeWriteLocker
linkLocker(link
);
222 link
->Update(resolvablePackage
, listener
);
224 // no link for the dependency yet -- create one
225 DependencyLink
* link
= new(std::nothrow
) DependencyLink(
230 status_t error
= link
->Init(this, dependency
->FileName());
237 fDependencyLinks
.Add(link
);
239 if (listener
!= NULL
) {
240 NodeWriteLocker
linkLocker(link
);
241 listener
->PackageLinkNodeAdded(link
);
251 PackageLinkDirectory::_RemoveLink(Link
* link
, PackageLinksListener
* listener
)
254 NodeWriteLocker
linkLocker(link
);
255 if (listener
!= NULL
)
256 listener
->PackageLinkNodeRemoved(link
);
260 link
->ReleaseReference();
266 PackageLinkDirectory::_CreateOrUpdateLink(Link
*& link
, Package
* package
,
267 Link::Type type
, const String
& name
, PackageLinksListener
* listener
)
270 link
= new(std::nothrow
) Link(package
, type
);
274 status_t error
= link
->Init(this, name
);
280 if (listener
!= NULL
) {
281 NodeWriteLocker
lLinkLocker(link
);
282 listener
->PackageLinkNodeAdded(link
);
285 NodeWriteLocker
lLinkLocker(link
);
286 link
->Update(package
, listener
);