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

📄 rndbtreemultifieldindex.cs

📁 Perst开源实时数据库
💻 CS
字号:
namespace Perst.Impl
{
    using System;
#if USE_GENERICS
    using System.Collections.Generic;
#endif
    using System.Collections;
    using System.Reflection;
    using System.Diagnostics;
    using Perst;
    
#if USE_GENERICS
    class RndBtreeMultiFieldIndex<T>:RndBtree<object[],T>, MultiFieldIndex<T> where T:class,IPersistent
#else
    class RndBtreeMultiFieldIndex:RndBtree, MultiFieldIndex
#endif
    {
        internal String className;
        internal String[] fieldNames;
        [NonSerialized()]
        Type cls;
        [NonSerialized()]
        MemberInfo[] mbr;
 
        internal RndBtreeMultiFieldIndex()
        {
        }

        private void locateFields() 
        {
            mbr = new MemberInfo[fieldNames.Length];
            for (int i = 0; i < fieldNames.Length; i++) 
            {
                Type compType;
                mbr[i] = ClassDescriptor.lookupComponent(cls, fieldNames[i], out compType);
                if (mbr[i] == null) 
                { 
                   throw new StorageError(StorageError.ErrorCode.INDEXED_FIELD_NOT_FOUND, className + "." + fieldNames[i]);
                }
            }
        }

        public Type IndexedClass 
        {
            get 
            { 
                return cls;
            }
        }

        public MemberInfo KeyField 
        {
            get 
            { 
                return mbr[0];
            }
        }

        public MemberInfo[] KeyFields 
        {
            get 
            { 
                return mbr;
            }
        }

        public override void OnLoad()
        {
            cls = ClassDescriptor.lookup(Storage, className);
#if USE_GENERICS
            if (cls != typeof(T)) 
            {
                throw new StorageError(StorageError.ErrorCode.INCOMPATIBLE_VALUE_TYPE, cls);
            }
#endif
            locateFields();
        }
        
#if USE_GENERICS
        internal RndBtreeMultiFieldIndex(string[] fieldNames, bool unique) 
        {
            this.cls = typeof(T);
#else
        internal RndBtreeMultiFieldIndex(Type cls, string[] fieldNames, bool unique) 
        {
            this.cls = cls;
#endif
            this.unique = unique;
            this.fieldNames = fieldNames;
            this.className = ClassDescriptor.getTypeName(cls);
            locateFields();
            type = ClassDescriptor.FieldType.tpRaw;        
        }
        
        [Serializable]
        internal class CompoundKey : IComparable
        {
            internal object[] keys;
            
            public int CompareTo(object o)
            {
                CompoundKey c = (CompoundKey) o;
                int n = keys.Length < c.keys.Length?keys.Length:c.keys.Length;
                for (int i = 0; i < n; i++)
                {
                    int diff = ((IComparable) keys[i]).CompareTo(c.keys[i]);
                    if (diff != 0)
                    {
                        return diff;
                    }
                }
                return  0; // allow to compare part of the compound key
            }
            
            internal CompoundKey(object[] keys)
            {
                this.keys = keys;
            }
        }
        
        private Key convertKey(Key key)
        {
            if (key == null)
            {
                return null;
            }
            if (key.type != ClassDescriptor.FieldType.tpArrayOfObject)
            {
                throw new StorageError(StorageError.ErrorCode.INCOMPATIBLE_KEY_TYPE);
            }
            return new Key(new CompoundKey((object[]) key.oval), key.inclusion != 0);
        }
        
        private Key extractKey(IPersistent obj)
        {
            object[] keys = new object[mbr.Length];
            for (int i = 0; i < keys.Length; i++)
            {
                keys[i] = mbr[i] is FieldInfo ? ((FieldInfo)mbr[i]).GetValue(obj) : ((PropertyInfo)mbr[i]).GetValue(obj, null);
                IPersistent p = keys[i] as IPersistent;
                if (p != null && !p.IsPersistent()) { 
                    Storage.MakePersistent(p);
                }
            }
            return new Key(new CompoundKey(keys));
        }
        
#if USE_GENERICS
        public bool Put(T obj) 
#else
        public bool Put(IPersistent obj) 
#endif
        {
            return base.Put(extractKey(obj), obj);
        }

#if USE_GENERICS
        public T Set(T obj) 
#else
        public IPersistent Set(IPersistent obj) 
#endif
        {
            return base.Set(extractKey(obj), obj);
        }

#if USE_GENERICS
        public override bool Remove(T obj) 
#else
        public bool Remove(IPersistent obj) 
#endif
        {
            try 
            { 
                base.Remove(new BtreeKey(extractKey(obj), obj));        
            }
            catch (StorageError x) 
            { 
                if (x.Code == StorageError.ErrorCode.KEY_NOT_FOUND) 
                { 
                    return false;
                }
                throw x;
            }
            return true;
        }
        
#if USE_GENERICS
        public override T Remove(Key key) 
#else
        public override IPersistent Remove(Key key) 
#endif
        {
            return base.Remove(convertKey(key));
        }       

#if USE_GENERICS
        public override bool Contains(T obj) 
#else
        public bool Contains(IPersistent obj) 
#endif
        {
            Key key = extractKey(obj);
            if (unique) 
            { 
                return base.Get(key) != null;
            } 
            else 
            { 
                IPersistent[] mbrs = Get(key, key);
                for (int i = 0; i < mbrs.Length; i++) 
                { 
                    if (mbrs[i] == obj) 
                    { 
                        return true;
                    }
                }
                return false;
            }
        }

#if USE_GENERICS
        public void Append(T obj) 
#else
        public void Append(IPersistent obj) 
#endif
        {
            throw new StorageError(StorageError.ErrorCode.UNSUPPORTED_INDEX_TYPE);
        }

#if USE_GENERICS
        public override T[] Get(Key from, Key till)
#else
        public override IPersistent[] Get(Key from, Key till)
#endif
        {
            ArrayList list = new ArrayList();
            if (root != null)
            {
                root.find(convertKey(from), convertKey(till), height, list);
            }
#if USE_GENERICS
            return (T[]) list.ToArray(cls);
#else
            return (IPersistent[]) list.ToArray(cls);
#endif
        }

#if USE_GENERICS
        public override T[] ToArray() 
        {
            T[] arr = new T[nElems];
#else
        public override IPersistent[] ToArray() 
        {
            IPersistent[] arr = (IPersistent[])Array.CreateInstance(cls, nElems);
#endif
            if (root != null) 
            { 
                root.traverseForward(height, arr, 0);
            }
            return arr;
        }

#if USE_GENERICS
        public override T Get(Key key) 
#else
        public override IPersistent Get(Key key) 
#endif
        {
            return base.Get(convertKey(key));
        }
 
#if USE_GENERICS
        public override IEnumerable<T> Range(Key from, Key till, IterationOrder order) 
#else
        public override IEnumerable Range(Key from, Key till, IterationOrder order) 
#endif
        { 
            return base.Range(convertKey(from), convertKey(till), order);
        }

        public override IDictionaryEnumerator GetDictionaryEnumerator(Key from, Key till, IterationOrder order) 
        {
            return base.GetDictionaryEnumerator(convertKey(from), convertKey(till), order);
        }

#if !USE_GENERICS
        public IEnumerable Select(string predicate) 
        { 
            Query query = new QueryImpl(Storage);
            return query.Select(cls, this, predicate);
        }
#endif
    }
}

⌨️ 快捷键说明

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