Forking what is left of ZeroNet and hopefully adding an AT Proto Frontend/Proxy
1import bisect
2from collections.abc import MutableSequence
3
4
5class CustomSortedList(MutableSequence):
6 def __init__(self):
7 super().__init__()
8 self.items = [] # (priority, added index, actual value)
9 self.logging = False
10
11 def __repr__(self):
12 return "<{0} {1}>".format(self.__class__.__name__, self.items)
13
14 def __len__(self):
15 return len(self.items)
16
17 def __getitem__(self, index):
18 if type(index) is int:
19 return self.items[index][2]
20 else:
21 return [item[2] for item in self.items[index]]
22
23 def __delitem__(self, index):
24 del self.items[index]
25
26 def __setitem__(self, index, value):
27 self.items[index] = self.valueToItem(value)
28
29 def __str__(self):
30 return str(self[:])
31
32 def insert(self, index, value):
33 self.append(value)
34
35 def append(self, value):
36 bisect.insort(self.items, self.valueToItem(value))
37
38 def updateItem(self, value, update_key=None, update_value=None):
39 self.remove(value)
40 if update_key is not None:
41 value[update_key] = update_value
42 self.append(value)
43
44 def sort(self, *args, **kwargs):
45 raise Exception("Sorted list can't be sorted")
46
47 def valueToItem(self, value):
48 return (self.getPriority(value), self.getId(value), value)
49
50 def getPriority(self, value):
51 return value
52
53 def getId(self, value):
54 return id(value)
55
56 def indexSlow(self, value):
57 for pos, item in enumerate(self.items):
58 if item[2] == value:
59 return pos
60 return None
61
62 def index(self, value):
63 item = (self.getPriority(value), self.getId(value), value)
64 bisect_pos = bisect.bisect(self.items, item) - 1
65 if bisect_pos >= 0 and self.items[bisect_pos][2] == value:
66 return bisect_pos
67
68 # Item probably changed since added, switch to slow iteration
69 pos = self.indexSlow(value)
70
71 if self.logging:
72 print("Slow index for %s in pos %s bisect: %s" % (item[2], pos, bisect_pos))
73
74 if pos is None:
75 raise ValueError("%r not in list" % value)
76 else:
77 return pos
78
79 def __contains__(self, value):
80 try:
81 self.index(value)
82 return True
83 except ValueError:
84 return False
85
86
87class WorkerTaskManager(CustomSortedList):
88 def __init__(self):
89 super().__init__()
90 self.inner_paths = {}
91
92 def getPriority(self, value):
93 return 0 - (value["priority"] - value["workers_num"] * 10)
94
95 def getId(self, value):
96 return value["id"]
97
98 def __contains__(self, value):
99 return value["inner_path"] in self.inner_paths
100
101 def __delitem__(self, index):
102 # Remove from inner path cache
103 del self.inner_paths[self.items[index][2]["inner_path"]]
104 super().__delitem__(index)
105
106 # Fast task search by inner_path
107
108 def append(self, task):
109 if task["inner_path"] in self.inner_paths:
110 raise ValueError("File %s already has a task" % task["inner_path"])
111 super().append(task)
112 # Create inner path cache for faster lookup by filename
113 self.inner_paths[task["inner_path"]] = task
114
115 def remove(self, task):
116 if task not in self:
117 raise ValueError("%r not in list" % task)
118 else:
119 super().remove(task)
120
121 def findTask(self, inner_path):
122 return self.inner_paths.get(inner_path, None)