Commit 4c3b2d61 authored by Jeremy Hylton's avatar Jeremy Hylton

Factor out some startup code to util module.

Add a couple of simple tests that make sure that start.py script
runs.  The tests are meager -- most of the possible arguments are
untested -- and only run on Unix.
parent 614533db
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Start the server storage. """Start the server storage.
$Id: start.py,v 1.37 2002/07/25 23:08:33 jeremy Exp $ $Id: start.py,v 1.38 2002/08/01 18:50:28 jeremy Exp $
""" """
from __future__ import nested_scopes from __future__ import nested_scopes
...@@ -30,7 +30,7 @@ def directory(p, n=1): ...@@ -30,7 +30,7 @@ def directory(p, n=1):
return d return d
def get_storage(m, n, cache={}): def get_storage(m, n, cache={}):
p=sys.path p = sys.path
d, m = os.path.split(m) d, m = os.path.split(m)
if m.endswith('.py'): if m.endswith('.py'):
m = m[:-3] m = m[:-3]
...@@ -102,6 +102,8 @@ def main(argv): ...@@ -102,6 +102,8 @@ def main(argv):
global LOG, INFO, ERROR global LOG, INFO, ERROR
from zLOG import LOG, INFO, ERROR, PANIC from zLOG import LOG, INFO, ERROR, PANIC
from ZEO.util import Environment
env = Environment(me)
# XXX hack for profiling support # XXX hack for profiling support
global unix, storages, zeo_pid, asyncore global unix, storages, zeo_pid, asyncore
...@@ -116,23 +118,6 @@ def main(argv): ...@@ -116,23 +118,6 @@ def main(argv):
args.append(a) args.append(a)
last = a last = a
if os.environ.has_key('INSTANCE_HOME'):
INSTANCE_HOME = os.environ['INSTANCE_HOME']
elif os.path.isdir(os.path.join(directory(me, 4),'var')):
INSTANCE_HOME = directory(me, 4)
else:
INSTANCE_HOME = os.getcwd()
if os.path.isdir(os.path.join(INSTANCE_HOME, 'var')):
var = os.path.join(INSTANCE_HOME, 'var')
else:
var = INSTANCE_HOME
zeo_pid = os.environ.get('ZEO_SERVER_PID',
os.path.join(var, 'ZEO_SERVER.pid'))
fs = os.path.join(var, 'Data.fs')
usage="""%s [options] [filename] usage="""%s [options] [filename]
where options are: where options are:
...@@ -175,7 +160,7 @@ def main(argv): ...@@ -175,7 +160,7 @@ def main(argv):
-s flag. -s flag.
if no file name is specified, then %s is used. if no file name is specified, then %s is used.
""" % (me, fs) """ % (me, env.fs)
try: try:
opts, args = getopt.getopt(args, 'p:Dh:U:sS:u:P:d') opts, args = getopt.getopt(args, 'p:Dh:U:sS:u:P:d')
...@@ -192,6 +177,7 @@ def main(argv): ...@@ -192,6 +177,7 @@ def main(argv):
UID = 'nobody' UID = 'nobody'
prof = None prof = None
detailed = 0 detailed = 0
fs = None
for o, v in opts: for o, v in opts:
if o =='-p': if o =='-p':
port = int(v) port = int(v)
...@@ -225,7 +211,6 @@ def main(argv): ...@@ -225,7 +211,6 @@ def main(argv):
sys.exit(1) sys.exit(1)
fs = args[0] fs = args[0]
## __builtins__.__debug__ = debug
if debug: if debug:
os.environ['Z_DEBUG_MODE'] = '1' os.environ['Z_DEBUG_MODE'] = '1'
if detailed: if detailed:
...@@ -259,8 +244,8 @@ def main(argv): ...@@ -259,8 +244,8 @@ def main(argv):
storages[n]=get_storage(m,a) storages[n]=get_storage(m,a)
if not storages: if not storages:
import ZODB.FileStorage from ZODB.FileStorage import FileStorage
storages['1']=ZODB.FileStorage.FileStorage(fs) storages['1'] = FileStorage(fs or env.fs)
# Try to set up a signal handler # Try to set up a signal handler
setup_signals(storages) setup_signals(storages)
...@@ -280,7 +265,7 @@ def main(argv): ...@@ -280,7 +265,7 @@ def main(argv):
except: except:
pass # getpid not supported pass # getpid not supported
else: else:
open(zeo_pid,'w').write("%s %s" % (ppid, pid)) open(env.zeo_pid,'w').write("%s %s" % (ppid, pid))
except: except:
# Log startup exception and tell zdaemon not to restart us. # Log startup exception and tell zdaemon not to restart us.
...@@ -324,6 +309,7 @@ def rotate_logs_handler(signum, frame): ...@@ -324,6 +309,7 @@ def rotate_logs_handler(signum, frame):
signal.signal(signal.SIGHUP, rotate_logs_handler) signal.signal(signal.SIGHUP, rotate_logs_handler)
def shutdown(storages, die=1): def shutdown(storages, die=1):
LOG("ZEO Server", INFO, "Received signal")
import asyncore import asyncore
# Do this twice, in case we got some more connections # Do this twice, in case we got some more connections
...@@ -343,7 +329,6 @@ def shutdown(storages, die=1): ...@@ -343,7 +329,6 @@ def shutdown(storages, die=1):
pass pass
try: try:
from zLOG import LOG, INFO
s = die and "shutdown" or "restart" s = die and "shutdown" or "restart"
LOG('ZEO Server', INFO, "Shutting down (%s)" % s) LOG('ZEO Server', INFO, "Shutting down (%s)" % s)
except: except:
......
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import os
import signal
import sys
import tempfile
import time
import unittest
import ZEO.start
from ZEO.ClientStorage import ClientStorage
from ZEO.util import Environment
class StartTests(unittest.TestCase):
cmd = "%s %s" % (sys.executable, ZEO.start.__file__)
if cmd[-1] == "c":
cmd = cmd[:-1]
def setUp(self):
self.pids = {}
self.env = Environment(self.cmd)
def tearDown(self):
try:
self.stop_server()
self.shutdown()
finally:
for ext in "", ".index", ".tmp", ".lock", ".old":
f = "Data.fs" + ext
try:
os.remove(f)
except os.error:
pass
try:
os.remove(self.env.zeo_pid)
except os.error:
pass
def stop_server(self):
if not os.path.exists(self.env.zeo_pid):
# If there's no pid file, assume the server isn't running
return
ppid, pid = map(int, open(self.env.zeo_pid).read().split())
self.kill(pids=[pid])
def kill(self, sig=signal.SIGTERM, pids=None):
if pids is None:
pids = self.pids
for pid in pids:
try:
os.kill(pid, sig)
except os.error, err:
print err
def wait(self, flag=0, pids=None):
if pids is None:
pids = self.pids
alive = []
for pid in self.pids:
try:
_pid, status = os.waitpid(pid, flag)
except os.error, err:
if err[0] == 10:
continue
print err
else:
if status == 0:
alive.append(pid)
return alive
def shutdown(self):
# XXX This is probably too complicated, but I'm not sure what
# the right thing to do is.
alive = self.wait(os.WNOHANG)
if not alive:
return
self.kill(pids=alive)
alive = self.wait(os.WNOHANG, alive)
if not alive:
return
self.kill(signal.SIGKILL, pids=alive)
alive = self.wait(pids=alive)
def fork(self, *args):
file = tempfile.mktemp()
pid = os.fork()
if pid:
self.pids[pid] = file
return file
else:
try:
f = os.popen(self.cmd + " " + " ".join(args))
buf = f.read()
f.close()
f = open(file, "wb")
f.write(buf)
f.close()
finally:
os._exit(0)
def system(self, *args):
file = self.fork(*args)
self.wait()
f = open(file, "rb")
buf = f.read()
f.close()
return buf
def connect(self, port=None, wait=1):
cs = ClientStorage(('', port), wait=wait)
cs.close()
def testNoPort(self):
outp = self.system("-s")
self.assert_(outp.find("No port specified") != -1)
def testStart(self):
port = 9090
outp = self.fork("-s", "-p", str(port))
self.connect(port=port)
def test_suite():
if os.name == "posix":
return unittest.makeSuite(StartTests)
else:
# Don't even bother with these tests on Windows
return None
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Utilities for setting up the server environment."""
import os
def parentdir(p, n=1):
"""Return the parent of p, n levels up."""
d = p
while n:
d = os.path.split(d)[0]
if not d or d == '.':
d = os.getcwd()
n -= 1
return d
class Environment:
def __init__(self, argv0):
v = os.environ.get("INSTANCE_HOME")
if v is None:
# looking for a Zope/var directory assuming that this code
# is installed in Zope/lib/python/ZEO
p = parentdir(argv0, 4)
if os.path.isdir(os.path.join(p, "var")):
v = p
else:
v = os.getcwd()
self.home = v
self.var = os.path.join(v, "var")
if not os.path.isdir(self.var):
self.var = self.home
pid = os.environ.get("ZEO_SERVER_PID")
if pid is None:
pid = os.path.join(v, "ZEO_SERVER.pid")
self.zeo_pid = pid
self.fs = os.path.join(self.var, "Data.fs")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment