/// <summary>
        /// Perform a JSON-syntax query
        /// </summary>
        /// <param name="queryString">The Json string representing the query object, which contains the query path, and traverse action objects.</param>
        /// <param name="queryPath">When provided, overrides the query path in the query object.</param>
        /// <returns>A json string representing query results.</returns>
        /// <exception cref="FanoutSearchQueryException">Throws if the query string is invalid.</exception>
        /// <exception cref="FanoutSearchQueryTimeoutException">Throws if the query timed out, and the server is set to not respond with partial result.</exception>"
        /// <exception cref="Trinity.Network.Messaging.MessageTooLongException">Throws if the query response is too big, and the server is set to not respond with partial result.</exception>
        public string JsonQuery(string queryString, string queryPath = "")
        {
            FanoutSearchDescriptor fanoutSearch_desc = _JsonQuery_impl(queryString, queryPath);

            using (StringWriter sw = new StringWriter(new StringBuilder(128, s_max_fanoutmsg_size)))
            {
                _SerializePaths(fanoutSearch_desc, sw);
                return(sw.ToString());
            }
        }
        /// <summary>
        /// Perform a Lambda-syntax query
        /// </summary>
        /// <param name="lambda">The query string, in LIKQ syntax.</param>
        /// <param name="getEdgeType">Get edge types, and interleave nodes and edge type arrays in the query result.</param>
        /// <returns>A json string representing query results.</returns>
        /// <exception cref="FanoutSearchQueryException">Throws if the query string is invalid.</exception>
        /// <exception cref="FanoutSearchQueryTimeoutException">Throws if the query timed out, and the server is set to not respond with partial result.</exception>"
        /// <exception cref="Trinity.Network.Messaging.MessageTooLongException">Throws if the query response is too big, and the server is set to not respond with partial result.</exception>
        public string LambdaQuery(string lambda)
        {
            FanoutSearchDescriptor fanoutSearch_desc = _LambdaQuery_impl(lambda);

            using (StringWriter sw = new StringWriter(new StringBuilder(128, s_max_fanoutmsg_size)))
            {
                _SerializePaths(fanoutSearch_desc, sw);
                return(sw.ToString());
            }
        }
예제 #3
0
        private static FanoutSearchDescriptor ConstructFanoutSearchOrigin(FSDescCallchainElement origin)
        {
            /***********************************************
            * Syntax:
            *
            * 1. StartFrom(long cellid, IEnumerable<string> select = null)
            * 2. StartFrom(IEnumerable<long> cellid, IEnumerable<string> select = null)
            * 3. StartFrom(string queryObject, IEnumerable<string> select = null)
            ***********************************************/

            ThrowIf(origin.Method != s_LIKQ_StartFrom, "Expecting " + s_LIKQ_StartFrom, origin.SyntaxNode);
            FanoutSearchDescriptor fs_desc = new FanoutSearchDescriptor("");

            fs_desc.m_origin_query = null;
            ThrowIf(origin.Arguments.Count < 1 || origin.Arguments.Count > 2, "Expecting 1 or 2 arguments", origin.SyntaxNode);

            ExpressionSyntax origin_cell_query = origin.Arguments[0].Expression;
            ExpressionSyntax selection         = origin.Arguments.Count < 2 ? null : origin.Arguments[1].Expression;

            switch (origin_cell_query.Kind())
            {
            case SyntaxKind.ObjectCreationExpression:
            case SyntaxKind.ImplicitArrayCreationExpression:
            case SyntaxKind.ArrayCreationExpression:
                fs_desc.m_origin = ConstructCollection <long>(origin_cell_query).ToList();
                break;

            case SyntaxKind.NumericLiteralExpression:
            case SyntaxKind.UnaryMinusExpression:
            case SyntaxKind.UnaryPlusExpression:
            {
                long cell_id      = 0;
                var  parse_result = long.TryParse(origin_cell_query.ToString(), out cell_id);
                ThrowIf(!parse_result, "Expecting a cell id", origin_cell_query);
                fs_desc.m_origin = new List <long> {
                    cell_id
                };
                break;
            }

            case SyntaxKind.StringLiteralExpression:
                fs_desc.m_origin_query = (origin_cell_query as LiteralExpressionSyntax).Token.ValueText;
                break;

            default:
                throw new LambdaDSLSyntaxErrorException("Invalid starting node argument", origin_cell_query);
            }

            if (selection != null)
            {
                fs_desc.m_selectFields.Add(ConstructCollection <string>(selection).ToList());
            }

            return(fs_desc);
        }
        // queryResultPaths represents a serialized json array, so we just concatenate it with
        // a wrapper
        private static void _WriteResults(HttpListenerResponse response, FanoutSearchDescriptor queryResultPaths)
        {
            using (var sw = new StreamWriter(response.OutputStream))
            {
                sw.WriteLine(@"{
    ""Results"":");
                _SerializePaths(queryResultPaths, sw);
                sw.WriteLine(@"
}");
            }
        }
예제 #5
0
 private static void ProcessJsonEdgeTypeDescriptor(FanoutSearchDescriptor fs_desc, string edge_desc)
 {
     if (edge_desc == "*" || edge_desc == "")
     {
         fs_desc.m_edgeTypes.Add(new EdgeTypeDescriptor(fs_desc));
     }
     else
     {
         fs_desc.m_edgeTypes.Add(new EdgeTypeDescriptor(fs_desc, edge_desc.Split(',')));
     }
 }
예제 #6
0
        private FanoutSearchDescriptor Take_impl(int startIndex, int count)
        {
            Debug.Assert(startIndex >= 0);
            Debug.Assert(count >= 0);
            FanoutSearchDescriptor that = this.MemberwiseClone() as FanoutSearchDescriptor;

            that.m_takeCount = count;
            that.m_skipCount = startIndex;
            that.m_results   = null;

            return(that);
        }
예제 #7
0
        private static void _SerializePaths(FanoutSearchDescriptor search, TextWriter writer)
        {
            long len = 0;

            try
            {
                var paths = search.ToList().AsParallel().Select(p =>
                {
                    StringBuilder builder = new StringBuilder();
                    p.Serialize(builder);
                    var newlen = Interlocked.Add(ref len, builder.Length);
                    if (newlen > s_max_rsp_size)
                    {
                        throw new MessageTooLongException();
                    }
                    return(builder.ToString());
                });
                bool first = true;
                writer.Write('[');


                foreach (var path in paths)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        writer.Write(',');
                    }

                    writer.Write(path);
                }
                writer.Write(']');
            }
            catch (AggregateException ex) when(ex.InnerExceptions.Any(_ => _ is MessageTooLongException || _ is OutOfMemoryException))
            {
                throw new MessageTooLongException();
            }
            catch (OutOfMemoryException)
            {
                throw new MessageTooLongException();
            }
        }
예제 #8
0
        internal static void ProcessJsonTraverseAction(FanoutSearchDescriptor fs_desc, JObject queryObject, int i, int len, string element_str)
        {
            List <long>   cell_ids       = null;
            bool          is_cell_id     = TryParseLongList(element_str, out cell_ids);
            bool          is_origin      = (i == 0);
            bool          is_last        = (i == len - 1 || i == len - 2);
            List <string> selectedFields = new List <string>();

            if (is_cell_id)
            {
                if (is_origin)
                {
                    fs_desc.m_origin = cell_ids;
                }
                else
                {
                    if (is_last) /* The last node, action set to return */
                    {
                        fs_desc.AddTraverseStep(ExpressionBuilder.GenerateTraverseActionFromCellIds(Action.Return, cell_ids), null);
                    }
                    else /* Intermediate node, action set to continue */
                    {
                        fs_desc.AddTraverseStep(ExpressionBuilder.GenerateTraverseActionFromCellIds(Action.Continue, cell_ids), null);
                    }
                }
            }
            else
            {
                dynamic action_object = queryObject[element_str];
                ProcessJsonSelectField(selectedFields, action_object);

                if (is_origin)
                {
                    ProcessJsonOriginNodeObject(fs_desc, action_object);
                }
                else /* not origin */
                {
                    ProcessJsonNonOriginNodeObject(fs_desc, is_last, action_object);
                }
            }

            fs_desc.m_selectFields.Add(selectedFields);
        }
예제 #9
0
        private static FanoutSearchDescriptor ConstructFanoutSearchBody(FanoutSearchDescriptor current, FSDescCallchainElement visitNode, FSDescCallchainElement followEdge, Action defaultTraverseAction)
        {
            List <string>      follow_edge_set = ConstructFollowEdgeSet(followEdge);
            EdgeTypeDescriptor ets             = current.FollowEdge(follow_edge_set.ToArray());

            if (visitNode == null)
            {
                return(ets.VisitNode(defaultTraverseAction));
            }
            else if (visitNode.Arguments.Count == 1)
            {
                return(ets.VisitNode(ConstructVisitNodeAction(visitNode.Arguments[0].Expression)));
            }
            else /*if (visitNode.Arguments.Count > 1)*/
            {
                return(ets.VisitNode(
                           ConstructVisitNodeAction(visitNode.Arguments[0].Expression),
                           ConstructCollection <string>(visitNode.Arguments[1].Expression) /*select*/));
            }
        }
예제 #10
0
        private string PathsToJsonArray(FanoutSearchDescriptor search, bool getEdgeType)
        {
            StringBuilder sb    = new StringBuilder();
            bool          first = true;

            sb.Append('[');
            foreach (var path in search)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    sb.Append(',');
                }
                OutputPath(path, sb, getEdgeType);
            }
            sb.Append(']');
            return(sb.ToString());
        }
예제 #11
0
        internal static void ProcessJsonQueryObject(FanoutSearchDescriptor fs_desc, string queryPath, JObject queryObject)
        {
            string[] path_elements = queryPath.Split(s_url_path_separator, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0, len = path_elements.Length; i != len; ++i)
            {
                var element_str = path_elements[i];

                if (0 == (i % 2)) /* Node */
                {
                    ProcessJsonTraverseAction(fs_desc, queryObject, i, len, element_str);
                }
                else /* Edge */
                {
                    ProcessJsonEdgeTypeDescriptor(fs_desc, element_str);
                }
            }

            if (0 == path_elements.Length % 2) /* There's no final node desc. Add a return command. */
            {
                fs_desc.AddTraverseStep(_ => Action.Return, null);
            }
        }
        private static FanoutSearchDescriptor _JsonQuery_impl(string queryString, string queryPath)
        {
            JObject queryObject = null;

            try { queryObject = JsonConvert.DeserializeObject <JObject>(queryString); } catch { }

            if (queryObject == null)
            {
                throw new FanoutSearchQueryException("The input is not a valid Json object.");
            }

            if (QueryPathInvalid(queryPath))
            {
                JToken queryPath_token = null;
                if (!queryObject.TryGetValue(JsonDSL.Path, out queryPath_token))
                {
                    throw new FanoutSearchQueryException("Query path not found");
                }
                queryPath = queryPath_token.ToString();
                if (QueryPathInvalid(queryPath))
                {
                    throw new FanoutSearchQueryException("Invalid query path");
                }
            }
            Log.WriteLine(LogLevel.Debug, "{0}", $"Json query: {queryString} \r\n QueryPath = {queryPath}");

            try
            {
                FanoutSearchDescriptor fanoutSearch_desc = new FanoutSearchDescriptor(queryPath, queryObject);
                return(fanoutSearch_desc);
            }
            catch (Exception ex)
            {
                throw new FanoutSearchQueryException("Error parsing the json query object", ex);
            }
        }
예제 #13
0
        internal static void ProcessJsonOriginNodeObject(FanoutSearchDescriptor fs_desc, dynamic action_object)
        {
            if (action_object == null)
            {
                throw new FanoutSearchQueryException("The starting node descriptor cannot be null");
            }
            JArray  id_array  = action_object[JsonDSL.Id];
            string  type_str  = action_object[JsonDSL.Type];
            JObject match_obj = action_object[JsonDSL.Match];

            if (id_array != null)
            {
                fs_desc.m_origin = id_array.Select(_ => (long)_).ToList();
            }
            else
            {
                /* construct origin query object */
                JObject query_object = new JObject();
                /* if match_obj not found, use the action object itself (remove query operators). */
                if (match_obj == null)
                {
                    match_obj = new JObject(action_object);
                    match_obj.Remove(JsonDSL.Id);
                    match_obj.Remove(JsonDSL.Type);
                    match_obj.Remove(JsonDSL.Match);
                    if (match_obj.Properties().Count() == 0)
                    {
                        throw new FanoutSearchQueryException("No match conditions for starting node");
                    }
                }

                query_object[JsonDSL.Match] = match_obj;
                query_object[JsonDSL.Type]  = type_str;
                fs_desc.m_origin_query      = query_object.ToString();
            }
        }
예제 #14
0
        private static void ProcessJsonNonOriginNodeObject(FanoutSearchDescriptor fs_desc, bool is_last, dynamic action_object)
        {
            Expression <Func <ICellAccessor, Action> > traverse_action = null;
            Action default_action = is_last ? Action.Return : Action.Continue;

            traverse_action = ExpressionBuilder.GenerateTraverseActionFromQueryObject(action_object, default_action);

            if (traverse_action != null)
            {
                fs_desc.AddTraverseStep(traverse_action, null);
            }
            else
            {
                /* either user didn't specify node desc, or node desc doesn't imply traverse action */
                if (is_last)
                {
                    fs_desc.AddTraverseStep(_ => Action.Return, null);
                }
                else
                {
                    fs_desc.AddTraverseStep(_ => Action.Continue, null);
                }
            }
        }
예제 #15
0
 internal EdgeTypeDescriptor(FanoutSearchDescriptor search, params string[] edge_types)
 {
     this.edge_types    = edge_types;
     this.fanout_search = search;
 }