KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 DAV/2 PHP/5.2.17
System : Linux localhost 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64
User : nobody ( 99)
PHP Version : 5.2.17
Disable Function : NONE
Directory :  /usr/lib64/python2.4/site-packages/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //usr/lib64/python2.4/site-packages/Alchemist.py
#! /usr/bin/python

## Alchemist - Python bindings for the Alchemist
## Copyright (C) 2000 Red Hat, Inc.
## Copyright (C) 2000 Tim Waugh <twaugh@redhat.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.

## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.

## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

from _alchemist import *
import exceptions
import imp
import time

def _mkData (_dat):
	if _dat == None:
		return None
	type = data_getType (_dat)
	if (type == Data.ADM_TYPE_LIST):
		return ListData (_dat)
	if (type == Data.ADM_TYPE_COPY):
		return CopyData (_dat)
	if (type == Data.ADM_TYPE_INT):
		return IntData (_dat)
	if (type == Data.ADM_TYPE_FLOAT):
		return FloatData (_dat)
	if (type == Data.ADM_TYPE_BOOL):
		return BoolData (_dat)
	if (type == Data.ADM_TYPE_STRING):
		return StringData (_dat)
	if (type == Data.ADM_TYPE_BASE64):
		return Base64Data (_dat)
	return None

class Data:
	## From alchemist.h:
        ADM_TYPE_UNKNOWN = 0
        ADM_TYPE_LIST    = 1
        ADM_TYPE_COPY    = 2
        ADM_TYPE_INT     = 3
        ADM_TYPE_FLOAT   = 4
        ADM_TYPE_BOOL    = 5
        ADM_TYPE_STRING  = 6
        ADM_TYPE_BASE64  = 7

	def __init__ (self, thing):
		self._dat = thing;

	def getContainer (self):
		return _mkData (data_getContainer (self._dat))

	def getContext (self):
		return Context(ctx = data_getContext (self._dat))

	def getType (self):
		return data_getType (self._dat)

	def isAlive (self):
		return data_isAlive (self._dat)

	def unlink (self):
		data_unlink (self._dat)

	def getName (self):
		return data_getName (self._dat)

	def setName (self, name):
		data_setName (self._dat, name)

	def getSource (self):
		return data_getSource (self._dat)

	def setSource (self, src):
		data_setSource (self._dat, src)

	def isProtected (self):
		return data_isProtected (self._dat)

	def setProtected (self, prot):
		data_setProtected (self._dat, prot)

	def getPos (self):
		return data_getPos (self._dat)

	def isIdentical(self, other):
		return data_isIdentical(self._dat, other._dat)

class ListData (Data):
	def isAnonymous (self):
		return list_isAnonymous (self._dat)

	def setAnonymous (self, anon):
		list_setAnonymous (self._dat, anon)

	def isAtomic (self):
		return list_isAtomic (self._dat)

	def setAtomic (self, atomic):
		list_setAtomic (self._dat, atomic)

	def isPrepend (self):
		return list_isPrepend (self._dat)

	def setPrepend (self, prep):
		list_setPrepend (self._dat, prep)

	def getNumChildren (self):
		return list_getNumChildren (self._dat)

	def getChildByIndex (self, index):
		return _mkData(list_getChildByIndex (self._dat,
								index))

	def getChildByName (self, name):
		return _mkData (list_getChildByName (self._dat,
								name))

	def hasChildNamed (self, name):
		return list_hasChildNamed (self._dat, name)

	def addChild (self, type, name):
		return _mkData (list_addChild (self._dat, type,
							  name))

	def moveChild (self, datum, index):
		list_moveChild (self._dat, datum._dat, index)

	def copyData (self, datum):
		return _mkData (list_copyData (self._dat,
							  datum._dat))

class CopyData (Data):
	def getValue (self):
		return copy_getValue (self._dat)

	def setValue (self, v):
		copy_setValue (self._dat, v)

class IntData (Data):
	def getValue (self):
		return int_getValue (self._dat)

	def setValue (self, v):
		int_setValue (self._dat, v)

class FloatData (Data):
	def getValue (self):
		return float_getValue (self._dat)

	def setValue (self, v):
		float_setValue (self._dat, v)

class BoolData (Data):
	def getValue (self):
		return bool_getValue (self._dat)

	def setValue (self, v):
		bool_setValue (self._dat, v)

class StringData (Data):
	def getValue (self):
		return string_getValue (self._dat)

	def setValue (self, v):
		string_setValue (self._dat, v)

class Base64Data (Data):
	def getValue (self):
		return base64_getValue (self._dat)

	def setValue (self, v):
		base64_setValue (self._dat, v)

class Identity:
	def __init__ (self, id):
		self._id = id

	def getParentA (self):
		A_id = identity_getParentA (self._id)
		if A_id == None:
			return None
		return Identity (A_id)

	def getParentB (self):
		B_id = identity_getParentB (self._id)
		if B_id == None:
			return None
		return Identity (B_id)

	def getName (self):
		return identity_getName (self._id)

	def setName (self, name):
		identity_setName (self._id, name)

	def getSerial (self):
		return identity_getSerial (self._id)

	def setSerial (self, serial):
		identity_setSerial (self._id, serial)

	def isAlive (self):
		return identity_isAlive (self._id)

	def isIdentical (self, other):
		return identity_isIdentical(self._id, other._id)

class Context:
	def __init__(self, name = None, serial = None, ctx = None, xml = None):
		if ctx != None:
			self._ctx = ctx
			return None

		if xml != None:
			self._ctx = context_fromXML(xml)
			return None

		if name != None and serial != None:
			self._ctx = context_create (name, serial)
			return None

		raise ContextError, "Illegal constructor parameters"

	def copy (self):
		return Context(ctx = context_copy (self._ctx))

	def flatten (self):
		context_flatten (self._ctx)

	def toXML (self):
		return context_toXML (self._ctx)

	def getDelete (self, index):
		return context_getDelete (self._ctx, index)

	def setDelete (self, path):
		context_setDelete (self._ctx, path)

	def clearDeleteByIndex (self, index):
		context_clearDeleteByIndex (self._ctx, index)

	def clearDeleteByString (self, path):
		context_clearDeleteByString (self._ctx, path)

	def getNumDeletes (self):
		return context_getNumDeletes (self._ctx)

	def getIdentityRoot (self):
		return Identity(context_getIdentityRoot (self._ctx))

	def getDataRoot (self):
		return _mkData(context_getDataRoot (self._ctx))

	def getDataByPath (self, path):
		return _mkData(context_getDataByPath (self._ctx, path))

	def isIdentical(self, other):
		return context_isIdentical(self._ctx, other._ctx)

def merge (name, serial, ctxA, ctxB):
	return Context(ctx = context_merge (name, serial, ctxA._ctx, ctxB._ctx))



def validateBoxCfg (box_cfg):
	"""
	validataBoxCfg: throws exceptions on invalid box_cfgs
	@box_cfg: A box_cfg @AdmList, to be checked for conformance.

	This function validates a box_cfg element, and throws a @BlackBoxError
	if it is an invalid element.

	box_cfg elements are defined as:
	Living, non-anonymous AdmList elements, containing a AdmString child
	named 'box_type', which specifies which type of BlackBox this box_cfg
	configures.

	Why, you may ask, do box_cfg elements not just have a cache optional
	child, that is itself a box_cfg element? Because then caches could
	have caches, and that way lies madness.

	throws: @ValueError if anything is wrong with the box_cfg
	"""
	if box_cfg == None:
		raise ValueError, "'None' passed as box_cfg"
	if box_cfg.__class__ != ListData:
		raise ValueError, "box_cfg is not an AdmList element"
	if not box_cfg.isAlive():
		raise ValueError, "Dead node passed as box_cfg"
	if box_cfg.isAnonymous():
		raise ValueError, "box_cfg is an annonymous AdmList element"
	try:
		box_type = box_cfg.getChildByName("box_type")
	except KeyError, e:
		raise ValueError, "box_cfg contains no 'box_type' child"
	if box_type.__class__ != StringData:
		raise ValueError, "box_cfg's box_type child is not an AdmString element"

class BlackBox:
	"""
	The BlackBox base class provides a generic class for Alchemist Data
	Library BlackBox modules to inherit. 
	"""
	def __init__ (self, box_cfg):
		"""
		__init__: Initialize a BlackBox
		@self: the class instance
		@box_cfg: a box_cfg conformant AdmList element

		This function is the initializer for BlackBoxes, it, and
		functions which overload it, must not keep references to,
		or modify in any way, the box_cfg it is passed.

		It is also a good idea if modules call validateBoxCfg on their
		box_cfgs before touching them, so that we get uniform error
		raising on broken data.
		"""
		self.me = self.__class__.__module__
		self.status = 0
		self._errNo = 0
		self._errStr = None		
		self.readable = 0
		self.writable = 0

		validateBoxCfg(box_cfg)

	def getStatus (self):
		"""
		getStatus: returns a BlackBox dependent status value.
		@self: this BlackBox instance
		"""
		return self.status

	def errNo (self):
		"""
		errNo: returns a BlackBox dependent error number.
		@self: this BlackBox instance
		"""
		return self._errNo

	def strError (self):
		"""
		strError: returns a BlackBox dependent error string.
		@self: this BlackBox instance
		"""
		return str(self._errStr)

	def isReadable (self):
		"""
		isReadable: if a read were attempted now, would it succede?
		@self: this BlackBox instance
		"""
		return self.readable

	def isWritable (self):
		"""
		isWritable: if a write were attempted now, would it succede?
		@self: this BlackBox instance
		"""
		return self.writable

	def read (self):
		"""
		read: read the contents of the BlackBox
		@self: this BlackBox instance

		This function must be callable multiple times, and if it cannot
		succede on a given call, it should return None. It should not
		cache returns information in the normal sense, unless the data
		is not dynamic. And it must not keep a reference to the
		AdmContext it returns.
		"""
		return None

	def version(self):
		"""
		version: returns the version of the context held in a black box.
		@self: this BlackBox instance

		This function should be overridden by all subclassess so that it
		returns a version number that is identical to the serial number
		of the context that /would/ have been returned had a read() call
		benn made instead of the version() call.
		"""
		return 0

	def readVersion (self,version):
		"""
		readVersion: reads a specific version of a BlackBox
		@self: this BlackBox instance

		This is a per-BlackBox function, and implementors should not
		provide it unless they can guarantee that the version read will
		be a perfect copy of the last context returned by 'read' for the
		version called, or None.

		A context's version is the serial number of the root node of
		it's identity tree.
		"""
		return None

	def write (self, context):
		"""
		write: write the contents of the BlackBox
		@self: this BlackBox instance

		This function must be callable multiple times. It writes a
		Context out to where ever the box does it, if it does anything.
		It must return 0 on failure, and a non-zero, positive integer
		on success.
		"""
		return 0


# We preload FileBlackBox, because we need it for bootstrap
# NOTE!: Because of the unique way in which python handles imports,
# This import MUST be after the BlackBox deffinition.
import FileBlackBox
from FileBlackBox import ReadContextFromFile, WriteContextToFile
ImportedBoxes = {"FileBlackBox" : FileBlackBox }

def getBox (box_cfg):
	"""
	getBox: automagically finds and loads an arbitrary BlackBox
	@box_cfg: a box_cfg conformant AdmList element

	This function takes a box_cfg conformant AdmList element, extracts
	its box_type child, reads the box type specified in it, and loads
	and configures the appropriate box, if the neccesary module can be
	found.

	Modules providing BlackBoxes must define a function getBox() which
	takes a box_cfg and returns None, or a configured BlackBox.

	returns: a configured BlackBox, or None, if no BlackBox can be found
	"""
	validateBoxCfg(box_cfg)

	# pull the type
	box_type = box_cfg.getChildByName("box_type").getValue()

	# Search for an appropriate module.
	# because it is always loaded Note that if we get this far, we
	# either succed, or return None. We swallow exceptions.
	if ImportedBoxes.has_key(box_type):
		# We've already loaded this module, lets not look for it again
		# We don't catch exceptions here, because we know that the module
		# exists, and any exceptions thrown should be config exceptions,
		# which we should let through.
		return ImportedBoxes[box_type].getBox(box_cfg)
	else:
		# new box, lets try to find it.
		try:
			box_mod_info = imp.find_module(box_type)
		except:
			return None

		if box_mod_info[0] != None:
			# if we find a path to load, try to load it.
			try:
				box_mod = imp.load_module(box_type,
							  box_mod_info[0],
							  box_mod_info[1],
							  box_mod_info[2])
				if box_mod_info[0] != None:
					box_mod_info[0].close()
				ImportedBoxes[box_type] = box_mod
			except:
			# if loading fails, we return None, not an exception
				return None
		
			return box_mod.getBox(box_cfg)
	
def validateBoxEntry (box_entry):
	"""
	validateBoxEntry: throws exceptions on invalid box_entrys
	@box_entry: A box_entry conformant @AdmList element, to be checked

	box_entry elements are defined as:
	Living, non-anonymous AdmList elements, containing a box_cfg child
	named 'box', and an optional box_cfg child named 'cache'. If cache
	exists, it must be a box_cfg element

	throws: @BlackBoxError if anything is wrong with the box_cfg
	"""
	if box_entry == None:
		raise ValueError, "'None' passed as box_entry"
	if box_entry.__class__ != ListData:
		raise ValueError, "box_entry is not an AdmList element"
	if not box_entry.isAlive():
		raise ValueError, "Dead node passed as box_entry"
	if box_entry.isAnonymous():
		raise ValueError, "box_entry is an annonymous AdmList element"
	try:
		box = box_entry.getChildByName("box")
		validateBoxCfg(box)
	except KeyError, e:
		raise ValueError, "box_entry contains no 'box' child"
	try:
		cache = box_entry.getChildByName("cache")
		validateBoxCfg(cache)
	except KeyError, e:
		pass

	return None

def validateNamespaceCfg (namespace_cfg):
	"""
	validateNamespaceCfg: throws exceptions on invalid namespace_cfgs
	@namespace_cfg: a namespace_cfg conformant @AdmList, to be checked.

	namespace_cfg elements are defined as:
	Living, non-anonymous AdmList elements, containing a non-anonymous
	AdmList child named "input_set", an optional non-anonymous AdmList
	child named "output_set", and an optional box_cfg child named "cache"

	"input_set" (and "output_set", if it exists), must be non-anonymous
	AdmList elements containing only box_entrys, and must be non-empty.

	Note that this is not an exclusive set, and config tools are free to
	add whatever additional children they want. However, the child
	"_namespace_config_" is reserved for future expansion.
	"""
	if namespace_cfg == None:
		raise ValueError, "'None' passed as namespace_cfg"
	if namespace_cfg.__class__ != ListData:
		raise ValueError, "namespace_cfg is not an AdmList element"
	if not namespace_cfg.isAlive():
		raise ValueError, "Dead node passed as namespace_cfg"
	if namespace_cfg.isAnonymous():
		raise ValueError, "namespace_cfg is an anonymous AdmList element"

	try:
		# validate input_set
		input_set = namespace_cfg.getChildByName("input_set")
		k = input_set.getNumChildren()
		if k == 0:
			raise ValueError, "namespace_cfg has an empty input_set"
		for i in xrange(k):
			box_entry = input_set.getChildByIndex(i)
			validateBoxEntry(box_entry)
			try:
				box_entry.getChildByName("cache")
			except KeyError, e:
				raise ValueError, "input set box_entry contains no 'cache' child"

	except KeyError, e:
		raise ValueError, "namespace_cfg contains no input_set"

	try:
		# validate output_set
		output_set = namespace_cfg.getChildByName("output_set")
		k = output_set.getNumChildren()
		if k == 0:
			raise ValueError, "namespace_cfg has an empty output_set"
		for i in xrange(k):
			validateBoxEntry(output_set.getChildByIndex(i))

	except KeyError, e:
		pass

	try:
		validateBoxCfg(namespace_cfg.getChildByName("cache"))
	except KeyError, e:
		pass

	return None
		

def validateMetaCtx (meta_context):
	"""
	validateMetaCtx: throws exceptions on invalid meta_contexts
	@meta_context: a meta_context conformant @AdmContext, to be checked.

	meta_context elements are defined as:
	AdmContexts, whose data tree root contains only valid namespace_cfg
	elements, or the reserved child "_switchboard_config_", which needs
	not be a valid namespace_cfg.
	"""
	if meta_context == None:
		raise ValueError, "'None' passed as meta_context"
	if meta_context.__class__ != Context:
		raise ValueError, "meta_context is not an AdmContext element"
	root = meta_context.getDataRoot()
	for i in xrange(root.getNumChildren()):
		child = root.getChildByIndex(i)
		if child.getName() != "_switchbord_config_":
			validateNamespaceCfg(child)

	return None

def readBox (box_entry):
	"""
	readBox: reads an arbitrary @BlackBox, with caching
	@box_entry: a box_entry conformant @AdmList element

	This function takes a box_entry element, and attempts to @getBox() it.
	If the @getBox() fails, it returns None. This allows configurations to
	fail silently over non-existant components, and is a general win. If
	it succedes, it attempts to read the box. If the read succedes, it writes
	to the cache box, if it is defined and @getBox() can find it. If the read
	fails, it reads from the cache box, if it is defined and @getBox can find
	it. Returns whatever Context was read, or None, on failure.

	returns: a Context, or None on failure
	"""
	validateBoxEntry(box_entry)

	# Fail silently if we don't have this box
	# This allows us to configure fpr undeployed systems.
	box = getBox(box_entry.getChildByName("box"))
	if box == None:
		return None

	context = box.read()

	# Try to load this box's cache
	try:
		cache = getBox(box_entry.getChildByName("cache"))
	except KeyError, e:
		cache = None

	# if the cache loads, do the right thing with it.
	if cache != None:
		if context != None:
			cache.write(context)
		else:
			context = cache.read()

	return context

def writeBox (box_entry, context):
	"""
	writeBox: writes to an arbitrary @BlackBox
	@box_entry: a box_entry conformant @AdmList element
	@context: an @AdmContext

	This function takes a box_entry element, and attempts to @getBox() it.
	If the @getBox() fails, it returns 0. This allows configurations to
	fail silently over non-existant components, and is a general win. If
	it succedes, it attempts to write the box, and returns the result of
	the write. The write will always return 0 on failure, or a positive
	non-zero integer on success.

	Specifics of which integer, and what it means, are box dependent.

	returns: 0 on failure, positive non-zero integer on success
	"""
	validateBoxEntry(box_entry)

	# Fail silently if we don't have this box
	# This allows us to configure fpr undeployed systems.
	box = getBox(box_entry.getChildByName("box"))
	if box == None:
		return 0

	return box.write(context)

class Switchboard:
	"""
	The Switchboard class provides a convienient collection of merge
	and cache logic, which interoperating with BlackBox modules and
	Alchemist Data Model elements forms the Alchemist Data Library.

	Switchboard instances are stateless, and can be reconfigured on
	the fly by altering their meta_context. However, since this is
	not the normal behaviour, and validation is very expensive, we
	only call validateMetaCtx() at init time. Modules altering the
	meta context outside that wish to validate more often can set
	validate = 1 on any method to force a validateMetaCtx call.

	The Switchboard deals with data in terms of Namespaces, which in this
	application are defined a ordered set of BlackBox supplied AdmContexts,
	their optional caches, the optional cache for the product of a cascade
	merge of the set, and an optional output set of consumers, specified as
	BlackBoxes.
	"""
	def __init__(self, meta_context = None, file_path = None):
		"""
		__init__: Initialize a Switchboard
		@self: this Switchboard instance
		@meta_context = None: a meta_context conforming AdmContext
		@file_path = None: a file path to load a meta_context from

		We used named parameters to specify which construction method
		we want. If they pass us a meta_context, we validate it and
		wire it up. If they pass us a file_path, we call the
		ReadContextFromFile function that the FileBlackBox module
		provided, validate the result, and wire it up. If we get
		nothing, we throw a ValueError exception.

		meta_context and file_path default to 'None'
		"""
		if meta_context != None:
			self.meta_context = meta_context
			validateMetaCtx(self.meta_context)
			return None

		if file_path != None:
			self.meta_context = ReadContextFromFile(file_path)
			validateMetaCtx(self.meta_context)
			return None

		raise ValueError, "Illegal Constructor parameters"

	def listNamespaces(self, validate = None):
		"""
		listNamespaces: list all Namespaces defined in the meta_context
		@self: this Switchboard instance
		@validate = None: a flag that can be set to force validation.

		returns: a list of all namespaces defined in the meta_context
		"""
		if validate:
			validateMetaCtx(self.meta_context)

		list = []
		root = self.meta_context.getDataRoot()
		for i in xrange(root.getNumChildren()):
			data_name = root.getChildByIndex(i).getName()
			if data_name != "_switchboard_config_":
				list.append(data_name)

		return list
		
	def readNamespaceCfg(self, name, validate = None):
		"""
		readNamespaceCfg: examine a namespace_cfg defined in the meta_context
		@self: this Switchboard instance
		@name: the name of the namespace you are requesting
		@validate = None: a flag that can be set to force validation.

		Gets the namespace_cfg from the meta_context, if it exists. Programs
		should always use this function, as it masks the reserved name,
		"_switchboard_config_", and will always work accross future changes
		in the meta_context format.
		"""
		if validate:
			validateMetaCtx(self.meta_context)

		if name == "_switchboard_config_":
			return None
		try:
			return self.meta_context.getDataByPath("/" + name)
		except KeyError, e:
			raise KeyError, "No such namespace"

	def cascadeNamespace(self, name, depth = None, validate = None):
		"""
		cascadeNamespace: cascade a namespace
		@self: this Switchboard instance
		@name: the name of a namespace to cascade
		@depth = None: an optional depth
		@validate = None: a flag that can be set to force validation.

		This function cascade merges a namespace's input set, and returns
		the result of the cascade. If a depth is specified, it cascades
		only to that depth, or the full set, which ever is least.

		To get the contexts to merge in the cascade, it performs a
		pullBox() call on each box_entry in the input_set, which may
		provide a cached copy, or may provide none at all. It cascades
		silently past empty pulls, and if it has nothing at the end, it
		builds a blank context, and gives you that.

		depth counting starts at 1, and goes up, in the same way that
		number of children starts at 1.
		"""
		if validate:
			validateMetaCtx(self.meta_context)

		namespace_cfg = self.readNamespaceCfg(name)

		input_set = namespace_cfg.getChildByName("input_set")

		# figure out how far to go.
		k = input_set.getNumChildren()
		if depth != None:
			k = min(depth, k)

		context_A = None
		# cascade merge the boxes
		for i in xrange(k):
			if context_A == None:
				# Search for a non-empty box
				context_A = readBox(input_set.getChildByIndex(i))
			else:
				context_B = readBox(input_set.getChildByIndex(i))
				if context_B != None:
					# We can't recover if this fails, so we dont catch the exception.
					# and we need the traceback to get back to the developers
					context_A = merge ("cascade_merge", 0, context_A, context_B)

		# Make sure we return something, even if it is an empty context.
		if context_A == None:
			context_A = Context(name = "cascade_merge", serial = 0)

		return context_A

	def isNamespaceDirty(self, name, validate = None):
		"""
		isNamespaceDirty: checks to see if a namespace is dirty
		"""
		if validate:
			validateMetaCtx(self.meta_context)

		namespace_cfg = self.readNamespaceCfg(name)

		input_set = namespace_cfg.getChildByName("input_set")
		for i in xrange(input_set.getNumChildren()):
			box_entry = input_set.getChildByIndex(i)

			# We fail silently on unavailable boxes
			box = getBox(box_entry.getChildByName("box"))
			if box == None:
				continue

			bversion = box.version()
			if bversion == None:
				continue

			# But we die on unavailable caches
			cache = getBox(box_entry.getChildByName("cache"))
			if cache == None:
				raise ValueError, "'cache' entry unavailable"

			cversion = cache.version()
			if cversion == None:
				# The box has not been cached, it must be dirty
				return 1

			if bversion > cversion:
				return 1

		return 0


	def readNamespace(self, name, force = None, validate = None):
		"""
		readNamespace: read a namespace
		@self: this Switchboard instance
		@name: the name of the namespace
		@force = None: an optional tag to force a fresh read
		@validate = None: a flag that can be set to force validation.

		This function reads a namespace from a full cascade of it's input set,
		or from its cache, if one is available. It does not write the cache.
		The force flag, if true, causes readNamespace to ignore its cache.

		returns: a flattend AdmContext.

		"""
		if validate:
			validateMetaCtx(self.meta_context)

		namespace_cfg = self.readNamespaceCfg(name)

		context = None
		# try to read the cache, but don't flatten it, as it is already flat
		if force == None:
			try:
				cache_box = getBox(namespace_cfg.getChildByName("cache"))
				if cache_box != None:
					context = cache_box.read()
			except KeyError, e:
				pass

		# if that failed, or we were forced, pull a cascade.
		if context == None:
			context = self.cascadeNamespace(name)
			if context != None:
				context.flatten()

		return context

	def writeNamespace(self, name, force = None, validate = None):
		"""
		writeNamespace: write a namespace to its consumers
		@self: this Switchboard instance
		@name: the name of the namespace to write.
		@force = None: an optional flag to force a cache flush
		@validate = None: a flag that can be set to force validation.

		This function pulls a namespaces cache, or a full cascade of the
		input set if the cache is empty, does not exist, or the force
		flag is set. It then writes out the cache (if it exists, and
		wasn't just read), and then writes to every box in the
		output set (if it exists).
		"""
		if validate:
			validateMetaCtx(self.meta_context)

		namespace_cfg = self.readNamespaceCfg(name)

		cache_read = None
		context = None

		# try to find the cache
		try:
			cache_box = getBox(namespace_cfg.getChildByName("cache"))
		except KeyError, e:
			cache_box = None

		# if we aren't forced, try to pull the cache
		if not force:
			if cache_box:
				context = cache_box.read()
				if context:
					cache_read = 1

		# if we still have nothing, cascade the namespace
		if context == None:
			context = self.cascadeNamespace(name)
			context.flatten()

		# make sure we dont write out a cache we just read
		if not cache_read and cache_box:
			# Version the context before we write it
			context.getIdentityRoot().setSerial(int(time.time()))
			cache_box.write(context)

		# write to the output set, if it exists.
		try:
			output_set = namespace_cfg.getChildByName("output_set")
			for i in xrange(output_set.getNumChildren()):
				writeBox(output_set.getChildByIndex(i), context)
		except KeyError, e:
			pass

		return context

Anon7 - 2021