예제 #1
0
파일: Sector.cs 프로젝트: jangocheng/TaskMQ
        public void Add(TaskQueue.ValueMap <string, object> key)
        {
            int outCmp = 0, idx;

            if (RootGradient.IndexElements.Count == 0)
            {
                initialSector.IndexElements.Add(new IndexElement(key));
                RootGradient.IndexElements.Add(new IndexElement(key)
                {
                    Reference = initialSector.Location
                });
                keysCount++;
                return;
            }
            IndexSector currentSector = RootGradient;

            for (int i = 0; i < MAXGRADIENTLEVEL; i++)
            {
                idx = currentSector.BinarySearch(key, out outCmp);
                if (currentSector.IsSerial)
                {
                    if (outCmp == 0 && currentSector.IndexElements.Count > 0)
                    {
                        // duplicates not allowed
                        throw new Exception("duplicates not allowed");
                        // actually allowed, but in this way remove operation will not perform correctly
                    }

                    Queue <QOperation> operationsQueue = new Queue <QOperation>();
                    operationsQueue.Enqueue(new QOperation()
                    {
                        Key       = key,
                        OpType    = QOperationType.ADDKEY,
                        Reference = currentSector,
                        index     = idx
                    });
                    while (operationsQueue.Count > 0)
                    {
                        QOperation op = operationsQueue.Dequeue();
                        switch (op.OpType)
                        {
                        case QOperationType.ADDKEY:
                            if (op.index < 0)
                            {
                                op.index = op.Reference.BinarySearch(op.Key, out outCmp);
                            }
                            IndexElement new_element;
                            if (op.Reference.IsSerial)
                            {
                                new_element = new IndexElement(op.Key);
                            }
                            else
                            {
                                new_element = new IndexElement(op.Key)
                                {
                                    Reference = op.location
                                }
                            };


                            if (op.Reference.IndexElements.Count == (op.Reference.IsSerial ? IndexMaxElementsCount : GradMaxElementsCount))
                            {
                                if (!op.Reference.IsSerial && op.Reference.TopGradientReference == ROOTGRADIENT)
                                {
                                    // allocate new root gradient
                                    IndexSector new_root_sector = new IndexSector(comparator, false);
                                    new_root_sector.IndexElements = new List <IndexElement>();
                                    new_root_sector.IndexElements.Add(new IndexElement(op.Reference.IndexElements[0].IndexKey)
                                    {
                                        Reference = op.Reference.Location
                                    });
                                    new_root_sector.TopGradientReference = ROOTGRADIENT;

                                    SetSector(new_root_sector);
                                    op.Reference.TopGradientReference = new_root_sector.Location;
                                    RootGradient = new_root_sector;
                                }
                                IndexSector grad = GetSector(op.Reference.TopGradientReference);
                                // overflow
                                IndexSector new_sector = new IndexSector(comparator, op.Reference.IsSerial);
                                new_sector.IndexElements        = new List <IndexElement>();
                                new_sector.TopGradientReference = op.Reference.TopGradientReference;
                                // split....
                                if (op.index != op.Reference.IndexElements.Count)
                                {
                                    //for (int j = op.index; j < op.Reference.IndexElements.Count; j++)
                                    //{
                                    //    if (comparator.Compare(op.Key, op.Reference.IndexElements[j].IndexKey) == 0) op.index++;
                                    //}
                                    op.Reference.IndexElements.Insert(op.index, new_element);
                                    int cutindex = op.Reference.IndexElements.Count / 2;
                                    new_sector.IndexElements = op.Reference.IndexElements.GetRange(cutindex, op.Reference.IndexElements.Count - cutindex);
                                    op.Reference.IndexElements.RemoveRange(cutindex, op.Reference.IndexElements.Count - cutindex);
                                    SetSector(new_sector);
                                    if (op.index == 0)
                                    {
                                        operationsQueue.Enqueue(new QOperation()
                                        {
                                            OpType    = QOperationType.UPDATEGRADIENTKEY,
                                            Key       = key,
                                            Reference = grad,
                                            location  = op.Reference.Location
                                        });
                                    }
                                    if (!op.Reference.IsSerial)
                                    {
                                        for (int j = 0; j < new_sector.IndexElements.Count; j++)
                                        {
                                            IndexSector reftoup = GetSector(new_sector.IndexElements[j].Reference);
                                            reftoup.TopGradientReference = new_sector.Location;
                                        }
                                    }
                                }
                                else
                                {
                                    // split not required
                                    new_sector.IndexElements.Add(new_element);
                                    SetSector(new_sector);
                                    if (!new_sector.IsSerial)
                                    {
                                        IndexSector reftoup = GetSector(new_element.Reference);
                                        reftoup.TopGradientReference = new_sector.Location;
                                    }
                                }

                                operationsQueue.Enqueue(new QOperation()
                                {
                                    OpType    = QOperationType.ADDKEY,
                                    Key       = new_sector.IndexElements[0].IndexKey,
                                    Reference = grad,
                                    index     = -1,
                                    location  = new_sector.Location
                                });
                            }
                            else
                            {
                                // just add element
                                //if (op.index == 0)
                                //    for (int j = op.index; j < op.Reference.IndexElements.Count; j++)
                                //    {
                                //        if (comparator.Compare(op.Key, op.Reference.IndexElements[j].IndexKey) == 0) op.index++;
                                //    }
                                op.Reference.IndexElements.Insert(op.index, new_element);
                                if ((op.index == 0 || op.Reference.IndexElements.Count == 1) && op.Reference.TopGradientReference != ROOTGRADIENT)
                                {
                                    operationsQueue.Enqueue(new QOperation()
                                    {
                                        OpType    = QOperationType.UPDATEGRADIENTKEY,
                                        Key       = new_element.IndexKey,
                                        Reference = GetSector(op.Reference.TopGradientReference),
                                        location  = op.Reference.Location
                                    });
                                }
                            }
                            break;

                        case QOperationType.UPDATEGRADIENTKEY:
                            for (int j = 0; j < op.Reference.IndexElements.Count; j++)
                            {
                                if (op.Reference.IndexElements[j].Reference == op.location)
                                {
                                    op.Reference.IndexElements[j].IndexKey = op.Key;

                                    if (j == 0 && op.Reference.TopGradientReference != ROOTGRADIENT)
                                    {
                                        operationsQueue.Enqueue(new QOperation()
                                        {
                                            OpType    = QOperationType.UPDATEGRADIENTKEY,
                                            Key       = op.Key,
                                            Reference = GetSector(op.Reference.TopGradientReference),
                                            location  = op.Reference.Location
                                        });
                                    }
                                    break;
                                }
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    //--------------
                    break;
                }
                else
                {
                    IndexElement el = null;
                    if (outCmp == 0)
                    {
                        el = currentSector.IndexElements[idx];
                    }
                    else
                    {
                        el = currentSector.IndexElements[idx > 0 ? idx - 1 : idx];
                    }

                    currentSector = GetSector(el.Reference);
                    // go deeper
                }
            }
            keysCount++;
        }
예제 #2
0
 public QOperationViewModel(QOperation _operation, string _key) : base(_operation, _key)
 {
 }