Skip to content

Commit 8c01c67

Browse files
committed
use Condition instead of Event for periodic event
1 parent b833880 commit 8c01c67

File tree

1 file changed

+66
-37
lines changed

1 file changed

+66
-37
lines changed

docker/start.py

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# CDDL HEADER END
1919

2020
#
21-
# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
21+
# Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
2222
#
2323

2424
import os
@@ -76,16 +76,58 @@
7676

7777
expected_token = None
7878

79-
sleep_event = threading.Event()
79+
80+
class PeriodicTimer:
81+
"""
82+
Helper class to facilitate waiting for periodic events.
83+
Requires the start() function to be called first.
84+
"""
85+
def __init__(self, interval):
86+
"""
87+
:param interval: interval in seconds
88+
"""
89+
self._interval = interval
90+
self._flag = 0
91+
self._cv = threading.Condition()
92+
93+
def start(self):
94+
threading.Thread(target=self.run, daemon=True).start()
95+
96+
def run(self):
97+
"""
98+
Run the timer and notify waiting threads after each interval
99+
"""
100+
while True:
101+
time.sleep(self._interval)
102+
self.notify_all()
103+
104+
def wait_for_tick(self):
105+
"""
106+
Wait for the next tick of the timer
107+
"""
108+
with self._cv:
109+
last_flag = self._flag
110+
while last_flag == self._flag:
111+
self._cv.wait()
112+
113+
def notify_all(self):
114+
"""
115+
Notify all listeners, possibly out of band.
116+
"""
117+
with self._cv:
118+
self._flag ^= 1
119+
self._cv.notify_all()
120+
121+
122+
periodic_timer = None
80123
app = Flask(__name__)
81124
auth = HTTPTokenAuth(scheme='Bearer')
82125
REINDEX_POINT = '/reindex'
83126

84127

85128
def trigger_reindex():
86129
# Signal the sync/indexer thread.
87-
sleep_event.set()
88-
sleep_event.clear()
130+
periodic_timer.notify_all()
89131

90132

91133
@auth.verify_token
@@ -100,7 +142,7 @@ def verify_token(token):
100142
@app.route(REINDEX_POINT)
101143
@auth.login_required
102144
def index():
103-
trigger_reindex()
145+
periodic_timer.notify_all()
104146

105147
return "Reindex triggered"
106148

@@ -193,7 +235,7 @@ def setup_redirect_source(logger, url_root):
193235
def wait_for_tomcat(logger, uri):
194236
"""
195237
Active/busy waiting for Tomcat to come up.
196-
Currently there is no upper time bound.
238+
Currently, there is no upper time bound.
197239
"""
198240
logger.info("Waiting for Tomcat to start")
199241

@@ -299,16 +341,7 @@ def indexer_no_projects(logger, uri, config_path, extra_indexer_options):
299341
indexer.execute()
300342

301343
logger.info("Waiting for reindex to be triggered")
302-
sleep_event.wait()
303-
304-
305-
def timeout_loop(logger, sync_period):
306-
while True:
307-
sleep_seconds = sync_period * 60
308-
logger.info("Sleeping for {} seconds".format(sleep_seconds))
309-
time.sleep(sleep_seconds)
310-
311-
trigger_reindex()
344+
periodic_timer.wait_for_tick()
312345

313346

314347
def project_syncer(logger, loglevel, uri, config_path, numworkers, env):
@@ -357,7 +390,7 @@ def project_syncer(logger, loglevel, uri, config_path, numworkers, env):
357390
save_config(logger, uri, config_path)
358391

359392
logger.info("Waiting for reindex to be triggered")
360-
sleep_event.wait()
393+
periodic_timer.wait_for_tick()
361394

362395

363396
def create_bare_config(logger, use_projects, extra_indexer_options=None):
@@ -412,7 +445,7 @@ def check_index_and_wipe_out(logger):
412445
"""
413446
Check index by running the indexer. If the index does not match
414447
currently running version and the CHECK_INDEX environment variable
415-
is non empty, wipe out the directories under data root.
448+
is non-empty, wipe out the directories under data root.
416449
"""
417450
check_index = os.environ.get('CHECK_INDEX')
418451
if check_index and os.path.exists(OPENGROK_CONFIG_FILE):
@@ -430,8 +463,8 @@ def check_index_and_wipe_out(logger):
430463
try:
431464
logger.info("Removing '{}'".format(path))
432465
shutil.rmtree(path)
433-
except Exception as e:
434-
logger.error("cannot delete '{}': {}".format(path, e))
466+
except Exception as exc:
467+
logger.error("cannot delete '{}': {}".format(path, exc))
435468

436469

437470
def start_rest_thread(logger):
@@ -451,14 +484,6 @@ def start_rest_thread(logger):
451484
rest_thread.start()
452485

453486

454-
def start_timeout_thread(logger, sync_period):
455-
logger.debug("Starting timeout thread")
456-
thread = threading.Thread(target=timeout_loop,
457-
name="Timeout thread",
458-
args=(logger, sync_period), daemon=True)
459-
thread.start()
460-
461-
462487
def main():
463488
log_level = os.environ.get('OPENGROK_LOG_LEVEL')
464489
if log_level:
@@ -479,11 +504,11 @@ def main():
479504
logger.debug("URL_ROOT = {}".format(url_root))
480505
logger.debug("URI = {}".format(uri))
481506

482-
sync_period = get_num_from_env(logger, 'SYNC_PERIOD_MINUTES', 10)
483-
if sync_period == 0:
507+
sync_period_mins = get_num_from_env(logger, 'SYNC_PERIOD_MINUTES', 10)
508+
if sync_period_mins == 0:
484509
logger.info("periodic synchronization disabled")
485510
else:
486-
logger.info("synchronization period = {} minutes".format(sync_period))
511+
logger.info("synchronization period = {} minutes".format(sync_period_mins))
487512

488513
# Note that deploy is done before Tomcat is started.
489514
deploy(logger, url_root)
@@ -505,15 +530,15 @@ def main():
505530
use_projects = False
506531

507532
#
508-
# Create empty configuration to avoid the non existent file exception
533+
# Create empty configuration to avoid the non-existent file exception
509534
# in the web app during the first web app startup.
510535
#
511536
if not os.path.exists(OPENGROK_CONFIG_FILE) or \
512537
os.path.getsize(OPENGROK_CONFIG_FILE) == 0:
513538
create_bare_config(logger, use_projects, extra_indexer_options.split())
514539

515540
#
516-
# Index check needs read-only configuration so it is placed
541+
# Index check needs read-only configuration, so it is called
517542
# right after create_bare_config().
518543
#
519544
check_index_and_wipe_out(logger)
@@ -579,8 +604,11 @@ def main():
579604
sync_thread.start()
580605

581606
start_rest_thread(logger)
582-
if sync_period > 0:
583-
start_timeout_thread(logger, sync_period)
607+
608+
if sync_period_mins > 0:
609+
global periodic_timer
610+
periodic_timer = PeriodicTimer(sync_period_mins * 60)
611+
periodic_timer.start()
584612

585613
# Start Tomcat last. It will be the foreground process.
586614
logger.info("Starting Tomcat")
@@ -595,8 +623,9 @@ def signal_handler(signum, frame):
595623
print("Received signal {}".format(signum))
596624

597625
global tomcat_popen
598-
print("Terminating Tomcat {}".format(tomcat_popen))
599-
tomcat_popen.terminate()
626+
if tomcat_popen:
627+
print("Terminating Tomcat {}".format(tomcat_popen))
628+
tomcat_popen.terminate()
600629

601630
sys.exit(0)
602631

0 commit comments

Comments
 (0)