/// <summary> /// Makes a Query where the expected result is a Graph i.e. a CONSTRUCT or DESCRIBE query /// </summary> /// <param name="handler">RDF Handler to process the results</param> /// <param name="sparqlQuery">SPARQL Query</param> public override void QueryWithResultGraph(IRdfHandler handler, string sparqlQuery) { //If no endpoints do nothing if (this._endpoints.Count == 0) { return; } //Fire off all the Asychronous Requests List <AsyncQueryWithResultGraph> asyncCalls = new List <AsyncQueryWithResultGraph>(); List <IAsyncResult> asyncResults = new List <IAsyncResult>(); int count = 0; foreach (SparqlRemoteEndpoint endpoint in this._endpoints) { //Limit the number of simultaneous requests we make to the user defined level (default 4) //We do this limiting check before trying to issue a request so that when the last request //is issued we'll always drop out of the loop and move onto our WaitAll() while (count >= this._maxSimultaneousRequests) { //First check that the count of active requests is accurate int active = asyncResults.Count(r => !r.IsCompleted); if (active < count) { //Some of the requests have already completed so we don't need to wait count = active; break; } else if (active > count) { //There are more active requests then we thought count = active; } //While the number of requests is at/above the maximum we'll wait for any of the requests to finish //Then we can decrement the count and if this drops back below our maximum then we'll go back into the //main loop and fire off our next request WaitHandle.WaitAny(asyncResults.Select(r => r.AsyncWaitHandle).ToArray()); count--; } //Make an asynchronous query to the next endpoint AsyncQueryWithResultGraph d = new AsyncQueryWithResultGraph(endpoint.QueryWithResultGraph); asyncCalls.Add(d); IAsyncResult asyncResult = d.BeginInvoke(sparqlQuery, null, null); asyncResults.Add(asyncResult); count++; } //Wait for all our requests to finish int waitTimeout = (base.Timeout > 0) ? base.Timeout : System.Threading.Timeout.Infinite; WaitHandle.WaitAll(asyncResults.Select(r => r.AsyncWaitHandle).ToArray(), waitTimeout); //Check for and handle timeouts if (!this._ignoreFailedRequests && !asyncResults.All(r => r.IsCompleted)) { for (int i = 0; i < asyncCalls.Count; i++) { try { asyncCalls[i].EndInvoke(asyncResults[i]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } throw new RdfQueryTimeoutException("Federated Querying failed due to one/more endpoints failing to return results within the Timeout specified which is currently " + (base.Timeout / 1000) + " seconds"); } //Now merge all the results together HashSet <String> varsSeen = new HashSet <string>(); bool cont = true; for (int i = 0; i < asyncCalls.Count; i++) { //Retrieve the result for this call AsyncQueryWithResultGraph call = asyncCalls[i]; IGraph g; try { g = call.EndInvoke(asyncResults[i]); } catch (Exception ex) { if (!this._ignoreFailedRequests) { //Clean up in the event of an error for (int j = i + 1; j < asyncCalls.Count; j++) { try { asyncCalls[j].EndInvoke(asyncResults[j]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } //If a single request fails then the entire query fails throw new RdfQueryException("Federated Querying failed due to the query against the endpoint '" + this._endpoints[i] + "' failing", ex); } else { //If we're ignoring failed requests we continue here continue; } } //Merge the result into the final results //If the handler has previously told us to stop we skip this step if (cont) { handler.StartRdf(); foreach (Triple t in g.Triples) { cont = handler.HandleTriple(t); //Stop if the Handler tells us to if (!cont) { break; } } handler.EndRdf(true); } } }
/// <summary> /// Makes a Query where the expected result is a Graph i.e. a CONSTRUCT or DESCRIBE query /// </summary> /// <param name="handler">RDF Handler to process the results</param> /// <param name="sparqlQuery">SPARQL Query</param> public override void QueryWithResultGraph(IRdfHandler handler, string sparqlQuery) { //If no endpoints do nothing if (this._endpoints.Count == 0) return; //Fire off all the Asychronous Requests List<AsyncQueryWithResultGraph> asyncCalls = new List<AsyncQueryWithResultGraph>(); List<IAsyncResult> asyncResults = new List<IAsyncResult>(); int count = 0; foreach (SparqlRemoteEndpoint endpoint in this._endpoints) { //Limit the number of simultaneous requests we make to the user defined level (default 4) //We do this limiting check before trying to issue a request so that when the last request //is issued we'll always drop out of the loop and move onto our WaitAll() while (count >= this._maxSimultaneousRequests) { //First check that the count of active requests is accurate int active = asyncResults.Count(r => !r.IsCompleted); if (active < count) { //Some of the requests have already completed so we don't need to wait count = active; break; } else if (active > count) { //There are more active requests then we thought count = active; } //While the number of requests is at/above the maximum we'll wait for any of the requests to finish //Then we can decrement the count and if this drops back below our maximum then we'll go back into the //main loop and fire off our next request WaitHandle.WaitAny(asyncResults.Select(r => r.AsyncWaitHandle).ToArray()); count--; } //Make an asynchronous query to the next endpoint AsyncQueryWithResultGraph d = new AsyncQueryWithResultGraph(endpoint.QueryWithResultGraph); asyncCalls.Add(d); IAsyncResult asyncResult = d.BeginInvoke(sparqlQuery, null, null); asyncResults.Add(asyncResult); count++; } //Wait for all our requests to finish int waitTimeout = (base.Timeout > 0) ? base.Timeout : System.Threading.Timeout.Infinite; WaitHandle.WaitAll(asyncResults.Select(r => r.AsyncWaitHandle).ToArray(), waitTimeout); //Check for and handle timeouts if (!this._ignoreFailedRequests && !asyncResults.All(r => r.IsCompleted)) { for (int i = 0; i < asyncCalls.Count; i++) { try { asyncCalls[i].EndInvoke(asyncResults[i]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } throw new RdfQueryTimeoutException("Federated Querying failed due to one/more endpoints failing to return results within the Timeout specified which is currently " + (base.Timeout / 1000) + " seconds"); } //Now merge all the results together HashSet<String> varsSeen = new HashSet<string>(); bool cont = true; for (int i = 0; i < asyncCalls.Count; i++) { //Retrieve the result for this call AsyncQueryWithResultGraph call = asyncCalls[i]; IGraph g; try { g = call.EndInvoke(asyncResults[i]); } catch (Exception ex) { if (!this._ignoreFailedRequests) { //Clean up in the event of an error for (int j = i + 1; j < asyncCalls.Count; j++) { try { asyncCalls[j].EndInvoke(asyncResults[j]); } catch { //Exceptions don't matter as we're just ensuring all the EndInvoke() calls are made } } //If a single request fails then the entire query fails throw new RdfQueryException("Federated Querying failed due to the query against the endpoint '" + this._endpoints[i] + "' failing", ex); } else { //If we're ignoring failed requests we continue here continue; } } //Merge the result into the final results //If the handler has previously told us to stop we skip this step if (cont) { handler.StartRdf(); foreach (Triple t in g.Triples) { cont = handler.HandleTriple(t); //Stop if the Handler tells us to if (!cont) break; } handler.EndRdf(true); } } }