-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPackageTable.h
More file actions
156 lines (131 loc) · 3.72 KB
/
PackageTable.h
File metadata and controls
156 lines (131 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "Package.h"
#include <unordered_map>
#include <list>
#include <mutex>
#include <assert.h>
using namespace std;
class PackageTable
{
unordered_map<string, Package *> m_table;
std::mutex m_lock;
public:
PackageTable() {}
~PackageTable() {
m_table.clear();
}
void print() {
std::lock_guard<std::mutex> lock(m_lock);
for (auto it = m_table.begin(); it != m_table.end(); ++it) {
Package *p = it->second;
if (p != nullptr) {
p->printDependencies();
}
}
}
Package *lookup(string inName) {
return m_table[inName];
}
int insert_update(Package *inPackage, list<string> inDeps) {
list<Package *> myDeps;
assert(inPackage != nullptr);
for (string dep : inDeps) {
assert(dep != inPackage->getName());
Package * depPackage = lookup(dep);
if (depPackage == nullptr) {
// missing dependency, return error
#ifndef NDEBUG
cout << "Missing dependency " << dep << " for package " << inPackage->getName() << endl;
#endif /* !NDEBUG */
return -1;
} else {
// Check for circular dependency
if (depPackage->search(inPackage->getName()) != nullptr) {
cout << "Circular dependency detected for package " << inPackage->getName() <<
" and updated dependency " << depPackage->getName() << endl;
return 1;
} else {
myDeps.push_back(depPackage);
}
}
}
inPackage->removeAllDependencies();
for (auto p : myDeps) {
inPackage->addDependency(p);
}
return 0;
}
int insert_new(Package *inPackage, list<string> inDeps) {
list<Package *> myDeps;
assert(inPackage != nullptr);
for (string dep : inDeps) {
assert(dep != inPackage->getName());
Package * depPackage = lookup(dep);
if (depPackage == nullptr) {
// missing dependency, return error
#ifndef NDEBUG
cout << "Missing dependency " << dep << " for package " << inPackage->getName() << endl;
#endif /* !NDEBUG */
delete inPackage;
return -1;
} else {
myDeps.push_back(depPackage);
}
}
// All dependencies are met.
for (Package *d : myDeps) {
inPackage->addDependency(d);
}
m_table[inPackage->getName()] = inPackage;
return 0;
}
/**
* Insert a package into the table if dependencies are met
* returns 0 on success
* returns 1 on error, due to a circular dependency
* returns -1 on failure, due to missing dependency
*/
int insert(string inPackageStr, list<string> inDeps) {
int err;
std::lock_guard<std::mutex> lock(m_lock);
Package *myPackage = lookup(inPackageStr);
if (myPackage != nullptr) {
// This is an update of an existing package and needs to be handled differently
err = insert_update(myPackage, inDeps);
} else {
myPackage = new Package(inPackageStr);
err = insert_new(myPackage, inDeps);
}
return err;
}
int remove(string inPackageStr) {
std::lock_guard<std::mutex> lock(m_lock);
Package *remPackage = lookup(inPackageStr);
if (remPackage == nullptr) {
// removing a package that doesn't exist is a noop
return 0;
}
// A package that is a sink node in the graph has no dependencies, thus it can be removed
if (remPackage->isSink()) {
remPackage->removeAllDependencies();
m_table.erase(inPackageStr);
delete remPackage;
return 0;
} else {
// Package that is not a sink is a dependency for another package,
// thus we must fail the removal.
return -1;
}
return 0;
}
int query(string inPackageStr) {
std::lock_guard<std::mutex> lock(m_lock);
Package *queryPackage = lookup(inPackageStr);
if (queryPackage == nullptr) {
// Package is not indexed
return -1;
} else {
// Package is indexed
return 0;
}
}
};