context: /* This file is part of the db4o object database http://www.db4o.com
  
  Copyright (C) 2004 - 2011  Versant Corporation http://www.versant.com
  
  db4o is free software; you can redistribute it and/or modify it under
  the terms of version 3 of the GNU General Public License as published
  by the Free Software Foundation.
  
  db4o is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  for more details.
  
  You should have received a copy of the GNU General Public License along
  with this program.  If not, see http://www.gnu.org/licenses/. */
  
  using Db4objects.Db4o.Foundation;
  using Db4objects.Db4o.Internal.Slots;
  
  namespace Db4objects.Db4o.Internal.Ids
  {
      /// <exclude></exclude>
      public class TransactionalIdSystemImpl : ITransactionalIdSystem
      {
          private readonly IClosure4 _globalIdSystem;
          private readonly TransactionalIdSystemImpl _parentIdSystem;
          private readonly IdSlotChanges _slotChanges;
  
          public TransactionalIdSystemImpl(IClosure4 freespaceManager, IClosure4 globalIdSystem
              , TransactionalIdSystemImpl parentIdSystem)
          {
              _globalIdSystem = globalIdSystem;
              _slotChanges = new IdSlotChanges(this, freespaceManager);
              _parentIdSystem = parentIdSystem;
          }
  
          public virtual void CollectCallBackInfo(ICallbackInfoCollector collector)
          {
              if (!_slotChanges.IsDirty())
              {
                  return;
              }
              _slotChanges.TraverseSlotChanges(new _IVisitor4_31(collector));
          }
  
          public virtual bool IsDirty()
          {
              return _slotChanges.IsDirty();
          }
  
          public virtual void Commit(FreespaceCommitter freespaceCommitter)
          {
              IVisitable slotChangeVisitable = new _IVisitable_52(this);
              freespaceCommitter.TransactionalIdSystem(this);
              AccumulateFreeSlots(freespaceCommitter, false);
              GlobalIdSystem().Commit(slotChangeVisitable, freespaceCommitter);
          }
  
          public virtual void AccumulateFreeSlots(FreespaceCommitter accumulator, bool forFreespace
              )
          {
              _slotChanges.AccumulateFreeSlots(accumulator, forFreespace, IsSystemIdSystem());
              if (_parentIdSystem != null)
              {
                  _parentIdSystem.AccumulateFreeSlots(accumulator, forFreespace);
              }
          }
  
          public virtual Slot CommittedSlot(int id)
          {
              if (id == 0)
              {
                  return null;
              }
              return GlobalIdSystem().CommittedSlot(id);
          }
  
          public virtual Slot CurrentSlot(int id)
          {
              var slot = ModifiedSlot(id);
              if (slot != null)
              {
                  return slot;
              }
              return CommittedSlot(id);
          }
  
          public virtual void Rollback()
          {
              _slotChanges.Rollback();
          }
  
          public virtual void Clear()
          {
              _slotChanges.Clear();
          }
  
          public virtual bool IsDeleted(int id)
          {
              return _slotChanges.IsDeleted(id);
          }
  
          public virtual void NotifySlotUpdated(int id, Slot slot, SlotChangeFactory slotChangeFactory
              )
          {
              _slotChanges.NotifySlotUpdated(id, slot, slotChangeFactory);
          }
  
          public virtual int NewId(SlotChangeFactory slotChangeFactory)
          {
              var id = AcquireId();
              _slotChanges.ProduceSlotChange(id, slotChangeFactory).NotifySlotCreated(null);
              return id;
          }
  
          public virtual int PrefetchID()
          {
              var id = AcquireId();
              _slotChanges.AddPrefetchedID(id);
              return id;
          }
  
          public virtual void PrefetchedIDConsumed(int id)
          {
              _slotChanges.PrefetchedIDConsumed(id);
          }
  
          public virtual void NotifySlotCreated(int id, Slot slot, SlotChangeFactory slotChangeFactory
              )
          {
              _slotChanges.NotifySlotCreated(id, slot, slotChangeFactory);
          }
  
          public virtual void NotifySlotDeleted(int id, SlotChangeFactory slotChangeFactory
              )
          {
              _slotChanges.NotifySlotDeleted(id, slotChangeFactory);
          }
  
          public virtual void Close()
          {
              _slotChanges.FreePrefetchedIDs(GlobalIdSystem());
          }
  
          private bool IsSystemIdSystem()
          {
              return _parentIdSystem == null;
          }
  
          public virtual void CompleteInterruptedTransaction(int transactionId1, int transactionId2
              )
          {
              GlobalIdSystem().CompleteInterruptedTransaction(transactionId1, transactionId2);
          }
  
          public virtual Slot ModifiedSlot(int id)
          {
              if (id == 0)
              {
                  return null;
              }
              var change = _slotChanges.FindSlotChange(id);
              if (change != null)
              {
                  if (change.SlotModified())
                  {
                      return change.NewSlot();
                  }
              }
              return ModifiedSlotInParentIdSystem(id);
          }
  
          public Slot ModifiedSlotInParentIdSystem(int id)
          {
              if (_parentIdSystem == null)
              {
                  return null;
              }
              return _parentIdSystem.ModifiedSlot(id);
          }
  
          private void TraverseSlotChanges(IVisitor4 visitor)
          {
              if (_parentIdSystem != null)
              {
                  _parentIdSystem.TraverseSlotChanges(visitor);
              }
              _slotChanges.TraverseSlotChanges(visitor);
          }
  
          private int AcquireId()
          {
              return GlobalIdSystem().NewId();
          }
  
          private IIdSystem GlobalIdSystem()
          {
              return ((IIdSystem) _globalIdSystem.Run());
          }
  
          private sealed class _IVisitor4_31 : IVisitor4
          {
              private readonly ICallbackInfoCollector collector;
  
              public _IVisitor4_31(ICallbackInfoCollector collector)
              {
                  this.collector = collector;
              }
  
              public void Visit(object slotChange)
              {
  
gt:                 var id = ((TreeInt) slotChange)._key;