blob: 19da8ef5fb318f46b89ef7256deed7a8eeaf9489 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
from xml.dom.minidom import parse, parseString, Node
from cStringIO import StringIO
#import md5
try:
import hashlib
_md5Obj = hashlib.md5
except ImportError:
import md5
_md5Obj = md5.new
class Hash:
""" Manage the hash of an XML sub-tree """
def __init__(self, node):
self.md5Sum = _md5Obj()
self._compute(node)
def addSubHash(self, hash):
""" Use this method to add the hash of a dependend-on XML fragment that is not in the sub-tree """
self.md5Sum.update(hash.getDigest())
def getDigest(self):
return self.md5Sum.digest()
def _compute(self, node):
attrs = node.attributes
self.md5Sum.update(node.nodeName)
for idx in range(attrs.length):
self.md5Sum.update(attrs.item(idx).nodeName)
self.md5Sum.update(attrs.item(idx).nodeValue)
for child in node.childNodes:
if child.nodeType == Node.ELEMENT_NODE:
self._compute(child)
#=====================================================================================
#
#=====================================================================================
class SchemaType:
def __init__ (self, node):
self.name = None
self.base = None
self.cpp = None
self.encode = None
self.decode = None
self.style = "normal"
self.stream = "#"
self.size = "1"
self.accessor = None
self.init = "0"
self.perThread = False
self.byRef = False
self.unmap = "#"
self.map = "#"
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = val
elif key == 'base':
self.base = val
elif key == 'cpp':
self.cpp = val
elif key == 'encode':
self.encode = val
elif key == 'decode':
self.decode = val
elif key == 'style':
self.style = val
elif key == 'stream':
self.stream = val
elif key == 'size':
self.size = val
elif key == 'accessor':
self.accessor = val
elif key == 'init':
self.init = val
elif key == 'perThread':
if val != 'y':
raise ValueError ("Expected 'y' in perThread attribute")
self.perThread = True
elif key == 'byRef':
if val != 'y':
raise ValueError ("Expected 'y' in byRef attribute")
self.byRef = True
elif key == 'unmap':
self.unmap = val
elif key == 'map':
self.map = val
else:
raise ValueError ("Unknown attribute in type '%s'" % key)
if self.name == None or self.base == None or self.cpp == None or \
self.encode == None or self.decode == None:
raise ValueError ("Missing required attribute(s) in type")
if self.byRef:
self.asArg = "const " + self.cpp + "&"
else:
self.asArg = self.cpp
def getName (self):
return self.name
def genAccessor (self, stream, varName, changeFlag = None, optional = False):
if self.perThread:
prefix = "getThreadStats()->"
if self.style == "wm":
raise ValueError ("'wm' style types can't be per-thread")
else:
prefix = ""
if self.accessor == "direct":
stream.write (" inline void set_" + varName + " (" + self.asArg + " val) {\n");
if not self.perThread:
stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
if self.style != "mma":
stream.write (" " + prefix + varName + " = val;\n")
if optional:
stream.write (" presenceMask[presenceByte_%s] |= presenceMask_%s;\n" % (varName, varName))
if self.style == "wm":
stream.write (" if (" + varName + "Low > val)\n")
stream.write (" " + varName + "Low = val;\n")
stream.write (" if (" + varName + "High < val)\n")
stream.write (" " + varName + "High = val;\n")
if self.style == "mma":
stream.write (" " + prefix + varName + "Count++;\n")
stream.write (" " + prefix + varName + "Total += val;\n")
stream.write (" if (" + prefix + varName + "Min > val)\n")
stream.write (" " + prefix + varName + "Min = val;\n")
stream.write (" if (" + prefix + varName + "Max < val)\n")
stream.write (" " + prefix + varName + "Max = val;\n")
if changeFlag != None:
stream.write (" " + changeFlag + " = true;\n")
stream.write (" }\n")
if self.style != "mma":
stream.write (" inline " + self.asArg + " get_" + varName + "() {\n");
if not self.perThread:
stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
stream.write (" return " + prefix + varName + ";\n")
stream.write (" }\n")
if optional:
stream.write (" inline void clr_" + varName + "() {\n")
stream.write (" presenceMask[presenceByte_%s] &= ~presenceMask_%s;\n" % (varName, varName))
if changeFlag != None:
stream.write (" " + changeFlag + " = true;\n")
stream.write (" }\n")
stream.write (" inline bool isSet_" + varName + "() {\n")
stream.write (" return (presenceMask[presenceByte_%s] & presenceMask_%s) != 0;\n" % (varName, varName))
stream.write (" }\n")
elif self.accessor == "counter":
stream.write (" inline void inc_" + varName + " (" + self.asArg + " by = 1) {\n");
if not self.perThread:
stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
stream.write (" " + prefix + varName + " += by;\n")
if self.style == "wm":
stream.write (" if (" + varName + "High < " + varName + ")\n")
stream.write (" " + varName + "High = " + varName + ";\n")
if changeFlag != None:
stream.write (" " + changeFlag + " = true;\n")
stream.write (" }\n");
stream.write (" inline void dec_" + varName + " (" + self.asArg + " by = 1) {\n");
if not self.perThread:
stream.write (" ::qpid::management::Mutex::ScopedLock mutex(accessLock);\n")
stream.write (" " + prefix + varName + " -= by;\n")
if self.style == "wm":
stream.write (" if (" + varName + "Low > " + varName + ")\n")
stream.write (" " + varName + "Low = " + varName + ";\n")
if changeFlag != None:
stream.write (" " + changeFlag + " = true;\n")
stream.write (" }\n");
def genHiLoStatResets (self, stream, varName):
if self.style == "wm":
stream.write (" " + varName + "High = " + varName + ";\n")
stream.write (" " + varName + "Low = " + varName + ";\n")
if self.style == "mma":
stream.write (" " + varName + "Count = 0;\n")
stream.write (" " + varName + "Total = 0;\n")
stream.write (" " + varName + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
stream.write (" " + varName + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
def genPerThreadHiLoStatResets (self, stream, varName, cpptype):
if self.style == "mma":
stream.write (" threadStats->" + varName + "Count = 0;\n")
stream.write (" threadStats->" + varName + "Total = 0;\n")
stream.write (" threadStats->" + varName + "Min = std::numeric_limits<" + cpptype + ">::max();\n")
stream.write (" threadStats->" + varName + "Max = std::numeric_limits<" + cpptype + ">::min();\n")
def genRead (self, stream, varName, indent=" "):
stream.write(indent + self.decode.replace("@", "buf").replace("#", varName) + ";\n")
def genUnmap (self, stream, varName, indent=" ", key=None, mapName="_map", _optional=False, _default=None):
if key is None:
key = varName
stream.write(indent + "if ((_i = " + mapName + ".find(\"" + key + "\")) != " + mapName + ".end()) {\n")
stream.write(indent + " " + varName + " = " +
self.unmap.replace("#", "_i->second") + ";\n")
if _optional:
stream.write(indent + " _found = true;\n")
stream.write(indent + "} else {\n")
default = _default
if not default:
default = self.init
stream.write(indent + " " + varName + " = " + default + ";\n")
stream.write(indent + "}\n")
def genWrite (self, stream, varName, indent=" "):
if self.style != "mma":
stream.write (indent + self.encode.replace ("@", "buf").replace ("#", varName) + ";\n")
if self.style == "wm":
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "High") + ";\n")
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "Low") + ";\n")
if self.style == "mma":
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "Count") + ";\n")
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "Count ? " + varName + "Min : 0") + ";\n")
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "Max") + ";\n")
stream.write (indent + self.encode.replace ("@", "buf") \
.replace ("#", varName + "Count ? " + varName + "Total / " +
varName + "Count : 0") + ";\n")
def genMap (self, stream, varName, indent=" ", key=None, mapName="_map"):
if key is None:
key = varName
if self.style != "mma":
var_cast = self.map.replace("#", varName)
stream.write(indent + mapName + "[\"" + key + "\"] = ::qpid::types::Variant(" + var_cast + ");\n")
if self.style == "wm":
var_cast_hi = self.map.replace("#", varName + "High")
var_cast_lo = self.map.replace("#", varName + "Low")
stream.write(indent + mapName + "[\"" + key + "High\"] = " +
"::qpid::types::Variant(" + var_cast_hi + ");\n")
stream.write(indent + mapName + "[\"" + key + "Low\"] = " +
"::qpid::types::Variant(" + var_cast_lo + ");\n")
if self.style == "mma":
var_cast = self.map.replace("#", varName + "Count")
stream.write(indent + mapName + "[\"" + key + "Count\"] = " + "::qpid::types::Variant(" + var_cast + ");\n")
var_cast = self.map.replace("#", varName + "Min")
stream.write(indent + mapName + "[\"" + key + "Min\"] = " +
"(" + varName + "Count ? ::qpid::types::Variant(" + var_cast + ") : ::qpid::types::Variant(0));\n")
var_cast = self.map.replace("#", varName + "Max")
stream.write(indent + mapName + "[\"" + key + "Max\"] = " + "::qpid::types::Variant(" + var_cast + ");\n")
var_cast = self.map.replace("#", "(" + varName + "Total / " + varName + "Count)")
stream.write(indent + mapName + "[\"" + key + "Avg\"] = " +
"(" + varName + "Count ? ::qpid::types::Variant(" + var_cast + ") : ::qpid::types::Variant(0));\n")
def getReadCode (self, varName, bufName):
result = self.decode.replace ("@", bufName).replace ("#", varName)
return result
def getWriteCode (self, varName, bufName):
result = self.encode.replace ("@", bufName).replace ("#", varName)
return result
#=====================================================================================
#
#=====================================================================================
class TypeSpec:
def __init__ (self, file):
self.types = {}
dom = parse (file)
document = dom.documentElement
if document.tagName != 'schema-types':
raise ValueError ("Expected 'schema-types' in type file")
for child in document.childNodes:
if child.nodeType == Node.ELEMENT_NODE:
if child.nodeName == 'type':
stype = SchemaType (child)
self.types[stype.getName ()] = stype
else:
raise ValueError ("Unknown type tag '%s'" % child.nodeName)
def getType (self, name):
return self.types[name]
#=====================================================================================
#
#=====================================================================================
class Type:
def __init__ (self, name, typespec):
self.type = typespec.getType (name)
#=====================================================================================
#
#=====================================================================================
class SchemaProperty:
def __init__ (self, node, typespec):
self.name = None
self.type = None
self.ref = None
self.access = "RO"
self.isIndex = 0
self.isParentRef = 0
self.isGeneralRef = 0
self.isOptional = 0
self.unit = None
self.min = None
self.max = None
self.maxLen = None
self.desc = None
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = makeValidCppSymbol(val)
elif key == 'type':
self.type = Type (val, typespec)
if self.type.type.accessor != 'direct':
raise ValueError ("Class properties must have a type with a direct accessor")
elif key == 'references':
self.ref = val
elif key == 'access':
self.access = val
elif key == 'index':
if val != 'y':
raise ValueError ("Expected 'y' in index attribute")
self.isIndex = 1
elif key == 'parentRef':
if val != 'y':
raise ValueError ("Expected 'y' in parentRef attribute")
self.isParentRef = 1
elif key == 'isGeneralReference':
if val != 'y':
raise ValueError ("Expected 'y' in isGeneralReference attribute")
self.isGeneralRef = 1
elif key == 'optional':
if val != 'y':
raise ValueError ("Expected 'y' in optional attribute")
self.isOptional = 1
elif key == 'unit':
self.unit = val
elif key == 'min':
self.min = val
elif key == 'max':
self.max = val
elif key == 'maxlen':
self.maxLen = val
elif key == 'desc':
self.desc = val
else:
raise ValueError ("Unknown attribute in property '%s'" % key)
if self.access == "RC" and self.isOptional == 1:
raise ValueError ("Properties with ReadCreate access must not be optional (%s)" % self.name)
if self.name == None:
raise ValueError ("Missing 'name' attribute in property")
if self.type == None:
raise ValueError ("Missing 'type' attribute in property")
def getName (self):
return self.name
def isConstructorArg (self):
if self.access == "RC" and self.isParentRef == 0:
return 1
return 0
def genDeclaration (self, stream, prefix=" "):
stream.write (prefix + self.type.type.cpp + " " + self.name + ";\n")
def genFormalParam (self, stream, variables):
stream.write (self.type.type.asArg + " _" + self.name)
def genAccessor (self, stream):
self.type.type.genAccessor (stream, self.name, "configChanged", self.isOptional == 1)
def genInitialize (self, stream, prefix="", indent=" "):
val = self.type.type.init
stream.write (indent + prefix + self.name + " = " + val + ";\n")
def genSchema (self, stream):
stream.write (" ft.clear();\n")
stream.write (" ft[NAME] = \"" + self.name + "\";\n")
stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
stream.write (" ft[ACCESS] = ACCESS_" + self.access + ";\n")
stream.write (" ft[IS_INDEX] = " + str (self.isIndex) + ";\n")
stream.write (" ft[IS_OPTIONAL] = " + str (self.isOptional) + ";\n")
if self.unit != None:
stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
if self.min != None:
stream.write (" ft[MIN] = " + self.min + ";\n")
if self.max != None:
stream.write (" ft[MAX] = " + self.max + ";\n")
if self.maxLen != None:
stream.write (" ft[MAXLEN] = " + self.maxLen + ";\n")
if self.desc != None:
stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
stream.write (" buf.putMap(ft);\n\n")
def genSchemaMap(self, stream):
stream.write (" {\n")
stream.write (" ::qpid::types::Variant::Map _value;\n")
stream.write (" _value[TYPE] = TYPE_" + self.type.type.base +";\n")
stream.write (" _value[ACCESS] = ACCESS_" + self.access + ";\n")
stream.write (" _value[IS_INDEX] = " + str (self.isIndex) + ";\n")
stream.write (" _value[IS_OPTIONAL] = " + str (self.isOptional) + ";\n")
if self.unit != None:
stream.write (" _value[UNIT] = \"" + self.unit + "\";\n")
if self.min != None:
stream.write (" _value[MIN] = " + self.min + ";\n")
if self.max != None:
stream.write (" _value[MAX] = " + self.max + ";\n")
if self.maxLen != None:
stream.write (" _value[MAXLEN] = " + self.maxLen + ";\n")
if self.desc != None:
stream.write (" _value[DESC] = \"" + self.desc + "\";\n")
stream.write (" _props[\"" + self.name + "\"] = _value;\n")
stream.write (" }\n\n")
def genSize (self, stream):
indent = " "
if self.isOptional:
stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
indent = " "
stream.write("%ssize += %s; // %s\n" % (indent, self.type.type.size.replace("#", self.name), self.name))
if self.isOptional:
stream.write(" }\n")
def genRead (self, stream):
indent = " "
if self.isOptional:
stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
indent = " "
self.type.type.genRead (stream, self.name, indent)
if self.isOptional:
stream.write(" }\n")
def genWrite (self, stream):
indent = " "
if self.isOptional:
stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
indent = " "
self.type.type.genWrite (stream, self.name, indent)
if self.isOptional:
stream.write(" }\n")
def genUnmap (self, stream):
indent = " "
if self.isOptional:
stream.write(" _found = false;\n")
self.type.type.genUnmap (stream, self.name, indent, _optional=self.isOptional)
if self.isOptional:
stream.write(" if (_found) {\n")
stream.write(" presenceMask[presenceByte_%s] |= presenceMask_%s;\n" %
(self.name, self.name))
stream.write(" }\n")
def genMap (self, stream):
indent = " "
if self.isOptional:
stream.write(" if (presenceMask[presenceByte_%s] & presenceMask_%s) {\n" % (self.name, self.name))
indent = " "
self.type.type.genMap (stream, self.name, indent)
if self.isOptional:
stream.write(" }\n")
def __repr__(self):
m = {}
m["name"] = self.name
m["type"] = self.type
m["ref"] = self.ref
m["access"] = self.access
m["isIndex"] = self.isIndex
m["isParentRef"] = self.isParentRef
m["isGeneralRef"] = self.isGeneralRef
m["isOptional"] = self.isOptional
m["unit"] = self.unit
m["min"] = self.min
m["max"] = self.max
m["maxLen"] = self.maxLen
m["desc"] = self.desc
return str(m)
#=====================================================================================
#
#=====================================================================================
class SchemaStatistic:
def __init__ (self, node, typespec):
self.name = None
self.type = None
self.unit = None
self.desc = None
self.assign = None
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = makeValidCppSymbol(val)
elif key == 'type':
self.type = Type (val, typespec)
elif key == 'unit':
self.unit = val
elif key == 'desc':
self.desc = val
elif key == 'assign':
self.assign = val
else:
raise ValueError ("Unknown attribute in statistic '%s'" % key)
if self.name == None:
raise ValueError ("Missing 'name' attribute in statistic")
if self.type == None:
raise ValueError ("Missing 'type' attribute in statistic")
def getName (self):
return self.name
def genDeclaration (self, stream, prefix=" "):
if self.type.type.style != "mma":
stream.write (prefix + self.type.type.cpp + " " + self.name + ";\n")
if self.type.type.style == 'wm':
stream.write (prefix + self.type.type.cpp + " " + self.name + "High;\n")
stream.write (prefix + self.type.type.cpp + " " + self.name + "Low;\n")
if self.type.type.style == "mma":
stream.write (prefix + self.type.type.cpp + " " + self.name + "Count;\n")
stream.write (prefix + "uint64_t " + self.name + "Total;\n")
stream.write (prefix + self.type.type.cpp + " " + self.name + "Min;\n")
stream.write (prefix + self.type.type.cpp + " " + self.name + "Max;\n")
def genAccessor (self, stream):
self.type.type.genAccessor (stream, self.name, "instChanged")
def genHiLoStatResets (self, stream):
self.type.type.genHiLoStatResets (stream, self.name)
def genPerThreadHiLoStatResets (self, stream):
self.type.type.genPerThreadHiLoStatResets (stream, self.name, self.type.type.cpp)
def genSchemaText (self, stream, name, desc):
stream.write (" ft.clear();\n")
stream.write (" ft[NAME] = \"" + name + "\";\n")
stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
if self.unit != None:
stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
if desc != None:
stream.write (" ft[DESC] = \"" + desc + "\";\n")
stream.write (" buf.putMap(ft);\n\n")
def genSchemaTextMap(self, stream, name, desc):
stream.write (" {\n")
stream.write (" ::qpid::types::Variant::Map _value;\n")
stream.write (" _value[TYPE] = TYPE_" + self.type.type.base +";\n")
if self.unit != None:
stream.write (" _value[UNIT] = \"" + self.unit + "\";\n")
if desc != None:
stream.write (" _value[DESC] = \"" + desc + "\";\n")
stream.write (" _stats[\"" + self.name + "\"] = _value;\n")
stream.write (" }\n\n")
def genSchema (self, stream):
if self.type.type.style != "mma":
self.genSchemaText (stream, self.name, self.desc)
if self.type.type.style == "wm":
descHigh = self.desc
descLow = self.desc
if self.desc != None:
descHigh = descHigh + " (High)"
descLow = descLow + " (Low)"
self.genSchemaText (stream, self.name + "High", descHigh)
self.genSchemaText (stream, self.name + "Low", descLow)
if self.type.type.style == "mma":
descCount = self.desc
descMin = self.desc
descMax = self.desc
descAverage = self.desc
if self.desc != None:
descCount = descCount + " (Samples)"
descMin = descMin + " (Min)"
descMax = descMax + " (Max)"
descAverage = descAverage + " (Average)"
self.genSchemaText (stream, self.name + "Samples", descCount)
self.genSchemaText (stream, self.name + "Min", descMin)
self.genSchemaText (stream, self.name + "Max", descMax)
self.genSchemaText (stream, self.name + "Average", descAverage)
def genSchemaMap (self, stream):
if self.type.type.style != "mma":
self.genSchemaTextMap (stream, self.name, self.desc)
if self.type.type.style == "wm":
descHigh = self.desc
descLow = self.desc
if self.desc != None:
descHigh = descHigh + " (High)"
descLow = descLow + " (Low)"
self.genSchemaTextMap (stream, self.name + "High", descHigh)
self.genSchemaTextMap (stream, self.name + "Low", descLow)
if self.type.type.style == "mma":
descCount = self.desc
descMin = self.desc
descMax = self.desc
descAverage = self.desc
if self.desc != None:
descCount = descCount + " (Samples)"
descMin = descMin + " (Min)"
descMax = descMax + " (Max)"
descAverage = descAverage + " (Average)"
self.genSchemaTextMap (stream, self.name + "Samples", descCount)
self.genSchemaTextMap (stream, self.name + "Min", descMin)
self.genSchemaTextMap (stream, self.name + "Max", descMax)
self.genSchemaTextMap (stream, self.name + "Average", descAverage)
def genAssign (self, stream):
if self.assign != None:
if self.type.type.perThread:
prefix = " threadStats->"
else:
prefix = ""
stream.write (" " + prefix + self.name + " = (" + self.type.type.cpp +
") (" + self.assign + ");\n")
def genWrite (self, stream):
if self.type.type.perThread:
self.type.type.genWrite (stream, "totals." + self.name)
else:
self.type.type.genWrite (stream, self.name)
def genMap (self, stream):
if self.type.type.perThread:
self.type.type.genMap(stream, "totals." + self.name, key=self.name)
else:
self.type.type.genMap(stream, self.name)
def genInitialize (self, stream, prefix="", indent=" "):
val = self.type.type.init
if self.type.type.style != "mma":
stream.write (indent + prefix + self.name + " = " + val + ";\n")
if self.type.type.style == "wm":
stream.write (indent + prefix + self.name + "High = " + val + ";\n")
stream.write (indent + prefix + self.name + "Low = " + val + ";\n")
if self.type.type.style == "mma":
stream.write (indent + prefix + self.name + "Count = 0;\n")
stream.write (indent + prefix + self.name + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
stream.write (indent + prefix + self.name + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
stream.write (indent + prefix + self.name + "Total = 0;\n")
def genInitializeTotalPerThreadStats (self, stream):
if self.type.type.style == "mma":
stream.write (" totals->" + self.name + "Count = 0;\n")
stream.write (" totals->" + self.name + "Min = std::numeric_limits<" + self.type.type.cpp + ">::max();\n")
stream.write (" totals->" + self.name + "Max = std::numeric_limits<" + self.type.type.cpp + ">::min();\n")
stream.write (" totals->" + self.name + "Total = 0;\n")
else:
stream.write (" totals->" + self.name + " = 0;\n")
def genAggregatePerThreadStats (self, stream):
if self.type.type.style == "mma":
stream.write (" totals->%sCount += threadStats->%sCount;\n" % (self.name, self.name))
stream.write (" if (totals->%sMin > threadStats->%sMin)\n" % (self.name, self.name))
stream.write (" totals->%sMin = threadStats->%sMin;\n" % (self.name, self.name))
stream.write (" if (totals->%sMax < threadStats->%sMax)\n" % (self.name, self.name))
stream.write (" totals->%sMax = threadStats->%sMax;\n" % (self.name, self.name))
stream.write (" totals->%sTotal += threadStats->%sTotal;\n" % (self.name, self.name))
else:
stream.write (" totals->%s += threadStats->%s;\n" % (self.name, self.name))
#=====================================================================================
#
#=====================================================================================
class SchemaArg:
def __init__ (self, node, typespec):
self.name = None
self.type = None
self.unit = None
self.dir = "I"
self.min = None
self.max = None
self.maxLen = None
self.desc = None
self.default = None
self.hash = Hash(node)
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = makeValidCppSymbol(val)
elif key == 'type':
self.type = Type (val, typespec)
elif key == 'unit':
self.unit = val
elif key == 'dir':
self.dir = val.upper ()
elif key == 'min':
self.min = val
elif key == 'max':
self.max = val
elif key == 'maxlen':
self.maxLen = val
elif key == 'desc':
self.desc = val
elif key == 'default':
self.default = val
else:
raise ValueError ("Unknown attribute in arg '%s'" % key)
if self.name == None:
raise ValueError ("Missing 'name' attribute in arg")
if self.type == None:
raise ValueError ("Missing 'type' attribute in arg")
def getName (self):
return self.name
def getDir (self):
return self.dir
def genSchema (self, stream, event=False):
stream.write (" ft.clear();\n")
stream.write (" ft[NAME] = \"" + self.name + "\";\n")
stream.write (" ft[TYPE] = TYPE_" + self.type.type.base +";\n")
if (not event):
stream.write (" ft[DIR] = \"" + self.dir + "\";\n")
if self.unit != None:
stream.write (" ft[UNIT] = \"" + self.unit + "\";\n")
if not event:
if self.min != None:
stream.write (" ft[MIN] = " + self.min + ";\n")
if self.max != None:
stream.write (" ft[MAX] = " + self.max + ";\n")
if self.maxLen != None:
stream.write (" ft[MAXLEN] = " + self.maxLen + ";\n")
if self.default != None:
stream.write (" ft[DEFAULT] = \"" + self.default + "\";\n")
if self.desc != None:
stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
stream.write (" buf.putMap(ft);\n\n")
def genSchemaMap (self, stream, event=False):
stream.write (" {\n")
stream.write (" ::qpid::types::Variant::Map _avalue;\n")
stream.write (" _avalue[TYPE] = TYPE_" + self.type.type.base +";\n")
if (not event):
stream.write (" _avalue[DIR] = \"" + self.dir + "\";\n")
if self.unit != None:
stream.write (" _avalue[UNIT] = \"" + self.unit + "\";\n")
if not event:
if self.min != None:
stream.write (" _avalue[MIN] = " + self.min + ";\n")
if self.max != None:
stream.write (" _avalue[MAX] = " + self.max + ";\n")
if self.maxLen != None:
stream.write (" _avalue[MAXLEN] = " + self.maxLen + ";\n")
if self.default != None:
stream.write (" _avalue[DEFAULT] = \"" + self.default + "\";\n")
if self.desc != None:
stream.write (" _avalue[DESC] = \"" + self.desc + "\";\n")
stream.write (" _args[\"" + self.name + "\"] = _avalue;\n")
stream.write (" }\n")
def genFormalParam (self, stream, variables):
stream.write ("%s _%s" % (self.type.type.asArg, self.name))
#=====================================================================================
#
#=====================================================================================
class SchemaMethod:
def __init__ (self, parent, node, typespec):
self.parent = parent
self.name = None
self.desc = None
self.args = []
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = makeValidCppSymbol(val)
elif key == 'desc':
self.desc = val
else:
raise ValueError ("Unknown attribute in method '%s'" % key)
for child in node.childNodes:
if child.nodeType == Node.ELEMENT_NODE:
if child.nodeName == 'arg':
arg = SchemaArg (child, typespec)
self.args.append (arg)
else:
raise ValueError ("Unknown method tag '%s'" % child.nodeName)
def getName (self):
return self.name
def getFullName (self):
return capitalize(self.parent.getName()) + self.name[0:1].upper() +\
self.name[1:]
def getArgCount (self):
return len (self.args)
#===================================================================================
# Code Generation Functions. The names of these functions (minus the leading "gen")
# match the substitution keywords in the template files.
#===================================================================================
def genNameUpper (self, stream, variables):
stream.write (self.getFullName ().upper ())
def genNameCamel (self, stream, variables):
stream.write (self.getFullName ())
def genOpenNamespaces (self, stream, variables):
self.parent.genOpenNamespaces(stream, variables)
def genCloseNamespaces (self, stream, variables):
self.parent.genCloseNamespaces(stream, variables)
def genArguments (self, stream, variables):
for arg in self.args:
ctype = arg.type.type.cpp
dirTag = arg.dir.lower() + "_"
stream.write (" " + ctype + " " + dirTag + arg.getName () + ";\n")
def genNamePackageLower (self, stream, variables):
self.parent.genNamePackageLower(stream, variables)
def genSchema (self, stream, variables):
stream.write (" ft.clear();\n")
stream.write (" ft[NAME] = \"" + self.name + "\";\n")
stream.write (" ft[ARGCOUNT] = " + str (len (self.args)) + ";\n")
if self.desc != None:
stream.write (" ft[DESC] = \"" + self.desc + "\";\n")
stream.write (" buf.putMap(ft);\n\n")
for arg in self.args:
arg.genSchema (stream)
def genSchemaMap (self, stream, variables):
stream.write (" {\n")
stream.write (" ::qpid::types::Variant::Map _value;\n")
stream.write (" ::qpid::types::Variant::Map _args;\n")
stream.write (" _value[ARGCOUNT] = " + str(len(self.args)) + ";\n")
if self.desc != None:
stream.write (" _value[DESC] = \"" + self.desc + "\";\n")
for arg in self.args:
arg.genSchemaMap (stream)
stream.write (" if (!_args.empty())\n")
stream.write (" _value[ARGS] = _args;\n")
stream.write (" _methods[\"" + self.name + "\"] = _value;\n")
stream.write (" }\n\n")
#=====================================================================================
#
#=====================================================================================
class SchemaEvent:
def __init__ (self, package, node, typespec, argset):
self.packageName = package
self.name = None
self.desc = None
self.sevText = "inform"
self.args = []
self.hash = Hash(node)
attrs = node.attributes
for idx in range (attrs.length):
key = attrs.item(idx).nodeName
val = attrs.item(idx).nodeValue
if key == 'name':
self.name = val
elif key == 'desc':
self.desc = val
elif key == 'sev':
self.sevText = val
elif key == 'args':
list = val.replace(" ", "").split(",")
for item in list:
if item not in argset.args:
raise Exception("undefined argument '%s' in event" % item)
self.args.append(argset.args[item])
self.hash.addSubHash(argset.args[item].hash)
else:
raise ValueError ("Unknown attribute in event '%s'" % key)
if self.sevText == "emerg" : self.sev = 0
elif self.sevText == "alert" : self.sev = 1
elif self.sevText == "crit" : self.sev = 2
elif self.sevText == "error" : self.sev = 3
elif self.sevText == "warn" : self.sev = 4
elif self.sevText == "notice" : self.sev = 5
elif self.sevText == "inform" : self.sev = 6
elif self.sevText == "debug" : self.sev = 7
else:
raise ValueError("Unknown severity '%s' in event '%s'" % (self.sevText, self.name))
def getName (self):
return self.name
def getNameCap(self):
return capitalize(self.name)
def getFullName (self):
return capitalize(self.package + capitalize(self.name))
def genAgentHeaderLocation (self, stream, variables):
stream.write(variables["agentHeaderDir"])
def getArgCount (self):
return len (self.args)
def genArgCount (self, stream, variables):
stream.write("%d" % len(self.args))
def genArgDeclarations(self, stream, variables):
for arg in self.args:
if arg.type.type.byRef:
ref = "&"
else:
ref = ""
stream.write(" const %s%s %s;\n" % (arg.type.type.cpp, ref, arg.name))
def genCloseNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("}")
def genConstructorArgs(self, stream, variables):
pre = ""
for arg in self.args:
if arg.type.type.byRef:
ref = "&"
else:
ref = ""
stream.write("%sconst %s%s _%s" % (pre, arg.type.type.cpp, ref, arg.name))
pre = ",\n "
def genConstructorInits(self, stream, variables):
pre = ""
for arg in self.args:
stream.write("%s%s(_%s)" % (pre, arg.name, arg.name))
pre = ",\n "
def genName(self, stream, variables):
stream.write(self.name)
def genNameCap(self, stream, variables):
stream.write(capitalize(self.name))
def genNamespace (self, stream, variables):
stream.write("::".join(self.packageName.split(".")))
def genNameLower(self, stream, variables):
stream.write(self.name.lower())
def genNameUpper(self, stream, variables):
stream.write(self.name.upper())
def genNamePackageLower(self, stream, variables):
stream.write(self.packageName.lower())
def genOpenNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("namespace %s {\n" % item)
def genSeverity(self, stream, variables):
stream.write("%d" % self.sev)
def genArgEncodes(self, stream, variables):
for arg in self.args:
stream.write(" " + arg.type.type.encode.replace("@", "buf").replace("#", arg.name) + ";\n")
def genArgMap(self, stream, variables):
for arg in self.args:
arg.type.type.genMap(stream, arg.name, " ", mapName="map")
#stream.write(" " + arg.type.type.encode.replace("@", "buf").replace("#", arg.name) + ";\n")
def genArgSchema(self, stream, variables):
for arg in self.args:
arg.genSchema(stream, True)
def genArgSchemaMap(self, stream, variables):
for arg in self.args:
arg.genSchemaMap(stream, True)
def genSchemaMD5(self, stream, variables):
sum = self.hash.getDigest()
for idx in range (len (sum)):
if idx != 0:
stream.write (",")
stream.write (hex (ord (sum[idx])))
class SchemaClass:
def __init__ (self, package, node, typespec, fragments, options):
self.packageName = package
self.properties = []
self.statistics = []
self.methods = []
self.events = []
self.options = options
self.hash = Hash(node)
attrs = node.attributes
self.name = makeValidCppSymbol(attrs['name'].nodeValue)
children = node.childNodes
for child in children:
if child.nodeType == Node.ELEMENT_NODE:
if child.nodeName == 'property':
sub = SchemaProperty (child, typespec)
self.properties.append (sub)
elif child.nodeName == 'statistic':
sub = SchemaStatistic (child, typespec)
self.statistics.append (sub)
elif child.nodeName == 'method':
sub = SchemaMethod (self, child, typespec)
self.methods.append (sub)
elif child.nodeName == 'group':
self.expandFragment (child, fragments)
else:
raise ValueError ("Unknown class tag '%s'" % child.nodeName)
# Adjust the 'assign' attributes for each statistic
for stat in self.statistics:
if stat.assign != None and stat.type.type.perThread:
stat.assign = self.adjust (stat.assign, self.statistics)
def adjust (self, text, statistics):
result = text
start = 0
while True:
next = None
for stat in statistics:
pos = result.find (stat.name, start)
if pos != -1 and (next == None or pos < next[0]):
next = (pos, stat.name)
if next == None:
return result
pos = next[0]
result = result[0:pos] + "threadStats->" + result[pos:]
start = pos + 9 + len(next[1])
def expandFragment (self, node, fragments):
attrs = node.attributes
name = attrs['name'].nodeValue
for fragment in fragments:
if fragment.name == name:
self.hash.addSubHash(fragment.hash)
for config in fragment.properties:
self.properties.append (config)
for inst in fragment.statistics:
self.statistics.append (inst)
for method in fragment.methods:
self.methods.append (method)
for event in fragment.events:
self.events.append (event)
return
raise ValueError ("Undefined group '%s'" % name)
def getName (self):
return self.name
def getNameCap (self):
return capitalize(self.name)
def getMethods (self):
return self.methods
def getEvents (self):
return self.events
def getPackageNameCap (self):
return capitalize(self.packageName)
#===================================================================================
# Code Generation Functions. The names of these functions (minus the leading "gen")
# match the substitution keywords in the template files.
#===================================================================================
def testExistOptionals (self, variables):
for prop in self.properties:
if prop.isOptional == 1:
return True
return False
def testExistPerThreadStats (self, variables):
for inst in self.statistics:
if inst.type.type.perThread:
return True
return False
def testExistPerThreadAssign (self, variables):
for inst in self.statistics:
if inst.type.type.perThread and inst.assign != None:
return True
return False
def testExistPerThreadResets (self, variables):
for inst in self.statistics:
if inst.type.type.perThread and inst.type.type.style == "mma":
return True
return False
def testNoStatistics (self, variables):
return len (self.statistics) == 0
def genAccessorMethods (self, stream, variables):
for config in self.properties:
if config.access != "RC":
config.genAccessor (stream)
for inst in self.statistics:
if inst.assign == None:
inst.genAccessor (stream)
def genAgentHeaderLocation (self, stream, variables):
stream.write(variables["agentHeaderDir"])
def genCloseNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("}")
def genConfigCount (self, stream, variables):
stream.write ("%d" % len (self.properties))
def genConfigDeclarations (self, stream, variables):
for element in self.properties:
element.genDeclaration (stream)
def genConstructorArgs (self, stream, variables):
# Constructor args are config elements with read-create access
result = ""
for element in self.properties:
if element.isConstructorArg ():
stream.write (", ")
element.genFormalParam (stream, variables)
def genConstructorInits (self, stream, variables):
for element in self.properties:
if element.isConstructorArg ():
stream.write ("," + element.getName () + "(_" + element.getName () + ")")
def genDoMethodArgs (self, stream, variables):
methodCount = 0
inArgCount = 0
for method in self.methods:
methodCount = methodCount + 1
for arg in method.args:
if arg.getDir () == "I" or arg.getDir () == "IO":
inArgCount = inArgCount + 1
if methodCount == 0:
stream.write ("string&, const string&, string& outStr, const string&")
else:
if inArgCount == 0:
stream.write ("string& methodName, const string&, string& outStr, const string& userId")
else:
stream.write ("string& methodName, const string& inStr, string& outStr, const string& userId")
def genDoMapMethodArgs (self, stream, variables):
methodCount = 0
inArgCount = 0
for method in self.methods:
methodCount = methodCount + 1
for arg in method.args:
if arg.getDir () == "I" or arg.getDir () == "IO":
inArgCount = inArgCount + 1
if methodCount == 0:
stream.write ("string&," +
" const ::qpid::types::Variant::Map&," +
" ::qpid::types::Variant::Map& outMap, const string&")
else:
if inArgCount == 0:
stream.write ("string& methodName," +
" const ::qpid::types::Variant::Map&," +
" ::qpid::types::Variant::Map& outMap, const string& userId")
else:
stream.write ("string& methodName," +
" const ::qpid::types::Variant::Map& inMap," +
" ::qpid::types::Variant::Map& outMap, const string& userId")
def genHiLoStatResets (self, stream, variables):
for inst in self.statistics:
if not inst.type.type.perThread:
inst.genHiLoStatResets (stream)
def genPerThreadHiLoStatResets (self, stream, variables):
for inst in self.statistics:
if inst.type.type.perThread:
inst.genPerThreadHiLoStatResets (stream)
def genInitializeElements (self, stream, variables):
for prop in self.properties:
if not prop.isConstructorArg() and not prop.isParentRef:
prop.genInitialize(stream)
for inst in self.statistics:
if not inst.type.type.perThread:
inst.genInitialize (stream)
def genInitializePerThreadElements (self, stream, variables):
for inst in self.statistics:
if inst.type.type.perThread:
inst.genInitialize (stream, "threadStats->", " ")
def genInitializeTotalPerThreadStats (self, stream, variables):
for inst in self.statistics:
if inst.type.type.perThread:
inst.genInitializeTotalPerThreadStats (stream)
def genAggregatePerThreadStats (self, stream, variables):
for inst in self.statistics:
if inst.type.type.perThread:
inst.genAggregatePerThreadStats (stream)
def genInstCount (self, stream, variables):
count = 0
for inst in self.statistics:
count = count + 1
if inst.type.type.style == "wm":
count = count + 2
if inst.type.type.style == "mma":
count = count + 3
stream.write ("%d" % count)
def genInstDeclarations (self, stream, variables):
for element in self.statistics:
if not element.type.type.perThread:
element.genDeclaration (stream)
def genPerThreadDeclarations (self, stream, variables):
for element in self.statistics:
if element.type.type.perThread:
element.genDeclaration (stream, " ")
def genPrimaryKey (self, stream, variables):
first = 1
for prop in self.properties:
# deliberately leave out the "vhostRef" fields since there's only one vhost,
# this serves to shorten the keys without compromising uniqueness
if prop.getName() != "vhostRef":
if prop.isIndex == 1:
if first:
first = None
else:
stream.write(" << \",\";\n")
var = prop.type.type.stream.replace("#", prop.getName())
stream.write(" key << %s" % var)
if not first:
stream.write(";")
def genNamespace (self, stream, variables):
stream.write("::".join(self.packageName.split(".")))
def genMethodArgIncludes (self, stream, variables):
for method in self.methods:
if method.getArgCount () > 0:
stream.write ("#include \"Args" + method.getFullName () + ".h\"\n")
def genMethodCount (self, stream, variables):
stream.write ("%d" % len (self.methods))
def genMethodHandlers (self, stream, variables):
inArgs = False
for method in self.methods:
for arg in method.args:
if arg.getDir () == "I" or arg.getDir () == "IO":
inArgs = True;
break
if inArgs:
stream.write("\n")
stream.write(" char *_tmpBuf = new char[inStr.length()];\n")
stream.write(" memcpy(_tmpBuf, inStr.data(), inStr.length());\n")
stream.write(" ::qpid::management::Buffer inBuf(_tmpBuf, inStr.length());\n")
for method in self.methods:
stream.write ("\n if (methodName == \"" + method.getName () + "\") {\n")
stream.write (" _matched = true;\n")
if method.getArgCount () == 0:
stream.write (" ::qpid::management::ArgsNone ioArgs;\n")
else:
stream.write (" Args" + method.getFullName () + " ioArgs;\n")
for arg in method.args:
if arg.getDir () == "I" or arg.getDir () == "IO":
stream.write (" " +\
arg.type.type.getReadCode ("ioArgs." +\
arg.dir.lower () + "_" +\
arg.name, "inBuf") + ";\n")
stream.write (" bool allow = manageable.AuthorizeMethod(METHOD_" +\
method.getName().upper() + ", ioArgs, userId);\n")
stream.write (" if (allow)\n")
stream.write (" status = manageable.ManagementMethod (METHOD_" +\
method.getName().upper() + ", ioArgs, text);\n")
stream.write (" else\n")
stream.write (" status = Manageable::STATUS_FORBIDDEN;\n")
stream.write (" outBuf.putLong (status);\n")
stream.write (" outBuf.putMediumString(::qpid::management::Manageable::StatusText (status, text));\n")
for arg in method.args:
if arg.getDir () == "O" or arg.getDir () == "IO":
stream.write (" " +\
arg.type.type.getWriteCode ("ioArgs." +\
arg.dir.lower () + "_" +\
arg.name, "outBuf") + ";\n")
stream.write(" }\n")
if inArgs:
stream.write ("\n delete [] _tmpBuf;\n")
def genMapMethodHandlers (self, stream, variables):
for method in self.methods:
stream.write ("\n if (methodName == \"" + method.getName () + "\") {\n")
if method.getArgCount () == 0:
stream.write (" ::qpid::management::ArgsNone ioArgs;\n")
else:
stream.write (" Args" + method.getFullName () + " ioArgs;\n")
stream.write (" ::qpid::types::Variant::Map::const_iterator _i;\n")
# decode each input argument from the input map
for arg in method.args:
if arg.getDir () == "I" or arg.getDir () == "IO":
arg.type.type.genUnmap(stream,
"ioArgs." + arg.dir.lower () + "_" + arg.name,
" ",
arg.name,
"inMap",
False,
arg.default)
stream.write (" bool allow = manageable.AuthorizeMethod(METHOD_" +\
method.getName().upper() + ", ioArgs, userId);\n")
stream.write (" if (allow)\n")
stream.write (" status = manageable.ManagementMethod (METHOD_" +\
method.getName().upper() + ", ioArgs, text);\n")
stream.write (" else\n")
stream.write (" status = Manageable::STATUS_FORBIDDEN;\n")
stream.write (" outMap[\"_status_code\"] = (uint32_t) status;\n")
stream.write (" outMap[\"_status_text\"] = ::qpid::management::Manageable::StatusText(status, text);\n")
for arg in method.args:
if arg.getDir () == "O" or arg.getDir () == "IO":
arg.type.type.genMap(stream,
"ioArgs." + arg.dir.lower () + "_" + arg.name,
" ",
arg.name,
"outMap")
stream.write (" return;\n }\n")
def genOpenNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("namespace %s {\n" % item)
def genPresenceMaskBytes (self, stream, variables):
count = 0
for prop in self.properties:
if prop.isOptional == 1:
count += 1
if count == 0:
stream.write("0")
else:
stream.write (str(((count - 1) / 8) + 1))
def genPresenceMaskConstants (self, stream, variables):
count = 0
for prop in self.properties:
if prop.isOptional == 1:
stream.write(" static const uint8_t presenceByte_%s = %d;\n" % (prop.name, count / 8))
stream.write(" static const uint8_t presenceMask_%s = %d;\n" % (prop.name, 1 << (count % 8)))
count += 1
def genPropertySchema (self, stream, variables):
for prop in self.properties:
prop.genSchema (stream)
def genPropertySchemaMap (self, stream, variables):
for prop in self.properties:
prop.genSchemaMap(stream)
def genSetGeneralReferenceDeclaration (self, stream, variables):
for prop in self.properties:
if prop.isGeneralRef:
stream.write ("void setReference(::qpid::management::ObjectId objectId) { " + prop.name + " = objectId; }\n")
def genStatisticSchema (self, stream, variables):
for stat in self.statistics:
stat.genSchema (stream)
def genStatisticSchemaMap (self, stream, variables):
for stat in self.statistics:
stat.genSchemaMap(stream)
def genMethodIdDeclarations (self, stream, variables):
number = 1
ext = ""
if variables['genForBroker']:
ext = "QPID_BROKER_EXTERN "
for method in self.methods:
stream.write (" " + ext + "static const uint32_t METHOD_" + method.getName().upper() +\
" = %d;\n" % number)
number = number + 1
def genMethodSchema (self, stream, variables):
for method in self.methods:
method.genSchema (stream, variables)
def genMethodSchemaMap(self, stream, variables):
for method in self.methods:
method.genSchemaMap(stream, variables)
def genName (self, stream, variables):
stream.write (self.name)
def genNameCap (self, stream, variables):
stream.write (capitalize(self.name))
def genNameLower (self, stream, variables):
stream.write (self.name.lower ())
def genNamePackageCap (self, stream, variables):
stream.write (self.getPackageNameCap ())
def genNamePackageLower (self, stream, variables):
stream.write (self.packageName.lower ())
def genPackageNameUpper (self, stream, variables):
up = "_".join(self.packageName.split("."))
stream.write (up.upper())
def genNameUpper (self, stream, variables):
stream.write (self.name.upper ())
def genParentArg (self, stream, variables):
for config in self.properties:
if config.isParentRef == 1:
stream.write (", ::qpid::management::Manageable* _parent")
return
def genParentRefAssignment (self, stream, variables):
for config in self.properties:
if config.isParentRef == 1:
stream.write (config.getName () + \
" = _parent->GetManagementObject()->getObjectId();")
return
def genSchemaMD5 (self, stream, variables):
sum = self.hash.getDigest()
for idx in range (len (sum)):
if idx != 0:
stream.write (",")
stream.write (hex (ord (sum[idx])))
def genAssign (self, stream, variables):
for inst in self.statistics:
if not inst.type.type.perThread:
inst.genAssign (stream)
def genPerThreadAssign (self, stream, variables):
for inst in self.statistics:
if inst.type.type.perThread:
inst.genAssign (stream)
def genSizeProperties (self, stream, variables):
for prop in self.properties:
prop.genSize (stream)
def genReadProperties (self, stream, variables):
for prop in self.properties:
prop.genRead (stream)
def genWriteProperties (self, stream, variables):
for prop in self.properties:
prop.genWrite (stream)
def genWriteStatistics (self, stream, variables):
for stat in self.statistics:
stat.genWrite (stream)
def genMapEncodeProperties(self, stream, variables):
for prop in self.properties:
prop.genMap (stream)
def genMapEncodeStatistics (self, stream, variables):
for stat in self.statistics:
stat.genMap (stream)
def genMapDecodeProperties (self, stream, variables):
for prop in self.properties:
prop.genUnmap (stream)
class SchemaEventArgs:
def __init__(self, package, node, typespec, fragments, options):
self.packageName = package
self.options = options
self.args = {}
children = node.childNodes
for child in children:
if child.nodeType == Node.ELEMENT_NODE:
if child.nodeName == 'arg':
arg = SchemaArg(child, typespec)
self.args[arg.name] = arg
else:
raise Exception("Unknown tag '%s' in <eventArguments>" % child.nodeName)
class SchemaPackage:
def __init__ (self, typefile, schemafile, options):
self.classes = []
self.fragments = []
self.typespec = TypeSpec (typefile)
self.eventArgSet = None
self.events = []
dom = parse (schemafile)
document = dom.documentElement
if document.tagName != 'schema':
raise ValueError ("Expected 'schema' node")
attrs = document.attributes
pname = attrs['package'].nodeValue
namelist = pname.split('.')
self.packageName = ".".join(namelist)
children = document.childNodes
for child in children:
if child.nodeType == Node.ELEMENT_NODE:
if child.nodeName == 'class':
cls = SchemaClass (self.packageName, child, self.typespec,
self.fragments, options)
self.classes.append (cls)
elif child.nodeName == 'group':
cls = SchemaClass (self.packageName, child, self.typespec,
self.fragments, options)
self.fragments.append (cls)
elif child.nodeName == 'eventArguments':
if self.eventArgSet:
raise Exception("Only one <eventArguments> may appear in a package")
self.eventArgSet = SchemaEventArgs(self.packageName, child, self.typespec, self.fragments, options)
elif child.nodeName == 'event':
event = SchemaEvent(self.packageName, child, self.typespec, self.eventArgSet)
self.events.append(event)
else:
raise ValueError ("Unknown schema tag '%s'" % child.nodeName)
def getPackageName (self):
return self.packageName
def getPackageNameCap (self):
return capitalize(self.packageName)
def getPackageNameLower (self):
return self.packageName.lower()
def getClasses (self):
return self.classes
def getEvents(self):
return self.events
def genAgentHeaderLocation (self, stream, variables):
stream.write(variables["agentHeaderDir"])
def genCloseNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("}")
def genNamespace (self, stream, variables):
stream.write("::".join(self.packageName.split(".")))
def genOpenNamespaces (self, stream, variables):
for item in self.packageName.split("."):
stream.write ("namespace %s {\n" % item)
def genPackageNameUpper (self, stream, variables):
up = "_".join(self.packageName.split("."))
stream.write (up.upper())
def genPackageName (self, stream, variables):
stream.write(self.packageName)
def genNamePackageLower (self, stream, variables):
stream.write (self.packageName.lower ())
def genClassIncludes (self, stream, variables):
for _class in self.classes:
stream.write ("#include \"")
_class.genNameCap (stream, variables)
stream.write (".h\"\n")
for _event in self.events:
stream.write ("#include \"Event")
_event.genNameCap(stream, variables)
stream.write (".h\"\n")
def genClassRegisters(self, stream, variables):
for _class in self.classes:
stream.write(" ")
_class.genNameCap(stream, variables)
stream.write("::registerSelf(agent);\n")
for _event in self.events:
stream.write(" Event")
_event.genNameCap(stream, variables)
stream.write("::registerSelf(agent);\n")
def genV2ClassMembers(self, stream, variables):
for _class in self.classes:
stream.write(" ::qmf::Schema data_%s;\n" % _class.name)
for _event in self.events:
stream.write(" ::qmf::Schema event_%s;\n" % _event.name)
def genV2ClassDefines(self, stream, variables):
for _class in self.classes:
stream.write("\n //\n // Data: %s\n //\n" % _class.name)
stream.write(" data_%s = qmf::Schema(SCHEMA_TYPE_DATA, package, \"%s\");\n" % (_class.name, _class.name))
for prop in _class.properties:
typeName, subType = self.qmfv2Type(prop.type)
access = self.qmfv2Access(prop.access)
stream.write(" {\n")
stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (prop.name, typeName))
if subType:
stream.write(" prop.setSubtype(\"%s\");\n" % subType)
stream.write(" prop.setAccess(%s);\n" % access)
if prop.isIndex == 1:
stream.write(" prop.setIndex(true);\n")
if prop.isOptional == 1:
stream.write(" prop.setOptional(true);\n")
if prop.unit:
stream.write(" prop.setUnit(\"%s\");\n" % prop.unit)
if prop.desc:
stream.write(" prop.setDesc(\"%s\");\n" % prop.desc)
stream.write(" data_%s.addProperty(prop);\n" % _class.name)
stream.write(" }\n\n")
for stat in _class.statistics:
typeName, subType = self.qmfv2Type(stat.type)
stream.write(" {\n")
stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (stat.name, typeName))
if subType:
stream.write(" prop.setSubtype(\"%s\");\n" % subType)
if stat.unit:
stream.write(" prop.setUnit(\"%s\");\n" % stat.unit)
if stat.desc:
stream.write(" prop.setDesc(\"%s\");\n" % stat.desc)
stream.write(" data_%s.addProperty(prop);\n" % _class.name)
stream.write(" }\n\n")
for method in _class.methods:
stream.write(" {\n")
stream.write(" qmf::SchemaMethod method(\"%s\");\n" % method.name)
if method.desc:
stream.write(" method.setDesc(\"%s\");\n" % method.desc)
for arg in method.args:
typeName, subType = self.qmfv2Type(arg.type)
stream.write(" {\n")
stream.write(" qmf::SchemaProperty arg(\"%s\", %s);\n" % (arg.name, typeName))
if subType:
stream.write(" arg.setSubtype(\"%s\");\n" % subType)
if arg.unit:
stream.write(" arg.setUnit(\"%s\");\n" % arg.unit)
if arg.desc:
stream.write(" arg.setDesc(\"%s\");\n" % arg.desc)
stream.write(" arg.setDirection(%s);\n" % self.qmfv2Dir(arg.dir))
stream.write(" method.addArgument(arg);\n")
stream.write(" }\n\n")
stream.write(" data_%s.addMethod(method);\n" % _class.name)
stream.write(" }\n\n")
stream.write(" session.registerSchema(data_%s);\n" % _class.name)
for _event in self.events:
stream.write("\n //\n // Event: %s\n //\n" % _event.name)
stream.write(" event_%s = qmf::Schema(SCHEMA_TYPE_EVENT, package, \"%s\");\n" % (_event.name, _event.name))
stream.write(" event_%s.setDefaultSeverity(%s);\n" % (_event.name, self.qmfv2Severity(_event.sev)))
for prop in _event.args:
typeName, subType = self.qmfv2Type(prop.type)
stream.write(" {\n")
stream.write(" qmf::SchemaProperty prop(\"%s\", %s);\n" % (prop.name, typeName))
if subType:
stream.write(" prop.setSubtype(\"%s\");\n" % subType)
if prop.unit:
stream.write(" prop.setUnit(\"%s\");\n" % prop.unit)
if prop.desc:
stream.write(" prop.setDesc(\"%s\");\n" % prop.desc)
stream.write(" event_%s.addProperty(prop);\n" % _event.name)
stream.write(" }\n\n")
stream.write(" session.registerSchema(event_%s);\n" % _event.name)
def qmfv2Type(self, typecode):
base = typecode.type.base
if base == "REF" : return ("qmf::SCHEMA_DATA_MAP", "reference")
if base == "U8" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "U16" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "U32" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "U64" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "S8" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "S16" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "S32" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "S64" : return ("qmf::SCHEMA_DATA_INT", None)
if base == "BOOL" : return ("qmf::SCHEMA_DATA_BOOL", None)
if base == "SSTR" : return ("qmf::SCHEMA_DATA_STRING", None)
if base == "LSTR" : return ("qmf::SCHEMA_DATA_STRING", None)
if base == "ABSTIME" : return ("qmf::SCHEMA_DATA_INT", "abstime")
if base == "DELTATIME" : return ("qmf::SCHEMA_DATA_INT", "deltatime")
if base == "FLOAT" : return ("qmf::SCHEMA_DATA_FLOAT", None)
if base == "DOUBLE" : return ("qmf::SCHEMA_DATA_FLOAT", None)
if base == "UUID" : return ("qmf::SCHEMA_DATA_UUID", None)
if base == "FTABLE" : return ("qmf::SCHEMA_DATA_MAP", None)
if base == "LIST" : return ("qmf::SCHEMA_DATA_LIST", None)
raise ValueError("Unknown base type %s" % base)
def qmfv2Access(self, code):
if code == "RC": return "qmf::ACCESS_READ_CREATE"
if code == "RO": return "qmf::ACCESS_READ_ONLY"
if code == "RW": return "qmf::ACCESS_READ_WRITE"
raise ValueError("Unknown access type %s" % code)
def qmfv2Dir(self, code):
if code == "I" : return "qmf::DIR_IN"
if code == "O" : return "qmf::DIR_OUT"
if code == "IO": return "qmf::DIR_IN_OUT"
raise ValueError("Unknown direction type %s" % code)
def qmfv2Severity(self, code):
if code == 0 : return "qmf::SEV_EMERG"
if code == 1 : return "qmf::SEV_ALERT"
if code == 2 : return "qmf::SEV_CRIT"
if code == 3 : return "qmf::SEV_ERROR"
if code == 4 : return "qmf::SEV_WARN"
if code == 5 : return "qmf::SEV_NOTICE"
if code == 6 : return "qmf::SEV_INFORM"
if code == 7 : return "qmf::SEV_DEBUG"
raise ValueError("Out of Range Severity %d" % code)
#=====================================================================================
# Utility Functions
#=====================================================================================
# Create a valid C++ symbol from the input string so that it can be
# used in generated C++ source. For instance, change "qpid.mgmt" to
# "qpidMgmt".
#
# Input: Raw string (str) to process
# Output: String (str) suitable for use as a C++ symbol
#
# Limitations: Currently, only strips periods ('.') from strings,
# eventually should strip :'s and ,'s and ''s, oh my!
def makeValidCppSymbol(input):
output = str()
capitalize = False
for char in input:
skip = False
if char == ".":
capitalize = True
skip = True
if not skip:
output += capitalize and char.upper() or char
capitalize = False
return output
# Capitalize a string by /only/ forcing the first character to be
# uppercase. The rest of the string is left alone. This is different
# from str.capitalize(), which forces the first character to uppercase
# and the rest to lowercase.
#
# Input: A string (str) to capitalize
# Output: A string (str) with the first character as uppercase
def capitalize(input):
return input[0].upper() + input[1:]