Ejemplo n.º 1
0
        /// <summary>
        /// Clear contents of this Collection.
        /// Changes will be saved right after clearing the contents.
        /// </summary>
        public virtual void Clear()
        {
            if (HeaderData.OccupiedBlocksHead != null && HeaderData.OccupiedBlocksTail != null)
            {
                HeaderData.DiskBuffer.IsDirty              = true;
                HeaderData.OccupiedBlocksTail.DataAddress  =
                    HeaderData.NextAllocatableAddress      =
                        HeaderData.StartAllocatableAddress = HeaderData.OccupiedBlocksHead.DataAddress;

                int segmentSize = File.GetSegmentSize();
                if (HeaderData.OccupiedBlocksHead.DataAddress + segmentSize != HeaderData.EndAllocatableAddress)
                {
                    //**** add to File.DeletedCollections the next _region for reuse...
                    //** read next segment of deleted collection
                    var           dbi = new DeletedBlockInfo();
                    Sop.DataBlock db;
                    db = DataBlockDriver.ReadBlockFromDisk(this,
                                                           HeaderData.OccupiedBlocksHead.DataAddress + segmentSize -
                                                           (int)File.DataBlockSize, true);
                    if (db.InternalNextBlockAddress >= 0)
                    {
                        dbi.StartBlockAddress = db.InternalNextBlockAddress;
                        dbi.EndBlockAddress   = db.InternalNextBlockAddress + segmentSize;

                        if (File.DeletedCollections != null)
                        {
                            bool oc = ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry;
                            ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry = ChangeRegistry;
                            File.DeletedCollections.Add(dbi);
                            ((CollectionOnDisk)File.DeletedCollections).ChangeRegistry = oc;
                        }

                        HeaderData.EndAllocatableAddress = HeaderData.OccupiedBlocksHead.DataAddress + segmentSize;
                    }
                }
            }
            HeaderData.Count = 0;
            if (HeaderData.diskBuffer != null)
            {
                HeaderData.diskBuffer.ClearData();
            }
            if (deletedBlocks != null)
            {
                deletedBlocks.Clear();
            }
            //if (MruManager != null)
            //    MruManager.Clear();
            //if (this.DataBlockDriver != null)
            //    this.DataBlockDriver.MruManager.Clear();
            //Blocks.Clear();
            currentDataBlock         = null;
            currentEntry             = null;
            _currentEntryDataAddress = -1;
            RegisterChange();
            Flush();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Get a deleted block from Collection 'block recycle bin' or from File 'collection recycle bin'.
        /// </summary>
        /// <param name="requestedBlockSize"> </param>
        /// <param name="isCollectionBlock"> </param>
        /// <param name="collectionDeletedBlock"> </param>
        /// <returns></returns>
        public DeletedBlockInfo GetDeletedBlock(int requestedBlockSize, bool isCollectionBlock,
                                                out bool collectionDeletedBlock)
        {
            collectionDeletedBlock = true;

            #region try to recycle from File collection recycle bin
            if (HeaderData == null || HeaderData.RecycledSegment == null)
            {
                if (File.DeletedCollections != null && GetTopParent() != File.DeletedCollections &&
                    File.DeletedCollections.Count > 0)
                {
                    collectionDeletedBlock = false;
                    return(File.DeletedCollections.GetTop());
                }
            }
            if (HeaderData != null && HeaderData.RecycledSegment != null)
            {
                long blockSize = HeaderData.RecycledSegment.Count * (int)DataBlockSize;
                if (blockSize >= requestedBlockSize)
                {
                    return(HeaderData.RecycledSegment);
                }
                if (!IsDeletedBlocksList)
                {
                    if (DeletedBlocks != null)
                    {
                        DeletedBlocks.AddAvailableBlock(HeaderData.RecycledSegment.StartBlockAddress,
                                                        blockSize);
                    }
                    HeaderData.RecycledSegment = null;
                }
            }
            #endregion

            #region try to recycle from Collection block recycle bin
            if (!IsDeletedBlocksList && DeletedBlocks != null && DeletedBlocks.Count > 0)
            {
                long availableBlockAddress;
                long availableBlockSize;
                if (DeletedBlocks.GetAvailableBlock(IsDeletedBlocksList, requestedBlockSize,
                                                    out availableBlockAddress, out availableBlockSize))
                {
                    var dbi = new DeletedBlockInfo
                    {
                        StartBlockAddress = availableBlockAddress,
                        Count             = (int)(availableBlockSize / (int)DataBlockSize)
                    };
                    return(dbi);
                }
            }
            #endregion
            return(null);
        }
Ejemplo n.º 3
0
 public void SetTop(DeletedBlockInfo value)
 {
     Locker.Lock();
     if (!MoveFirst())
     {
         Locker.Unlock();
         return;
     }
     Remove();
     Add(value);
     Locker.Unlock();
 }
Ejemplo n.º 4
0
 public DeletedBlockInfo Get(long dataAddress)
 {
     Locker.Lock();
     if (Search(dataAddress))
     {
         var dbi = new DeletedBlockInfo
         {
             StartBlockAddress = (long)CurrentKey, EndBlockAddress = (long)CurrentValue
         };
         Locker.Unlock();
         return(dbi);
     }
     Locker.Unlock();
     return(null);
 }
Ejemplo n.º 5
0
        public DeletedBlockInfo GetTop()
        {
            Locker.Lock();
            if (!MoveFirst())
            {
                Locker.Unlock();
                return(null);
            }
            var dbi = new DeletedBlockInfo
            {
                StartBlockAddress = (long)CurrentKey, EndBlockAddress = (long)CurrentValue
            };

            Locker.Unlock();
            return(dbi);
        }
Ejemplo n.º 6
0
        public void Add(DeletedBlockInfo value)
        {
            Locker.Lock();
            if (Search(value.StartBlockAddress))
            {
                Locker.Unlock();
                return;
            }

            if (Log.Logger.Instance.IsVerboseEnabled)
            {
                Log.Logger.Instance.Log(Log.LogLevels.Verbose, "FileRecycler.Add: {0}", value.ToString());
            }

            var itm = new BTreeItemOnDisk(DataBlockSize, value.StartBlockAddress, value.EndBlockAddress);

            base.Add(itm);
            Locker.Unlock();
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Rollback a transaction
        /// </summary>
        public override void InternalRollback(bool isDisposing)
        {
            if (_addStore == null && ModifiedCollections == null)
            {
                return;
            }
            if (CurrentCommitPhase == CommitPhase.Committed)
            {
                throw new InvalidOperationException(
                          string.Format("Transaction '{0}' is already committed, can't rollback.", Id));
            }
            if (CurrentCommitPhase == CommitPhase.Rolledback)
            {
                throw new InvalidOperationException(
                          string.Format("Transaction '{0}' was rolled back, can't roll it back again.", Id));
            }

            _inCommit++;
            try
            {
                //** Step 1. truncate all newly added blocks beyond eof before transaction began
                //** Step 2. copy all preserved blocks in transaction log onto respective
                //** collection on disk to revert changes. Ensure to mark each reverted block so during
                //** crash while rollback, we can resume where we left off.
                //** Step 3. Clear memory of this transaction objects

                //** Revert from backup
                RestoreData();

                //** Clear memory of this transaction's objects
                var parents = new Dictionary <CollectionOnDisk, object>(ModifiedCollections.Count);
                foreach (KeyValuePair <RecordKey, CollectionOnDisk> de in ModifiedCollections)
                {
                    de.Value.HeaderData.IsModifiedInTransaction = false;
                    //** clear memory of objects belonging to the transaction...
                    if (de.Key.Filename != DataBackupFilename)
                    {
                        parents[de.Value.GetTopParent()]    = null;
                        de.Value.HeaderData.RecycledSegment = de.Value.HeaderData.RecycledSegmentBeforeTransaction;
                        if (de.Value.HeaderData.RecycledSegment != null)
                        {
                            de.Value.HeaderData.RecycledSegment =
                                (DeletedBlockInfo)de.Value.HeaderData.RecycledSegment.Clone();
                        }
                        RemoveInMemory(de.Value, de.Key.Address);
                    }
                }
                if (!(OwnsRoot && isDisposing))
                {
                    foreach (CollectionOnDisk cod in parents.Keys)
                    {
                        cod.OnRollback();
                        if (cod is BTreeAlgorithm)
                        {
                            var sdod = ((BTreeAlgorithm)cod).Container;
                            if (sdod == null)
                            {
                                continue;
                            }
                            sdod.Reload();
                        }
                        else
                        {
                            cod.Load();
                        }
                    }
                }
                //** Truncate all newly added blocks beyond eof
                if (_fileGrowthStore != null)
                {
                    var dbis = new List <KeyValuePair <DeletedBlockInfo, OnDisk.File.IFile> >(_fileGrowthStore.Count);
                    foreach (var de in _fileGrowthStore)
                    {
                        var key = de.Key;
                        var f   = (OnDisk.File.IFile)Server.FileSet[key.Filename];
                        if (f == null)
                        {
                            continue;
                        }
                        //** add to deleted blocks the newly extended blocks!
                        var dbi = new DeletedBlockInfo {
                            StartBlockAddress = de.Key.Address
                        };
                        dbi.EndBlockAddress = dbi.StartBlockAddress + de.Value;
                        dbis.Add(new KeyValuePair <DeletedBlockInfo, OnDisk.File.IFile>(dbi, f));
                    }
                    _addStore.Clear();
                    _fileGrowthStore.Clear();
                    _recycledCollectionStore.Clear();
                    int oldCommit = _inCommit;
                    _inCommit = 0;
                    if (Server.HasTrashBin)
                    {
                        foreach (KeyValuePair <DeletedBlockInfo, OnDisk.File.IFile> itm in dbis)
                        {
                            //** add to deleted blocks the newly extended blocks!
                            itm.Value.DeletedCollections.Add(itm.Key);
                        }
                        foreach (KeyValuePair <DeletedBlockInfo, OnDisk.File.IFile> itm in dbis)
                        {
                            itm.Value.DeletedCollections.Flush();
                            itm.Value.DeletedCollections.OnCommit();
                        }
                    }
                    _inCommit = oldCommit;
                }
                if (OwnsRoot && isDisposing)
                {
                    foreach (CollectionOnDisk cod in parents.Keys)
                    {
                        cod.CloseStream();
                    }
                }

                ClearStores(true);

                //** if no more ongoing transaction, we can safely delete the transaction backup data file
                File.Delete(Server.Path + DataBackupFilename);
            }
            finally
            {
                _inCommit--;
                if (Parent == null)
                {
                    CollectionOnDisk.transaction = null;
                }
                else if (Parent.Children != null)
                {
                    Parent.Children.Remove(this);
                }
            }
            CurrentCommitPhase = CommitPhase.Rolledback;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Rollback uncomitted transactions.
        /// NOTE: this should be invoked upon restart so uncommited transaction(s)
        /// when program quits in previous run can be rolled back.
        /// </summary>
        /// <param name="serverFilename"> </param>
        /// <param name="serverProfile"> </param>
        /// <param name="createOpenObjectServerIfNoRollbackLog"> </param>
        public static Sop.ObjectServerWithTransaction RollbackAll(string serverFilename, Preferences preferences,
                                                                  bool createOpenObjectServerIfNoRollbackLog)
        {
            if (string.IsNullOrEmpty(serverFilename))
            {
                throw new ArgumentNullException("serverFilename");
            }

            if (!Sop.Utility.Utility.HasRequiredDirectoryAccess(serverFilename))
            {
                throw new InvalidOperationException(
                          string.Format("Not enough rights/access on directory containing file '{0}'.",
                                        serverFilename));
            }

            string serverRootPath = System.IO.Path.GetDirectoryName(serverFilename);

            if (string.IsNullOrEmpty(serverRootPath))
            {
                serverRootPath = System.Environment.CurrentDirectory;
            }
            string[] appendLogs = null;


            if (preferences != null && preferences.MemoryExtenderMode)
            {
                if (Sop.Utility.Utility.FileExists(serverFilename))
                {
                    Sop.Utility.Utility.FileDelete(serverFilename);
                    Sop.Utility.Utility.FileDelete(string.Format("{0}.{1}",
                                                                 serverFilename, ObjectServer.DataInfExtensionLiteral));
                }
            }


            //** NOTE: ProcessUpdateLog needs to be done ahead of RollbackAll as the latter
            //** removes backup files which are used by the former

            //** rollback all pending transaction updates...
            ProcessUpdateLog(serverRootPath, true);

            //** Rollback (delete) root trans created DB objects...
            if (TransactionRoot.RollbackAll(serverRootPath))
            {
                /** AppendLogxx.txt
                 *  Grow d:\Sopbin\Sop\File.dta 1050624 2096
                 */
                appendLogs = Directory.GetFiles(serverRootPath,
                                                string.Format("{0}*.txt", AppendLogLiteral));
            }
            #region Process append logs
            if (appendLogs != null &&
                (createOpenObjectServerIfNoRollbackLog || appendLogs.Length > 0))
            {
                if (Sop.Utility.Utility.FileExists(serverFilename))
                {
                    var r = new ObjectServerWithTransaction(serverFilename, null, preferences);
                    r.Open();
                    foreach (string s in appendLogs)
                    {
                        ITransactionLogger trans = Transaction.BeginWithNewRoot(r);
                        //** open the file and do restore for each backed up entry
                        using (var sr = new StreamReader(s))
                        {
                            while (sr.Peek() >= 0)
                            {
                                string l = sr.ReadLine();
                                if (l.StartsWith(GrowToken))
                                {
                                    int    i1 = l.LastIndexOf(' ');
                                    int    i2 = l.LastIndexOf(' ', i1 - 1);
                                    string s2 = l.Substring(i2, i1 - i2);
                                    long   address;
                                    if (long.TryParse(s2, out address))
                                    {
                                        string fName = l.Substring(GrowToken.Length, i2 - GrowToken.Length);
                                        var    f     = (OnDisk.File.IFile)r.GetFile(fName);
                                        if (f != null)
                                        {
                                            var dbi = new DeletedBlockInfo();
                                            dbi.StartBlockAddress = address;
                                            int segmentSize;
                                            if (int.TryParse(l.Substring(i1), out segmentSize))
                                            {
                                                dbi.EndBlockAddress = dbi.StartBlockAddress + segmentSize;
                                                if (f.DeletedCollections != null)
                                                {
                                                    f.DeletedCollections.Transaction = trans;
                                                    f.DeletedCollections.Add(dbi);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        r.Flush();
                        trans.Commit();
                        //** remove the Backup log file, we're done rolling back and it's no longer needed
                        Sop.Utility.Utility.FileDelete(s);
                    }
                    r.Dispose();
                    //return r;
                }
                else
                {
                    foreach (string s in appendLogs)
                    {
                        Sop.Utility.Utility.FileDelete(s);
                    }
                }
            }
            #endregion
            return(null);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// DeSerialize
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="reader"></param>
        public override void Unpack(IInternalPersistent parent,
                                    BinaryReader reader)
        {
            System.IO.BinaryReader binaryReader = reader;
            long l = binaryReader.ReadInt64();

            if (l >= 0)
            {
                DiskBuffer.DataAddress = l;
            }
            long cnt = binaryReader.ReadInt64();
            long saa = binaryReader.ReadInt64();

            if ((Count > 0 && cnt == 0) ||
                StartAllocatableAddress > 0 && saa == 0)
            {
                binaryReader.ReadInt64();
                binaryReader.ReadInt64();
                binaryReader.ReadInt64();
                binaryReader.ReadInt64();
                if (reader.ReadBoolean())
                {
                    var rs = new DeletedBlockInfo();
                    rs.Unpack(parent, reader);
                }
                return;
            }
            Count = cnt;                   //BinaryReader.ReadInt32();
            StartAllocatableAddress = saa; // BinaryReader.ReadInt64();
            EndAllocatableAddress   = binaryReader.ReadInt64();
            NextAllocatableAddress  = binaryReader.ReadInt64();
            long          obh = binaryReader.ReadInt64();
            long          obt = binaryReader.ReadInt64();
            DataBlockSize dataBlockSize;

            if (parent != null)
            {
                File.File f = (File.File)InternalPersistent.GetParent(parent, typeof(File.File), true);
                dataBlockSize = f.DataBlockSize;
            }
            else
            {
                dataBlockSize = (DataBlockSize)DiskBuffer.Length;
            }
            if (obh >= 0)
            {
                OccupiedBlocksHead             = new Sop.DataBlock(dataBlockSize);
                OccupiedBlocksHead.DataAddress = obh;
            }
            else if (OccupiedBlocksHead != null)
            {
                OccupiedBlocksHead = null;
            }
            if (obt >= 0)
            {
                OccupiedBlocksTail             = new Sop.DataBlock(dataBlockSize);
                OccupiedBlocksTail.DataAddress = obt;
            }
            else if (OccupiedBlocksTail != null)
            {
                OccupiedBlocksTail = null;
            }

            if (reader.ReadBoolean())
            {
                RecycledSegment = new DeletedBlockInfo();
                RecycledSegment.Unpack(parent, reader);
                RecycledSegmentBeforeTransaction = (DeletedBlockInfo)RecycledSegment.Clone();
            }
        }