Changeset 1134


Ignore:
Timestamp:
01/15/09 15:04:50 (12 years ago)
Author:
svonolfe
Message:

Further improved locking mechanism (avoid race conditions, performance) (#372)

Location:
trunk/sources/HeuristicLab.Hive.Server.ADODataAccess
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Hive.Server.ADODataAccess/CachedDataAdapter.cs

    r1131 r1134  
    2525using System.Text;
    2626using HeuristicLab.Hive.Contracts.BusinessObjects;
    27 using System.Runtime.CompilerServices;
    2827using System.Data;
     28using System.Threading;
    2929
    3030namespace HeuristicLab.Hive.Server.ADODataAccess {
     
    4141    private static bool cacheFilled = false;
    4242
     43    private static ReaderWriterLock cacheLock =
     44      new ReaderWriterLock();
     45
    4346    protected DataTable dataTable =
    4447      new DataTable();
     
    4750      new List<ICachedDataAdapter>();
    4851
    49     [MethodImpl(MethodImplOptions.Synchronized)]
    5052    protected CachedDataAdapter() {
     53      cacheLock.AcquireWriterLock(Timeout.Infinite);
     54
    5155      if (!cacheFilled) {
    5256        FillCache();
     
    5458      }
    5559
     60      cacheLock.ReleaseWriterLock();
     61
    5662      ServiceLocator.GetTransactionManager().OnUpdate +=
    5763        new EventHandler(CachedDataAdapter_OnUpdate);
     
    6066    protected virtual RowT FindSingleRow(Selector dbSelector,
    6167      Selector cacheSelector) {
     68      cacheLock.AcquireReaderLock(Timeout.Infinite);
     69     
    6270      RowT row =
    6371         FindSingleRow(cacheSelector);
     
    6977      }
    7078
     79      cacheLock.ReleaseReaderLock();
     80
    7181      return row;
    7282    }
     
    7484    protected virtual IEnumerable<RowT> FindMultipleRows(Selector dbSelector,
    7585        Selector cacheSelector) {
     86      cacheLock.AcquireReaderLock(Timeout.Infinite);
     87
    7688      IList<RowT> result =
    7789         new List<RowT>(cacheSelector());
     
    8597        }
    8698      }
     99
     100      cacheLock.ReleaseReaderLock();
    87101
    88102      return result;
     
    105119    protected virtual ICollection<ObjT> FindMultiple(Selector dbSelector,
    106120      Selector cacheSelector) {
     121      cacheLock.AcquireReaderLock(Timeout.Infinite);
     122
    107123      ICollection<ObjT> result =
    108124        FindMultiple(cacheSelector);
     
    110126      ICollection<ObjT> resultDb =
    111127        FindMultiple(dbSelector);
     128
     129      cacheLock.ReleaseReaderLock();
    112130
    113131      foreach (ObjT obj in resultDb) {
     
    119137    }
    120138
    121     [MethodImpl(MethodImplOptions.Synchronized)]
    122139    protected abstract RowT InsertNewRowInCache(ObjT obj);
    123140
    124     [MethodImpl(MethodImplOptions.Synchronized)]
    125141    protected abstract void FillCache();
    126142
    127     [MethodImpl(MethodImplOptions.Synchronized)]
    128143    public abstract void SyncWithDb();
    129144
    130     [MethodImpl(MethodImplOptions.Synchronized)]
    131145    protected abstract bool PutInCache(ObjT obj);
    132146
    133147    protected abstract RowT FindCachedById(long id);
    134148
    135     [MethodImpl(MethodImplOptions.Synchronized)]
    136149    void CachedDataAdapter_OnUpdate(object sender, EventArgs e) {
    137150      foreach (ICachedDataAdapter parent in this.parentAdapters) {
     
    140153
    141154      this.SyncWithDb();
    142     }
    143 
    144     [MethodImpl(MethodImplOptions.Synchronized)]
    145     protected virtual void RemoveRowFromCache(RowT row) {
    146       cache.Rows.Remove(row);
    147155    }
    148156
     
    167175    }
    168176
    169     [MethodImpl(MethodImplOptions.Synchronized)]
     177    private void AddToCache(RowT row) {
     178      cacheLock.AcquireWriterLock(Timeout.Infinite);
     179
     180      cache.ImportRow(row);
     181      row.Table.Rows.Remove(row);
     182
     183      cacheLock.ReleaseWriterLock();
     184    }
     185
     186    private RowT AddToCache(ObjT obj) {
     187      cacheLock.AcquireWriterLock(Timeout.Infinite);
     188
     189      RowT row =  InsertNewRowInCache(obj);
     190
     191      cacheLock.ReleaseWriterLock();
     192
     193      return row;
     194    }
     195
     196    private void RemoveRowFromCache(RowT row) {
     197      cacheLock.AcquireWriterLock(Timeout.Infinite);
     198
     199      dataTable.ImportRow(row);
     200      cache.Rows.Remove(row);
     201
     202      cacheLock.ReleaseWriterLock();
     203
     204      UpdateRow(row);
     205    }
     206
    170207    public override void Update(ObjT obj) {
    171208      if (obj != null) {
     
    175212        if (row == null) {
    176213          if (PutInCache(obj)) {
    177             row = InsertNewRowInCache(obj);
     214            row = AddToCache(obj);
    178215          } else {
    179216            row = InsertNewRow(obj);
     
    184221
    185222        obj.Id = (long)row[row.Table.PrimaryKey[0]];
     223        LockRow(obj.Id);
    186224
    187225        ConvertObj(obj, row);
     
    191229
    192230        if (IsCached(row) &&
    193             !PutInCache(obj)) {
    194           //remove from cache
    195           dataTable.ImportRow(row);
     231            !PutInCache(obj)) {         
    196232          RemoveRowFromCache(row);
    197 
    198           UpdateRow(row);
    199233        } else if (!IsCached(row) &&
    200234          PutInCache(obj)) {
    201           //add to cache
    202           cache.ImportRow(row);
    203           row.Table.Rows.Remove(row);
    204         }
     235          AddToCache(row);
     236        }
     237
     238        UnlockRow(obj.Id);
    205239      }
    206240    }
  • trunk/sources/HeuristicLab.Hive.Server.ADODataAccess/ClientAdapter.cs

    r1131 r1134  
    176176    protected override dsHiveServer.ClientRow
    177177      InsertNewRowInCache(ClientInfo client) {
    178       dsHiveServer.ClientRow row = data.NewClientRow();
     178      dsHiveServer.ClientRow row = cache.NewClientRow();
    179179      row.ResourceId = client.Id;
    180180      cache.AddClientRow(row);
  • trunk/sources/HeuristicLab.Hive.Server.ADODataAccess/DataAdapterBase.cs

    r1131 r1134  
    2626using System.Text;
    2727using HeuristicLab.Hive.Contracts.BusinessObjects;
    28 using System.Runtime.CompilerServices;
     28using System.Threading;
    2929
    3030namespace HeuristicLab.Hive.Server.ADODataAccess {
     
    3333    where RowT : System.Data.DataRow
    3434    where ObjT : IHiveObject, new() {
     35
     36    private static Mutex lockersMutex =
     37      new Mutex();
     38
     39    private static IDictionary<long, Mutex> lockers =
     40      new Dictionary<long, Mutex>();
     41
     42    private static IDictionary<long, int> lockCount =
     43      new Dictionary<long, int>();
     44
     45    protected void LockRow(long id) {
     46      Mutex rowLock = null;
     47
     48      /////begin critical section////
     49      lockersMutex.WaitOne();
     50
     51      if (!lockers.ContainsKey(id)) {
     52        lockers[id] = new Mutex();
     53        lockCount[id] = 0;
     54      }
     55      rowLock = lockers[id];
     56      lockCount[id]++;
     57     
     58      lockersMutex.ReleaseMutex();
     59      /////end critical section////
     60
     61      rowLock.WaitOne();
     62    }
     63
     64    protected void UnlockRow(long id) {
     65      Mutex rowLock = lockers[id];
     66      rowLock.ReleaseMutex();
     67
     68      /////begin critical section////
     69      lockersMutex.WaitOne();
     70
     71      lockCount[id]--;
     72      if (lockCount[id] == 0)
     73        lockers.Remove(id);
     74
     75      lockersMutex.ReleaseMutex();
     76      /////end critical section////
     77    }
     78   
    3579    protected AdapterT Adapter {
    3680      get {
     
    4488    protected abstract ObjT ConvertRow(RowT row, ObjT obj);
    4589
    46     [MethodImpl(MethodImplOptions.Synchronized)]
    4790    protected abstract RowT InsertNewRow(ObjT obj);
    4891
    49     [MethodImpl(MethodImplOptions.Synchronized)]
    5092    protected abstract void UpdateRow(RowT row);
    5193
     
    119161    }
    120162
    121     [MethodImpl(MethodImplOptions.Synchronized)]
    122163    public virtual void Update(ObjT obj) {
    123164      if (obj != null) {
     
    127168        if (row == null) {
    128169          row = InsertNewRow(obj);
     170          UpdateRow(row);
    129171        }
    130172
     173        obj.Id = (long)row[row.Table.PrimaryKey[0]];
     174        LockRow(obj.Id);
     175
    131176        ConvertObj(obj, row);
    132 
    133177        UpdateRow(row);
    134178
    135         obj.Id = (long)row[row.Table.PrimaryKey[0]];
     179        UnlockRow(obj.Id);
    136180      }
    137181    }
     
    149193    }
    150194
    151     [MethodImpl(MethodImplOptions.Synchronized)]
    152195    public virtual bool Delete(ObjT obj) {
     196      bool success = false;
     197     
    153198      if (obj != null) {
     199        LockRow(obj.Id);
     200
    154201        RowT row =
    155202          GetRowById(obj.Id);
     
    159206          UpdateRow(row);
    160207
    161           return true;
     208          success = true;
    162209        }
    163       }
    164 
    165       return false;
     210
     211        UnlockRow(obj.Id);
     212      }
     213
     214      return success;
    166215    }
    167216  }
  • trunk/sources/HeuristicLab.Hive.Server.ADODataAccess/JobAdapter.cs

    r1131 r1134  
    160160    protected override dsHiveServer.JobRow
    161161      InsertNewRowInCache(Job job) {
    162       dsHiveServer.JobRow row = data.NewJobRow();
     162      dsHiveServer.JobRow row = cache.NewJobRow();
    163163      cache.AddJobRow(row);
    164164
Note: See TracChangeset for help on using the changeset viewer.