summaryrefslogtreecommitdiff
path: root/python/qpid
diff options
context:
space:
mode:
authorTed Ross <tross@apache.org>2008-09-03 18:01:44 +0000
committerTed Ross <tross@apache.org>2008-09-03 18:01:44 +0000
commit13191e7951b29453c75db8384391d26f0402139d (patch)
treeb3ca5bd5f9c8523924cf9d1a0fe118099bef9894 /python/qpid
parentb8cf7ea1034fa6216183f03022c83efdb154f3ee (diff)
downloadqpid-python-13191e7951b29453c75db8384391d26f0402139d.tar.gz
QPID-1174 Updates to the management framework
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@691700 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'python/qpid')
-rw-r--r--python/qpid/management.py181
-rw-r--r--python/qpid/managementdata.py80
2 files changed, 199 insertions, 62 deletions
diff --git a/python/qpid/management.py b/python/qpid/management.py
index 83c29a78a5..99c902ab30 100644
--- a/python/qpid/management.py
+++ b/python/qpid/management.py
@@ -69,6 +69,53 @@ class mgmtObject (object):
for cell in row:
setattr (self, cell[0], cell[1])
+class objectId(object):
+ """ Object that represents QMF object identifiers """
+
+ def __init__(self, codec):
+ self.first = codec.read_uint64()
+ self.second = codec.read_uint64()
+
+ def __cmp__(self, other):
+ if other == None:
+ return 1
+ if self.first < other.first:
+ return -1
+ if self.first > other.first:
+ return 1
+ if self.second < other.second:
+ return -1
+ if self.second > other.second:
+ return 1
+ return 0
+
+
+ def index(self):
+ return (self.first, self.second)
+
+ def getFlags(self):
+ return (self.first & 0xF000000000000000) >> 60
+
+ def getSequence(self):
+ return (self.first & 0x0FFF000000000000) >> 48
+
+ def getBroker(self):
+ return (self.first & 0x0000FFFFF0000000) >> 28
+
+ def getBank(self):
+ return self.first & 0x000000000FFFFFFF
+
+ def getObject(self):
+ return self.second
+
+ def isDurable(self):
+ return self.getSequence() == 0
+
+ def encode(self, codec):
+ codec.write_uint64(self.first)
+ codec.write_uint64(self.second)
+
+
class methodResult:
""" Object that contains the result of a method call """
@@ -308,6 +355,8 @@ class managementClient:
self.handleClassInd (ch, codec)
elif hdr[0] == 'h':
self.handleHeartbeat (ch, codec)
+ elif hdr[0] == 'e':
+ self.handleEvent (ch, codec)
else:
self.parse (ch, codec, hdr[0], hdr[1])
ch.accept(msg)
@@ -386,7 +435,7 @@ class managementClient:
elif typecode == 9: # DELTATIME
codec.write_uint64 (long (value))
elif typecode == 10: # REF
- codec.write_uint64 (long (value))
+ value.encode(codec)
elif typecode == 11: # BOOL
codec.write_uint8 (int (value))
elif typecode == 12: # FLOAT
@@ -429,7 +478,7 @@ class managementClient:
elif typecode == 9: # DELTATIME
data = codec.read_uint64 ()
elif typecode == 10: # REF
- data = codec.read_uint64 ()
+ data = objectId(codec)
elif typecode == 11: # BOOL
data = codec.read_uint8 ()
elif typecode == 12: # FLOAT
@@ -551,9 +600,9 @@ class managementClient:
ch.send ("qpid.management", smsg)
def handleClassInd (self, ch, codec):
- pname = str (codec.read_str8 ())
- cname = str (codec.read_str8 ())
- hash = codec.read_bin128 ()
+ pname = str (codec.read_str8())
+ cname = str (codec.read_str8())
+ hash = codec.read_bin128()
if pname not in self.packages:
return
@@ -574,6 +623,32 @@ class managementClient:
if self.ctrlCb != None:
self.ctrlCb (ch.context, self.CTRL_HEARTBEAT, timestamp)
+ def handleEvent (self, ch, codec):
+ if self.eventCb == None:
+ return
+ timestamp = codec.read_uint64()
+ objId = objectId(codec)
+ packageName = str(codec.read_str8())
+ className = str(codec.read_str8())
+ hash = codec.read_bin128()
+ name = str(codec.read_str8())
+ classKey = (packageName, className, hash)
+ if classKey not in self.schema:
+ return;
+ schemaClass = self.schema[classKey]
+ row = []
+ es = schemaClass['E']
+ arglist = None
+ for ename in es:
+ (edesc, eargs) = es[ename]
+ if ename == name:
+ arglist = eargs
+ if arglist == None:
+ return
+ for arg in arglist:
+ row.append((arg[0], self.decodeValue(codec, arg[1])))
+ self.eventCb(ch.context, classKey, objId, name, row)
+
def parseSchema (self, ch, codec):
""" Parse a received schema-description message. """
self.decOutstanding (ch)
@@ -597,22 +672,23 @@ class managementClient:
configs = []
insts = []
methods = {}
- events = []
+ events = {}
configs.append (("id", 4, "", "", 1, 1, None, None, None, None, None))
insts.append (("id", 4, None, None))
for idx in range (configCount):
ft = codec.read_map ()
- name = str (ft["name"])
- type = ft["type"]
- access = ft["access"]
- index = ft["index"]
- unit = None
- min = None
- max = None
- maxlen = None
- desc = None
+ name = str (ft["name"])
+ type = ft["type"]
+ access = ft["access"]
+ index = ft["index"]
+ optional = ft["optional"]
+ unit = None
+ min = None
+ max = None
+ maxlen = None
+ desc = None
for key, value in ft.items ():
if key == "unit":
@@ -626,7 +702,7 @@ class managementClient:
elif key == "desc":
desc = str (value)
- config = (name, type, unit, desc, access, index, min, max, maxlen)
+ config = (name, type, unit, desc, access, index, min, max, maxlen, optional)
configs.append (config)
for idx in range (instCount):
@@ -685,6 +761,33 @@ class managementClient:
args.append (arg)
methods[mname] = (mdesc, args)
+ for idx in range (eventCount):
+ ft = codec.read_map ()
+ ename = str (ft["name"])
+ argCount = ft["argCount"]
+ if "desc" in ft:
+ edesc = str (ft["desc"])
+ else:
+ edesc = None
+
+ args = []
+ for aidx in range (argCount):
+ ft = codec.read_map ()
+ name = str (ft["name"])
+ type = ft["type"]
+ unit = None
+ desc = None
+
+ for key, value in ft.items ():
+ if key == "unit":
+ unit = str (value)
+ elif key == "desc":
+ desc = str (value)
+
+ arg = (name, type, unit, desc)
+ args.append (arg)
+ events[ename] = (edesc, args)
+
schemaClass = {}
schemaClass['C'] = configs
schemaClass['I'] = insts
@@ -695,6 +798,22 @@ class managementClient:
if self.schemaCb != None:
self.schemaCb (ch.context, classKey, configs, insts, methods, events)
+ def parsePresenceMasks(self, codec, schemaClass):
+ """ Generate a list of not-present properties """
+ excludeList = []
+ bit = 0
+ for element in schemaClass['C'][1:]:
+ if element[9] == 1:
+ if bit == 0:
+ mask = codec.read_uint8()
+ bit = 1
+ if (mask & bit) == 0:
+ excludeList.append(element[0])
+ bit = bit * 2
+ if bit == 256:
+ bit = 0
+ return excludeList
+
def parseContent (self, ch, cls, codec, seq=0):
""" Parse a received content message. """
if (cls == 'C' or (cls == 'B' and seq == 0)) and self.configCb == None:
@@ -716,21 +835,26 @@ class managementClient:
timestamps.append (codec.read_uint64 ()) # Current Time
timestamps.append (codec.read_uint64 ()) # Create Time
timestamps.append (codec.read_uint64 ()) # Delete Time
-
+ objId = objectId(codec)
schemaClass = self.schema[classKey]
if cls == 'C' or cls == 'B':
- for element in schemaClass['C'][:]:
+ notPresent = self.parsePresenceMasks(codec, schemaClass)
+
+ if cls == 'C' or cls == 'B':
+ row.append(("id", objId))
+ for element in schemaClass['C'][1:]:
tc = element[1]
name = element[0]
- data = self.decodeValue (codec, tc)
- row.append ((name, data))
+ if name in notPresent:
+ row.append((name, None))
+ else:
+ data = self.decodeValue(codec, tc)
+ row.append((name, data))
if cls == 'I' or cls == 'B':
- if cls == 'B':
- start = 1
- else:
- start = 0
- for element in schemaClass['I'][start:]:
+ if cls == 'I':
+ row.append(("id", objId))
+ for element in schemaClass['I'][1:]:
tc = element[1]
name = element[0]
data = self.decodeValue (codec, tc)
@@ -763,9 +887,12 @@ class managementClient:
codec = Codec (self.spec)
sequence = self.seqMgr.reserve ((userSequence, classId, methodName))
self.setHeader (codec, ord ('M'), sequence)
- codec.write_uint64 (objId) # ID of object
+ objId.encode(codec)
+ codec.write_str8 (classId[0])
+ codec.write_str8 (classId[1])
+ codec.write_bin128 (classId[2])
codec.write_str8 (methodName)
- bank = (objId & 0x0000FFFFFF000000) >> 24
+ bank = objId.getBank()
# Encode args according to schema
if classId not in self.schema:
diff --git a/python/qpid/managementdata.py b/python/qpid/managementdata.py
index fc9eb391b7..5a8b9cdf9d 100644
--- a/python/qpid/managementdata.py
+++ b/python/qpid/managementdata.py
@@ -71,14 +71,14 @@ class ManagementData:
#
def registerObjId (self, objId):
- if not objId in self.idBackMap:
- self.idBackMap[objId] = self.nextId
+ if not objId.index() in self.idBackMap:
+ self.idBackMap[objId.index()] = self.nextId
self.idMap[self.nextId] = objId
self.nextId += 1
- def displayObjId (self, objId):
- if objId in self.idBackMap:
- return self.idBackMap[objId]
+ def displayObjId (self, objIdIndex):
+ if objIdIndex in self.idBackMap:
+ return self.idBackMap[objIdIndex]
else:
return 0
@@ -86,7 +86,7 @@ class ManagementData:
if displayId in self.idMap:
return self.idMap[displayId]
else:
- return 0
+ return None
def displayClassName (self, cls):
(packageName, className, hash) = cls
@@ -102,19 +102,20 @@ class ManagementData:
self.tables[className] = {}
# Register the ID so a more friendly presentation can be displayed
- id = long (list[0][1])
- self.registerObjId (id)
+ objId = list[0][1]
+ oidx = objId.index()
+ self.registerObjId (objId)
# If this object hasn't been seen before, create a new object record with
# the timestamps and empty lists for configuration and instrumentation data.
- if id not in self.tables[className]:
- self.tables[className][id] = (timestamps, [], [])
+ if oidx not in self.tables[className]:
+ self.tables[className][oidx] = (timestamps, [], [])
- (unused, oldConf, oldInst) = self.tables[className][id]
+ (unused, oldConf, oldInst) = self.tables[className][oidx]
# For config updates, simply replace old config list with the new one.
if context == 0: #config
- self.tables[className][id] = (timestamps, list, oldInst)
+ self.tables[className][oidx] = (timestamps, list, oldInst)
# For instrumentation updates, carry the minimum and maximum values for
# "hi-lo" stats forward.
@@ -132,7 +133,7 @@ class ManagementData:
if oldInst[idx][1] < value:
value = oldInst[idx][1]
newInst.append ((key, value))
- self.tables[className][id] = (timestamps, oldConf, newInst)
+ self.tables[className][oidx] = (timestamps, oldConf, newInst)
finally:
self.lock.release ()
@@ -211,11 +212,13 @@ class ManagementData:
pass
def refName (self, oid):
- if oid == 0:
+ if oid == None:
return "NULL"
- return str (self.displayObjId (oid))
+ return str (self.displayObjId (oid.index()))
def valueDisplay (self, classKey, key, value):
+ if value == None:
+ return "<NULL>"
for kind in range (2):
schema = self.schema[classKey][kind]
for item in schema:
@@ -437,7 +440,7 @@ class ManagementData:
if classKey in self.tables:
ids = self.listOfIds(classKey, tokens[1:])
for objId in ids:
- (ts, config, inst) = self.tables[classKey][self.rawObjId(objId)]
+ (ts, config, inst) = self.tables[classKey][self.rawObjId(objId).index()]
createTime = self.disp.timestamp (ts[1])
destroyTime = "-"
if ts[2] > 0:
@@ -486,32 +489,32 @@ class ManagementData:
rows = []
timestamp = None
- config = self.tables[classKey][ids[0]][1]
+ config = self.tables[classKey][ids[0].index()][1]
for eIdx in range (len (config)):
key = config[eIdx][0]
if key != "id":
row = ("property", key)
for id in ids:
if timestamp == None or \
- timestamp < self.tables[classKey][id][0][0]:
- timestamp = self.tables[classKey][id][0][0]
- (key, value) = self.tables[classKey][id][1][eIdx]
+ timestamp < self.tables[classKey][id.index()][0][0]:
+ timestamp = self.tables[classKey][id.index()][0][0]
+ (key, value) = self.tables[classKey][id.index()][1][eIdx]
row = row + (self.valueDisplay (classKey, key, value),)
rows.append (row)
- inst = self.tables[classKey][ids[0]][2]
+ inst = self.tables[classKey][ids[0].index()][2]
for eIdx in range (len (inst)):
key = inst[eIdx][0]
if key != "id":
row = ("statistic", key)
for id in ids:
- (key, value) = self.tables[classKey][id][2][eIdx]
+ (key, value) = self.tables[classKey][id.index()][2][eIdx]
row = row + (self.valueDisplay (classKey, key, value),)
rows.append (row)
titleRow = ("Type", "Element")
for id in ids:
- titleRow = titleRow + (self.refName (id),)
+ titleRow = titleRow + (self.refName(id),)
caption = "Object of type %s.%s:" % (classKey[0], classKey[1])
if timestamp != None:
caption = caption + " (last sample time: " + self.disp.timestamp (timestamp) + ")"
@@ -563,13 +566,15 @@ class ManagementData:
access = self.accessName (config[4])
extra = ""
if config[5] == 1:
- extra = extra + "index "
+ extra += "index "
if config[6] != None:
- extra = extra + "Min: " + str (config[6])
+ extra += "Min: " + str(config[6]) + " "
if config[7] != None:
- extra = extra + "Max: " + str (config[7])
+ extra += "Max: " + str(config[7]) + " "
if config[8] != None:
- extra = extra + "MaxLen: " + str (config[8])
+ extra += "MaxLen: " + str(config[8]) + " "
+ if config[9] == 1:
+ extra += "optional "
rows.append ((name, typename, unit, access, extra, desc))
for config in self.schema[classKey][1]:
@@ -613,7 +618,7 @@ class ManagementData:
def getClassForId (self, objId):
""" Given an object ID, return the class key for the referenced object """
for classKey in self.tables:
- if objId in self.tables[classKey]:
+ if objId.index() in self.tables[classKey]:
return classKey
return None
@@ -659,14 +664,19 @@ class ManagementData:
def makeIdRow (self, displayId):
if displayId in self.idMap:
- rawId = self.idMap[displayId]
+ objId = self.idMap[displayId]
else:
return None
- return (displayId,
- rawId,
- (rawId & 0x7FFF000000000000) >> 48,
- (rawId & 0x0000FFFFFF000000) >> 24,
- (rawId & 0x0000000000FFFFFF))
+ if objId.getFlags() == 0:
+ flags = ""
+ else:
+ flags = str(objId.getFlags())
+ seq = objId.getSequence()
+ if seq == 0:
+ seqText = "<durable>"
+ else:
+ seqText = str(seq)
+ return (displayId, flags, seqText, objId.getBroker(), objId.getBank(), hex(objId.getObject()))
def listIds (self, select):
rows = []
@@ -683,7 +693,7 @@ class ManagementData:
return
rows.append(row)
self.disp.table("Translation of Display IDs:",
- ("DisplayID", "RawID", "BootSequence", "Bank", "Object"),
+ ("DisplayID", "Flags", "BootSequence", "Broker", "Bank", "Object"),
rows)
def do_list (self, data):