diff options
| author | Ted Ross <tross@apache.org> | 2008-09-03 18:01:44 +0000 |
|---|---|---|
| committer | Ted Ross <tross@apache.org> | 2008-09-03 18:01:44 +0000 |
| commit | 13191e7951b29453c75db8384391d26f0402139d (patch) | |
| tree | b3ca5bd5f9c8523924cf9d1a0fe118099bef9894 /python/qpid | |
| parent | b8cf7ea1034fa6216183f03022c83efdb154f3ee (diff) | |
| download | qpid-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.py | 181 | ||||
| -rw-r--r-- | python/qpid/managementdata.py | 80 |
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): |
