|
|
403b09 |
From 1aa300c53f070436888150ae582dad23cddac03b Mon Sep 17 00:00:00 2001
|
|
|
403b09 |
From: David Kupka <dkupka@redhat.com>
|
|
|
403b09 |
Date: Mon, 15 Aug 2016 08:01:59 +0200
|
|
|
403b09 |
Subject: [PATCH] schema cache: Store API schema cache in memory
|
|
|
403b09 |
|
|
|
403b09 |
Read whole cache into memory and keep it there for lifetime of api
|
|
|
403b09 |
object. This removes the need to repetitively open/close the cache and
|
|
|
403b09 |
speeds up every access to it.
|
|
|
403b09 |
|
|
|
403b09 |
https://fedorahosted.org/freeipa/ticket/6048
|
|
|
403b09 |
|
|
|
403b09 |
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
|
|
|
403b09 |
---
|
|
|
403b09 |
ipaclient/remote_plugins/schema.py | 51 +++++++++++++++++++++-----------------
|
|
|
403b09 |
1 file changed, 28 insertions(+), 23 deletions(-)
|
|
|
403b09 |
|
|
|
403b09 |
diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
index aadc891750782b0961bc46989e3693d1d3ed0ecb..2fc6cce3eca392447cd4230216900116002934f4 100644
|
|
|
403b09 |
--- a/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
+++ b/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
@@ -3,6 +3,7 @@
|
|
|
403b09 |
#
|
|
|
403b09 |
|
|
|
403b09 |
import collections
|
|
|
403b09 |
+import contextlib
|
|
|
403b09 |
import errno
|
|
|
403b09 |
import fcntl
|
|
|
403b09 |
import json
|
|
|
403b09 |
@@ -315,24 +316,6 @@ class _SchemaObjectPlugin(_SchemaPlugin):
|
|
|
403b09 |
schema_key = 'classes'
|
|
|
403b09 |
|
|
|
403b09 |
|
|
|
403b09 |
-class _LockedZipFile(zipfile.ZipFile):
|
|
|
403b09 |
- """ Add locking to zipfile.ZipFile
|
|
|
403b09 |
- Shared lock is used with read mode, exclusive with write mode.
|
|
|
403b09 |
- """
|
|
|
403b09 |
- def __enter__(self):
|
|
|
403b09 |
- if 'r' in self.mode:
|
|
|
403b09 |
- fcntl.flock(self.fp, fcntl.LOCK_SH)
|
|
|
403b09 |
- elif 'w' in self.mode or 'a' in self.mode:
|
|
|
403b09 |
- fcntl.flock(self.fp, fcntl.LOCK_EX)
|
|
|
403b09 |
-
|
|
|
403b09 |
- return super(_LockedZipFile, self).__enter__()
|
|
|
403b09 |
-
|
|
|
403b09 |
- def __exit__(self, type_, value, traceback):
|
|
|
403b09 |
- fcntl.flock(self.fp, fcntl.LOCK_UN)
|
|
|
403b09 |
-
|
|
|
403b09 |
- return super(_LockedZipFile, self).__exit__(type_, value, traceback)
|
|
|
403b09 |
-
|
|
|
403b09 |
-
|
|
|
403b09 |
class _SchemaNameSpace(collections.Mapping):
|
|
|
403b09 |
|
|
|
403b09 |
def __init__(self, schema, name):
|
|
|
403b09 |
@@ -450,6 +433,7 @@ class Schema(object):
|
|
|
403b09 |
self._dict = {}
|
|
|
403b09 |
self._namespaces = {}
|
|
|
403b09 |
self._help = None
|
|
|
403b09 |
+ self._file = six.StringIO()
|
|
|
403b09 |
|
|
|
403b09 |
for ns in self.namespaces:
|
|
|
403b09 |
self._dict[ns] = {}
|
|
|
403b09 |
@@ -486,9 +470,20 @@ class Schema(object):
|
|
|
403b09 |
except AttributeError:
|
|
|
403b09 |
pass
|
|
|
403b09 |
|
|
|
403b09 |
- def _open_schema(self, filename, mode):
|
|
|
403b09 |
+ @contextlib.contextmanager
|
|
|
403b09 |
+ def _open(self, filename, mode):
|
|
|
403b09 |
path = os.path.join(self._DIR, filename)
|
|
|
403b09 |
- return _LockedZipFile(path, mode)
|
|
|
403b09 |
+
|
|
|
403b09 |
+ with open(path, mode) as f:
|
|
|
403b09 |
+ if mode.startswith('r'):
|
|
|
403b09 |
+ fcntl.flock(f, fcntl.LOCK_SH)
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ fcntl.flock(f, fcntl.LOCK_EX)
|
|
|
403b09 |
+
|
|
|
403b09 |
+ try:
|
|
|
403b09 |
+ yield f
|
|
|
403b09 |
+ finally:
|
|
|
403b09 |
+ fcntl.flock(f, fcntl.LOCK_UN)
|
|
|
403b09 |
|
|
|
403b09 |
def _fetch(self, client):
|
|
|
403b09 |
if not client.isconnected():
|
|
|
403b09 |
@@ -523,7 +518,11 @@ class Schema(object):
|
|
|
403b09 |
self._expiration = ttl + time.time()
|
|
|
403b09 |
|
|
|
403b09 |
def _read_schema(self):
|
|
|
403b09 |
- with self._open_schema(self._fingerprint, 'r') as schema:
|
|
|
403b09 |
+ self._file.truncate(0)
|
|
|
403b09 |
+ with self._open(self._fingerprint, 'r') as f:
|
|
|
403b09 |
+ self._file.write(f.read())
|
|
|
403b09 |
+
|
|
|
403b09 |
+ with zipfile.ZipFile(self._file, 'r') as schema:
|
|
|
403b09 |
self._dict['fingerprint'] = self._fingerprint
|
|
|
403b09 |
|
|
|
403b09 |
for name in schema.namelist():
|
|
|
403b09 |
@@ -566,7 +565,8 @@ class Schema(object):
|
|
|
403b09 |
logger.warning("Failed to write schema: {}".format(e))
|
|
|
403b09 |
return
|
|
|
403b09 |
|
|
|
403b09 |
- with self._open_schema(self._fingerprint, 'w') as schema:
|
|
|
403b09 |
+ self._file.truncate(0)
|
|
|
403b09 |
+ with zipfile.ZipFile(self._file, 'w', zipfile.ZIP_DEFLATED) as schema:
|
|
|
403b09 |
for key, value in self._dict.items():
|
|
|
403b09 |
if key in self.namespaces:
|
|
|
403b09 |
ns = value
|
|
|
403b09 |
@@ -579,8 +579,13 @@ class Schema(object):
|
|
|
403b09 |
schema.writestr('_help',
|
|
|
403b09 |
json.dumps(self._generate_help(self._dict)))
|
|
|
403b09 |
|
|
|
403b09 |
+ self._file.seek(0)
|
|
|
403b09 |
+ with self._open(self._fingerprint, 'w') as f:
|
|
|
403b09 |
+ f.truncate(0)
|
|
|
403b09 |
+ f.write(self._file.read())
|
|
|
403b09 |
+
|
|
|
403b09 |
def _read(self, path):
|
|
|
403b09 |
- with self._open_schema(self._fingerprint, 'r') as zf:
|
|
|
403b09 |
+ with zipfile.ZipFile(self._file, 'r') as zf:
|
|
|
403b09 |
return json.loads(zf.read(path))
|
|
|
403b09 |
|
|
|
403b09 |
def read_namespace_member(self, namespace, member):
|
|
|
403b09 |
--
|
|
|
403b09 |
2.7.4
|
|
|
403b09 |
|