ciocore 5.1.1__py2.py3-none-any.whl → 10.0.0b3__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ciocore/VERSION +1 -1
- ciocore/__init__.py +23 -1
- ciocore/api_client.py +655 -160
- ciocore/auth/__init__.py +5 -3
- ciocore/cli.py +501 -0
- ciocore/common.py +15 -13
- ciocore/conductor_submit.py +77 -60
- ciocore/config.py +127 -13
- ciocore/data.py +162 -77
- ciocore/docsite/404.html +746 -0
- ciocore/docsite/apidoc/api_client/index.html +3605 -0
- ciocore/docsite/apidoc/apidoc/index.html +909 -0
- ciocore/docsite/apidoc/config/index.html +1652 -0
- ciocore/docsite/apidoc/data/index.html +1553 -0
- ciocore/docsite/apidoc/hardware_set/index.html +2460 -0
- ciocore/docsite/apidoc/package_environment/index.html +1507 -0
- ciocore/docsite/apidoc/package_tree/index.html +2386 -0
- ciocore/docsite/assets/_mkdocstrings.css +16 -0
- ciocore/docsite/assets/images/favicon.png +0 -0
- ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js +29 -0
- ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js.map +7 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
- ciocore/docsite/assets/javascripts/lunr/tinyseg.js +206 -0
- ciocore/docsite/assets/javascripts/lunr/wordcut.js +6708 -0
- ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js +42 -0
- ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js.map +7 -0
- ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css +1 -0
- ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
- ciocore/docsite/assets/stylesheets/palette.06af60db.min.css +1 -0
- ciocore/docsite/assets/stylesheets/palette.06af60db.min.css.map +1 -0
- ciocore/docsite/cmdline/docs/index.html +871 -0
- ciocore/docsite/cmdline/downloader/index.html +934 -0
- ciocore/docsite/cmdline/packages/index.html +878 -0
- ciocore/docsite/cmdline/uploader/index.html +995 -0
- ciocore/docsite/how-to-guides/index.html +869 -0
- ciocore/docsite/index.html +895 -0
- ciocore/docsite/logo.png +0 -0
- ciocore/docsite/objects.inv +0 -0
- ciocore/docsite/search/search_index.json +1 -0
- ciocore/docsite/sitemap.xml +3 -0
- ciocore/docsite/sitemap.xml.gz +0 -0
- ciocore/docsite/stylesheets/extra.css +26 -0
- ciocore/docsite/stylesheets/tables.css +167 -0
- ciocore/downloader/base_downloader.py +644 -0
- ciocore/downloader/download_runner_base.py +47 -0
- ciocore/downloader/job_downloader.py +119 -0
- ciocore/{downloader.py → downloader/legacy_downloader.py} +12 -9
- ciocore/downloader/log.py +73 -0
- ciocore/downloader/logging_download_runner.py +87 -0
- ciocore/downloader/perpetual_downloader.py +63 -0
- ciocore/downloader/registry.py +97 -0
- ciocore/downloader/reporter.py +135 -0
- ciocore/exceptions.py +8 -2
- ciocore/file_utils.py +51 -50
- ciocore/hardware_set.py +449 -0
- ciocore/loggeria.py +89 -20
- ciocore/package_environment.py +110 -48
- ciocore/package_query.py +182 -0
- ciocore/package_tree.py +319 -258
- ciocore/retry.py +0 -0
- ciocore/uploader/_uploader.py +547 -364
- ciocore/uploader/thread_queue_job.py +176 -0
- ciocore/uploader/upload_stats/__init__.py +3 -4
- ciocore/uploader/upload_stats/stats_formats.py +10 -4
- ciocore/validator.py +34 -2
- ciocore/worker.py +174 -151
- ciocore-10.0.0b3.dist-info/METADATA +928 -0
- ciocore-10.0.0b3.dist-info/RECORD +128 -0
- {ciocore-5.1.1.dist-info → ciocore-10.0.0b3.dist-info}/WHEEL +1 -1
- ciocore-10.0.0b3.dist-info/entry_points.txt +2 -0
- tests/instance_type_fixtures.py +175 -0
- tests/package_fixtures.py +205 -0
- tests/test_api_client.py +297 -12
- tests/test_base_downloader.py +104 -0
- tests/test_cli.py +149 -0
- tests/test_common.py +1 -7
- tests/test_config.py +40 -18
- tests/test_data.py +162 -173
- tests/test_downloader.py +118 -0
- tests/test_hardware_set.py +139 -0
- tests/test_job_downloader.py +213 -0
- tests/test_package_query.py +38 -0
- tests/test_package_tree.py +91 -291
- tests/test_submit.py +44 -18
- tests/test_uploader.py +1 -4
- ciocore/__about__.py +0 -10
- ciocore/cli/conductor.py +0 -191
- ciocore/compat.py +0 -15
- ciocore-5.1.1.data/scripts/conductor +0 -19
- ciocore-5.1.1.data/scripts/conductor.bat +0 -13
- ciocore-5.1.1.dist-info/METADATA +0 -408
- ciocore-5.1.1.dist-info/RECORD +0 -47
- tests/mocks/api_client_mock.py +0 -51
- /ciocore/{cli → downloader}/__init__.py +0 -0
- {ciocore-5.1.1.dist-info → ciocore-10.0.0b3.dist-info}/top_level.txt +0 -0
ciocore/worker.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import queue
|
|
2
3
|
import sys
|
|
3
4
|
import threading
|
|
5
|
+
import time
|
|
4
6
|
import traceback
|
|
5
7
|
|
|
6
|
-
try:
|
|
7
|
-
import Queue as queue
|
|
8
|
-
except ImportError:
|
|
9
|
-
import queue
|
|
10
|
-
|
|
11
8
|
import ciocore
|
|
9
|
+
import ciocore.loggeria
|
|
10
|
+
import ciocore.uploader.thread_queue_job
|
|
12
11
|
|
|
13
|
-
logger = logging.getLogger("{}.worker".format(
|
|
12
|
+
logger = logging.getLogger("{}.uploader.worker".format(
|
|
13
|
+
ciocore.loggeria.CONDUCTOR_LOGGER_NAME))
|
|
14
14
|
|
|
15
|
-
# This is used to signal to workers
|
|
15
|
+
# This is used to signal to workers i workf should continue or not
|
|
16
16
|
WORKING = True
|
|
17
|
+
EMPTY_JOB = "empty_job"
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class Reporter():
|
|
19
21
|
def __init__(self, metric_store=None):
|
|
@@ -42,13 +44,14 @@ class Reporter():
|
|
|
42
44
|
return self.thread
|
|
43
45
|
|
|
44
46
|
logger.debug('starting reporter thread')
|
|
45
|
-
thd = threading.Thread(
|
|
47
|
+
thd = threading.Thread(
|
|
48
|
+
target=self.target, name=self.__class__.__name__)
|
|
46
49
|
thd.daemon = True
|
|
47
50
|
thd.start()
|
|
48
51
|
self.thread = thd
|
|
49
52
|
return self.thread
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
|
|
54
|
+
|
|
52
55
|
class ThreadWorker(object):
|
|
53
56
|
'''
|
|
54
57
|
Abstract worker class.
|
|
@@ -57,7 +60,7 @@ class ThreadWorker(object):
|
|
|
57
60
|
|
|
58
61
|
TODO: move this into it's own lib
|
|
59
62
|
'''
|
|
60
|
-
|
|
63
|
+
|
|
61
64
|
def __init__(self, **kwargs):
|
|
62
65
|
|
|
63
66
|
# the in_queue provides work for us to do
|
|
@@ -77,10 +80,10 @@ class ThreadWorker(object):
|
|
|
77
80
|
|
|
78
81
|
# create a list to hold the threads that we create
|
|
79
82
|
self.threads = []
|
|
80
|
-
|
|
83
|
+
|
|
81
84
|
self.thread_complete_counter = Counter()
|
|
82
|
-
self._worker_started = Marker()
|
|
83
85
|
self._job_counter = Counter()
|
|
86
|
+
self.task_count = 0
|
|
84
87
|
|
|
85
88
|
def do_work(self, job):
|
|
86
89
|
'''
|
|
@@ -102,7 +105,8 @@ class ThreadWorker(object):
|
|
|
102
105
|
exit()
|
|
103
106
|
|
|
104
107
|
def kill(self, block=False):
|
|
105
|
-
logger.debug('killing workers %s (%s threads)',
|
|
108
|
+
logger.debug('killing workers %s (%s threads)',
|
|
109
|
+
self.__class__.__name__, len(self.threads))
|
|
106
110
|
for _ in self.threads:
|
|
107
111
|
self.in_queue.put(self.PoisonPill())
|
|
108
112
|
|
|
@@ -115,52 +119,62 @@ class ThreadWorker(object):
|
|
|
115
119
|
return True
|
|
116
120
|
|
|
117
121
|
def join(self):
|
|
118
|
-
logger.debug("Waiting for in_queue to join. (
|
|
119
|
-
|
|
122
|
+
logger.debug("Waiting for in_queue to join. (%s-%s). %s items left.",
|
|
123
|
+
self.__class__.__name__, self, self.in_queue.qsize())
|
|
124
|
+
|
|
120
125
|
while True:
|
|
121
126
|
try:
|
|
122
|
-
logger.debug("Getting remaining task from in_queue (
|
|
127
|
+
logger.debug("Getting remaining task from in_queue (%s-%s). %s items left.",
|
|
128
|
+
self.__class__.__name__, self, self.in_queue.qsize())
|
|
123
129
|
job = self.in_queue.get(block=False)
|
|
124
|
-
logger.debug("Dropping task
|
|
130
|
+
logger.debug("Dropping task %s from in_queue (%s-%s). %s items left.",
|
|
131
|
+
job, self.__class__.__name__, self, self.in_queue.qsize())
|
|
125
132
|
self.in_queue.task_done()
|
|
126
133
|
except queue.Empty:
|
|
127
|
-
logger.debug("in_queue is empty (
|
|
134
|
+
logger.debug("in_queue is empty (%s-%s). %s items left.",
|
|
135
|
+
self.__class__.__name__, self, self.in_queue.qsize())
|
|
128
136
|
break
|
|
129
137
|
|
|
130
138
|
self.kill(True)
|
|
131
139
|
|
|
132
140
|
# Basic thread target loop.
|
|
133
|
-
@ciocore.common.dec_catch_exception(raise_=True)
|
|
141
|
+
# @ciocore.common.dec_catch_exception(raise_=True)
|
|
134
142
|
def target(self, thread_int):
|
|
135
143
|
|
|
136
144
|
while not ciocore.common.SIGINT_EXIT:
|
|
137
145
|
try:
|
|
138
|
-
|
|
146
|
+
|
|
139
147
|
job = None
|
|
140
148
|
|
|
141
149
|
try:
|
|
142
150
|
logger.debug("Worker querying for job")
|
|
143
151
|
job = self.in_queue.get(timeout=2)
|
|
144
|
-
queue_size = self.in_queue.qsize()
|
|
152
|
+
queue_size = self.in_queue.qsize()
|
|
145
153
|
|
|
146
154
|
except queue.Empty:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
|
|
156
|
+
logger.debug("Worker in queue raised Empty (_job_counter=%s, task_count=%s",
|
|
157
|
+
self._job_counter.value, self.task_count)
|
|
158
|
+
|
|
159
|
+
if self._job_counter.value >= self.task_count:
|
|
160
|
+
logger.debug(
|
|
161
|
+
"Worker has completed all of its tasks (%s)", job)
|
|
150
162
|
self.thread_complete_counter.decrement()
|
|
151
163
|
break
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
|
|
165
|
+
elif self._job_counter.value == 0:
|
|
154
166
|
logger.debug("Worker waiting for first job")
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
|
|
168
|
+
time.sleep(1)
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
logger.debug("Worker got job %s", job)
|
|
158
172
|
self._job_counter.increment()
|
|
159
|
-
logger.debug("Processing Job '
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
173
|
+
logger.debug("Processing Job '%s' #%s on %s. %s tasks remaining in queue", job,
|
|
174
|
+
self._job_counter.value,
|
|
175
|
+
self,
|
|
176
|
+
queue_size)
|
|
177
|
+
|
|
164
178
|
# exit if we were passed 'PoisonPill'
|
|
165
179
|
self.check_for_poison_pill(job)
|
|
166
180
|
|
|
@@ -168,11 +182,15 @@ class ThreadWorker(object):
|
|
|
168
182
|
try:
|
|
169
183
|
output = None
|
|
170
184
|
output = self.do_work(job, thread_int)
|
|
185
|
+
logger.debug("Output from do_work(): '%s'", output)
|
|
171
186
|
except Exception as exception:
|
|
172
|
-
logger.
|
|
187
|
+
logger.error(
|
|
188
|
+
'CAUGHT EXCEPTION on job "%s" [%s]":\n', job, self)
|
|
189
|
+
logger.error(traceback.format_exc())
|
|
173
190
|
|
|
174
191
|
# if there is no error queue to dump data into, then simply raise the exception
|
|
175
|
-
if
|
|
192
|
+
if self.error_queue is None:
|
|
193
|
+
logger.debug("Re-raising exception")
|
|
176
194
|
raise
|
|
177
195
|
|
|
178
196
|
# Otherwise put the exception in the error queue
|
|
@@ -189,12 +207,13 @@ class ThreadWorker(object):
|
|
|
189
207
|
self.mark_done()
|
|
190
208
|
|
|
191
209
|
except Exception:
|
|
192
|
-
logger.error(
|
|
210
|
+
logger.error(
|
|
211
|
+
'[thread %s]+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=', thread_int)
|
|
193
212
|
logger.error(traceback.print_exc())
|
|
194
213
|
logger.error(traceback.format_exc())
|
|
195
214
|
raise
|
|
196
|
-
|
|
197
|
-
logger.info("Worker
|
|
215
|
+
|
|
216
|
+
logger.info("Worker %s completed", self)
|
|
198
217
|
|
|
199
218
|
def start(self):
|
|
200
219
|
'''
|
|
@@ -207,9 +226,10 @@ class ThreadWorker(object):
|
|
|
207
226
|
for thread_int in range(self.thread_count):
|
|
208
227
|
name = "%s-%s" % (self.__class__.__name__, thread_int)
|
|
209
228
|
logger.debug('starting thread %s', name)
|
|
210
|
-
|
|
229
|
+
|
|
211
230
|
# thread will begin execution on self.target()
|
|
212
|
-
thd = threading.Thread(
|
|
231
|
+
thd = threading.Thread(
|
|
232
|
+
target=self.target, args=(thread_int,), name=name)
|
|
213
233
|
|
|
214
234
|
# make sure threads don't stop the program from exiting
|
|
215
235
|
thd.daemon = True
|
|
@@ -217,7 +237,7 @@ class ThreadWorker(object):
|
|
|
217
237
|
# start thread
|
|
218
238
|
thd.start()
|
|
219
239
|
self.threads.append(thd)
|
|
220
|
-
|
|
240
|
+
|
|
221
241
|
self.thread_complete_counter.value = self.thread_count
|
|
222
242
|
|
|
223
243
|
return self.threads
|
|
@@ -225,11 +245,11 @@ class ThreadWorker(object):
|
|
|
225
245
|
def mark_done(self):
|
|
226
246
|
try:
|
|
227
247
|
self.in_queue.task_done()
|
|
228
|
-
|
|
248
|
+
|
|
229
249
|
except ValueError:
|
|
230
250
|
# this will happen if we are draining queues
|
|
231
251
|
logger.debug('WORKING: %s', WORKING)
|
|
232
|
-
|
|
252
|
+
|
|
233
253
|
if WORKING:
|
|
234
254
|
logger.error('error hit when marking task_done')
|
|
235
255
|
# this should not happen if we are still working
|
|
@@ -237,25 +257,32 @@ class ThreadWorker(object):
|
|
|
237
257
|
return
|
|
238
258
|
|
|
239
259
|
def put_job(self, job):
|
|
260
|
+
|
|
261
|
+
if job is None:
|
|
262
|
+
logger.debug(
|
|
263
|
+
"Attempting to put job 'None' in out_queue (%s -> %s). Skipping.", self, self.out_queue)
|
|
264
|
+
return
|
|
265
|
+
|
|
240
266
|
# don't to anything if we were not provided an out_queue
|
|
241
|
-
logger.debug(
|
|
242
|
-
|
|
267
|
+
logger.debug(
|
|
268
|
+
"Attempting to put job to out_queue (%s -> %s)", job, self.out_queue)
|
|
269
|
+
|
|
243
270
|
if not self.out_queue:
|
|
244
271
|
return
|
|
245
272
|
|
|
246
273
|
# if were not supposed to be working, don't create new jobs
|
|
247
274
|
if not WORKING:
|
|
248
275
|
return
|
|
249
|
-
|
|
250
|
-
logger.debug("Adding job to out_queue (
|
|
251
|
-
|
|
276
|
+
|
|
277
|
+
logger.debug("Adding job to out_queue (%s -> %s)", job, self.out_queue)
|
|
278
|
+
|
|
252
279
|
# add item to job
|
|
253
280
|
self.out_queue.put(job)
|
|
254
281
|
return True
|
|
255
|
-
|
|
256
|
-
def is_complete(self):
|
|
282
|
+
|
|
283
|
+
def is_complete(self):
|
|
257
284
|
return self.thread_complete_counter.value == 0
|
|
258
|
-
|
|
285
|
+
|
|
259
286
|
|
|
260
287
|
class MetricStore():
|
|
261
288
|
'''
|
|
@@ -282,15 +309,16 @@ class MetricStore():
|
|
|
282
309
|
if self.started:
|
|
283
310
|
logger.debug('metric_store already started')
|
|
284
311
|
return None
|
|
285
|
-
|
|
312
|
+
|
|
286
313
|
logger.debug('starting metric_store')
|
|
287
|
-
|
|
314
|
+
|
|
288
315
|
self.stop = False
|
|
289
|
-
self.thread = threading.Thread(
|
|
316
|
+
self.thread = threading.Thread(
|
|
317
|
+
target=self.target, name=self.__class__.__name__)
|
|
290
318
|
self.thread.daemon = True
|
|
291
319
|
self.thread.start()
|
|
292
320
|
self.started = True
|
|
293
|
-
|
|
321
|
+
|
|
294
322
|
return self.thread
|
|
295
323
|
|
|
296
324
|
def set(self, key, value):
|
|
@@ -315,19 +343,20 @@ class MetricStore():
|
|
|
315
343
|
if filename:
|
|
316
344
|
if 'files' not in self.metric_store:
|
|
317
345
|
self.metric_store['files'] = {}
|
|
318
|
-
|
|
346
|
+
|
|
319
347
|
if filename not in self.metric_store['files']:
|
|
320
|
-
self.metric_store['files'][filename] = {
|
|
321
|
-
|
|
348
|
+
self.metric_store['files'][filename] = {
|
|
349
|
+
'bytes_to_upload': 0, 'bytes_uploaded': 0, 'already_uploaded': False}
|
|
350
|
+
|
|
322
351
|
if variable == 'bytes_uploaded':
|
|
323
352
|
self.metric_store['files'][filename]['bytes_uploaded'] += step_size
|
|
324
|
-
|
|
353
|
+
|
|
325
354
|
elif variable == 'bytes_to_upload':
|
|
326
355
|
self.metric_store['files'][filename]['bytes_to_upload'] = step_size
|
|
327
|
-
|
|
356
|
+
|
|
328
357
|
elif variable == 'already_uploaded':
|
|
329
|
-
|
|
330
|
-
|
|
358
|
+
# True/False
|
|
359
|
+
self.metric_store['files'][filename]['already_uploaded'] = step_size
|
|
331
360
|
|
|
332
361
|
def set_dict(self, dict_name, key, value):
|
|
333
362
|
self.update_queue.put(('set_dict', dict_name, key, value))
|
|
@@ -371,17 +400,17 @@ class MetricStore():
|
|
|
371
400
|
@ciocore.common.dec_catch_exception(raise_=True)
|
|
372
401
|
def target(self):
|
|
373
402
|
logger.debug('created metric_store target thread')
|
|
374
|
-
|
|
403
|
+
|
|
375
404
|
while not self.stop:
|
|
376
|
-
|
|
377
|
-
logger.debug("Metric store self.stop
|
|
378
|
-
|
|
405
|
+
|
|
406
|
+
logger.debug("Metric store self.stop=%s", self.stop)
|
|
407
|
+
|
|
379
408
|
try:
|
|
380
409
|
# block until update given
|
|
381
410
|
update_tuple = self.update_queue.get(True, 2)
|
|
382
|
-
|
|
411
|
+
|
|
383
412
|
except queue.Empty:
|
|
384
|
-
continue
|
|
413
|
+
continue
|
|
385
414
|
|
|
386
415
|
method = update_tuple[0]
|
|
387
416
|
method_args = update_tuple[1:]
|
|
@@ -413,9 +442,10 @@ class JobManager():
|
|
|
413
442
|
self._queue_started = False
|
|
414
443
|
self.error_handler_stop = False
|
|
415
444
|
self.error_handler_thread = None
|
|
445
|
+
self.task_count = None
|
|
416
446
|
|
|
417
447
|
def drain_queues(self):
|
|
418
|
-
logger.
|
|
448
|
+
logger.debug('draining queues')
|
|
419
449
|
# http://stackoverflow.com/questions/6517953/clear-all-items-from-the-queue
|
|
420
450
|
for the_queue in self.work_queues:
|
|
421
451
|
the_queue.mutex.acquire()
|
|
@@ -424,7 +454,7 @@ class JobManager():
|
|
|
424
454
|
return True
|
|
425
455
|
|
|
426
456
|
def mark_all_tasks_complete(self):
|
|
427
|
-
logger.
|
|
457
|
+
logger.debug('clearing out all tasks')
|
|
428
458
|
# http://stackoverflow.com/questions/6517953/clear-all-items-from-the-queue
|
|
429
459
|
for the_queue in self.work_queues:
|
|
430
460
|
the_queue.mutex.acquire()
|
|
@@ -438,7 +468,7 @@ class JobManager():
|
|
|
438
468
|
WORKING = False
|
|
439
469
|
for worker in self.workers:
|
|
440
470
|
logger.debug("Killing worker: %s", worker)
|
|
441
|
-
worker.kill(block=True)
|
|
471
|
+
worker.kill(block=True) # Wait to ensure the worker was killed
|
|
442
472
|
|
|
443
473
|
def kill_reporters(self):
|
|
444
474
|
for reporter in self.reporters:
|
|
@@ -446,67 +476,89 @@ class JobManager():
|
|
|
446
476
|
reporter.kill()
|
|
447
477
|
|
|
448
478
|
def stop_work(self, force=False):
|
|
449
|
-
|
|
479
|
+
|
|
450
480
|
global WORKING
|
|
451
|
-
|
|
481
|
+
|
|
452
482
|
if WORKING:
|
|
453
|
-
|
|
483
|
+
|
|
454
484
|
logger.info("Stopping Worker Manager")
|
|
455
|
-
|
|
485
|
+
|
|
456
486
|
WORKING = False # stop any new jobs from being created
|
|
457
487
|
self.drain_queues() # clear out any jobs in queue
|
|
458
488
|
self.kill_workers() # kill all threads
|
|
459
489
|
self.kill_reporters()
|
|
460
490
|
self.mark_all_tasks_complete() # reset task counts
|
|
461
|
-
|
|
491
|
+
|
|
462
492
|
self.metric_store.stop = True
|
|
463
|
-
self.metric_store.join()
|
|
464
|
-
|
|
493
|
+
# self.metric_store.join()
|
|
494
|
+
|
|
465
495
|
self.error_handler_stop = True
|
|
466
|
-
self.error_handler_thread.join()
|
|
467
|
-
|
|
496
|
+
# self.error_handler_thread.join()
|
|
497
|
+
|
|
468
498
|
else:
|
|
469
499
|
logger.info("Worker Manager has already been stopped.")
|
|
470
|
-
|
|
500
|
+
|
|
471
501
|
return self.error
|
|
472
502
|
|
|
473
503
|
@ciocore.common.dec_catch_exception(raise_=True)
|
|
474
504
|
def error_handler_target(self):
|
|
475
505
|
|
|
476
506
|
while not self.error_handler_stop:
|
|
477
|
-
|
|
507
|
+
|
|
478
508
|
try:
|
|
479
|
-
error = self.error_queue.get(True,
|
|
480
|
-
|
|
509
|
+
error = self.error_queue.get(True, 0.5)
|
|
510
|
+
|
|
481
511
|
except queue.Empty:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
512
|
+
|
|
513
|
+
if self.error:
|
|
514
|
+
break
|
|
515
|
+
|
|
516
|
+
else:
|
|
517
|
+
continue
|
|
518
|
+
|
|
519
|
+
logger.error('Got something from the error queue: %s', error)
|
|
485
520
|
self.error.append(error)
|
|
486
521
|
try:
|
|
487
522
|
self.error_queue.task_done()
|
|
488
523
|
except ValueError:
|
|
489
524
|
pass
|
|
490
525
|
|
|
526
|
+
self.stop_work(force=True)
|
|
527
|
+
|
|
491
528
|
def start_error_handler(self):
|
|
492
|
-
|
|
529
|
+
|
|
493
530
|
logger.debug('Creating error handler thread')
|
|
494
|
-
self.error_handler_thread = threading.Thread(
|
|
531
|
+
self.error_handler_thread = threading.Thread(
|
|
532
|
+
target=self.error_handler_target, name="ErrorThread")
|
|
495
533
|
self.error_handler_thread.daemon = True
|
|
496
534
|
self.error_handler_thread.start()
|
|
497
|
-
|
|
535
|
+
|
|
498
536
|
return None
|
|
499
537
|
|
|
500
|
-
def add_task(self, task):
|
|
501
|
-
|
|
538
|
+
def add_task(self, task, project=None):
|
|
539
|
+
|
|
502
540
|
# This allows us to keep track of the difference between an empty queue
|
|
503
541
|
# because no tasks have been added or an empty queue because all the tasks
|
|
504
542
|
# have been completed
|
|
505
|
-
if not self._queue_started:
|
|
543
|
+
if not self._queue_started:
|
|
544
|
+
logger.debug("Initializing Queue - queue started")
|
|
506
545
|
self._queue_started = True
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
546
|
+
self.task_count = 0
|
|
547
|
+
|
|
548
|
+
job = ciocore.uploader.thread_queue_job.ThreadQueueJob(path=task[0],
|
|
549
|
+
md5=task[1],
|
|
550
|
+
project=project)
|
|
551
|
+
self.work_queues[0].put(job)
|
|
552
|
+
|
|
553
|
+
for worker in self.workers:
|
|
554
|
+
worker.task_count += 1
|
|
555
|
+
logger.debug("Incremented task count on worker %s to %s",
|
|
556
|
+
worker, worker.task_count)
|
|
557
|
+
|
|
558
|
+
self.task_count += 1
|
|
559
|
+
logger.debug("Incremented task count on manager to %s",
|
|
560
|
+
self.task_count)
|
|
561
|
+
|
|
510
562
|
return True
|
|
511
563
|
|
|
512
564
|
def start(self):
|
|
@@ -523,7 +575,6 @@ class JobManager():
|
|
|
523
575
|
next_queue = None
|
|
524
576
|
last_queue = self.work_queues[0]
|
|
525
577
|
last_worker = next(reversed(self.job_description))
|
|
526
|
-
|
|
527
578
|
for worker_description in self.job_description:
|
|
528
579
|
worker_class = worker_description[0]
|
|
529
580
|
args = []
|
|
@@ -537,13 +588,9 @@ class JobManager():
|
|
|
537
588
|
|
|
538
589
|
kwargs['in_queue'] = last_queue
|
|
539
590
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
else:
|
|
544
|
-
next_queue = queue.Queue()
|
|
545
|
-
self.work_queues.append(next_queue)
|
|
546
|
-
kwargs['out_queue'] = next_queue
|
|
591
|
+
next_queue = queue.Queue()
|
|
592
|
+
self.work_queues.append(next_queue)
|
|
593
|
+
kwargs['out_queue'] = next_queue
|
|
547
594
|
|
|
548
595
|
kwargs['error_queue'] = self.error_queue
|
|
549
596
|
kwargs['metric_store'] = self.metric_store
|
|
@@ -576,79 +623,55 @@ class JobManager():
|
|
|
576
623
|
self.metric_store.stop = True
|
|
577
624
|
self.metric_store.join()
|
|
578
625
|
logger.debug('metric store in sync')
|
|
579
|
-
|
|
626
|
+
|
|
580
627
|
self.error_handler_stop = True
|
|
581
628
|
self.error_handler_thread.join()
|
|
582
|
-
|
|
629
|
+
|
|
583
630
|
if self.error:
|
|
584
631
|
return self.error
|
|
585
|
-
|
|
632
|
+
|
|
586
633
|
self.kill_workers()
|
|
587
634
|
self.kill_reporters()
|
|
588
|
-
|
|
635
|
+
|
|
589
636
|
return None
|
|
590
637
|
|
|
591
638
|
def worker_queue_status_text(self):
|
|
592
|
-
msg =
|
|
639
|
+
msg = "\n{:#^80}\n".format('QUEUE STATUS')
|
|
593
640
|
for index, worker_info in enumerate(self.job_description):
|
|
594
641
|
worker_class = worker_info[0]
|
|
595
642
|
q_size = self.work_queues[index].qsize()
|
|
596
643
|
worker_threads = self.workers[index].threads
|
|
597
644
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
num_active_threads = len([thd for thd in worker_threads if thd.isAlive()])
|
|
601
|
-
except AttributeError:
|
|
602
|
-
num_active_threads = len([thd for thd in worker_threads if thd.is_alive()])
|
|
645
|
+
num_active_threads = len(
|
|
646
|
+
[thd for thd in worker_threads if thd.is_alive()])
|
|
603
647
|
|
|
604
648
|
msg += '%s \titems in queue: %s' % (q_size, worker_class.__name__)
|
|
605
649
|
msg += '\t\t%s threads' % num_active_threads
|
|
606
650
|
msg += '\n'
|
|
607
651
|
return msg
|
|
608
|
-
|
|
652
|
+
|
|
609
653
|
def is_complete(self):
|
|
610
654
|
|
|
611
|
-
is_complete = True
|
|
612
|
-
|
|
613
|
-
# Manager has completed if all workers have completed
|
|
614
655
|
for worker in self.workers:
|
|
615
|
-
logger.debug("Worker
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
656
|
+
logger.debug("Worker %s is complete: %s",
|
|
657
|
+
worker.__class__.__name__, worker.is_complete())
|
|
658
|
+
|
|
659
|
+
return self.get_last_worker().is_complete()
|
|
660
|
+
|
|
661
|
+
def get_last_worker(self):
|
|
662
|
+
return self.workers[-1]
|
|
663
|
+
|
|
664
|
+
|
|
622
665
|
class Counter(object):
|
|
623
|
-
|
|
666
|
+
|
|
624
667
|
def __init__(self):
|
|
625
668
|
self.value = 0
|
|
626
669
|
self._lock = threading.Lock()
|
|
627
|
-
|
|
670
|
+
|
|
628
671
|
def increment(self):
|
|
629
672
|
with self._lock:
|
|
630
673
|
self.value += 1
|
|
631
|
-
|
|
674
|
+
|
|
632
675
|
def decrement(self):
|
|
633
676
|
with self._lock:
|
|
634
|
-
self.value -= 1
|
|
635
|
-
|
|
636
|
-
class Marker(object):
|
|
637
|
-
|
|
638
|
-
def __init__(self):
|
|
639
|
-
self.marker = False
|
|
640
|
-
self._lock = threading.Lock()
|
|
641
|
-
|
|
642
|
-
def mark(self):
|
|
643
|
-
|
|
644
|
-
with self._lock:
|
|
645
|
-
|
|
646
|
-
logger.debug("Lock aquired (marker={})".format(self.marker))
|
|
647
|
-
|
|
648
|
-
if self.marker:
|
|
649
|
-
return True
|
|
650
|
-
|
|
651
|
-
else:
|
|
652
|
-
|
|
653
|
-
self.marker = True
|
|
654
|
-
return False
|
|
677
|
+
self.value -= 1
|