⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 versionedstorage.cs

📁 Perst开源实时数据库
💻 CS
📖 第 1 页 / 共 4 页
字号:
using System;
using System.Collections;
using Perst;

namespace Rdf 
{
    /// <summary>Root class for Perst storage</summary>
    public class DatabaseRoot:PersistentResource 
    {
        /// <summary>Root object in the graph</summary>
        public VersionHistory rootObject;
        /// <summary>Index used to access object by URI prefix</summary>
        public Index          prefixUriIndex;
        /// <summary>Index used to access object by URI suffix</summary>
        public Index          suffixUriIndex;
        /// <summary>Index used to search object by string property name:value pair</summary>
        public CompoundIndex  strPropIndex;
        /// <summary>Index used to search object by numeric property name:value pair</summary>
        public CompoundIndex  numPropIndex;
        /// <summary>Index used to search object by datetime property name:value pair</summary>
        public CompoundIndex  timePropIndex;
        /// <summary>Index used to search object by reference property name:value pair</summary>
        public CompoundIndex  refPropIndex;
        /// <summary>Index used to locate property definition by property name</summary>
        public FieldIndex     propDefIndex;
        /// <summary>Index used to perform spatial search locating overlapped rectangles</summary>
        public Index          inverseIndex;
        /// <summary>Inverse keywords index</summary>
        public SpatialIndexR2 spatialIndex;
        /// <summary>Set of the latest versions</summary>
        public ISet           latest;
        /// <summary>Timestamp index</summary>
        public FieldIndex     timeIndex;
        /// <summary>Type of the types</summary>
        public VersionHistory metatype;
    }

    /// <summary>Which verions of the object should be inspected</summary>
    public enum SearchKind 
    {
        /// <summary>Latest version in version history</summary>
        LatestVersion,
        /// <summary>All versions in version history</summary>
        AllVersions,
        /// <summary>Latest version before sepcified timestamp</summary>
        LatestBefore,
        /// <summary>Oldest version after sepcified timestamp</summary>
        OldestAfter
    }

    /// <summary>
    /// Main class
    /// </summary>
    public class VersionedStorage 
    { 
        Storage      db;
        DatabaseRoot root;

        /// <summary>
        /// List of separator characters used to split string into keywords
        /// </summary>
        public static char[] keywordSeparators = 
        {
            ' ', 
            ','
        };

        /// <summary>
        /// List of most commonly used words which should be ignored andnot included in inverse index
        /// </summary>
        public static Hashtable keywordStopList = new Hashtable();

        static VersionedStorage()  
        {
            keywordStopList["the"] = true;
            keywordStopList["at"] = true;
            keywordStopList["of"] = true;
            keywordStopList["a"] = true;
            keywordStopList["to"] = true;
            keywordStopList["at"] = true;
            keywordStopList["and"] = true;
            keywordStopList["or"] = true;
            keywordStopList["i"] = true;
        }

        /// <summary>Open database</summary>
        /// <param name="filePath">path to the database file</param>    
        public void Open(string filePath) 
        { 
            db = StorageFactory.Instance.CreateStorage(); 
            db.Open(filePath);
            root = (DatabaseRoot)db.Root;
            if (root == null) 
            {
                root = new DatabaseRoot();
                root.prefixUriIndex = db.CreateIndex(typeof(string), true);
                root.suffixUriIndex = db.CreateIndex(typeof(string), true);
                root.strPropIndex = db.CreateIndex(new Type[]{typeof(PropDef), typeof(string)}, false);
                root.numPropIndex = db.CreateIndex(new Type[]{typeof(PropDef), typeof(double)}, false);
                root.refPropIndex = db.CreateIndex(new Type[]{typeof(PropDef), typeof(VersionHistory)}, false);
                root.timePropIndex = db.CreateIndex(new Type[]{typeof(PropDef), typeof(DateTime)}, false);
                root.propDefIndex = db.CreateFieldIndex(typeof(PropDef), "name", true);            
                root.timeIndex = db.CreateFieldIndex(typeof(Thing), "timestamp", false);
                root.inverseIndex = db.CreateIndex(typeof(string), false);
                root.spatialIndex = db.CreateSpatialIndexR2();
                root.latest = db.CreateSet();
                CreateMetaType();
                db.Root = root;
            }
        }
    
        /// <summary>Get verion history by URI</summary>
        /// <param name="uri">object URI</param>
        /// <returns>version history or null if no such object is found</returns>
        public VersionHistory GetObject(string uri) 
        {
            return (VersionHistory)root.prefixUriIndex[uri];
        }

        /// <summary>Get latest verion of object with specified URI</summary>
        /// <param name="uri">object URI</param>
        /// <returns>latest version of object or null if no such object is found</returns>
        public Thing GetLatestVersion(string uri) 
        {
            VersionHistory vh = (VersionHistory)root.prefixUriIndex[uri];
            return (vh != null) ? vh.Latest : null;
        }        

        /// <summary>Get verion history by URI and timestamp</summary>
        /// <param name="uri">object URI</param>
        /// <param name="kind">search kind, should be object SearchKind.LatestVersion, SearchKind.LatestBefore or 
        /// SearchKind.OldestAfter</param>
        /// <param name="timestamp">timestamp used to locate version</param>
        /// <returns>version of the object or null if no such version is found</returns>
        public Thing GetVersion(string uri, SearchKind kind, DateTime timestamp) 
        {
            VersionHistory vh = (VersionHistory)root.prefixUriIndex[uri];
            if (vh != null) 
            { 
                return vh.GetVersion(kind, timestamp);
            }
            return null;
        }

        /// <summary>Create bew object. If version history with this URI is not exists, it is created first.
        /// Then new object version is created and appended to this version history.
        /// </summary>
        /// <param name="uri">object URI</param>
        /// <param name="type">URI of object type</param>
        /// <param name="props">object properties</param>
        /// <returns>created object version</returns>
        public Thing CreateObject(string uri, string type, NameVal[] props) 
        {
            VersionHistory vh = (VersionHistory)root.prefixUriIndex[uri];
            if (vh == null) 
            {
                VersionHistory typeVh = null;
                typeVh = GetObject(type);
                if (typeVh == null) 
                { 
                    typeVh = CreateVersionHistory(type, root.metatype);
                    CreateObject(root.metatype.Latest, typeVh, new NameVal[0]);
                }
                vh = CreateVersionHistory(uri, typeVh);
            } 
            else 
            { 
                root.latest.Remove(vh.Latest);
            }
            return CreateObject(vh.type.Latest, vh, props); 
        }

        /// <summary>Get iterator through object matching specified search parameters</summary>
        /// <param name="type">String representing type of the object (direct or indirect - IsInstanceOf
        /// method will be used to check if object belongs to the specified type). It may be null, 
        /// in this case type criteria is skipped.</param>
        /// <param name="uri">Object URI pattern. It may be null, in this case URI is not inspected.</param>
        /// <param name="patterns">array of name:value pairs specifying search condition for object properties</param>
        /// <param name="kind">search kind used to select inspected versions</param>
        /// <param name="timestamp">timestamp used to select versions, if kind is SearchKind.LatestVersion
        /// or SearchKind.AllVersions this parameter is ignored</param>
        /// <returns>Enumerator through object meet search criteria.</returns>
        public IEnumerable Search(string type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp) 
        {
            VersionHistory typeVh = null;
            root.SharedLock();
            try 
            {
                if (type != null) 
                { 
                    typeVh = GetObject(type);
                    if (typeVh == null) 
                    { 
                        return new object[0]; // empty selection
                    }
                }
                if (uri != null) 
                {
                    int wc = uri.IndexOf('*');
                    if (wc < 0) 
                    { 
                        return new SearchResult(root, typeVh, null, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(uri, uri));
                    } 
                    else if (wc > 0) 
                    { 
                        String prefix = uri.Substring(0, wc);
                        return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(prefix));
                    } 
                    else if ((wc = uri.LastIndexOf('*')) < uri.Length-1) 
                    {
                        String suffix = ReverseString(uri.Substring(wc+1, uri.Length-wc-1));
                        return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.suffixUriIndex.GetEnumerator(suffix));
                    }
                }
                if (patterns.Length > 0) 
                { 
                    NameVal prop = patterns[0];
                    object val = prop.val;
                    NameVal[] restOfPatterns = SubArray(patterns);

                    switch (prop.name) 
                    {
                        case Symbols.Timestamp: 
                  
                            if (val is Range) 
                            { 
                                Range range = (Range)val;
                                if (range.from is DateTime) 
                                {
                                    Key fromKey = new Key((DateTime)range.from, range.fromInclusive);
                                    Key tillKey = new Key((DateTime)range.till, range.tillInclusive);
                                    return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, 
                                        root.timeIndex.GetEnumerator(fromKey, tillKey));
                                    
                                }
                            } 
                            else if (val is DateTime) 
                            {
                                Key key = new Key((DateTime)val);
                                return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, 
                                    root.timeIndex.GetEnumerator(key, key));                            
                            } 
                            return new object[0]; // empty selection
                        case Symbols.Rectangle:
                            if (val is NameVal[]) 
                            {
                                NameVal[] coord = (NameVal[])val;
                                if (coord.Length == 4) 
                                {
                                    RectangleR2 r = new RectangleR2((double)coord[0].val, 
                                        (double)coord[1].val, 
                                        (double)coord[2].val, 
                                        (double)coord[3].val);
                                    return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, 
                                        root.spatialIndex.Overlaps(r).GetEnumerator());
                                }
                            }
                            break;
                        case Symbols.Point:
                            if (val is NameVal[]) 
                            {
                                NameVal[] coord = (NameVal[])val;
                                if (coord.Length == 2) 
                                {
                                    double x = (double)coord[0].val;
                                    double y = (double)coord[1].val;
                                    RectangleR2 r = new RectangleR2(x, y, x, y);
                                    return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, 
                                        root.spatialIndex.Overlaps(r).GetEnumerator());
                                }
                            }
                            break;
                        case Symbols.Keyword:
                            if (val is string) 
                            {
                                ArrayList keywords = new ArrayList();
                                foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) 
                                {
                                    if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword))
                                    {
                                        keywords.Add(keyword);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -