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.
Files changed (126) hide show
  1. ciocore/VERSION +1 -1
  2. ciocore/__init__.py +23 -1
  3. ciocore/api_client.py +655 -160
  4. ciocore/auth/__init__.py +5 -3
  5. ciocore/cli.py +501 -0
  6. ciocore/common.py +15 -13
  7. ciocore/conductor_submit.py +77 -60
  8. ciocore/config.py +127 -13
  9. ciocore/data.py +162 -77
  10. ciocore/docsite/404.html +746 -0
  11. ciocore/docsite/apidoc/api_client/index.html +3605 -0
  12. ciocore/docsite/apidoc/apidoc/index.html +909 -0
  13. ciocore/docsite/apidoc/config/index.html +1652 -0
  14. ciocore/docsite/apidoc/data/index.html +1553 -0
  15. ciocore/docsite/apidoc/hardware_set/index.html +2460 -0
  16. ciocore/docsite/apidoc/package_environment/index.html +1507 -0
  17. ciocore/docsite/apidoc/package_tree/index.html +2386 -0
  18. ciocore/docsite/assets/_mkdocstrings.css +16 -0
  19. ciocore/docsite/assets/images/favicon.png +0 -0
  20. ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js +29 -0
  21. ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js.map +7 -0
  22. ciocore/docsite/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
  23. ciocore/docsite/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
  24. ciocore/docsite/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
  25. ciocore/docsite/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
  26. ciocore/docsite/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
  27. ciocore/docsite/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
  28. ciocore/docsite/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
  29. ciocore/docsite/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
  30. ciocore/docsite/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
  31. ciocore/docsite/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
  32. ciocore/docsite/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
  33. ciocore/docsite/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
  34. ciocore/docsite/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
  35. ciocore/docsite/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
  36. ciocore/docsite/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
  37. ciocore/docsite/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
  38. ciocore/docsite/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
  39. ciocore/docsite/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
  40. ciocore/docsite/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
  41. ciocore/docsite/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
  42. ciocore/docsite/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
  43. ciocore/docsite/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
  44. ciocore/docsite/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
  45. ciocore/docsite/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
  46. ciocore/docsite/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
  47. ciocore/docsite/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
  48. ciocore/docsite/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
  49. ciocore/docsite/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
  50. ciocore/docsite/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
  51. ciocore/docsite/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
  52. ciocore/docsite/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
  53. ciocore/docsite/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
  54. ciocore/docsite/assets/javascripts/lunr/tinyseg.js +206 -0
  55. ciocore/docsite/assets/javascripts/lunr/wordcut.js +6708 -0
  56. ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js +42 -0
  57. ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js.map +7 -0
  58. ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css +1 -0
  59. ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
  60. ciocore/docsite/assets/stylesheets/palette.06af60db.min.css +1 -0
  61. ciocore/docsite/assets/stylesheets/palette.06af60db.min.css.map +1 -0
  62. ciocore/docsite/cmdline/docs/index.html +871 -0
  63. ciocore/docsite/cmdline/downloader/index.html +934 -0
  64. ciocore/docsite/cmdline/packages/index.html +878 -0
  65. ciocore/docsite/cmdline/uploader/index.html +995 -0
  66. ciocore/docsite/how-to-guides/index.html +869 -0
  67. ciocore/docsite/index.html +895 -0
  68. ciocore/docsite/logo.png +0 -0
  69. ciocore/docsite/objects.inv +0 -0
  70. ciocore/docsite/search/search_index.json +1 -0
  71. ciocore/docsite/sitemap.xml +3 -0
  72. ciocore/docsite/sitemap.xml.gz +0 -0
  73. ciocore/docsite/stylesheets/extra.css +26 -0
  74. ciocore/docsite/stylesheets/tables.css +167 -0
  75. ciocore/downloader/base_downloader.py +644 -0
  76. ciocore/downloader/download_runner_base.py +47 -0
  77. ciocore/downloader/job_downloader.py +119 -0
  78. ciocore/{downloader.py → downloader/legacy_downloader.py} +12 -9
  79. ciocore/downloader/log.py +73 -0
  80. ciocore/downloader/logging_download_runner.py +87 -0
  81. ciocore/downloader/perpetual_downloader.py +63 -0
  82. ciocore/downloader/registry.py +97 -0
  83. ciocore/downloader/reporter.py +135 -0
  84. ciocore/exceptions.py +8 -2
  85. ciocore/file_utils.py +51 -50
  86. ciocore/hardware_set.py +449 -0
  87. ciocore/loggeria.py +89 -20
  88. ciocore/package_environment.py +110 -48
  89. ciocore/package_query.py +182 -0
  90. ciocore/package_tree.py +319 -258
  91. ciocore/retry.py +0 -0
  92. ciocore/uploader/_uploader.py +547 -364
  93. ciocore/uploader/thread_queue_job.py +176 -0
  94. ciocore/uploader/upload_stats/__init__.py +3 -4
  95. ciocore/uploader/upload_stats/stats_formats.py +10 -4
  96. ciocore/validator.py +34 -2
  97. ciocore/worker.py +174 -151
  98. ciocore-10.0.0b3.dist-info/METADATA +928 -0
  99. ciocore-10.0.0b3.dist-info/RECORD +128 -0
  100. {ciocore-5.1.1.dist-info → ciocore-10.0.0b3.dist-info}/WHEEL +1 -1
  101. ciocore-10.0.0b3.dist-info/entry_points.txt +2 -0
  102. tests/instance_type_fixtures.py +175 -0
  103. tests/package_fixtures.py +205 -0
  104. tests/test_api_client.py +297 -12
  105. tests/test_base_downloader.py +104 -0
  106. tests/test_cli.py +149 -0
  107. tests/test_common.py +1 -7
  108. tests/test_config.py +40 -18
  109. tests/test_data.py +162 -173
  110. tests/test_downloader.py +118 -0
  111. tests/test_hardware_set.py +139 -0
  112. tests/test_job_downloader.py +213 -0
  113. tests/test_package_query.py +38 -0
  114. tests/test_package_tree.py +91 -291
  115. tests/test_submit.py +44 -18
  116. tests/test_uploader.py +1 -4
  117. ciocore/__about__.py +0 -10
  118. ciocore/cli/conductor.py +0 -191
  119. ciocore/compat.py +0 -15
  120. ciocore-5.1.1.data/scripts/conductor +0 -19
  121. ciocore-5.1.1.data/scripts/conductor.bat +0 -13
  122. ciocore-5.1.1.dist-info/METADATA +0 -408
  123. ciocore-5.1.1.dist-info/RECORD +0 -47
  124. tests/mocks/api_client_mock.py +0 -51
  125. /ciocore/{cli → downloader}/__init__.py +0 -0
  126. {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(ciocore.common.CONDUCTOR_LOGGER_NAME))
12
+ logger = logging.getLogger("{}.uploader.worker".format(
13
+ ciocore.loggeria.CONDUCTOR_LOGGER_NAME))
14
14
 
15
- # This is used to signal to workers if work should continue or not
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(target=self.target, name=self.__class__.__name__)
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)', self.__class__.__name__, len(self.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. ({}-{}). {} items left.".format(self.__class__.__name__, self, self.in_queue.qsize()))
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 ({}-{}). {} items left.".format(self.__class__.__name__, self, self.in_queue.qsize()))
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 {} from in_queue ({}-{}). {} items left.".format(job, self.__class__.__name__, self, self.in_queue.qsize()))
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 ({}-{}). {} items left.".format(self.__class__.__name__, self, self.in_queue.qsize()))
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
- if self._job_counter.value > 0:
149
- logger.debug("Worker has completed all of its tasks.".format(job))
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
- else:
164
+
165
+ elif self._job_counter.value == 0:
154
166
  logger.debug("Worker waiting for first job")
155
- continue
156
-
157
- logger.debug("Worker got job {}".format(job))
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 '{}' #{} on {}. {} tasks remaining in queue".format( job,
160
- self._job_counter.value,
161
- self,
162
- queue_size))
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.exception('CAUGHT EXCEPTION on job "{}" [{}]":\n'.format(job, self))
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 not self.error_queue:
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('[thread %s]+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=', thread_int)
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 {} completed".format(self))
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(target=self.target, args=(thread_int,), name=name)
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("Attempting to put job to out_queue ({} -> {})".format(job,self, self.out_queue))
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 ({} -> {})".format(job,self, self.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(target=self.target, name=self.__class__.__name__)
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] = {'bytes_to_upload': 0, 'bytes_uploaded': 0, 'already_uploaded': False}
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
- self.metric_store['files'][filename]['already_uploaded'] = step_size # True/False
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={}".format(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.error('draining queues')
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.error('clearing out all tasks')
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) # Wait to ensure the worker was killed
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, 2)
480
-
509
+ error = self.error_queue.get(True, 0.5)
510
+
481
511
  except queue.Empty:
482
- continue
483
-
484
- logger.error('Got something from the error queue: {}'.format(error))
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(target=self.error_handler_target, name="ErrorThread")
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
- self.work_queues[0].put(task)
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
- if last_worker == worker_class:
541
- # the last worker does not need an output queue
542
- kwargs['out_queue'] = None
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 = '\n' + '#' * 80 + '\n'
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
- # thread.isAlive() was renamed to is_alive() in Python 3.9
599
- try:
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 {} is complete: {}".format(worker.__class__.__name__, worker.is_complete()))
616
- is_complete &= worker.is_complete()
617
-
618
- logger.debug("All Workers have completed: {}".format(is_complete))
619
-
620
- return is_complete
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