public void GetEnqueueHandler(Object o, EventArgs args) {
Channel queue = (Channel) o;
// Looking up state
AsDhtGetState adgs = (AsDhtGetState) _adgs_table[queue];
if(adgs == null) {
return;
}
int idx = (int) adgs.queueMapping[queue];
// Test to see if we got any results and place them into results if necessary
ISender sendto = null;
MemBlock token = null;
try {
RpcResult rpc_reply = (RpcResult) queue.Dequeue();
ArrayList result = (ArrayList) rpc_reply.Result;
//Result may be corrupted
if(result == null) {
throw new Exception("Invalid result");
}
ArrayList values = (ArrayList) result[0];
int remaining = (int) result[1];
if(remaining > 0) {
token = MemBlock.Reference((byte[]) result[2]);
sendto = rpc_reply.ResultSender;
}
// Going through the return values and adding them to our
// results, if a majority of our servers say a data exists
// we say it is a valid data and return it to the caller
foreach (Hashtable ht in values) {
MemBlock mbVal = MemBlock.Reference((byte[]) ht["value"]);
int count = 1;
Hashtable res = null;
lock(adgs.SyncRoot) {
res = (Hashtable) adgs.results[mbVal];
if(res == null) {
res = new Hashtable();
adgs.results[mbVal] = res;
adgs.ttls[mbVal] = ht["ttl"];
}
else {
adgs.ttls[mbVal] = (int) adgs.ttls[mbVal] + (int) ht["ttl"];
}
res[idx] = true;
count = ((ICollection) adgs.results[mbVal]).Count;
}
if(count == MAJORITY) {
ht["ttl"] = (int) adgs.ttls[mbVal] / MAJORITY;
adgs.returns.Enqueue(ht);
}
}
}
catch (Exception) {
sendto = null;
token = null;
}
// We were notified that more results were available! Let's go get them!
if(token != null && sendto != null) {
Channel new_queue = new Channel(1);
lock(adgs.SyncRoot) {
adgs.queueMapping[new_queue] = idx;
}
lock(_adgs_table.SyncRoot) {
_adgs_table[new_queue] = adgs;
}
new_queue.EnqueueEvent += this.GetEnqueueHandler;
new_queue.CloseEvent += this.GetCloseHandler;
try {
_rpc.Invoke(sendto, new_queue, "dht.Get",
adgs.brunet_address_for_key[idx], token);
}
catch(Exception) {
lock(adgs.SyncRoot) {
adgs.queueMapping.Remove(new_queue);
}
lock(_adgs_table.SyncRoot) {
_adgs_table.Remove(new_queue);
}
new_queue.EnqueueEvent -= this.GetEnqueueHandler;
new_queue.CloseEvent -= this.GetCloseHandler;
}
}
}