remove relative imports. new close function

This commit is contained in:
Benoit Chesneau 2010-01-18 04:18:25 +01:00
parent 4e6f60f4d8
commit 4bfdd60501
9 changed files with 56 additions and 37 deletions

View File

@ -34,7 +34,7 @@ import socket
import sys import sys
import time import time
from .worker import Worker from gunicorn.worker import Worker
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -122,17 +122,18 @@ class Arbiter(object):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_sockopts(sock) self.set_sockopts(sock)
sock.bind(address) sock.bind(address)
sock.listen(2048) sock.listen(1024)
return sock return sock
def set_sockopts(self, sock): def set_sockopts(self, sock):
sock.setblocking(0) sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 0) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
if hasattr(socket, "TCP_CORK"): if hasattr(socket, "TCP_CORK"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1)
elif hasattr(socket, "TCP_NOPUSH"): elif hasattr(socket, "TCP_NOPUSH"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NOPUSH, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NOPUSH, 1)
def run(self): def run(self):
self.manage_workers() self.manage_workers()

View File

@ -24,5 +24,5 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE. # OTHER DEALINGS IN THE SOFTWARE.
from request import HTTPRequest, RequestError from gunicorn.http.request import HTTPRequest, RequestError
from response import HTTPResponse from gunicorn.http.response import HTTPResponse

View File

@ -22,7 +22,6 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE. # OTHER DEALINGS IN THE SOFTWARE.
from ctypes import *
class HttpParser(object): class HttpParser(object):
@ -35,7 +34,8 @@ class HttpParser(object):
def headers(self, headers, buf): def headers(self, headers, buf):
""" take a string buff. It return """ take a string buff. It return
environ or None if parsing isn't done. new position or -1 if parsing isn't done.
headers dict is updated.
""" """
if self._headers: if self._headers:
return self._headers return self._headers
@ -53,6 +53,7 @@ class HttpParser(object):
return -1 return -1
def finalize_headers(self, headers, headers_str, pos): def finalize_headers(self, headers, headers_str, pos):
""" parse the headers """
lines = headers_str.split("\r\n") lines = headers_str.split("\r\n")
# parse first line of headers # parse first line of headers
@ -75,12 +76,14 @@ class HttpParser(object):
return pos return pos
def _first_line(self, line): def _first_line(self, line):
""" parse first line """
method, path, version = line.strip().split(" ") method, path, version = line.strip().split(" ")
self.version = version.strip() self.version = version.strip()
self.method = method.upper() self.method = method.upper()
self.path = path self.path = path
def _parse_headerl(self, line): def _parse_headerl(self, line):
""" parse header line"""
name, value = line.split(": ", 1) name, value = line.split(": ", 1)
name = name.strip() name = name.strip()
self._headers[name] = value.strip() self._headers[name] = value.strip()
@ -99,11 +102,14 @@ class HttpParser(object):
@property @property
def is_chunked(self): def is_chunked(self):
""" is TE: chunked ?"""
transfert_encoding = self._headers.get('Transfer-Encoding', False) transfert_encoding = self._headers.get('Transfer-Encoding', False)
return (transfert_encoding == "chunked") return (transfert_encoding == "chunked")
@property @property
def content_len(self): def content_len(self):
""" return content length as integer or
None."""
transfert_encoding = self._headers.get('Transfer-Encoding') transfert_encoding = self._headers.get('Transfer-Encoding')
content_length = self._headers.get('Content-Length') content_length = self._headers.get('Content-Length')
if transfert_encoding is None: if transfert_encoding is None:
@ -114,6 +120,7 @@ class HttpParser(object):
return None return None
def body_eof(self): def body_eof(self):
"""do we have all the body ?"""
#TODO : add chunk #TODO : add chunk
if self._content_len == 0: if self._content_len == 0:
return True return True
@ -122,7 +129,7 @@ class HttpParser(object):
def read_chunk(self, data): def read_chunk(self, data):
dlen = len(data) dlen = len(data)
i = data.find("\n") i = data.find("\n")
if i != -1: if i != -1:
chunk = data[:i].strip().split(";", 1) chunk = data[:i].strip().split(";", 1)
chunk_size = int(line.pop(0), 16) chunk_size = int(line.pop(0), 16)
if chunk_size <= 0: if chunk_size <= 0:
@ -131,6 +138,11 @@ class HttpParser(object):
self.start_offset = i+1 self.start_offset = i+1
def filter_body(self, data): def filter_body(self, data):
""" filter body and return a tuple:
body_chunk, new_buffer. They could be None.
new_fubber is always None if it's empty.
"""
dlen = len(data) dlen = len(data)
chunk = None chunk = None
if self.is_chunked: if self.is_chunked:
@ -138,10 +150,9 @@ class HttpParser(object):
else: else:
if self._content_len > 0: if self._content_len > 0:
nr = min(dlen, self._content_len) nr = min(dlen, self._content_len)
print nr
chunk = data[:nr] chunk = data[:nr]
self._content_len -= nr self._content_len -= nr
data = None data = None
self.start_offset = 0 self.start_offset = 0
return chunk, data return (chunk, data)

View File

@ -35,9 +35,9 @@ import array
import logging import logging
from gunicorn import __version__ from gunicorn import __version__
from .http_parser import HttpParser from gunicorn.http.http_parser import HttpParser
from .tee import TeeInput from gunicorn.http.tee import TeeInput
from ..util import CHUNK_SIZE, read_partial from gunicorn.util import CHUNK_SIZE, read_partial
NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+')
@ -80,8 +80,7 @@ class HTTPRequest(object):
buf += data buf += data
i = self.parser.headers(headers, buf) i = self.parser.headers(headers, buf)
if i != -1: break if i != -1: break
if not buf:
self.socket.close()
if not headers: if not headers:
return {} return {}

View File

@ -26,15 +26,17 @@
import errno import errno
import socket import socket
import select
import time import time
from ..util import http_date, write, read_partial import os
from gunicorn.util import http_date, write, read_partial, close
class HTTPResponse(object): class HTTPResponse(object):
def __init__(self, sock, response, req): def __init__(self, sock, response, req):
self.req = req self.req = req
self.sock = sock self.sock = sock.dup()
self.data = response self.data = response
self.headers = req.response_headers or {} self.headers = req.response_headers or {}
self.status = req.response_status self.status = req.response_status
@ -58,8 +60,9 @@ class HTTPResponse(object):
for chunk in self.data: for chunk in self.data:
write(self.sock, chunk) write(self.sock, chunk)
self.sock.close()
close(self.sock)
if hasattr(self.data, "close"): if hasattr(self.data, "close"):
self.data.close() self.data.close()

View File

@ -34,9 +34,8 @@ read or restart etc ... It's based on TeeInput from unicorn.
import os import os
import StringIO import StringIO
import tempfile import tempfile
from ctypes import create_string_buffer
from ..util import MAX_BODY, CHUNK_SIZE from gunicorn.util import MAX_BODY, CHUNK_SIZE
class TeeInput(object): class TeeInput(object):
@ -121,8 +120,7 @@ class TeeInput(object):
break break
line = self.readline() line = self.readline()
return lines return lines
def next(self): def next(self):
r = self.readline() r = self.readline()
if not r: if not r:

View File

@ -29,7 +29,7 @@ import optparse as op
import os import os
import sys import sys
from arbiter import Arbiter from gunicorn.arbiter import Arbiter
LOG_LEVELS = { LOG_LEVELS = {
"critical": logging.CRITICAL, "critical": logging.CRITICAL,

View File

@ -42,12 +42,22 @@ monthname = [None,
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def close(sock):
try:
sock.shutdown(2)
except socket.error:
pass
try:
sock.close()
except socket.error:
pass
def read_partial(sock, length): def read_partial(sock, length):
while True: while True:
try: try:
ret = select.select([sock.fileno()], [], [], 2.0) ret = select.select([sock.fileno()], [], [], 2.0)
if ret[0]: break if ret[0]: break
except socket.error, e: except select.error, e:
if e[0] == errno.EINTR: if e[0] == errno.EINTR:
break break
raise raise
@ -70,7 +80,6 @@ def write_nonblock(sock, data):
if ret[1]: break if ret[1]: break
except socket.error, e: except socket.error, e:
if e[0] == errno.EINTR: if e[0] == errno.EINTR:
time.sleep(1)
break break
raise raise
write(sock, data) write(sock, data)

View File

@ -35,8 +35,8 @@ import sys
import tempfile import tempfile
import time import time
from . import http from gunicorn import http
from . import util from gunicorn import util
class Worker(object): class Worker(object):
@ -96,7 +96,7 @@ class Worker(object):
while self.alive: while self.alive:
try: try:
ret = select.select([self.socket], [], [], 2.0) ret = select.select([self.socket], [], [], 15)
if ret[0]: if ret[0]:
break break
except select.error, e: except select.error, e:
@ -115,11 +115,7 @@ class Worker(object):
# loop and wait for some lovin. # loop and wait for some lovin.
while self.alive: while self.alive:
try: try:
res = self.socket.accept() client, addr = self.socket.accept()
if res is None:
break
client, addr = res
client.setblocking(0)
# handle connection # handle connection
self.handle(client, addr) self.handle(client, addr)
@ -143,5 +139,7 @@ class Worker(object):
except Exception, e: except Exception, e:
self.log.exception("Error processing request. [%s]" % str(e)) self.log.exception("Error processing request. [%s]" % str(e))
msg = "HTTP/1.0 500 Internal Server Error\r\n\r\n" msg = "HTTP/1.0 500 Internal Server Error\r\n\r\n"
util.write_nonblock(client, msg) #util.write_nonblock(client, msg)
client.close() util.close(client)
del client