Prep for 1.4.0:
- Enabled ketama and compression in pylibmc_wrapper. Both options are better for clusters. - Oracle: Use a more optimal query for POSKeyError logging. - Fixed a NameError that occurred when getting the history of an object where transaction extended info was set.
This commit is contained in:
parent
d517455956
commit
1b6b36e029
12
CHANGES.txt
12
CHANGES.txt
|
@ -1,4 +1,16 @@
|
||||||
|
|
||||||
|
1.4.0 (2010-09-30)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Enabled ketama and compression in pylibmc_wrapper. Both options
|
||||||
|
are better for clusters.
|
||||||
|
|
||||||
|
- Oracle: Use a more optimal query for POSKeyError logging.
|
||||||
|
|
||||||
|
- Fixed a NameError that occurred when getting the history of an
|
||||||
|
object where transaction extended info was set.
|
||||||
|
|
||||||
|
|
||||||
1.4.0c4 (2010-09-17)
|
1.4.0c4 (2010-09-17)
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,3 @@
|
||||||
[buildout]
|
[buildout]
|
||||||
extends = buildout.cfg
|
extends = buildout.cfg
|
||||||
parts = cx_Oracle ${buildout:base-parts}
|
|
||||||
eggs += cx_Oracle
|
eggs += cx_Oracle
|
||||||
oracle_home = /usr/lib/oracle/xe/app/oracle/product/10.2.0/server
|
|
||||||
|
|
||||||
[cx_Oracle]
|
|
||||||
recipe = zc.recipe.egg:custom
|
|
||||||
environment = oracle-env
|
|
||||||
rpath = ${buildout:oracle_home}/lib
|
|
||||||
|
|
||||||
[oracle-env]
|
|
||||||
ORACLE_HOME = ${buildout:oracle_home}
|
|
||||||
|
|
||||||
[test]
|
|
||||||
environment = oracle-env
|
|
||||||
|
|
||||||
[test-coverage]
|
|
||||||
environment = oracle-env
|
|
||||||
|
|
|
@ -105,14 +105,12 @@ class MySQLTransactionControl(TransactionControl):
|
||||||
|
|
||||||
def get_tid(self, cursor):
|
def get_tid(self, cursor):
|
||||||
"""Returns the most recent tid."""
|
"""Returns the most recent tid."""
|
||||||
# Lock in share mode to ensure the data being read is up to date.
|
|
||||||
if self.keep_history:
|
if self.keep_history:
|
||||||
stmt = """
|
stmt = """
|
||||||
SELECT tid
|
SELECT tid
|
||||||
FROM transaction
|
FROM transaction
|
||||||
ORDER BY tid DESC
|
ORDER BY tid DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
LOCK IN SHARE MODE
|
|
||||||
"""
|
"""
|
||||||
cursor.execute(stmt)
|
cursor.execute(stmt)
|
||||||
else:
|
else:
|
||||||
|
@ -121,7 +119,6 @@ class MySQLTransactionControl(TransactionControl):
|
||||||
FROM object_state
|
FROM object_state
|
||||||
ORDER BY tid DESC
|
ORDER BY tid DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
LOCK IN SHARE MODE
|
|
||||||
"""
|
"""
|
||||||
cursor.execute(stmt)
|
cursor.execute(stmt)
|
||||||
if not cursor.rowcount:
|
if not cursor.rowcount:
|
||||||
|
@ -210,4 +207,3 @@ class OracleTransactionControl(TransactionControl):
|
||||||
cursor.execute(stmt, (
|
cursor.execute(stmt, (
|
||||||
tid, packed and 'Y' or 'N', self.Binary(username),
|
tid, packed and 'Y' or 'N', self.Binary(username),
|
||||||
self.Binary(description), self.Binary(extension)))
|
self.Binary(description), self.Binary(extension)))
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,18 @@ from _pylibmc import MemcachedError # pylibmc >= 0.9
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
|
behaviors = {
|
||||||
|
"tcp_nodelay": True,
|
||||||
|
"ketama": True,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, servers):
|
def __init__(self, servers):
|
||||||
self._client = pylibmc.Client(servers, binary=True)
|
self._client = pylibmc.Client(servers, binary=True)
|
||||||
self._client.set_behaviors({
|
self._client.set_behaviors(self.behaviors)
|
||||||
"tcp_nodelay": True,
|
if pylibmc.support_compression:
|
||||||
#"no block": True,
|
self.min_compress_len = 1000
|
||||||
#"buffer requests": True,
|
else:
|
||||||
})
|
self.min_compress_len = 0
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
try:
|
try:
|
||||||
|
@ -45,19 +49,22 @@ class Client(object):
|
||||||
|
|
||||||
def set(self, key, value):
|
def set(self, key, value):
|
||||||
try:
|
try:
|
||||||
return self._client.set(key, value)
|
return self._client.set(
|
||||||
|
key, value, min_compress_len=self.min_compress_len)
|
||||||
except MemcachedError:
|
except MemcachedError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_multi(self, d):
|
def set_multi(self, d):
|
||||||
try:
|
try:
|
||||||
return self._client.set_multi(d)
|
return self._client.set_multi(
|
||||||
|
d, min_compress_len=self.min_compress_len)
|
||||||
except MemcachedError:
|
except MemcachedError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def add(self, key, value):
|
def add(self, key, value):
|
||||||
try:
|
try:
|
||||||
return self._client.add(key, value)
|
return self._client.add(
|
||||||
|
key, value, min_compress_len=self.min_compress_len)
|
||||||
except MemcachedError:
|
except MemcachedError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -72,4 +79,3 @@ class Client(object):
|
||||||
self._client.flush_all()
|
self._client.flush_all()
|
||||||
except MemcachedError:
|
except MemcachedError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ from ZODB.UndoLogCompatible import UndoLogCompatible
|
||||||
from ZODB.utils import p64
|
from ZODB.utils import p64
|
||||||
from ZODB.utils import u64
|
from ZODB.utils import u64
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.interface import Interface
|
|
||||||
import base64
|
import base64
|
||||||
import cPickle
|
import cPickle
|
||||||
import logging
|
import logging
|
||||||
|
@ -399,18 +398,14 @@ class RelStorage(
|
||||||
msg = ["POSKeyError on oid %d: %s" % (oid_int, reason)]
|
msg = ["POSKeyError on oid %d: %s" % (oid_int, reason)]
|
||||||
|
|
||||||
if adapter.keep_history:
|
if adapter.keep_history:
|
||||||
rows = adapter.dbiter.iter_transactions(cursor)
|
tid = adapter.txncontrol.get_tid(cursor)
|
||||||
row = None
|
if not tid:
|
||||||
for row in rows:
|
|
||||||
# just get the first row
|
|
||||||
break
|
|
||||||
if not row:
|
|
||||||
# This happens when initializing a new database or
|
# This happens when initializing a new database or
|
||||||
# after packing, so it's not a warning.
|
# after packing, so it's not a warning.
|
||||||
logfunc = log.debug
|
logfunc = log.debug
|
||||||
msg.append("No previous transactions exist")
|
msg.append("No previous transactions exist")
|
||||||
else:
|
else:
|
||||||
msg.append("Current transaction is %d" % row[0])
|
msg.append("Current transaction is %d" % tid)
|
||||||
|
|
||||||
tids = []
|
tids = []
|
||||||
try:
|
try:
|
||||||
|
@ -980,7 +975,7 @@ class RelStorage(
|
||||||
for tid_int, username, description, extension, length in rows:
|
for tid_int, username, description, extension, length in rows:
|
||||||
tid = p64(tid_int)
|
tid = p64(tid_int)
|
||||||
if extension:
|
if extension:
|
||||||
d = loads(extension)
|
d = cPickle.loads(extension)
|
||||||
else:
|
else:
|
||||||
d = {}
|
d = {}
|
||||||
d.update({"time": TimeStamp(tid).timeTime(),
|
d.update({"time": TimeStamp(tid).timeTime(),
|
||||||
|
|
|
@ -459,6 +459,25 @@ class GenericRelStorageTests(
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
def checkHistoryWithExtension(self):
|
||||||
|
# Verify the history method works with transactions that have
|
||||||
|
# extended info.
|
||||||
|
db = DB(self._storage)
|
||||||
|
try:
|
||||||
|
conn = db.open()
|
||||||
|
try:
|
||||||
|
conn.root()['pi'] = 3.14
|
||||||
|
transaction.get().setExtendedInfo("digits", 3)
|
||||||
|
transaction.commit()
|
||||||
|
history = self._storage.history(conn.root()._p_oid)
|
||||||
|
self.assertEqual(len(history), 1)
|
||||||
|
if self.keep_history:
|
||||||
|
self.assertEqual(history[0]['digits'], 3)
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
def checkPackDutyCycle(self):
|
def checkPackDutyCycle(self):
|
||||||
# Exercise the code in the pack algorithm that releases the
|
# Exercise the code in the pack algorithm that releases the
|
||||||
# commit lock for a time to allow concurrent transactions to commit.
|
# commit lock for a time to allow concurrent transactions to commit.
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -13,7 +13,7 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
"""A backend for ZODB that stores pickles in a relational database."""
|
"""A backend for ZODB that stores pickles in a relational database."""
|
||||||
|
|
||||||
VERSION = "1.4.0c4"
|
VERSION = "1.4.0"
|
||||||
|
|
||||||
# The choices for the Trove Development Status line:
|
# The choices for the Trove Development Status line:
|
||||||
# Development Status :: 5 - Production/Stable
|
# Development Status :: 5 - Production/Stable
|
||||||
|
@ -21,7 +21,7 @@ VERSION = "1.4.0c4"
|
||||||
# Development Status :: 3 - Alpha
|
# Development Status :: 3 - Alpha
|
||||||
|
|
||||||
classifiers = """\
|
classifiers = """\
|
||||||
Development Status :: 4 - Beta
|
Development Status :: 5 - Production/Stable
|
||||||
Intended Audience :: Developers
|
Intended Audience :: Developers
|
||||||
License :: OSI Approved :: Zope Public License
|
License :: OSI Approved :: Zope Public License
|
||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
|
|
Loading…
Reference in New Issue