Commit b09c876e authored by Aurel's avatar Aurel

redefine handler

merge loadBefore with other load in client part
first version for undo method


git-svn-id: https://svn.erp5.org/repos/neo/branches/prototype3@62 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 06b23421
...@@ -3,15 +3,15 @@ import os ...@@ -3,15 +3,15 @@ import os
from time import time from time import time
from threading import Lock, Condition from threading import Lock, Condition
from cPickle import dumps, loads from cPickle import dumps, loads
from zlib import compress, alder32, decompress from zlib import compress, adler32, decompress
from neo.client.mq import MQ from neo.client.mq import MQ
from neo.node import NodeManager, MasterNode from neo.node import NodeManager, MasterNode
from neo.event import EventManager from neo.event import EventManager
from neo.connection import ListeningConnection, ClientConnection from neo.connection import ListeningConnection, ClientConnection
from neo.protocol import Packet, INVALID_UUID, CLIENT_NODE_TYPE, UP_TO_DATE_STATE from neo.protocol import Packet, INVALID_UUID, CLIENT_NODE_TYPE, UP_TO_DATE_STATE
from neo.client.master import MasterEventHandler from neo.client.handler import ClientEventHandler
from neo.client.NEOStorage import NEOStorageConflictError, NEOStorageKeyError from neo.client.NEOStorage import NEOStorageConflictError, NEOStorageNotFoundError
class ConnectionManager(object): class ConnectionManager(object):
"""This class manage a pool of connection to storage node.""" """This class manage a pool of connection to storage node."""
...@@ -27,15 +27,15 @@ class ConnectionManager(object): ...@@ -27,15 +27,15 @@ class ConnectionManager(object):
l = Lock() l = Lock()
self.connection_lock_acquire = l.acquire self.connection_lock_acquire = l.acquire
self.connection_lock_release = l.release self.connection_lock_release = l.release
def _initNodeConnection(self, addr): def _initNodeConnection(self, addr):
"""Init a connection to a given storage node.""" """Init a connection to a given storage node."""
handler = StorageEventHandler(self.storage) handler = ClientEventHandler(self.storage)
conn = ClientConnection(self.storage.em, handler, addr) conn = ClientConnection(self.storage.em, handler, addr)
msg_id = conn.getNextId() msg_id = conn.getNextId()
p = Packet() p = Packet()
p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid, addr[0], p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid, addr[0],
addr[1], 'main') addr[1], self.storage.name)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
while 1: while 1:
self.em.poll(1) self.em.poll(1)
...@@ -43,7 +43,7 @@ class ConnectionManager(object): ...@@ -43,7 +43,7 @@ class ConnectionManager(object):
break break
logging.debug('connected to a storage node %s' %(addr,)) logging.debug('connected to a storage node %s' %(addr,))
return conn return conn
def _dropConnection(self,): def _dropConnection(self,):
"""Drop a connection.""" """Drop a connection."""
pass pass
...@@ -78,19 +78,20 @@ class ConnectionManager(object): ...@@ -78,19 +78,20 @@ class ConnectionManager(object):
else: else:
# Create new connection to node # Create new connection to node
return self._createNodeConnection(node) return self._createNodeConnection(node)
class Application(object): class Application(object):
"""The client node application.""" """The client node application."""
def __init__(self, master_addr, master_port, **kw): def __init__(self, master_addr, master_port, name, **kw):
logging.basicConfig(level = logging.DEBUG) logging.basicConfig(level = logging.DEBUG)
logging.debug('master node address is %s, port is %d' %(master_addr, master_port)) logging.debug('master node address is %s, port is %d' %(master_addr, master_port))
# Internal Attributes # Internal Attributes
self.name = name
self.em = EventManager() self.em = EventManager()
self.nm = NodeManager() self.nm = NodeManager()
self.cm = ConnectionManager(self) self.cm = ConnectionManager(self)
self.pt = None self.pt = None
self.primary_master_node = None self.primary_master_node = None
self.master_conn = None self.master_conn = None
...@@ -107,8 +108,8 @@ class Application(object): ...@@ -107,8 +108,8 @@ class Application(object):
# object_stored is used to know if storage node # object_stored is used to know if storage node
# accepted the object or raised a conflict # accepted the object or raised a conflict
# 0 : no answer yet # 0 : no answer yet
# 1 : ok # -1 : conflict
# 2 : conflict # oid, serial : ok
self.object_stored = 0 self.object_stored = 0
# Lock definition : # Lock definition :
# _oid_lock is used in order to not call multiple oid # _oid_lock is used in order to not call multiple oid
...@@ -121,7 +122,7 @@ class Application(object): ...@@ -121,7 +122,7 @@ class Application(object):
# _info_lock is used when retrieving information for object or transaction # _info_lock is used when retrieving information for object or transaction
lock = Lock() lock = Lock()
self._oid_lock_acquire = lock.acquire self._oid_lock_acquire = lock.acquire
self._oid_lock_release = lock.release self._oid_lock_release = lock.release
lock = Lock() lock = Lock()
self._txn_lock_acquire = lock.acquire self._txn_lock_acquire = lock.acquire
self._txn_lock_release = lock.release self._txn_lock_release = lock.release
...@@ -147,7 +148,7 @@ class Application(object): ...@@ -147,7 +148,7 @@ class Application(object):
defined_master_addr = (master_addr, master_port) defined_master_addr = (master_addr, master_port)
while 1: while 1:
self.node_not_ready = 0 self.node_not_ready = 0
logging.debug("trying to connect to primary master...") logging.debug("trying to connect to primary master...")
self.connectToPrimaryMasterNode(defined_master_addr) self.connectToPrimaryMasterNode(defined_master_addr)
if not self.node_not_ready and self.pt.filled(): if not self.node_not_ready and self.pt.filled():
# got a connection and partition table # got a connection and partition table
...@@ -161,7 +162,7 @@ class Application(object): ...@@ -161,7 +162,7 @@ class Application(object):
def connectToPrimaryMasterNode(self, defined_master_addr): def connectToPrimaryMasterNode(self, defined_master_addr):
"""Connect to the primary master node.""" """Connect to the primary master node."""
handler = MasterEventHandler(self) handler = ClientEventHandler(self)
n = MasterNode(server = defined_master_addr) n = MasterNode(server = defined_master_addr)
self.nm.add(n) self.nm.add(n)
...@@ -172,7 +173,7 @@ class Application(object): ...@@ -172,7 +173,7 @@ class Application(object):
p = Packet() p = Packet()
p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid, p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid,
defined_master_addr[0], defined_master_addr[0],
defined_master_addr[1], 'main') defined_master_addr[1], self.name)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
while 1: while 1:
...@@ -195,7 +196,7 @@ class Application(object): ...@@ -195,7 +196,7 @@ class Application(object):
p = Packet() p = Packet()
p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid, p.requestNodeIdentification(msg_id, CLIENT_NODE_TYPE, self.uuid,
self.primary_master_node.server[0], self.primary_master_node.server[0],
self.primary_master_node.server[1] , 'main') self.primary_master_node.server[1] , self.name)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
self.master_conn = conn self.master_conn = conn
...@@ -242,9 +243,9 @@ class Application(object): ...@@ -242,9 +243,9 @@ class Application(object):
if len(hist) == 0: if len(hist) == 0:
raise NEOStorageNotFoundError() raise NEOStorageNotFoundError()
return hist[0][0] return hist[0][0]
def _load(self, oid, serial="", cache=0): def _load(self, oid, serial="", cache=0):
"""Internal method which manage load and loadSerial.""" """Internal method which manage load ,loadSerial and loadBefore."""
partition_id = oid % self.num_paritions partition_id = oid % self.num_paritions
# Only used up to date node for retrieving object # Only used up to date node for retrieving object
storage_node_list = [x for x in self.pt.getCellList(partition_id, True) \ storage_node_list = [x for x in self.pt.getCellList(partition_id, True) \
...@@ -259,7 +260,7 @@ class Application(object): ...@@ -259,7 +260,7 @@ class Application(object):
p.askObjectByOID(msg_id, oid, serial) p.askObjectByOID(msg_id, oid, serial)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
# Wait for answer # Wait for answer
self.loaded_object = None self.loaded_object = None
try: try:
while 1: while 1:
...@@ -270,7 +271,7 @@ class Application(object): ...@@ -270,7 +271,7 @@ class Application(object):
# OID not found # OID not found
continue continue
# Copy object data here to release lock as soon as possible # Copy object data here to release lock as soon as possible
noid, serial, compression, checksum, data = self.loaded_object noid, start_serial, end_serial, compression, checksum, data = self.loaded_object
finally: finally:
self._load_lock_release() self._load_lock_release()
# Check data here # Check data here
...@@ -281,7 +282,7 @@ class Application(object): ...@@ -281,7 +282,7 @@ class Application(object):
# Reacquire lock and try again # Reacquire lock and try again
self._load_lock_acquire() self._load_lock_acquire()
continue continue
elif compression and checksum != alder32(data): elif compression and checksum != adler32(data):
# Check checksum if we use compression # Check checksum if we use compression
logging.error('wrong checksum from node %s for oid %s' \ logging.error('wrong checksum from node %s for oid %s' \
%(storage_node.getServer(), oid)) %(storage_node.getServer(), oid))
...@@ -300,10 +301,10 @@ class Application(object): ...@@ -300,10 +301,10 @@ class Application(object):
if cache: if cache:
self.cache_lock_acquire() self.cache_lock_acquire()
try: try:
self.cache[oid] = serial, data self.cache[oid] = start_serial, data
finally: finally:
self.cache_lock_release() self.cache_lock_release()
return loads(data), serial return loads(data), start_serial, end_serial
def load(self, oid, version=None): def load(self, oid, version=None):
"""Load an object for a given oid.""" """Load an object for a given oid."""
...@@ -315,13 +316,18 @@ class Application(object): ...@@ -315,13 +316,18 @@ class Application(object):
finally: finally:
self._cache_lock_release() self._cache_lock_release()
# Otherwise get it from storage node # Otherwise get it from storage node
return self._load(oid, cache=1) return self._load(oid, cache=1)[:2]
def loadSerial(self, oid, serial): def loadSerial(self, oid, serial):
"""Load an object for a given oid and serial.""" """Load an object for a given oid and serial."""
# Do not try in cache as it managed only up-to-date object # Do not try in cache as it managed only up-to-date object
return self._load(oid, serial), None return self._load(oid, serial)[:2], None
def loadBefore(oid, tid):
"""Load an object for a given oid before tid committed."""
# Do not try in cache as it managed only up-to-date object
return self._load(oid, tid)
def tpc_begin(self, transaction, tid=None, status=' '): def tpc_begin(self, transaction, tid=None, status=' '):
"""Begin a new transaction.""" """Begin a new transaction."""
# First get a transaction, only one is allowed at a time # First get a transaction, only one is allowed at a time
...@@ -341,7 +347,7 @@ class Application(object): ...@@ -341,7 +347,7 @@ class Application(object):
p.askNewTID(msg_id) p.askNewTID(msg_id)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
# Wait for answer # Wait for answer
while 1: while 1:
self.em.poll(1) self.em.poll(1)
if self.tid is not None: if self.tid is not None:
...@@ -359,7 +365,7 @@ class Application(object): ...@@ -359,7 +365,7 @@ class Application(object):
# Store data on each node # Store data on each node
ddata = dumps(data) ddata = dumps(data)
compressed_data = compress(ddata) compressed_data = compress(ddata)
crc = alder32(compressed_data) crc = adler32(compressed_data)
for storage_node in storage_node_list: for storage_node in storage_node_list:
conn = self.cm.getConnForNode(storage_node.getUUID()) conn = self.cm.getConnForNode(storage_node.getUUID())
msg_id = conn.getNextId() msg_id = conn.getNextId()
...@@ -390,7 +396,7 @@ class Application(object): ...@@ -390,7 +396,7 @@ class Application(object):
# Store object in tmp cache # Store object in tmp cache
self.txn_data_dict[oid] = ddata self.txn_data_dict[oid] = ddata
break break
def tpc_vote(self, transaction): def tpc_vote(self, transaction):
"""Store current transaction.""" """Store current transaction."""
if transaction is not self.txn: if transaction is not self.txn:
...@@ -418,7 +424,7 @@ class Application(object): ...@@ -418,7 +424,7 @@ class Application(object):
"""Clear some transaction parameter and release lock.""" """Clear some transaction parameter and release lock."""
self.txn = None self.txn = None
self._txn_lock_release() self._txn_lock_release()
def tpc_abort(self, transaction): def tpc_abort(self, transaction):
"""Abort current transaction.""" """Abort current transaction."""
if transaction is not self.txn: if transaction is not self.txn:
...@@ -426,7 +432,7 @@ class Application(object): ...@@ -426,7 +432,7 @@ class Application(object):
try: try:
# Abort transaction on each node used for it # Abort transaction on each node used for it
# In node where objects were stored # In node where objects were stored
aborted_node = {} aborted_node = {}
for oid in self.txn_oid_list: for oid in self.txn_oid_list:
partition_id = oid % self.num_paritions partition_id = oid % self.num_paritions
storage_node_list = self.pt.getCellList(partition_id, True) storage_node_list = self.pt.getCellList(partition_id, True)
...@@ -450,7 +456,7 @@ class Application(object): ...@@ -450,7 +456,7 @@ class Application(object):
conn.addPacket(p) conn.addPacket(p)
finally: finally:
self._clear_txn() self._clear_txn()
def tpc_finish(self, transaction, f=None): def tpc_finish(self, transaction, f=None):
"""Finish current transaction.""" """Finish current transaction."""
if self.txn is not transaction: if self.txn is not transaction:
...@@ -478,7 +484,7 @@ class Application(object): ...@@ -478,7 +484,7 @@ class Application(object):
for oid in self.txn_data_dict.keys: for oid in self.txn_data_dict.keys:
ddata = self.txn_data_dict[oid] ddata = self.txn_data_dict[oid]
# Now serial is same as tid # Now serial is same as tid
self.cache[oid] = self.tid, ddata self.cache[oid] = self.tid, ddata
finally: finally:
self.cache_lock_release() self.cache_lock_release()
# Release transaction # Release transaction
...@@ -486,66 +492,43 @@ class Application(object): ...@@ -486,66 +492,43 @@ class Application(object):
finally: finally:
self._clear_txn() self._clear_txn()
def loadBefore(self, oid, tid): def undo(self, transaction_id, txn):
partition_id = oid % self.num_paritions if transaction is not self.txn:
# Only used up to date node for retrieving object raise POSException.StorageTransactionError(self, transaction)
storage_node_list = [x for x in self.pt.getCellList(partition_id, True) \ # First get transaction information from master node
if x.getState() == UP_TO_DATE_STATE] self._info_lock_acquire()
self._load_before_lock_acquire() try:
data = None partition_id = transaction_id % self.num_paritions
# Store data on each node storage_node_list = self.pt.getCellList(partition_id, True)
for storage_node in storage_node_list: for storage_node in storage_node_list:
conn = self.cm.getConnForNode(storage_node.getUUID()) conn = self.cm.getConnForNode(storage_node.getUUID())
msg_id = conn.getNextId() msg_id = conn.getNextId()
p = Packet() p = Packet()
p.askObjectByTID(msg_id, oid, tid) p.askTransactionInformation(msg_id, tid)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
# Wait for answer # Wait for answer
self.loaded_object_by_tid = None self.txn_info = None
try:
while 1: while 1:
self.em.poll(1) self.em.poll(1)
if self.loaded_object_by_tid is not None: if self.txn_info is not None:
break break
if self.loaded_object_by_tid == -1: oid_list = self.txn_info['oids']
# OID not found finally:
continue self._info_lock_releas()
# Copy object data here to release lock as soon as possible # Second get object data from storage node using loadBefore
noid, start, end, compression, checksum, data = self.loaded_object data_dict = {}
finally: for oid in oid_list:
self._load_before_lock_release() data, start, end = self.loadBefore(oid, transaction_id)
# Check data here data_dict[oid] = data
if noid != oid: # Third do transaction with old data
# Oops, try with next node self.tpc_begin(txn)
logging.error('got wrong oid %s instead of %s from node %s' \ for oid in data_dict.keys():
%(noid, oid, storage_node.getServer())) data = data_dict[oid]
# Reacquire lock and try again self.store(oid, self.tid, data, None, txn)
self._load_before_lock_acquire() self.tpc_vote(txn)
continue self.tpc_finish(txn)
elif compression and checksum != alder32(data):
# Check checksum if we use compression
logging.error('wrong checksum from node %s for oid %s' \
%(storage_node.getServer(), oid))
# Reacquire lock and try again
self._load_before_lock_acquire()
continue
else:
break
if data is None:
# We didn't got any object from storage node
raise NEOStorageNotFoundError()
# Uncompress data
if compression:
data = decompressed(data)
return loads(data), start, end
def undo(self, transaction_id, txn):
if transaction is not self.txn:
raise POSException.StorageTransactionError(self, transaction)
raise NotImplementedError
def undoInfo(self, first, last, specification=None): def undoInfo(self, first, last, specification=None):
# First get list of transaction from master node # First get list of transaction from master node
self._info_lock_acquire() self._info_lock_acquire()
...@@ -553,7 +536,7 @@ class Application(object): ...@@ -553,7 +536,7 @@ class Application(object):
conn = self.master_conn conn = self.master_conn
msg_id = conn.getNextId() msg_id = conn.getNextId()
p = Packet() p = Packet()
p.getTIDList(msg_id, first, last, specification) p.askTIDs(msg_id, first, last, specification)
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
# Wait for answer # Wait for answer
...@@ -576,16 +559,17 @@ class Application(object): ...@@ -576,16 +559,17 @@ class Application(object):
conn.addPacket(p) conn.addPacket(p)
conn.expectMessage(msg_id) conn.expectMessage(msg_id)
# Wait for answer # Wait for answer
self.undo_txn_info = None self.txn_info = None
while 1: while 1:
self.em.poll(1) self.em.poll(1)
if self.undo_txn_info is not None: if self.txn_info is not None:
break break
undo_txn_list.append(self.undo_txn_info) self.txn_info.pop("oids")
undo_txn_list.append(self.txn_info)
return undo_txn_dict return undo_txn_dict
finally: finally:
self._info_lock_release() self._info_lock_release()
def history(self, oid, version, length=1, filter=None, object_only=0): def history(self, oid, version, length=1, filter=None, object_only=0):
self._info_lock_acquire() self._info_lock_acquire()
history_list = [] history_list = []
...@@ -634,6 +618,7 @@ class Application(object): ...@@ -634,6 +618,7 @@ class Application(object):
break break
# create history dict # create history dict
self.txn_info.remove('id') self.txn_info.remove('id')
self.txn_info.remove('oids')
self.txn_info['serial'] = serial self.txn_info['serial'] = serial
self.txn_info['version'] = None self.txn_info['version'] = None
self.txn_info['size'] = size self.txn_info['size'] = size
......
...@@ -7,7 +7,10 @@ from neo.protocol import Packet, MASTER_NODE_TYPE, STORAGE_NODE_TYPE, CLIENT_NOD ...@@ -7,7 +7,10 @@ from neo.protocol import Packet, MASTER_NODE_TYPE, STORAGE_NODE_TYPE, CLIENT_NOD
from neo.node import MasterNode, StorageNode, ClientNode from neo.node import MasterNode, StorageNode, ClientNode
from neo.pt import PartitionTable from neo.pt import PartitionTable
class MasterEventHandler(EventHandler): from ZODB.TimeStamp import TimeStamp
from ZODB.utils import p64
class ClientEventHandler(EventHandler):
"""This class deals with events for a master.""" """This class deals with events for a master."""
def __init__(self, app): def __init__(self, app):
...@@ -27,17 +30,16 @@ class MasterEventHandler(EventHandler): ...@@ -27,17 +30,16 @@ class MasterEventHandler(EventHandler):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
app = self.app app = self.app
node = app.nm.getNodeByServer(conn.getAddress()) node = app.nm.getNodeByServer(conn.getAddress())
if node_type != MASTER_NODE_TYPE: # It can be eiter a master node or a storage node
# The peer is not a master node! if node_type == CLIENT_NODE_TYPE:
logging.error('%s:%d is not a master node', ip_address, port)
app.nm.remove(node)
conn.close() conn.close()
return return
if conn.getAddress() != (ip_address, port): if conn.getAddress() != (ip_address, port):
# The server address is different! Then why was # The server address is different! Then why was
# the connection successful? # the connection successful?
logging.error('%s:%d is waiting for %s:%d', logging.error('%s:%d is waiting for %s:%d',
conn.getAddress()[0], conn.getAddress()[1], ip_address, port) conn.getAddress()[0], conn.getAddress()[1],
ip_address, port)
app.nm.remove(node) app.nm.remove(node)
conn.close() conn.close()
return return
...@@ -45,20 +47,32 @@ class MasterEventHandler(EventHandler): ...@@ -45,20 +47,32 @@ class MasterEventHandler(EventHandler):
conn.setUUID(uuid) conn.setUUID(uuid)
node.setUUID(uuid) node.setUUID(uuid)
# Create partition table if necessary if node_type == MASTER_NODE_TYPE:
if app.pt is None: # Create partition table if necessary
app.pt = PartitionTable(num_partitions, num_replicas) if app.pt is None:
app.pt = PartitionTable(num_partitions, num_replicas)
# Ask a primary master.
msg_id = conn.getNextId() # Ask a primary master.
conn.addPacket(Packet().askPrimaryMaster(msg_id)) msg_id = conn.getNextId()
conn.expectMessage(msg_id) conn.addPacket(Packet().askPrimaryMaster(msg_id))
conn.expectMessage(msg_id)
else: else:
self.handleUnexpectedPacket(conn, packet) self.handleUnexpectedPacket(conn, packet)
# Master node handler
def handleAnswerPrimaryMaster(self, conn, packet, primary_uuid, known_master_list): def handleAnswerPrimaryMaster(self, conn, packet, primary_uuid, known_master_list):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
uuid = conn.getUUID()
if uuid is None:
self.handleUnexpectedPacket(conn, packet)
return
app = self.app app = self.app
node = app.nm.getNodeByUUID(uuid)
# This must be sent only by primary master node
if not isinstance(node, MasterNode):
return
# Register new master nodes. # Register new master nodes.
for ip_address, port, uuid in known_master_list: for ip_address, port, uuid in known_master_list:
addr = (ip_address, port) addr = (ip_address, port)
...@@ -73,7 +87,7 @@ class MasterEventHandler(EventHandler): ...@@ -73,7 +87,7 @@ class MasterEventHandler(EventHandler):
n.setUUID(uuid) n.setUUID(uuid)
if primary_uuid != INVALID_UUID: if primary_uuid != INVALID_UUID:
# The primary master is defined. # The primary master is defined.
if app.primary_master_node is not None \ if app.primary_master_node is not None \
and app.primary_master_node.getUUID() != primary_uuid: and app.primary_master_node.getUUID() != primary_uuid:
# There are multiple primary master nodes. This is # There are multiple primary master nodes. This is
...@@ -91,44 +105,91 @@ class MasterEventHandler(EventHandler): ...@@ -91,44 +105,91 @@ class MasterEventHandler(EventHandler):
else: else:
self.handleUnexpectedPacket(conn, packet) self.handleUnexpectedPacket(conn, packet)
def handleSendPartitionTable(self, conn, packet, row_list): def handleSendPartitionTable(self, conn, packet, ptid, row_list):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
uuid = conn.getUUID()
if uuid is None:
self.handleUnexpectedPacket(conn, packet)
return
app = self.app app = self.app
node = app.nm.getNodeByUUID(uuid)
# This must be sent only by primary master node
if not isinstance(node, MasterNode) \
or app.primary_master_node is None \
or app.primary_master_node.getUUID() != uuid:
return
for offset, node in row_list: for offset, node in row_list:
app.pt.setRow(offset, row) app.pt.setRow(offset, row)
else: else:
self.handleUnexpectedPacket(conn, packet) self.handleUnexpectedPacket(conn, packet)
def handleNotifyNodeInformation(self, conn, packet, node_list): def handleNotifyNodeInformation(self, conn, packet, node_list):
app = self.app if isinstance(conn, ClientConnection):
for node_type, ip_address, port, uuid, state in node_list: uuid = conn.getUUID()
# Register new nodes. if uuid is None:
addr = (ip_address, port) self.handleUnexpectedPacket(conn, packet)
if app.server == addr: return
# This is self.
continue
else:
n = app.app.nm.getNodeByServer(addr)
if n is None:
if node_type == MASTER_NODE:
n = MasterNode(server = addr)
elif node_typ == STORAGE_NODE:
n = StorageNode(server = addr)
elif node_typ == CLIENT_NODE:
n = ClientNode(server = addr)
else:
continue
app.app.nm.add(n)
if uuid != INVALID_UUID: app = self.app
# If I don't know the UUID yet, believe what the peer node = app.nm.getNodeByUUID(uuid)
# told me at the moment. # This must be sent only by primary master node
if n.getUUID() is None: if not isinstance(node, MasterNode) \
n.setUUID(uuid) or app.primary_master_node is None \
or app.primary_master_node.getUUID() != uuid:
def handleNotifyPartitionChanges(self, conn, packet, cell_list): return
for node_type, ip_address, port, uuid, state in node_list:
# Register new nodes.
addr = (ip_address, port)
if app.server == addr:
# This is self.
continue
else:
n = app.app.nm.getNodeByServer(addr)
if n is None:
if node_type == MASTER_NODE:
n = MasterNode(server = addr)
if uuid != INVALID_UUID:
# If I don't know the UUID yet, believe what the peer
# told me at the moment.
if n.getUUID() is None:
n.setUUID(uuid)
elif node_typ == STORAGE_NODE:
if uuid == INVALID_UUID:
# No interest.
continue
n = StorageNode(server = addr)
elif node_typ == CLIENT_NODE:
if uuid == INVALID_UUID:
# No interest.
continue
n = ClientNode(server = addr)
else:
continue
app.app.nm.add(n)
n.setState(state)
else:
self.handleUnexpectedPacket(conn, packet)
def handleNotifyPartitionChanges(self, conn, packet, ptid, cell_list):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
app = self.app app = self.app
uuid = conn.getUUID()
if uuid is None:
self.handleUnexpectedPacket(conn, packet)
return
app = self.app
node = app.nm.getNodeByUUID(uuid)
# This must be sent only by primary master node
if not isinstance(node, MasterNode) \
or app.primary_master_node is None \
or app.primary_master_node.getUUID() != uuid:
return
for cell in cell_list: for cell in cell_list:
app.pt.addNode(cell) app.pt.addNode(cell)
else: else:
...@@ -144,9 +205,9 @@ class MasterEventHandler(EventHandler): ...@@ -144,9 +205,9 @@ class MasterEventHandler(EventHandler):
def handleNotifyTransactionFinished(self, conn, packet, tid): def handleNotifyTransactionFinished(self, conn, packet, tid):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
app = self.app app = self.app
if tid != app.tid: if tid != app.tid:
# what's this ? # What's this ?
raise raise NEOStorageError
else: else:
app.txn_finished = 1 app.txn_finished = 1
else: else:
...@@ -155,10 +216,60 @@ class MasterEventHandler(EventHandler): ...@@ -155,10 +216,60 @@ class MasterEventHandler(EventHandler):
def handleInvalidateObjects(self, conn, packet, oid_list): def handleInvalidateObjects(self, conn, packet, oid_list):
raise NotImplementedError('this method must be overridden') raise NotImplementedError('this method must be overridden')
def handleAnswerNewOIDList(self, conn, packet, oid_list): def handleAnswerNewOIDs(self, conn, packet, oid_list):
if isinstance(conn, ClientConnection): if isinstance(conn, ClientConnection):
app = self.app app = self.app
app.new_oid_list = oid_list app.new_oid_list = oid_list
app.new_oid_list.reverse() app.new_oid_list.reverse()
else: else:
self.handleUnexpectedPacket(conn, packet) self.handleUnexpectedPacket(conn, packet)
# Storage node handler
def handleAnwserObjectByOID(self, oid, start_serial, end_serial, compression,
checksum, data):
if isinstance(conn, ClientConnection):
app = self.app
app.loaded_object = (oid, start_serial, end_serial, compression,
checksum, data)
else:
self.handleUnexpectedPacket(conn, packet)
def handleAnswerStoreObject(self, conflicting, oid, serial):
if isinstance(conn, ClientConnection):
app = self.app
if conflicting == '1':
app.object_stored = -1
else:
app.object_stored = oid, serial
else:
self.handleUnexpectedPacket(conn, packet)
def handleAnswerStoreTransaction(self, tid):
if isinstance(conn, ClientConnection):
app = self.app
app.txn_stored = 1
else:
self.handleUnexpectedPacket(conn, packet)
def handleAnswerTransactionInformation(self, tid, user, desc, oid_list):
if isinstance(conn, ClientConnection):
app = self.app
# transaction information are returned as a dict
info = {}
info['time'] = TimeStamp(p64(long(tid))).timeTime()
info['user_name'] = user
info['description'] = desc
info['id'] = p64(long(tid))
info['oids'] = oid_list
app.txn_info = info
else:
self.handleUnexpectedPacket(conn, packet)
def handleAnswerObjectHistory(self, oid, history_list):
if isinstance(conn, ClientConnection):
app = self.app
# history_list is a list of tuple (serial, size)
self.history = oid, history_list
else:
self.handleUnexpectedPacket(conn, packet)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment