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			NodeWriteLocker writeLocker(linkDirectory);
75			fListener->PackageLinkNodeAdded(linkDirectory);
76		}
77	}
78
79	return B_OK;
80}
81
82
83void
84PackageLinksDirectory::RemovePackage(Package* package)
85{
86	NodeWriteLocker writeLocker(this);
87
88	// get the package's link directory and remove the package from it
89	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
90	if (linkDirectory == NULL)
91		return;
92
93	BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory);
94
95	linkDirectory->RemovePackage(package, fListener);
96
97	// if empty, remove the link directory itself
98	if (linkDirectory->IsEmpty()) {
99		if (fListener != NULL) {
100			NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
101			fListener->PackageLinkNodeRemoved(linkDirectory);
102		}
103
104		RemoveChild(linkDirectory);
105	}
106}
107
108
109void
110PackageLinksDirectory::UpdatePackageDependencies(Package* package)
111{
112	NodeWriteLocker writeLocker(this);
113
114	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
115	if (linkDirectory == NULL)
116		return;
117
118	linkDirectory->UpdatePackageDependencies(package, fListener);
119}
120
121