Exemple #1
0
        /// <summary>
        /// Register the query and initialize the aggregation object (the context),
        /// so that it is ready for fan-out search.
        /// </summary>
        /// <returns>
        /// true on a successful registration. It is guaranteed that the return value only depends
        /// on the validity of the predicates, and the same queryMessage will have the same return
        /// value on all the servers, so that we only have to check on one server for the status.
        /// </returns>
        private bool RegisterQuery(FanoutQueryMessage queryMessage, int transaction_id, int aggregate_server_id)
        {
            try
            {
                var obj = new AggregationObject
                {
                    results           = new List <FanoutPathDescriptor>(),
                    local_signals     = new SemaphoreSlim(0),
                    aggregationServer = aggregate_server_id,
                    maxHop            = queryMessage.maxHop,
                    predicates        = m_compiler.CompileQueryPredicates(queryMessage.predicates),
                    edgeTypes         = queryMessage.edge_types,
                    stopwatch         = new Stopwatch(),
                };

                obj.stopwatch.Start();
                m_aggregationObjects[transaction_id] = obj;
            }
            catch (Exception ex)
            {
                Log.WriteLine(LogLevel.Error, ex.ToString());
                return(false);
            }

            return(true);
        }
Exemple #2
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);
        }
Exemple #3
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;
                }
            }
Exemple #4
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);
        }
Exemple #5
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);

#if NETSTANDARD2_0
            m_memory_cache.Set(key_query, entry, m_entry_option);
            m_memory_cache.Set(key_trans, entry, m_entry_option);
#else
            m_memory_cache.Set(key_query, entry, m_cache_policy);
            m_memory_cache.Set(key_trans, entry, m_cache_policy);
#endif
        }
Exemple #6
0
 public QueryResultCacheEntry(int trans, AggregationObject aggr)
 {
     aggregation_obj = aggr;
     transaction_id  = trans;
 }