protected void GenTreeHandler(object chano, EventArgs args) {
if (LogEnabled) {
ProtocolLog.Write(ProtocolLog.MapReduce,
String.Format("MapReduce: {0}, GenTreeHandler", _node.Address));
}
Channel gtchan = (Channel)chano;
MapReduceInfo[] children;
object gtchan_result = null;
try {
gtchan_result = gtchan.Dequeue();
children = (MapReduceInfo[])gtchan_result;
}
catch(Exception x) {
//We could fail to return (queue is empty), or get a bad result
Exception rx = gtchan_result as Exception;
if( rx != null) {
x = rx; //x should have been a bad cast
}
if (LogEnabled) {
ProtocolLog.Write(ProtocolLog.MapReduce,
String.Format("MapReduce: {0}, GenTreeHandler exception ({1})", _node.Address, x));
}
HandleException(null, x);
return;
}
//The usual transactional bit:
State state = _state;
State old_state;
State new_state;
do {
old_state = state;
new_state = old_state.UpdateTree(children);
state = Interlocked.CompareExchange<State>(ref _state, new_state, old_state);
}
while( state != old_state);
if( new_state.Done ) {
//We don't need to start calling our children
if (LogEnabled) {
ProtocolLog.Write(ProtocolLog.MapReduce,
String.Format("MapReduce: {0}, done on GenTreeHandler", _node.Address));
}
SendResult( new_state.ReduceResult );
return;
}
//Now we need to start calling our children:
foreach(MapReduceInfo mri in children) {
Channel child_q = new Channel(1, mri);
child_q.CloseEvent += this.ChildCallback;
try {
if (LogEnabled) {
ProtocolLog.Write(ProtocolLog.MapReduce,
String.Format("MapReduce: {0}, calling child ({1})", _node.Address, mri.Sender.ToUri()));
}
_rpc.Invoke(mri.Sender, child_q, "mapreduce.Start", mri.Args.ToHashtable());
}
catch(Exception x) {
if (LogEnabled) {
ProtocolLog.Write(ProtocolLog.MapReduce,
String.Format("MapReduce: {0}, child ({1}) call threw: {2}.", _node.Address, mri.Sender.ToUri(), x));
}
HandleException(mri.Sender, x);
}
}
}