summaryrefslogtreecommitdiff
path: root/cpp/managementgen/qmfgen/schema.py
diff options
context:
space:
mode:
authorTed Ross <tross@apache.org>2008-11-21 18:46:24 +0000
committerTed Ross <tross@apache.org>2008-11-21 18:46:24 +0000
commit57c7e6d45483b94d4306eb93f285f4cbaa52bd57 (patch)
tree408000aaa36bffbb1410d0929b2704cba97fab9f /cpp/managementgen/qmfgen/schema.py
parent61523667e8589275138a66ad23fda254c66c7dfe (diff)
downloadqpid-python-57c7e6d45483b94d4306eb93f285f4cbaa52bd57.tar.gz
Renamed the python package for the qmf code generation as it conflicts
with the package for the qmf apis. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@719671 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/managementgen/qmfgen/schema.py')
-rwxr-xr-xcpp/managementgen/qmfgen/schema.py1339
1 files changed, 1339 insertions, 0 deletions
diff --git a/cpp/managementgen/qmfgen/schema.py b/cpp/managementgen/qmfgen/schema.py
new file mode 100755
index 0000000000..692a474992
--- /dev/null
+++ b/cpp/managementgen/qmfgen/schema.py
@@ -0,0 +1,1339 @@
+#
+# 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
+
+class Hash:
+ """ Manage the hash of an XML sub-tree """
+ def __init__(self, node):
+ self.md5Sum = md5.new()
+ 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.accessor = None
+ self.init = "0"
+ self.perThread = False
+ self.byRef = False
+
+ 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 == '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
+
+ 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::sys::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::sys::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::sys::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::sys::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 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 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 = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + self.name + "\");\n")
+ stream.write (" ft.setInt (TYPE, TYPE_" + self.type.type.base +");\n")
+ stream.write (" ft.setInt (ACCESS, ACCESS_" + self.access + ");\n")
+ stream.write (" ft.setInt (IS_INDEX, " + str (self.isIndex) + ");\n")
+ stream.write (" ft.setInt (IS_OPTIONAL, " + str (self.isOptional) + ");\n")
+ if self.unit != None:
+ stream.write (" ft.setString (UNIT, \"" + self.unit + "\");\n")
+ if self.min != None:
+ stream.write (" ft.setInt (MIN, " + self.min + ");\n")
+ if self.max != None:
+ stream.write (" ft.setInt (MAX, " + self.max + ");\n")
+ if self.maxLen != None:
+ stream.write (" ft.setInt (MAXLEN, " + self.maxLen + ");\n")
+ if self.desc != None:
+ stream.write (" ft.setString (DESC, \"" + self.desc + "\");\n")
+ stream.write (" buf.put (ft);\n\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")
+
+
+#=====================================================================================
+#
+#=====================================================================================
+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 = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + name + "\");\n")
+ stream.write (" ft.setInt (TYPE, TYPE_" + self.type.type.base +");\n")
+ if self.unit != None:
+ stream.write (" ft.setString (UNIT, \"" + self.unit + "\");\n")
+ if desc != None:
+ stream.write (" ft.setString (DESC, \"" + desc + "\");\n")
+ stream.write (" buf.put (ft);\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 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 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 = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + self.name + "\");\n")
+ stream.write (" ft.setInt (TYPE, TYPE_" + self.type.type.base +");\n")
+ if (not event):
+ stream.write (" ft.setString (DIR, \"" + self.dir + "\");\n")
+ if self.unit != None:
+ stream.write (" ft.setString (UNIT, \"" + self.unit + "\");\n")
+ if not event:
+ if self.min != None:
+ stream.write (" ft.setInt (MIN, " + self.min + ");\n")
+ if self.max != None:
+ stream.write (" ft.setInt (MAX, " + self.max + ");\n")
+ if self.maxLen != None:
+ stream.write (" ft.setInt (MAXLEN, " + self.maxLen + ");\n")
+ if self.default != None:
+ stream.write (" ft.setString (DEFAULT, \"" + self.default + "\");\n")
+ if self.desc != None:
+ stream.write (" ft.setString (DESC, \"" + self.desc + "\");\n")
+ stream.write (" buf.put (ft);\n\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 = FieldTable ();\n")
+ stream.write (" ft.setString (NAME, \"" + self.name + "\");\n")
+ stream.write (" ft.setInt (ARGCOUNT, " + str (len (self.args)) + ");\n")
+ if self.desc != None:
+ stream.write (" ft.setString (DESC, \"" + self.desc + "\");\n")
+ stream.write (" buf.put (ft);\n\n")
+ for arg in self.args:
+ arg.genSchema (stream)
+
+#=====================================================================================
+#
+#=====================================================================================
+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 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 genArgSchema(self, stream, variables):
+ for arg in self.args:
+ arg.genSchema(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 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&, Buffer&, Buffer& outBuf")
+ else:
+ if inArgCount == 0:
+ stream.write ("string& methodName, Buffer&, Buffer& outBuf")
+ else:
+ stream.write ("string& methodName, Buffer& inBuf, Buffer& outBuf")
+
+ 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 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):
+ 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")
+ 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 (" status = coreObject->ManagementMethod (METHOD_" +\
+ method.getName().upper() + ", ioArgs, text);\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 (" 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 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 genMethodIdDeclarations (self, stream, variables):
+ number = 1
+ for method in self.methods:
+ stream.write (" 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 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 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 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)
+
+
+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 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 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")
+
+
+#=====================================================================================
+# 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:]