/ securityd / src / structure.cpp
structure.cpp
  1  /*
  2   * Copyright (c) 2000-2001,2004,2009 Apple Inc. All Rights Reserved.
  3   * 
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   * 
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  
 25  //
 26  // structure - structural framework for securityd objects
 27  //
 28  #include "structure.h"
 29  
 30  
 31  //
 32  // NodeCore always has a destructor (because it's virtual),
 33  // but its dump support is conditionally included.
 34  //
 35  NodeCore::~NodeCore()
 36  try {
 37  #if defined(DEBUGDUMP)
 38  	StLock<Mutex> _(mCoreLock);
 39  	mCoreNodes.erase(this);
 40  #endif //DEBUGDUMP
 41  } catch(...) {
 42      return;
 43  }
 44  
 45  
 46  //
 47  // Basic object mesh maintainance
 48  //
 49  void NodeCore::parent(NodeCore &p)
 50  {
 51  	StLock<Mutex> _(*this);
 52  	mParent = &p;
 53  }
 54  
 55  void NodeCore::referent(NodeCore &r)
 56  {
 57  	StLock<Mutex> _(*this);
 58  	assert(!mReferent);
 59  	mReferent = &r;
 60  }
 61  	
 62  void NodeCore::clearReferent()
 63  {
 64  	StLock<Mutex> _(*this);
 65  	mReferent = NULL;
 66  }
 67  
 68  
 69  void NodeCore::addReference(NodeCore &p)
 70  {
 71  	StLock<Mutex> _(*this);
 72  	assert(p.mReferent == this);
 73  	mReferences.insert(&p);
 74  }
 75  
 76  void NodeCore::removeReference(NodeCore &p)
 77  {
 78  	StLock<Mutex> _(*this);
 79  	mReferences.erase(&p);
 80  }
 81  
 82  //
 83  // ClearReferences clears the reference set but does not propagate
 84  // anything; it is NOT recursive.
 85  //
 86  void NodeCore::clearReferences()
 87  {
 88  	StLock<Mutex> _(*this);
 89  	secinfo("ssnode", "%p clearing all %d references", this, int(mReferences.size()));
 90  	mReferences.erase(mReferences.begin(), mReferences.end());
 91  }
 92  
 93  
 94  //
 95  // Kill should be overloaded by Nodes to implement any cleanup and release
 96  // operations that should happen at LOGICAL death of the represented object.
 97  // This is where you should release ports, close files, etc.
 98  // This default behavior, which you MUST include in your override,
 99  // propagates kills to all active references, recursively.
100  //
101  void NodeCore::kill()
102  {
103  	StLock<Mutex> _(*this);
104  	for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++)
105  		(*it)->kill();
106  	clearReferences();
107  }
108  
109  
110  void NodeCore::kill(NodeCore &ref)
111  {
112  	StLock<Mutex> _(*this);
113  	ref.kill();
114  	removeReference(ref);
115  }
116  
117  
118  //
119  // NodeCore-level support for state dumping.
120  // Call NodeCore::dumpAll() to debug-dump all nodes.
121  // Note that enabling DEBUGDUMP serializes all node creation/destruction
122  // operations, and thus may cause significant shifts in thread interactions.
123  //
124  #if defined(DEBUGDUMP)
125  
126  // The (uncounted) set of all known NodeCores in existence, with protective lock
127  set<NodeCore *> NodeCore::mCoreNodes;
128  Mutex NodeCore::mCoreLock;
129  
130  // add a new NodeCore to the known set
131  NodeCore::NodeCore()
132  	: Mutex(Mutex::recursive)
133  {
134  	StLock<Mutex> _(mCoreLock);
135  	mCoreNodes.insert(this);
136  }
137  
138  // partial-line common dump text for any NodeCore
139  // override this to add text to your Node type's state dump output
140  void NodeCore::dumpNode()
141  {
142   Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly()));
143  	if (mParent)
144  		Debug::dump(" parent=%p", mParent.get());
145  	if (mReferent)
146  		Debug::dump(" referent=%p", mReferent.get());
147  }
148  
149  // full-line dump of a NodeCore
150  // override this to completely re-implement the dump format for your Node type
151  void NodeCore::dump()
152  {
153   dumpNode();
154  	if (!mReferences.empty()) {
155  		Debug::dump(" {");
156  		for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) {
157  			Debug::dump(" %p", it->get());
158  			if ((*it)->mReferent != this)
159  				Debug::dump("!*INVALID*");
160  		}
161  		Debug::dump(" }");
162  	}
163  	Debug::dump("\n");
164  }
165  
166  // dump all known nodes
167  void NodeCore::dumpAll()
168  {
169   StLock<Mutex> _(mCoreLock);
170  	time_t now; time(&now);
171  	Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now));
172  	for (set<NodeCore *>::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++)
173  		(*it)->dump();
174  	Debug::dump("END NODE DUMP\n\n");
175  }
176  
177  #endif //DEBUGDUMP