Commit 7358c9bf authored by Grégory Wisniewski's avatar Grégory Wisniewski

Define a new Enum class that don't fails with static analysies. This allow

gather good results from tools like 'pylint'.
Use this for cluster state for now, others will follow.


git-svn-id: https://svn.erp5.org/repos/neo/trunk@1333 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 911111de
...@@ -21,7 +21,7 @@ from time import time ...@@ -21,7 +21,7 @@ from time import time
from struct import pack, unpack from struct import pack, unpack
from neo import protocol from neo import protocol
from neo.protocol import UUID_NAMESPACES, BOOTING_CLUSTER_STATE from neo.protocol import UUID_NAMESPACES, ClusterStates
from neo.node import NodeManager from neo.node import NodeManager
from neo.event import EventManager from neo.event import EventManager
from neo.connection import ListeningConnection, ClientConnection from neo.connection import ListeningConnection, ClientConnection
...@@ -111,7 +111,7 @@ class Application(object): ...@@ -111,7 +111,7 @@ class Application(object):
self.listening_conn = ListeningConnection(self.em, None, self.listening_conn = ListeningConnection(self.em, None,
addr = self.server, connector_handler = self.connector_handler) addr = self.server, connector_handler = self.connector_handler)
self.cluster_state = BOOTING_CLUSTER_STATE self.cluster_state = ClusterStates.BOOTING
# Start the election of a primary master node. # Start the election of a primary master node.
self.electPrimary() self.electPrimary()
...@@ -375,7 +375,7 @@ class Application(object): ...@@ -375,7 +375,7 @@ class Application(object):
partition table or make a new table from scratch, if this is the first time.""" partition table or make a new table from scratch, if this is the first time."""
logging.info('begin the recovery of the status') logging.info('begin the recovery of the status')
self.changeClusterState(protocol.RECOVERING_CLUSTER_STATE) self.changeClusterState(ClusterStates.RECOVERING)
em = self.em em = self.em
self.loid = None self.loid = None
...@@ -384,7 +384,7 @@ class Application(object): ...@@ -384,7 +384,7 @@ class Application(object):
self.target_uuid = None self.target_uuid = None
# collect the last partition table available # collect the last partition table available
while self.cluster_state == protocol.RECOVERING_CLUSTER_STATE: while self.cluster_state == ClusterStates.RECOVERING:
em.poll(1) em.poll(1)
logging.info('startup allowed') logging.info('startup allowed')
...@@ -473,7 +473,7 @@ class Application(object): ...@@ -473,7 +473,7 @@ class Application(object):
"""Verify the data in storage nodes and clean them up, if necessary.""" """Verify the data in storage nodes and clean them up, if necessary."""
em, nm = self.em, self.nm em, nm = self.em, self.nm
self.changeClusterState(protocol.VERIFYING_CLUSTER_STATE) self.changeClusterState(ClusterStates.VERIFYING)
# wait for any missing node # wait for any missing node
logging.debug('waiting for the cluster to be operational') logging.debug('waiting for the cluster to be operational')
...@@ -556,7 +556,7 @@ class Application(object): ...@@ -556,7 +556,7 @@ class Application(object):
em = self.em em = self.em
nm = self.nm nm = self.nm
self.changeClusterState(protocol.RUNNING_CLUSTER_STATE) self.changeClusterState(ClusterStates.RUNNING)
# This dictionary is used to hold information on transactions being finished. # This dictionary is used to hold information on transactions being finished.
self.finishing_transaction_dict = {} self.finishing_transaction_dict = {}
...@@ -641,13 +641,13 @@ class Application(object): ...@@ -641,13 +641,13 @@ class Application(object):
nm, em = self.nm, self.em nm, em = self.nm, self.em
# select the storage handler # select the storage handler
if state == protocol.BOOTING_CLUSTER_STATE: if state == ClusterStates.BOOTING:
storage_handler = recovery.RecoveryHandler storage_handler = recovery.RecoveryHandler
elif state == protocol.RECOVERING_CLUSTER_STATE: elif state == ClusterStates.RECOVERING:
storage_handler = recovery.RecoveryHandler storage_handler = recovery.RecoveryHandler
elif state == protocol.VERIFYING_CLUSTER_STATE: elif state == ClusterStates.VERIFYING:
storage_handler = verification.VerificationHandler storage_handler = verification.VerificationHandler
elif state == protocol.RUNNING_CLUSTER_STATE: elif state == ClusterStates.RUNNING:
storage_handler = storage.StorageServiceHandler storage_handler = storage.StorageServiceHandler
else: else:
RuntimeError('Unexpected node type') RuntimeError('Unexpected node type')
...@@ -664,7 +664,7 @@ class Application(object): ...@@ -664,7 +664,7 @@ class Application(object):
# those node types keep their own handler # those node types keep their own handler
continue continue
if node.isClient(): if node.isClient():
if state != protocol.RUNNING_CLUSTER_STATE: if state != ClusterStates.RUNNING:
conn.close() conn.close()
handler = client.ClientServiceHandler handler = client.ClientServiceHandler
elif node.isStorage(): elif node.isStorage():
...@@ -715,7 +715,7 @@ class Application(object): ...@@ -715,7 +715,7 @@ class Application(object):
while 1: while 1:
self.em.poll(1) self.em.poll(1)
if len(self.finishing_transaction_dict) == 0: if len(self.finishing_transaction_dict) == 0:
if self.cluster_state == protocol.RUNNING_CLUSTER_STATE: if self.cluster_state == ClusterStates.RUNNING:
sys.exit("Application has been asked to shut down") sys.exit("Application has been asked to shut down")
else: else:
# no more transaction, ask clients to shutdown # no more transaction, ask clients to shutdown
...@@ -740,12 +740,12 @@ class Application(object): ...@@ -740,12 +740,12 @@ class Application(object):
def identifyStorageNode(self, uuid, node): def identifyStorageNode(self, uuid, node):
state = protocol.RUNNING_STATE state = protocol.RUNNING_STATE
handler = None handler = None
if self.cluster_state == protocol.RECOVERING_CLUSTER_STATE: if self.cluster_state == ClusterStates.RECOVERING:
if uuid is None: if uuid is None:
logging.info('reject empty storage node') logging.info('reject empty storage node')
raise protocol.NotReadyError raise protocol.NotReadyError
handler = recovery.RecoveryHandler handler = recovery.RecoveryHandler
elif self.cluster_state == protocol.VERIFYING_CLUSTER_STATE: elif self.cluster_state == ClusterStates.VERIFYING:
if uuid is None or node is None: if uuid is None or node is None:
# if node is unknown, it has been forget when the current # if node is unknown, it has been forget when the current
# partition was validated by the admin # partition was validated by the admin
...@@ -754,12 +754,12 @@ class Application(object): ...@@ -754,12 +754,12 @@ class Application(object):
# conflicting UUID are rejected in the identification handler. # conflicting UUID are rejected in the identification handler.
state = protocol.PENDING_STATE state = protocol.PENDING_STATE
handler = verification.VerificationHandler handler = verification.VerificationHandler
elif self.cluster_state == protocol.RUNNING_CLUSTER_STATE: elif self.cluster_state == ClusterStates.RUNNING:
if uuid is None or node is None: if uuid is None or node is None:
# same as for verification # same as for verification
state = protocol.PENDING_STATE state = protocol.PENDING_STATE
handler = storage.StorageServiceHandler handler = storage.StorageServiceHandler
elif self.cluster_state == protocol.STOPPING_CLUSTER_STATE: elif self.cluster_state == ClusterStates.STOPPING:
raise protocol.NotReadyError raise protocol.NotReadyError
else: else:
raise RuntimeError('unhandled cluster state') raise RuntimeError('unhandled cluster state')
...@@ -785,7 +785,7 @@ class Application(object): ...@@ -785,7 +785,7 @@ class Application(object):
logging.info('Accept a master %s' % dump(uuid)) logging.info('Accept a master %s' % dump(uuid))
elif node_type == protocol.CLIENT_NODE_TYPE: elif node_type == protocol.CLIENT_NODE_TYPE:
# refuse any client before running # refuse any client before running
if self.cluster_state != protocol.RUNNING_CLUSTER_STATE: if self.cluster_state != ClusterStates.RUNNING:
logging.info('Reject a connection from a client') logging.info('Reject a connection from a client')
raise protocol.NotReadyError raise protocol.NotReadyError
node_ctor = self.nm.createClient node_ctor = self.nm.createClient
......
...@@ -19,7 +19,7 @@ from neo import logging ...@@ -19,7 +19,7 @@ from neo import logging
from neo import protocol from neo import protocol
from neo.master.handlers import MasterHandler from neo.master.handlers import MasterHandler
from neo.protocol import RUNNING_STATE from neo.protocol import ClusterStates, RUNNING_STATE
from neo.util import dump from neo.util import dump
class AdministrationHandler(MasterHandler): class AdministrationHandler(MasterHandler):
...@@ -38,7 +38,7 @@ class AdministrationHandler(MasterHandler): ...@@ -38,7 +38,7 @@ class AdministrationHandler(MasterHandler):
self.app.changeClusterState(state) self.app.changeClusterState(state)
p = protocol.noError('cluster state changed') p = protocol.noError('cluster state changed')
conn.answer(p, packet.getId()) conn.answer(p, packet.getId())
if state == protocol.STOPPING_CLUSTER_STATE: if state == ClusterStates.STOPPING:
self.app.cluster_state = state self.app.cluster_state = state
self.app.shutdown() self.app.shutdown()
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
from neo.neoctl.neoctl import NeoCTL, NotReadyException from neo.neoctl.neoctl import NeoCTL, NotReadyException
from neo.util import bin, dump from neo.util import bin, dump
from neo import protocol from neo import protocol
from neo.protocol import ClusterStates
action_dict = { action_dict = {
'print': { 'print': {
...@@ -53,9 +54,7 @@ class TerminalNeoCTL(object): ...@@ -53,9 +54,7 @@ class TerminalNeoCTL(object):
return protocol.node_types.getFromStr(value) return protocol.node_types.getFromStr(value)
def asClusterState(self, value): def asClusterState(self, value):
if not value.endswith('_CLUSTER_STATE'): return ClusterStates.getByName(value.upper())
value += '_CLUSTER_STATE'
return protocol.cluster_states.getFromStr(value)
def asNode(self, value): def asNode(self, value):
return bin(value) return bin(value)
...@@ -154,7 +153,7 @@ class TerminalNeoCTL(object): ...@@ -154,7 +153,7 @@ class TerminalNeoCTL(object):
""" """
Starts cluster operation after a startup. Starts cluster operation after a startup.
Equivalent to: Equivalent to:
set cluster VERIFYING_CLUSTER_STATE set cluster verifying
""" """
assert len(params) == 0 assert len(params) == 0
self.neoctl.startCluster() self.neoctl.startCluster()
......
...@@ -20,6 +20,7 @@ from neo.connection import ClientConnection ...@@ -20,6 +20,7 @@ from neo.connection import ClientConnection
from neo.event import EventManager from neo.event import EventManager
from neo.neoctl.handler import CommandEventHandler from neo.neoctl.handler import CommandEventHandler
from neo import protocol from neo import protocol
from neo.protocol import ClusterStates
class NotReadyException(Exception): class NotReadyException(Exception):
pass pass
...@@ -126,7 +127,7 @@ class NeoCTL(object): ...@@ -126,7 +127,7 @@ class NeoCTL(object):
""" """
Set cluster into "verifying" state. Set cluster into "verifying" state.
""" """
self.setClusterState(protocol.VERIFYING_CLUSTER_STATE) self.setClusterState(ClusterStates.VERIFYING)
def dropNode(self, node): def dropNode(self, node):
""" """
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
from struct import pack, unpack, error from struct import pack, unpack, error
from socket import inet_ntoa, inet_aton from socket import inet_ntoa, inet_aton
from neo.util import Enum
class EnumItem(int): class EnumItem(int):
""" """
Enumerated value type. Enumerated value type.
...@@ -52,7 +54,7 @@ class EnumItem(int): ...@@ -52,7 +54,7 @@ class EnumItem(int):
def __repr__(self): def __repr__(self):
return '<EnumItem %r (%r)>' % (self.name, int(self)) return '<EnumItem %r (%r)>' % (self.name, int(self))
class Enum(dict): class OldEnum(dict):
""" """
C-style enumerated type support with extended typechecking. C-style enumerated type support with extended typechecking.
Instantiate with a dict whose keys are variable names and values are Instantiate with a dict whose keys are variable names and values are
...@@ -79,6 +81,7 @@ class Enum(dict): ...@@ -79,6 +81,7 @@ class Enum(dict):
def getFromStr(self, value, default=None): def getFromStr(self, value, default=None):
return self.str_enum_dict.get(value, default) return self.str_enum_dict.get(value, default)
# The protocol version (major, minor). # The protocol version (major, minor).
PROTOCOL_VERSION = (4, 0) PROTOCOL_VERSION = (4, 0)
...@@ -88,7 +91,7 @@ MAX_PACKET_SIZE = 0x4000000 ...@@ -88,7 +91,7 @@ MAX_PACKET_SIZE = 0x4000000
PACKET_HEADER_SIZE = 10 PACKET_HEADER_SIZE = 10
# Message types. # Message types.
packet_types = Enum({ packet_types = OldEnum({
# Error is a special type of message, because this can be sent against any other message, # Error is a special type of message, because this can be sent against any other message,
# even if such a message does not expect a reply usually. Any -> Any. # even if such a message does not expect a reply usually. Any -> Any.
...@@ -304,7 +307,7 @@ packet_types = Enum({ ...@@ -304,7 +307,7 @@ packet_types = Enum({
}) })
# Error codes. # Error codes.
error_codes = Enum({ error_codes = OldEnum({
'NO_ERROR_CODE': 0, 'NO_ERROR_CODE': 0,
'NOT_READY_CODE': 1, 'NOT_READY_CODE': 1,
'OID_NOT_FOUND_CODE': 2, 'OID_NOT_FOUND_CODE': 2,
...@@ -314,17 +317,18 @@ error_codes = Enum({ ...@@ -314,17 +317,18 @@ error_codes = Enum({
'INTERNAL_ERROR_CODE': 8, 'INTERNAL_ERROR_CODE': 8,
}) })
# Cluster states class ClusterStates(Enum):
cluster_states = Enum({
'BOOTING_CLUSTER_STATE': 1, BOOTING = Enum.Item(1)
'RECOVERING_CLUSTER_STATE': 2, RECOVERING = Enum.Item(2)
'VERIFYING_CLUSTER_STATE': 3, VERIFYING = Enum.Item(3)
'RUNNING_CLUSTER_STATE': 4, RUNNING = Enum.Item(4)
'STOPPING_CLUSTER_STATE': 5, STOPPING = Enum.Item(5)
})
ClusterStates = ClusterStates()
# Node types. # Node types.
node_types = Enum({ node_types = OldEnum({
'MASTER_NODE_TYPE' : 1, 'MASTER_NODE_TYPE' : 1,
'STORAGE_NODE_TYPE' : 2, 'STORAGE_NODE_TYPE' : 2,
'CLIENT_NODE_TYPE' : 3, 'CLIENT_NODE_TYPE' : 3,
...@@ -332,7 +336,7 @@ node_types = Enum({ ...@@ -332,7 +336,7 @@ node_types = Enum({
}) })
# Node states. # Node states.
node_states = Enum({ node_states = OldEnum({
'RUNNING_STATE': 0, 'RUNNING_STATE': 0,
'TEMPORARILY_DOWN_STATE': 1, 'TEMPORARILY_DOWN_STATE': 1,
'DOWN_STATE': 2, 'DOWN_STATE': 2,
...@@ -354,7 +358,7 @@ node_state_prefix_dict = { ...@@ -354,7 +358,7 @@ node_state_prefix_dict = {
} }
# Partition cell states. # Partition cell states.
cell_states = Enum({ cell_states = OldEnum({
'UP_TO_DATE_STATE': 0, 'UP_TO_DATE_STATE': 0,
'OUT_OF_DATE_STATE': 1, 'OUT_OF_DATE_STATE': 1,
'FEEDING_STATE': 2, 'FEEDING_STATE': 2,
...@@ -494,9 +498,9 @@ def handle_errors(decoder): ...@@ -494,9 +498,9 @@ def handle_errors(decoder):
return wrapper return wrapper
def _decodeClusterState(state): def _decodeClusterState(state):
cluster_state = cluster_states.get(state) cluster_state = ClusterStates.get(state)
if cluster_state is None: if cluster_state is None:
raise PacketMalformedError('invalid node state %d' % state) raise PacketMalformedError('invalid cluster state %d' % state)
return cluster_state return cluster_state
def _decodeNodeState(state): def _decodeNodeState(state):
......
...@@ -28,6 +28,7 @@ import unittest ...@@ -28,6 +28,7 @@ import unittest
import tempfile import tempfile
import traceback import traceback
from neo.protocol import ClusterStates
from neo.client.Storage import Storage from neo.client.Storage import Storage
from neo.tests import getNewUUID from neo.tests import getNewUUID
from neo.util import dump from neo.util import dump
...@@ -433,13 +434,13 @@ class NEOCluster(object): ...@@ -433,13 +434,13 @@ class NEOCluster(object):
self.expectCondition(callback, timeout, delay) self.expectCondition(callback, timeout, delay)
def expectClusterRecovering(self, timeout=0, delay=1): def expectClusterRecovering(self, timeout=0, delay=1):
self.expectClusterState(protocol.RECOVERING_CLUSTER_STATE) self.expectClusterState(ClusterStates.RECOVERING)
def expectClusterVeryfing(self, timeout=0, delay=1): def expectClusterVeryfing(self, timeout=0, delay=1):
self.expectClusterState(protocol.VERIFYING_CLUSTER_STATE) self.expectClusterState(ClusterStates.VERIFYING)
def expectClusterRunning(self, timeout=0, delay=1): def expectClusterRunning(self, timeout=0, delay=1):
self.expectClusterState(protocol.RUNNING_CLUSTER_STATE) self.expectClusterState(ClusterStates.RUNNING)
def __del__(self): def __del__(self):
if self.cleanup_on_delete: if self.cleanup_on_delete:
......
...@@ -23,6 +23,7 @@ from Persistence import Persistent ...@@ -23,6 +23,7 @@ from Persistence import Persistent
from neo.tests.functional import NEOCluster, NEOFunctionalTest from neo.tests.functional import NEOCluster, NEOFunctionalTest
from neo.client.Storage import Storage as NEOStorage from neo.client.Storage import Storage as NEOStorage
from neo import protocol from neo import protocol
from neo.protocol import ClusterStates
class PObject(Persistent): class PObject(Persistent):
...@@ -388,7 +389,7 @@ class StorageTests(NEOFunctionalTest): ...@@ -388,7 +389,7 @@ class StorageTests(NEOFunctionalTest):
every 1000 partition when sending a partition table. """ every 1000 partition when sending a partition table. """
self.__setup(storage_number=2, partitions=5000, master_node_count=1) self.__setup(storage_number=2, partitions=5000, master_node_count=1)
neoctl = self.neo.getNEOCTL() neoctl = self.neo.getNEOCTL()
self.neo.expectClusterState(protocol.RUNNING_CLUSTER_STATE) self.neo.expectClusterState(ClusterStates.RUNNING)
def testDropNodeThenRestartCluster(self): def testDropNodeThenRestartCluster(self):
""" Start a cluster with more than one storage, down one, shutdown the """ Start a cluster with more than one storage, down one, shutdown the
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import re
from zlib import adler32 from zlib import adler32
from struct import pack, unpack from struct import pack, unpack
from time import time, gmtime from time import time, gmtime
...@@ -91,3 +92,43 @@ def parseMasterList(masters, except_node=None): ...@@ -91,3 +92,43 @@ def parseMasterList(masters, except_node=None):
return master_node_list return master_node_list
class Enum(dict):
"""
Simulate an enumeration, define them as follow :
class MyEnum(Enum):
ITEM1 = Enum.Item(0)
ITEM2 = Enum.Item(1)
Enum items must be written in full upper case
"""
class Item(int):
def __new__(cls, value):
instance = super(Enum.Item, cls).__new__(cls, value)
instance._enum = None
instance._name = None
return instance
def __str__(self):
return self._name
def __repr__(self):
return "<EnumItem %s (%d)>" % (self._name, self)
def __eq__(self, other):
assert isinstance(other, (Enum.Item, int, float, long))
assert self._enum == other._enum
return int(self) == int(other)
def __init__(self):
for name in dir(self):
if not re.match('^[A-Z_]*$', name):
continue
item = getattr(self, name)
item._name = name
item._enum = self
self[int(item)] = item
def getByName(self, name):
return getattr(self, name)
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