1/*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "PackageLinksDirectory.h"
8
9#include <AutoDeleter.h>
10
11#include "DebugSupport.h"
12#include "PackageLinkDirectory.h"
13#include "PackageLinksListener.h"
14#include "Utils.h"
15
16
17PackageLinksDirectory::PackageLinksDirectory()
18	:
19	Directory(0),
20	fListener(NULL)
21		// the ID needs to be assigned later, when added to a volume
22{
23	get_real_time(fModifiedTime);
24}
25
26
27PackageLinksDirectory::~PackageLinksDirectory()
28{
29}
30
31
32timespec
33PackageLinksDirectory::ModifiedTime() const
34{
35	return fModifiedTime;
36}
37
38
39status_t
40PackageLinksDirectory::AddPackage(Package* package)
41{
42	// Create a package link directory -- there might already be one, but since
43	// that's unlikely, we don't bother to check and recheck later.
44	PackageLinkDirectory* linkDirectory
45		= new(std::nothrow) PackageLinkDirectory;
46	if (linkDirectory == NULL)
47		return B_NO_MEMORY;
48	BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory,
49		true);
50
51	status_t error = linkDirectory->Init(this, package);
52	if (error != B_OK)
53		RETURN_ERROR(error);
54
55	// add the link directory
56	NodeWriteLocker writeLocker(this);
57	if (Node* child = FindChild(linkDirectory->Name())) {
58		// There already is an entry with the name.
59		PackageLinkDirectory* otherLinkDirectory
60			= dynamic_cast<PackageLinkDirectory*>(child);
61		if (otherLinkDirectory == NULL)
62			RETURN_ERROR(B_BAD_VALUE);
63
64		// There's already a package link directory. Delete the one we created
65		// and add the package to the pre-existing one.
66		linkDirectory->RemovePackage(package, NULL);
67		linkDirectory = otherLinkDirectory;
68		linkDirectory->AddPackage(package, fListener);
69	} else {
70		// No entry is in the way, so just add the link directory.
71		AddChild(linkDirectory);
72
73		if (fListener != NULL)
74			linkDirectory->NotifyDirectoryAdded(fListener);
75	}
76
77	return B_OK;
78}
79
80
81void
82PackageLinksDirectory::RemovePackage(Package* package)
83{
84	NodeWriteLocker writeLocker(this);
85
86	// get the package's link directory and remove the package from it
87	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
88	if (linkDirectory == NULL)
89		return;
90
91	BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory);
92
93	linkDirectory->RemovePackage(package, fListener);
94
95	// if empty, remove the link directory itself
96	if (linkDirectory->IsEmpty()) {
97		if (fListener != NULL) {
98			NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
99			fListener->PackageLinkNodeRemoved(linkDirectory);
100		}
101
102		RemoveChild(linkDirectory);
103	}
104}
105
106
107void
108PackageLinksDirectory::UpdatePackageDependencies(Package* package)
109{
110	NodeWriteLocker writeLocker(this);
111
112	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
113	if (linkDirectory == NULL)
114		return;
115
116	linkDirectory->UpdatePackageDependencies(package, fListener);
117}
118
119