示例#1
0
        private List <FanoutPathDescriptor> _GetOriginPathDescriptors(FanoutQueryMessageReader request)
        {
            List <FanoutPathDescriptor> origins = new List <FanoutPathDescriptor>();

            if (request.originQuery.Length == 0) // no query string for origin. use the provided origin IDs.
            {
                origins.AddRange(request.origin.Select(_ => new FanoutPathDescriptor(_)));
                Log.WriteLine(LogLevel.Debug, "FanoutSearchQueryHandler: origin = {0}", string.Join(",", request.origin));
            }
            else // use the query string to get origin IDs.
            {
                try
                {
                    Log.WriteLine(LogLevel.Debug, "FanoutSearchQueryHandler: origin query string = {0}", request.originQuery);

                    JObject query_object = JObject.Parse(request.originQuery);
                    object  match_object = query_object[JsonDSL.Match];
                    string  type_string  = (string)query_object[JsonDSL.Type];

                    origins.AddRange(s_indexServiceFunc(match_object, type_string).Select(_ => new FanoutPathDescriptor(_)));
                }
                catch (IndexingServiceNotRegisteredException)
                {
                    Log.WriteLine(LogLevel.Error, "FanoutSearchQueryHandler: index service not registered.");
                    return(null);
                }
                catch (Exception ex)
                {
                    Log.WriteLine(LogLevel.Error, "Failed to query index service: {0}", ex.ToString());
                    return(null);
                }
            }

            return(origins);
        }
示例#2
0
        private void _SendSeedMessagesAndWaitForResults(FanoutQueryMessageReader request, int my_transaction, AggregationObject aggregation_obj, List <FanoutPathDescriptor> origin_path_descriptors)
        {
            Debug.Assert(origin_path_descriptors.Count != 0);

            // send the first(seed) search messages out.
            var grouped_origin_path_descs = from pd in origin_path_descriptors
                                            group pd by Global.CloudStorage.GetServerIdByCellId(pd.hop_0);

            var seed_message_cnt    = grouped_origin_path_descs.Count();
            var wait_count_per_seed = GetWaitCount(request.maxHop);

            foreach (var g in grouped_origin_path_descs)
            {
                MessageDispatcher.DispatchOriginMessage(g.Key, my_transaction, g);
            }

            var quota_stopwatch = Stopwatch.StartNew();

            int minimum_nowait_result_count = MinimalRequiredResultCount(request);

            if (minimum_nowait_result_count == 0)
            {
                minimum_nowait_result_count = int.MaxValue;
            }

            long waitCount = 0;
            long waitMax   = seed_message_cnt * wait_count_per_seed;

            for (; waitCount < waitMax; ++waitCount)
            {
                var time_left = s_query_time_quota - quota_stopwatch.ElapsedMilliseconds;

                if (!_QueryTimeoutEnabled())
                {
                    aggregation_obj.local_signals.Wait();
                }
                else if (time_left > 0)
                {
                    if (!aggregation_obj.local_signals.Wait((int)time_left))
                    {
                        break;
                    }
                }
                else /*time out*/ break {
                    ;
                }

                if (aggregation_obj.results.Count >= minimum_nowait_result_count)
                {
                    break;
                }
            }
示例#3
0
        private string GetQueryResultCacheRequestKey(FanoutQueryMessageReader request)
        {
            StringBuilder sb = new StringBuilder("request:");

            sb.Append(Serializer.ToString(request.origin));
            sb.Append(':');
            sb.Append(request.originQuery);
            sb.Append(':');
            sb.Append(Serializer.ToString(request.predicates));
            sb.Append(':');
            sb.Append(Serializer.ToString(request.edge_types));
            return(sb.ToString());
        }
示例#4
0
        internal void RegisterQueryResult(int transaction_id, FanoutQueryMessageReader request, AggregationObject aggregation_obj)
        {
            if (aggregation_obj.results.Count == 0)
            {
                Log.WriteLine(LogLevel.Debug, "QueryResultCache: ignoring empty query result, transaction id = {0}.", transaction_id);
                return;
            }

            QueryResultCacheEntry entry = new QueryResultCacheEntry(transaction_id, aggregation_obj);
            string key_query            = GetQueryResultCacheRequestKey(request);
            string key_trans            = GetQueryResultCacheTransactionKey(entry.transaction_id);

            m_memory_cache.Set(key_query, entry, m_cache_policy);
            m_memory_cache.Set(key_trans, entry, m_cache_policy);
        }
示例#5
0
        /// <returns>null if no cached query result is found.</returns>
        internal AggregationObject GetCachedQueryResult(FanoutQueryMessageReader query)
        {
            string key = GetQueryResultCacheRequestKey(query);
            QueryResultCacheEntry entry = (QueryResultCacheEntry)m_memory_cache.Get(key);

            if (entry == null)
            {
                return(null);
            }
            int result_cnt = entry.aggregation_obj.results.Count;

            if (result_cnt < FanoutSearchModule.MinimalRequiredResultCount(query))
            {
                return(null);
            }

            Log.WriteLine(LogLevel.Debug, "QueryResultCache: Cache hit.");

            return(entry.aggregation_obj);
        }
示例#6
0
        /// <summary>
        /// The main query handler.
        /// </summary>
        public override void FanoutSearchQueryHandler(FanoutQueryMessageReader request, FanoutResultMessageWriter response)
        {
            int my_transaction = -1;
            List <ResultPathDescriptor> rpaths = null;
            Stopwatch         query_timer      = new Stopwatch();
            AggregationObject aggregation_obj  = null;
            bool cached  = false;
            int  eresult = FanoutSearchErrorCode.OK;

            //obtain a transaction id atomically
            using (var _transaction = GetTransactionId(c_master_server_id))
            {
                my_transaction = _transaction.transaction_id;
            }

            Log.WriteLine("Transaction #{0} begins.", my_transaction);
            query_timer.Start();

            if (s_cache_enabled)
            {
                aggregation_obj = m_cache.GetCachedQueryResult(request);
            }

            if (aggregation_obj != null)
            {
                cached = true;
            }
            else
            {
                aggregation_obj = _DoFanoutSearch(my_transaction, request);
            }

            if (aggregation_obj == null)
            {
                eresult = FanoutSearchErrorCode.Error;
            }
            if (aggregation_obj != null && aggregation_obj.timed_out && !s_timeout_return_partial_results)
            {
                eresult = FanoutSearchErrorCode.Timeout; aggregation_obj = null;
            }

            if (aggregation_obj != null)
            {
                rpaths = _PullSelectionsAndAssembleResults(my_transaction, request, aggregation_obj);
            }
            else
            {
                rpaths = new List <ResultPathDescriptor>();
            }

            response.transaction_id = (aggregation_obj != null) ? my_transaction : eresult;
            response.paths          = rpaths;

            if (aggregation_obj != null && s_cache_enabled && !aggregation_obj.timed_out)
            {
                m_cache.RegisterQueryResult(my_transaction, request, aggregation_obj);
            }

            response.metadata_keys.Add("results_pulled_from_cache");
            response.metadata_values.Add(cached.ToString());
            s_metadataUpdateFunc(request, response);

            query_timer.Stop();
            Log.WriteLine("Transaction #{0} finished. Time = {1}ms.", my_transaction, query_timer.ElapsedMilliseconds);
        }
示例#7
0
        private AggregationObject _DoFanoutSearch(int transaction_id, FanoutQueryMessageReader request)
        {
            AggregationObject aggregation_obj = null;
            Stopwatch         fanout_timer    = new Stopwatch();
            bool query_registered             = false;

            do
            {
                List <FanoutPathDescriptor> origin_path_descriptors = _GetOriginPathDescriptors(request);
                fanout_timer.Start();

                if (origin_path_descriptors == null)
                {
                    aggregation_obj = null;
                    break;
                }

                //  Broadcast initialization message
                Parallel.For(0, Global.ServerCount, i =>
                {
                    using (var init_msg = new QueryInitializationMessageWriter(request, transaction_id, Global.MyServerID))
                    {
                        QueryInitialization(i, init_msg);
                    }
                });

                /* From this point on, we cannot abort this query without uninitializing our peers. */
                Log.WriteLine(LogLevel.Debug, "Transaction #{0} initialization synchronization complete, time = {1}ms.", transaction_id, fanout_timer.ElapsedMilliseconds);

                query_registered = m_aggregationObjects.TryGetValue(transaction_id, out aggregation_obj);
                if (!query_registered)
                {
                    Log.WriteLine(LogLevel.Error, "Transaction #{0}: Query registration failed.", transaction_id);
                    aggregation_obj = null;
                    break;
                }

                // For 0-hop queries, we simply return what we have in origin_path_descriptors
                if (request.maxHop == 0)
                {
                    aggregation_obj.results = origin_path_descriptors;
                    break;
                }

                _SendSeedMessagesAndWaitForResults(request, transaction_id, aggregation_obj, origin_path_descriptors);
            } while (false);

            // Query complete. Clean it up.
            if (query_registered)
            {
                Parallel.For(0, Global.ServerCount, i =>
                {
                    using (var uninit_msg = new TransactionIdMessageWriter(transaction_id))
                    {
                        QueryUninitialization(i, uninit_msg);
                    }
                });
            }

            fanout_timer.Stop();
            Log.WriteLine("Transaction #{0} Fanout finished. Time = {1}ms.", transaction_id, fanout_timer.ElapsedMilliseconds);
            return(aggregation_obj);
        }