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 @@
##############################################################################
"""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
......@@ -30,7 +30,7 @@ def directory(p, n=1):
return d
def get_storage(m, n, cache={}):
p=sys.path
p = sys.path
d, m = os.path.split(m)
if m.endswith('.py'):
m = m[:-3]
......@@ -102,6 +102,8 @@ def main(argv):
global LOG, INFO, ERROR
from zLOG import LOG, INFO, ERROR, PANIC
from ZEO.util import Environment
env = Environment(me)
# XXX hack for profiling support
global unix, storages, zeo_pid, asyncore
......@@ -116,23 +118,6 @@ def main(argv):
args.append(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]
where options are:
......@@ -175,7 +160,7 @@ def main(argv):
-s flag.
if no file name is specified, then %s is used.
""" % (me, fs)
""" % (me, env.fs)
try:
opts, args = getopt.getopt(args, 'p:Dh:U:sS:u:P:d')
......@@ -192,6 +177,7 @@ def main(argv):
UID = 'nobody'
prof = None
detailed = 0
fs = None
for o, v in opts:
if o =='-p':
port = int(v)
......@@ -225,7 +211,6 @@ def main(argv):
sys.exit(1)
fs = args[0]
## __builtins__.__debug__ = debug
if debug:
os.environ['Z_DEBUG_MODE'] = '1'
if detailed:
......@@ -259,8 +244,8 @@ def main(argv):
storages[n]=get_storage(m,a)
if not storages:
import ZODB.FileStorage
storages['1']=ZODB.FileStorage.FileStorage(fs)
from ZODB.FileStorage import FileStorage
storages['1'] = FileStorage(fs or env.fs)
# Try to set up a signal handler
setup_signals(storages)
......@@ -280,7 +265,7 @@ def main(argv):
except:
pass # getpid not supported
else:
open(zeo_pid,'w').write("%s %s" % (ppid, pid))
open(env.zeo_pid,'w').write("%s %s" % (ppid, pid))
except:
# Log startup exception and tell zdaemon not to restart us.
......@@ -324,6 +309,7 @@ def rotate_logs_handler(signum, frame):
signal.signal(signal.SIGHUP, rotate_logs_handler)
def shutdown(storages, die=1):
LOG("ZEO Server", INFO, "Received signal")
import asyncore
# Do this twice, in case we got some more connections
......@@ -343,7 +329,6 @@ def shutdown(storages, die=1):
pass
try:
from zLOG import LOG, INFO
s = die and "shutdown" or "restart"
LOG('ZEO Server', INFO, "Shutting down (%s)" % s)
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