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:
Shane Hathaway 2010-09-30 10:17:16 +00:00
parent d517455956
commit 1b6b36e029
7 changed files with 52 additions and 40 deletions

View File

@ -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)
-------------------- --------------------

View File

@ -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

View File

@ -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)))

View File

@ -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

View File

@ -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(),

View File

@ -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.

View File

@ -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