Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fast file transfers, part 1: Provide a file wrapper.

  • Loading branch information...
commit 8773d32fa581a827df3767d706eb5a6d421210cb 1 parent 02d1599
Jonas Haag authored
7  bjoern/bjoernmodule.c
@@ -2,6 +2,7 @@
2 2
 #include "server.h"
3 3
 #include "wsgi.h"
4 4
 #include "bjoernmodule.h"
  5
+#include "filewrapper.h"
5 6
 
6 7
 
7 8
 PyDoc_STRVAR(listen_doc,
@@ -78,9 +79,13 @@ static PyMethodDef Bjoern_FunctionTable[] = {
78 79
 
79 80
 PyMODINIT_FUNC initbjoern()
80 81
 {
  82
+  _init_common();
  83
+  _init_filewrapper();
  84
+
  85
+  PyType_Ready(&FileWrapper_Type);
  86
+  assert(FileWrapper_Type.tp_flags & Py_TPFLAGS_READY);
81 87
   PyType_Ready(&StartResponse_Type);
82 88
   assert(StartResponse_Type.tp_flags & Py_TPFLAGS_READY);
83  
-  _initialize_static_strings();
84 89
 
85 90
   PyObject* bjoern_module = Py_InitModule("bjoern", Bjoern_FunctionTable);
86 91
   PyModule_AddObject(bjoern_module, "version", Py_BuildValue("(iii)", 1, 1, 1));
2  bjoern/common.c
@@ -26,7 +26,7 @@ size_t unquote_url_inplace(char* url, size_t len)
26 26
   return len;
27 27
 }
28 28
 
29  
-void _initialize_static_strings()
  29
+void _init_common()
30 30
 {
31 31
   #define _(name) _##name = PyString_FromString(#name)
32 32
   _(REMOTE_ADDR); _(PATH_INFO); _(QUERY_STRING); _(close);
7  bjoern/common.h
@@ -7,12 +7,17 @@
7 7
 #include <stdbool.h>
8 8
 #include <string.h>
9 9
 
  10
+#define TYPE_ERROR_INNER(what, expected, ...) \
  11
+  PyErr_Format(PyExc_TypeError, what " must be " expected " " __VA_ARGS__)
  12
+#define TYPE_ERROR(what, expected, got) \
  13
+  TYPE_ERROR_INNER(what, expected, "(got '%.200s' object instead)", Py_TYPE(got)->tp_name)
  14
+
10 15
 typedef struct { char* data; size_t len; } string;
11 16
 
12 17
 enum http_status { HTTP_BAD_REQUEST = 1, HTTP_LENGTH_REQUIRED, HTTP_SERVER_ERROR };
13 18
 
14 19
 size_t unquote_url_inplace(char* url, size_t len);
15  
-void _initialize_static_strings();
  20
+void (_init_common)();
16 21
 
17 22
 PyObject *_REMOTE_ADDR, *_PATH_INFO, *_QUERY_STRING, *_REQUEST_METHOD, *_GET,
18 23
          *_HTTP_CONTENT_LENGTH, *_CONTENT_LENGTH, *_HTTP_CONTENT_TYPE, *_CONTENT_TYPE,
52  bjoern/filewrapper.c
... ...
@@ -0,0 +1,52 @@
  1
+#include "filewrapper.h"
  2
+
  3
+static PyObject*
  4
+FileWrapper_New(PyObject* self, PyObject* args, PyObject* kwargs)
  5
+{
  6
+  PyObject* file;
  7
+  if(!PyArg_ParseTuple(args, "O:FileWrapper", &file))
  8
+    return NULL;
  9
+  if(!PyFile_Check(file)) {
  10
+    TYPE_ERROR("FileWrapper argument", "file", file);
  11
+    return NULL;
  12
+  }
  13
+  Py_INCREF(file);
  14
+  FileWrapper* wrapper = PyObject_NEW(FileWrapper, &FileWrapper_Type);
  15
+  wrapper->file = file;
  16
+  return (PyObject*)wrapper;
  17
+}
  18
+
  19
+static PyObject*
  20
+FileWrapper_GetAttrO(PyObject* self, PyObject* name)
  21
+{
  22
+  return PyObject_GetAttr(((FileWrapper*)self)->file, name);
  23
+}
  24
+
  25
+static PyObject*
  26
+FileWrapper_Iter(PyObject* self)
  27
+{
  28
+  return PyObject_GetIter(((FileWrapper*)self)->file);
  29
+}
  30
+
  31
+static void
  32
+FileWrapper_dealloc(PyObject* self)
  33
+{
  34
+  Py_DECREF(((FileWrapper*)self)->file);
  35
+  PyObject_FREE(self);
  36
+}
  37
+
  38
+PyTypeObject FileWrapper_Type = {
  39
+  PyVarObject_HEAD_INIT(NULL, 0)
  40
+  "FileWrapper",                    /* tp_name (__name__)                     */
  41
+  sizeof(FileWrapper),              /* tp_basicsize                           */
  42
+  0,                                /* tp_itemsize                            */
  43
+  (destructor)FileWrapper_dealloc,  /* tp_dealloc                             */
  44
+};
  45
+
  46
+void _init_filewrapper()
  47
+{
  48
+  FileWrapper_Type.tp_new = FileWrapper_New;
  49
+  FileWrapper_Type.tp_iter = FileWrapper_Iter;
  50
+  FileWrapper_Type.tp_getattro = FileWrapper_GetAttrO;
  51
+  FileWrapper_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
  52
+}
10  bjoern/filewrapper.h
... ...
@@ -0,0 +1,10 @@
  1
+#include "common.h"
  2
+
  3
+PyTypeObject FileWrapper_Type;
  4
+
  5
+typedef struct {
  6
+  PyObject_HEAD
  7
+  PyObject* file;
  8
+} FileWrapper;
  9
+
  10
+void (_init_filewrapper)();
8  bjoern/request.c
... ...
@@ -1,6 +1,7 @@
1 1
 #include <Python.h>
2 2
 #include <cStringIO.h>
3 3
 #include "request.h"
  4
+#include "filewrapper.h"
4 5
 
5 6
 static inline void PyDict_ReplaceKey(PyObject* dict, PyObject* k1, PyObject* k2);
6 7
 static PyObject* wsgi_http_header(string header);
@@ -287,6 +288,13 @@ void _initialize_request_module(const char* server_host, const int server_port)
287 288
     PycString_IMPORT;
288 289
     wsgi_base_dict = PyDict_New();
289 290
 
  291
+    /* dct['wsgi.file_wrapper'] = FileWrapper */
  292
+    PyDict_SetItemString(
  293
+      wsgi_base_dict,
  294
+      "wsgi.file_wrapper",
  295
+      (PyObject*)&FileWrapper_Type
  296
+    );
  297
+
290 298
     /* dct['SCRIPT_NAME'] = '' */
291 299
     PyDict_SetItemString(
292 300
       wsgi_base_dict,
8  bjoern/wsgi.c
@@ -2,11 +2,6 @@
2 2
 #include "bjoernmodule.h"
3 3
 #include "wsgi.h"
4 4
 
5  
-#define TYPE_ERROR_INNER(what, expected, ...) \
6  
-  PyErr_Format(PyExc_TypeError, what " must be " expected " " __VA_ARGS__)
7  
-#define TYPE_ERROR(what, expected, got) \
8  
-  TYPE_ERROR_INNER(what, expected, "(got '%.200s' object instead)", Py_TYPE(got)->tp_name)
9  
-
10 5
 static PyObject* (start_response)(PyObject* self, PyObject* args, PyObject *kwargs);
11 6
 static size_t wsgi_getheaders(Request*, PyObject* buf);
12 7
 static inline bool inspect_headers(Request*);
@@ -327,8 +322,7 @@ start_response(PyObject* self, PyObject* args, PyObject* kwargs)
327 322
 }
328 323
 
329 324
 PyTypeObject StartResponse_Type = {
330  
-  PyObject_HEAD_INIT(NULL)
331  
-  0,                          /* ob_size (deprecated)                       */
  325
+  PyVarObject_HEAD_INIT(NULL, 0)
332 326
   "start_response",           /* tp_name (__name__)                         */
333 327
   sizeof(StartResponse),      /* tp_basicsize                               */
334 328
   0,                          /* tp_itemsize                                */

0 notes on commit 8773d32

Please sign in to comment.
Something went wrong with that request. Please try again.