Beispiel #1
0
/**
   Populates the vector of event data buffers (vectors), vector of
   event source objects, vector of event source fields and the vector
   of event datasets by querying the messages on InputVariables.
 */
void NSDFWriter::openEventData(const Eref &eref)
{
    if (filehandle_ <= 0){
        return;
    }
    for (unsigned int ii = 0; ii < eventInputs_.size(); ++ii){
        stringstream path;
        path << eref.objId().path() << "/" << "eventInput[" << ii << "]";
        ObjId inputObj = ObjId(path.str());
        Element * el = inputObj.element();
        const DestFinfo * dest = static_cast<const DestFinfo*>(el->cinfo()->findFinfo("input"));
        vector < ObjId > src;
        vector < string > srcFields;
        el->getMsgSourceAndSender(dest->getFid(), src, srcFields);
        if (src.size() > 1){
            cerr << "NSDFWriter::openEventData - only one source can be connected to an eventInput" <<endl;
        } else if (src.size() == 1){
            eventSrcFields_.push_back(srcFields[0]);
            eventSrc_.push_back(src[0].path());
            events_.resize(eventSrc_.size());
            stringstream path;
            path << src[0].path() << "." << srcFields[0];
            hid_t dataSet = getEventDataset(src[0].path(), srcFields[0]);
            eventDatasets_.push_back(dataSet);            
        } else {
            cerr <<"NSDFWriter::openEventData - cannot handle multiple connections at single input." <<endl;
        }
    }
}
Beispiel #2
0
void Shell::doMove( Id orig, ObjId newParent )
{
	if ( orig == Id() ) {
		cout << "Error: Shell::doMove: Cannot move root Element\n";
		return;
	}

	if ( newParent.element() == 0 ) {
		cout << "Error: Shell::doMove: Cannot move object to null parent \n";
		return;
	}
	if ( Neutral::isDescendant( newParent, orig ) ) {
		cout << "Error: Shell::doMove: Cannot move object to descendant in tree\n";
		return;
		
	}
	const string& name = orig.element()->getName();
	if ( Neutral::child( newParent.eref(), name ) != Id() ) {
			stringstream ss;
			ss << "Shell::doMove: Object with same name already present: '"
			   	<< newParent.path() << "/" << name << "'. Move failed.";
			warning( ss.str() );
			return;
	}

	SetGet2< Id, ObjId >::set( ObjId(), "move", orig, newParent );
	// innerMove( orig, newParent );
}
Beispiel #3
0
void remoteFieldGetVec( const Eref& e, unsigned int bindIndex,
				vector< double >& getRecvBuf )
{
	static ObjId oi( 3 );
	static PostMaster* p = reinterpret_cast< PostMaster* >( oi.data() );
	p->remoteFieldGetVec( e, bindIndex, getRecvBuf );
}
Beispiel #4
0
void Shell::recvGet( const Eref& e, const Qinfo* q, PrepackedBuffer pb )
{
	if ( myNode_ == 0 ) {
		if ( gettingVector_ ) {
			ObjId tgt = q->src();
			// unsigned int linearIndex = q->src().eref().index().value();
			unsigned int linearIndex = 
				tgt.element()->dataHandler()->linearIndex( tgt.dataId );
			if ( linearIndex >= getBuf_.size() ) {
				if ( linearIndex >= getBuf_.capacity() )
					getBuf_.reserve( linearIndex * 2 );
				getBuf_.resize( linearIndex + 1 );
			}
			assert ( linearIndex < getBuf_.size() );
			double*& c = getBuf_[ linearIndex ];
			c = new double[ pb.dataSize() ];
			memcpy( c, pb.data(), pb.dataSize() * sizeof( double ) );
			// cout << myNode_ << ":" << q->threadNum() << ": Shell::recvGet[" << linearIndex << "]= (" << pb.dataSize() << ", " <<  *c << ")\n";
		} else  {
			assert ( getBuf_.size() == 1 );
			double*& c = getBuf_[ 0 ];
			c = new double[ pb.dataSize() ];
			memcpy( c, pb.data(), pb.dataSize() * sizeof( double ) );
			handleAck( 0, OkStatus );
		}
		++numGetVecReturns_;
	}
}
Beispiel #5
0
void remoteGetVec( const Eref& e, unsigned int bindIndex,
				vector< vector< double > >& getRecvBuf,
				vector< unsigned int >& numOnNode )
{
	static ObjId oi( 3 );
	static PostMaster* p = reinterpret_cast< PostMaster* >( oi.data() );
	p->remoteGetVec( e, bindIndex, getRecvBuf, numOnNode );
}
ObjId OneToOneDataIndexMsg::findOtherEnd( ObjId f ) const
{
	if ( f.element() == e1() )
		return ObjId( e2()->id(), f.dataIndex );
	else if ( f.element() == e2() )
		return ObjId( e1()->id(), f.dataIndex );

	return ObjId( 0, BADINDEX );
}
Beispiel #7
0
// Utility function: return the compartment in which the specified
// object is located.
// Simply traverses the tree toward the root till it finds a
// compartment. Pools use a special msg, but this works for reacs too.
ObjId getCompt( Id id )
{
	ObjId pa = Neutral::parent( id.eref() ).id;
	if ( pa == ObjId() )
		return pa;
	else if ( pa.element()->cinfo()->isA( "ChemCompt" ) )
		return pa;
	return getCompt( pa );
}
Beispiel #8
0
void EndoMesh::setSurround( const Eref& e, ObjId v )
{
	if ( !v.element()->cinfo()->isA( "ChemCompt" ) ) {
		cout << "Warning: 'surround' may only be set to an object of class 'ChemCompt'\n";
		cout << v.path() << " is of class " << v.element()->cinfo()->name() << endl;
		return;
	}
	surround_ = v;
	parent_ = reinterpret_cast< const MeshCompt* >( v.data() );
}
ObjId OneToAllMsg::findOtherEnd( ObjId f ) const
{
	if ( f.element() == e1() ) {
		if ( f.dataIndex == i1_ )
			return ObjId( e2()->id(), 0 );
	} else if ( f.element() == e2() ) {
		return ObjId( e1()->id(), i1_ );
	}
	
	return ObjId( 0, BADINDEX );
}
// static function, executed by the Synapse Element when a message is
// dropped from the Element. Contracts the parent synapse array to fit.
// Typically the SynHandler won't resize, easier to just leave an
// unused entry. Could even reuse if a synapse is added later, but all
// this policy is independent of the Synapse class.
void Synapse::dropMsgCallback(
				const Eref& e, const string& finfoName, 
			    ObjId msg, unsigned int msgLookup )
{
	if ( finfoName == "addSpike" ) {
		ObjId pa = Neutral::parent( e );
		SynHandlerBase* sh = 
				reinterpret_cast< SynHandlerBase* >( pa.data() );
		sh->dropSynapse( msgLookup );
	}
}
Beispiel #11
0
ObjId OneToAllMsg::findOtherEnd( ObjId f ) const
{
	if ( f.id() == e1() ) {
		if ( f.dataId == i1_ )
			return ObjId( e2()->id(), 0 );
		else
		  return ObjId( e2()->id(), DataId::bad() );
	} else if ( f.id() == e2() ) {
		return ObjId( e1()->id(), i1_ );
	}
	
	return ObjId::bad();
}
// static function, executed by the Synapse Element when a message is
// added to the Element. Expands the parent synapse array to fit.
void Synapse::addMsgCallback(
				const Eref& e, const string& finfoName, 
			    ObjId msg, unsigned int msgLookup )
{
	if ( finfoName == "addSpike" ) {
		ObjId pa = Neutral::parent( e );
		SynHandlerBase* sh = 
				reinterpret_cast< SynHandlerBase* >( pa.data() );
		unsigned int synapseNumber = sh->addSynapse();
		SetGet2< unsigned int, unsigned int >::set( 
						msg, "fieldIndex", msgLookup, synapseNumber );
	}
}
Beispiel #13
0
void dispatchBuffers( const Eref& e, HopIndex hopIndex )
{
	static ObjId oi( 3 );
	static PostMaster* p = reinterpret_cast< PostMaster* >( oi.data() );
	if ( Shell::numNodes() == 1 )
		return;
	if ( hopIndex.hopType() == MooseSetHop ||
	  	hopIndex.hopType() == MooseGetHop ) {
		p->dispatchSetBuf( e );
	}
	if ( hopIndex.hopType() == MooseSetVecHop ) {
		p->dispatchSetBuf( e );
	}
	// More complicated stuff for get operations.
}
Beispiel #14
0
void HDF5DataWriter::recvData(const Eref&e, 
				ObjId src, const double* start, unsigned int num )
{
    string path = src.path();
    if (nodemap_.find(path) == nodemap_.end()){
        // first time call, initialize entries in map
        hid_t dataid =  get_dataset(path);
        if (dataid < 0){
            cerr << "Warning: could not create data set for " << path << endl;
        }
        nodemap_[path] = dataid;
        datamap_[path] = vector<double>();
    }
    const double * end = start + num;
    // append only the new data. old_size is guaranteed to be 0 on
    // write and the table vecs will also be cleared.
    datamap_[path].insert(datamap_[path].end(), start, end);

    SetGet0::set(src, "clearVec"); //Unsure what this is for.
	
// #ifndef NDEBUG
//     // debug leftover entries coming from table
//     cout << "HDF5DataWriter::recvData: vec_size=" << vec_size << endl;
//     cout << "HDF5DataWriter::recvData: dataSize=" << pb.dataSize() << endl;
//     cout << "HDF5DataWriter::recvData: numEntries=" << pb.numEntries()  << endl;
//     cout << "HDF5DataWriter::recvData: size=" << pb.size() << endl;
//     cout << "HDF5DataWriter::recvData: data()" << endl;
//     for (int ii = 0; ii <= vec_size; ++ii){
//         cout << ii << "\t" << pb.data()[ii] << endl;
//     }
// #endif
}
Beispiel #15
0
void Neutral::setName( const Eref& e, string name )
{
	if ( e.id().value() <= 3 ) {
		cout << "Warning: Neutral::setName on '" << e.id().path() << 
			   "'.Cannot rename core objects\n";
		return;
	}
	ObjId pa = parent( e );
	Id sibling = Neutral::child( pa.eref(), name );
	if ( sibling == Id() ) { // OK, no existing object with same name.
		e.element()->setName( name );
	} else {
		cout << "Warning: Neutral::setName: an object with the name '" <<
			name << "'\n already exists on the same parent. Not changed\n";
	}
}
Beispiel #16
0
// static function
bool Neutral::isDescendant( Id me, Id ancestor )
{
	static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" );
	static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	static const FuncId pafid = pf2->getFid();

	Eref e = me.eref();
	
	while ( e.element()->id() != Id() && e.element()->id() != ancestor ) {
		ObjId mid = e.element()->findCaller( pafid );
		assert( mid != ObjId() );
		ObjId fid = Msg::getMsg( mid )->findOtherEnd( e.objId() );
		e = fid.eref();
	}
	return ( e.element()->id() == ancestor );
}
Beispiel #17
0
double* addToBuf( const Eref& er, HopIndex hopIndex, unsigned int size )
{
	static ObjId oi( 3 );
	static PostMaster* p = reinterpret_cast< PostMaster* >( oi.data() );
	if ( hopIndex.hopType() == MooseSendHop ) {
		return p->addToSendBuf( er, hopIndex.bindIndex(), size );
	} else if ( hopIndex.hopType() == MooseSetHop ||
			 hopIndex.hopType() == MooseSetVecHop ) {
		p->clearPendingSetGet(); // Cannot touch set buffer if pending.
		return p->addToSetBuf( er, hopIndex.bindIndex(),
						size, hopIndex.hopType() );
	} else if ( hopIndex.hopType() == MooseTestHop ) {
		return addToTestBuf( er, hopIndex.bindIndex(), size );
	}
	assert( 0 ); // Should not get here.
	return 0;
}
Beispiel #18
0
void NSDFWriter::writeModelTree()
{
    vector< string > tokens;
    ObjId mRoot(modelRoot_);
    string rootPath = MODELTREEPATH + string("/") + mRoot.element()->getName();
    hid_t rootGroup = require_group(filehandle_, rootPath);
    hid_t tmp;
    htri_t exists;
    herr_t status;
    deque<Id> nodeQueue;
    deque<hid_t> h5nodeQueue;
    nodeQueue.push_back(mRoot);
    h5nodeQueue.push_back(rootGroup);
    // TODO: need to clarify what happens with array elements. We can
    // have one node per vec and set a count field for the number of
    // elements
    while (nodeQueue.size() > 0){
        ObjId node = nodeQueue.front();
        nodeQueue.pop_front();
        hid_t prev = h5nodeQueue.front();;
        h5nodeQueue.pop_front();
        vector < Id > children;
        Neutral::children(node.eref(), children);
        for ( unsigned int ii = 0; ii < children.size(); ++ii){
            string name = children[ii].element()->getName();
            // skip the system elements
            if (children[ii].path() == "/Msgs"
                || children[ii].path() == "/clock"
                || children[ii].path() == "/classes"
                || children[ii].path() == "/postmaster"){
                continue;
            }
            exists = H5Lexists(prev, name.c_str(), H5P_DEFAULT);
            if (exists > 0){
                tmp = H5Gopen2(prev, name.c_str(), H5P_DEFAULT);
            } else {
                tmp = H5Gcreate2(prev, name.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
            }
            writeScalarAttr< string >(tmp, "uid", children[ii].path());
            nodeQueue.push_back(children[ii]);
            h5nodeQueue.push_back(tmp);
        }
        status = H5Gclose(prev);
    }
}
Beispiel #19
0
void Shell::destroy( const Eref& e, ObjId oid)
{
	Neutral *n = reinterpret_cast< Neutral* >( e.data() );
	assert( n );
	// cout << myNode_ << ": Shell::destroy done for element id: " << eid << ", name = " << eid.element()->getName() << endl;
	n->destroy( oid.eref(), 0 );
	if ( cwe_.id == oid.id )
		cwe_ = ObjId();
}
Beispiel #20
0
Id ReadCell::startGraftCell( const string& cellPath )
{
	/*
	 * If path exists, return with error. This will also catch the case where
	 * cellPath is "/", and we will not have to check for this separately
	 * later.
	 */
	Id cellId( cellPath );
	if ( cellId.path() == cellPath ) {
		cerr << "Warning: ReadCell: cell '" << cellPath << "' already exists.\n";
		cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
		return Id();
	}
	
        ObjId parentObjId;
	string cellName;
	string::size_type pos_1 = cellPath.find_first_of( "/" );
	string::size_type pos_2 = cellPath.find_last_of( "/" );
	
	if ( pos_1 != 0 ) {
		cerr << "Error: ReadCell: *start_cell should be given absolute path.\n";
		cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
		return Id();
	}
	
	if ( pos_2 == 0 ) {
            parentObjId = ObjId("/");
		cellName = cellPath.substr( 1 );
	} else {
		string parentPath = cellPath.substr( 0, pos_2  );
		parentObjId = ObjId( parentPath );
		if ( parentObjId.bad() ) {
			cerr << "Error: ReadCell: cell path '" << cellPath
				<< "' not found.\n";
			cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
			return Id();
		}
		
		cellName = cellPath.substr( pos_2 + 1 );
	}
	
	unsigned int size = 1;
	return shell_->doCreate( "Compartment", parentObjId, cellName, size, MooseGlobal );
}
Beispiel #21
0
// Static function 
string Neutral::path( const Eref& e )
{
	static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" );
	static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	static const FuncId pafid = pf2->getFid();

	vector< ObjId > pathVec;
	ObjId curr = e.objId();
	stringstream ss;

	pathVec.push_back( curr );
	while ( curr.id != Id() ) {
		ObjId mid = curr.eref().element()->findCaller( pafid );
		if ( mid == ObjId() ) {
			cout << "Error: Neutral::path:Cannot follow msg of ObjId: " <<
				   	e.objId() << " for func: " << pafid << endl;
			break;
		}
		curr = Msg::getMsg( mid )->findOtherEnd( curr );
		pathVec.push_back( curr );
	}
	if ( pathVec.size() <= 1 )
		return "/";
	for ( unsigned int i = 1; i < pathVec.size(); ++i ) {
		ss << "/";
		ObjId& oid = pathVec[ pathVec.size() - i - 1 ];
		ss << oid.element()->getName();
		if ( !oid.element()->hasFields() )
			ss << "[" << oid.dataIndex << "]";
		/*
		if ( !oid.element()->hasFields() )
			ss << "[" << oid.dataIndex << "]";
		if ( oid.element()->numData() > 1 )
			ss << "[" << oid.dataIndex << "]";
			*/
	}
	// Append braces if Eref was for a fieldElement. This should
	// work even if it is off-node.
	if ( e.element()->hasFields() ) {
		ss << "[" << e.fieldIndex() << "]";
	}

	return ss.str();
}
Beispiel #22
0
ObjId SparseMsg::findOtherEnd( ObjId f ) const
{
	if ( f.element() == e1() ) {
		const unsigned int* entry;
		const unsigned int* colIndex;
		unsigned int num = matrix_.getRow( f.dataIndex, &entry, &colIndex );
		if ( num > 0 ) { // Return the first matching entry.
			return ObjId( e2()->id(), colIndex[0] );
		}
		return ObjId( 0, BADINDEX );
	} else if ( f.element() == e2() ) { // Bad! Slow! Avoid!
		vector< unsigned int > entry;
		vector< unsigned int > rowIndex;
		unsigned int num = matrix_.getColumn( f.dataIndex, entry, rowIndex );
		if ( num > 0 ) { // Return the first matching entry.
				return ObjId( e1()->id(), DataId( rowIndex[0] ) );
		}
	}
	return ObjId( 0, BADINDEX );
}
Beispiel #23
0
/**
 * Reads in SynChans and SpikeGens.
 *
 * Unlike Compartments, HHChannels, etc., neither of these are zombified.
 * In other words, their fields are not managed by HSolve, and their "process"
 * functions are invoked to do their calculations. For SynChans, the process
 * calls are made by their respective clocks, and hence the process message is
 * not dropped. On the other hand, we drop the SpikeGen process messages here,
 * and explicitly call the SpikeGen process() from the HSolve via a pointer.
 */
void HSolveActive::readSynapses()
{
    vector< Id > spikeId;
    vector< Id > synId;
    vector< Id >::iterator syn;
    vector< Id >::iterator spike;
    SynChanStruct synchan;

    for ( unsigned int ic = 0; ic < nCompt_; ++ic )
    {
        synId.clear();
        HSolveUtils::synchans( compartmentId_[ ic ], synId );
        for ( syn = synId.begin(); syn != synId.end(); ++syn )
        {
            synchan.compt_ = ic;
            synchan.elm_ = *syn;
            synchan_.push_back( synchan );
        }

        static const Finfo* procDest = SpikeGen::initCinfo()->findFinfo( "process");
        assert( procDest );
        const DestFinfo* df = dynamic_cast< const DestFinfo* >( procDest );
        assert( df );

        spikeId.clear();
        HSolveUtils::spikegens( compartmentId_[ ic ], spikeId );
        // Very unlikely that there will be >1 spikegens in a compartment,
        // but lets take care of it anyway.
        for ( spike = spikeId.begin(); spike != spikeId.end(); ++spike )
        {
            spikegen_.push_back(
                SpikeGenStruct( &V_[ ic ], spike->eref() )
            );

            ObjId mid = spike->element()->findCaller( df->getFid() );
            if ( ! mid.bad()  )
                Msg::deleteMsg( mid );
        }
    }
}
/**
   Utility function to delete incoming messages on orig.
   To be used in zombifying elements.
*/
void HSolve::deleteIncomingMessages( Element * orig, const string finfo)
{
    const DestFinfo * concenDest = dynamic_cast<const DestFinfo*>(orig->cinfo()->findFinfo(finfo));
    assert(concenDest);
    ObjId mid = orig->findCaller(concenDest->getFid());
    while (! mid.bad())
    {
        const Msg * msg = Msg::getMsg(mid);
        assert(msg);
        ObjId other = msg->findOtherEnd(orig->id());
        Element * otherEl = other.id.element();
        if (otherEl &&  HSolve::handledClasses().find(otherEl->cinfo()->name()) != HSolve::handledClasses().end())
        {
            Msg::deleteMsg(mid);
        }
        else
        {
            break; // Have to do this otherwise it is an infinite loop
        }
        mid = orig->findCaller(concenDest->getFid());
    }
}
Beispiel #25
0
/**
 * Adds a typical channel to a compartment:
 *     - Connects up the 'channel' message between chan and compt.
 *     - Sets the Gbar field on the channel.
 * 
 * Typical channels currently are: HHChannel, HHChannel2D and SynChan. All of
 * these have the same "channel" interface, and have a "Gbar" field.
 */
bool ReadCell::addCanonicalChannel(
	Id compt,
	Id chan, 
	double value,
	double dia,
	double length )
{
    string className = chan.element()->cinfo()->name();
	if (
		className == "HHChannel" ||
		className == "HHChannel2D" ||
		className == "SynChan" ||
		className == "NMDAChan"
	) {
		ObjId mid = shell_->doAddMsg(
			"Single",
			compt,
			"channel",
			chan,
			"channel"
		);
		if ( mid.bad() )
			cout << "failed to connect message from compt " << compt << 
					" to channel " << chan << endl;
		
		if ( value > 0 ) {
			value *= calcSurf( length, dia );
		} else {
			value = -value;
		}
		
		if ( !graftFlag_ )
			++numChannels_;
		
		return Field< double >::set( chan, "Gbar", value );
	}
	
	return 0;
}
Beispiel #26
0
bool Shell::innerMove( Id orig, ObjId newParent )
{
	static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" );
	static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	static const FuncId pafid = pf2->getFid();
	static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" );

	assert( !( orig == Id() ) );
	assert( !( newParent.element() == 0 ) );

	ObjId mid = orig.element()->findCaller( pafid );
	Msg::deleteMsg( mid );

	Msg* m = new OneToAllMsg( newParent.eref(), orig.element(), 0 );
	assert( m );
	if ( !f1->addMsg( pf, m->mid(), newParent.element() ) ) {
		cout << "move: Error: unable to add parent->child msg from " <<
			newParent.element()->getName() << " to " << 
			orig.element()->getName() << "\n";
		return 0;
	}
	return 1;
}
Beispiel #27
0
/**
 * Static utility function. Attaches child element to parent element.
 * Must only be called from functions executing in parallel on all nodes,
 * as it does a local message addition
 * MsgIndex is needed to be sure that the same msg identifies parent-child
 * connection on all nodes.
 */
bool Shell::adopt( ObjId parent, Id child, unsigned int msgIndex ) {
	static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" );
	// static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	// static const FuncId pafid = pf2->getFid();
	static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" );

	assert( !( child.element() == 0 ) );
	assert( !( child == Id() ) );
	assert( !( parent.element() == 0 ) );

	Msg* m = new OneToAllMsg( parent.eref(), child.element(), msgIndex );
	assert( m );

	// cout << myNode_ << ", Shell::adopt: mid = " << m->mid() << ", pa =" << parent << "." << parent()->getName() << ", kid=" << child << "." << child()->getName() << "\n";

	if ( !f1->addMsg( pf, m->mid(), parent.element() ) ) {
		cout << "move: Error: unable to add parent->child msg from " <<
			parent.element()->getName() << " to " << 
			child.element()->getName() << "\n";
		return 0;
	}
	return 1;
}
Beispiel #28
0
ObjId Neutral::parent( ObjId oid )
{
	static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" );
	static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	static const FuncId pafid = pf2->getFid();

	if ( oid.id == Id() ) {
		cout << "Warning: Neutral::parent: tried to take parent of root\n";
		return Id();
	}

	ObjId mid = oid.element()->findCaller( pafid );
	assert( mid != ObjId() );

	ObjId pa = Msg::getMsg( mid )->findOtherEnd( oid );
	return pa;
}
Beispiel #29
0
/// non-static func. Returns the Id found by traversing the specified path.
ObjId Shell::doFind( const string& path ) const
{
	if ( path == "/" || path == "/root" )
		return ObjId();

	ObjId curr;
	vector< string > names;
	vector< unsigned int > indices;
	bool isAbsolute = chopPath( path, names, indices );
	assert( names.size() == indices.size() );

	if ( !isAbsolute )
		curr = cwe_;

	for ( unsigned int i = 0; i < names.size(); ++i ) {
		if ( names[i] == "." ) {
		} else if ( names[i] == ".." ) {
			curr = Neutral::parent( curr.eref() );
		} else {
			ObjId pa = curr;
			curr = Neutral::child( curr.eref(), names[i] );
			if ( curr == ObjId() ) // Neutral::child returned Id(), ie, bad.
				return ObjId( 0, BADINDEX );
			if ( curr.element()->hasFields() ) {
				curr.dataIndex = pa.dataIndex;
				curr.fieldIndex = indices[i];
			} else {
				curr.dataIndex = indices[i];
				if ( curr.element()->numData() <= curr.dataIndex  )
					return ObjId( 0, BADINDEX );
			}
		}
	}
	
	assert( curr.element() );
	if ( curr.element()->numData() <= curr.dataIndex )
		return ObjId( 0, BADINDEX );
	if ( curr.fieldIndex > 0 && !curr.element()->hasFields() )
		return ObjId( 0, BADINDEX );

	return curr;
}
Beispiel #30
0
void ReadCell::addChannelMessage( Id chan )
{
	/*
	* Get child objects of type Mstring, named addmsg1, 2, etc.
	* These define extra messages to be assembled at setup.
	* Similar to what was done with GENESIS.
	*/
	vector< Id > kids;
	Neutral::children( chan.eref(), kids );
	Shell *shell = reinterpret_cast< Shell* >( Id().eref().data() );
	Id cwe = shell->getCwe();
	shell->setCwe( chan );
	for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i )
	{
		// Ignore kid if its name does not begin with "addmsg"..
		const string& name = i->element()->getName();
		if ( name.find( "addmsg", 0 ) != 0 )
			continue;

		string s = Field< string >::get( *i, "value" );
		vector< string > token;
		tokenize( s, " 	", token );
		assert( token.size() == 4 );
		ObjId src = shell->doFind( token[0] );
		ObjId dest = shell->doFind( token[2] );

		// I would like to assert, or warn here, but there are legitimate 
		// cases where not all possible messages are actually available 
		// to set up. So I just bail.
		if ( src.bad() || dest.bad()) {
#ifndef NDEBUG
				/*
			cout << "ReadCell::addChannelMessage( " << chan.path() << 
				"): " << name << " " << s << 
				": Bad src " << src << " or dest " << dest << endl;
				*/
#endif
			continue; 
		}
		ObjId mid = 
			shell->doAddMsg( "single", src, token[1], dest, token[3] );
		assert( !mid.bad());
	}
	shell->setCwe( cwe );
}