The Identity, Policy and Audit system
CentOS Sources
2016-11-03 403b09ab980c02ef36095973349a13e0181c794a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
From 1aa300c53f070436888150ae582dad23cddac03b Mon Sep 17 00:00:00 2001
From: David Kupka <dkupka@redhat.com>
Date: Mon, 15 Aug 2016 08:01:59 +0200
Subject: [PATCH] schema cache: Store API schema cache in memory
 
Read whole cache into memory and keep it there for lifetime of api
object. This removes the need to repetitively open/close the cache and
speeds up every access to it.
 
https://fedorahosted.org/freeipa/ticket/6048
 
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
---
 ipaclient/remote_plugins/schema.py | 51 +++++++++++++++++++++-----------------
 1 file changed, 28 insertions(+), 23 deletions(-)
 
diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py
index aadc891750782b0961bc46989e3693d1d3ed0ecb..2fc6cce3eca392447cd4230216900116002934f4 100644
--- a/ipaclient/remote_plugins/schema.py
+++ b/ipaclient/remote_plugins/schema.py
@@ -3,6 +3,7 @@
 #
 
 import collections
+import contextlib
 import errno
 import fcntl
 import json
@@ -315,24 +316,6 @@ class _SchemaObjectPlugin(_SchemaPlugin):
     schema_key = 'classes'
 
 
-class _LockedZipFile(zipfile.ZipFile):
-    """ Add locking to zipfile.ZipFile
-    Shared lock is used with read mode, exclusive with write mode.
-    """
-    def __enter__(self):
-        if 'r' in self.mode:
-            fcntl.flock(self.fp, fcntl.LOCK_SH)
-        elif 'w' in self.mode or 'a' in self.mode:
-            fcntl.flock(self.fp, fcntl.LOCK_EX)
-
-        return super(_LockedZipFile, self).__enter__()
-
-    def __exit__(self, type_, value, traceback):
-        fcntl.flock(self.fp, fcntl.LOCK_UN)
-
-        return super(_LockedZipFile, self).__exit__(type_, value, traceback)
-
-
 class _SchemaNameSpace(collections.Mapping):
 
     def __init__(self, schema, name):
@@ -450,6 +433,7 @@ class Schema(object):
         self._dict = {}
         self._namespaces = {}
         self._help = None
+        self._file = six.StringIO()
 
         for ns in self.namespaces:
             self._dict[ns] = {}
@@ -486,9 +470,20 @@ class Schema(object):
             except AttributeError:
                 pass
 
-    def _open_schema(self, filename, mode):
+    @contextlib.contextmanager
+    def _open(self, filename, mode):
         path = os.path.join(self._DIR, filename)
-        return _LockedZipFile(path, mode)
+
+        with open(path, mode) as f:
+            if mode.startswith('r'):
+                fcntl.flock(f, fcntl.LOCK_SH)
+            else:
+                fcntl.flock(f, fcntl.LOCK_EX)
+
+            try:
+                yield f
+            finally:
+                fcntl.flock(f, fcntl.LOCK_UN)
 
     def _fetch(self, client):
         if not client.isconnected():
@@ -523,7 +518,11 @@ class Schema(object):
         self._expiration = ttl + time.time()
 
     def _read_schema(self):
-        with self._open_schema(self._fingerprint, 'r') as schema:
+        self._file.truncate(0)
+        with self._open(self._fingerprint, 'r') as f:
+            self._file.write(f.read())
+
+        with zipfile.ZipFile(self._file, 'r') as schema:
             self._dict['fingerprint'] = self._fingerprint
 
             for name in schema.namelist():
@@ -566,7 +565,8 @@ class Schema(object):
                 logger.warning("Failed to write schema: {}".format(e))
                 return
 
-        with self._open_schema(self._fingerprint, 'w') as schema:
+        self._file.truncate(0)
+        with zipfile.ZipFile(self._file, 'w', zipfile.ZIP_DEFLATED) as schema:
             for key, value in self._dict.items():
                 if key in self.namespaces:
                     ns = value
@@ -579,8 +579,13 @@ class Schema(object):
             schema.writestr('_help',
                             json.dumps(self._generate_help(self._dict)))
 
+        self._file.seek(0)
+        with self._open(self._fingerprint, 'w') as f:
+            f.truncate(0)
+            f.write(self._file.read())
+
     def _read(self, path):
-        with self._open_schema(self._fingerprint, 'r') as zf:
+        with zipfile.ZipFile(self._file, 'r') as zf:
             return json.loads(zf.read(path))
 
     def read_namespace_member(self, namespace, member):
-- 
2.7.4