Free cookie consent management tool by TermsFeed Policy Generator

Changeset 500


Ignore:
Timestamp:
08/11/08 22:31:03 (16 years ago)
Author:
gkronber
Message:

worked on #197 (Use SQLite backend to store waiting engines and results instead of in-memory dictionaries)

Location:
trunk/sources/HeuristicLab.Grid
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Grid/EngineStore.cs

    r499 r500  
    2323using System.Collections.Generic;
    2424using System.Text;
     25using System.Linq;
    2526using System.Threading;
    2627using System.ServiceModel;
     28using System.Data.Common;
    2729
    2830namespace HeuristicLab.Grid {
    2931  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
    3032  public class EngineStore : IEngineStore {
    31     private List<Guid> engineList;
    32     private Dictionary<Guid, byte[]> waitingEngines;
    33     private Dictionary<Guid, byte[]> runningEngines;
    3433    private Dictionary<Guid, ManualResetEvent> waitHandles;
    35     private Dictionary<Guid, byte[]> results;
    36     private Dictionary<Guid, DateTime> resultDate;
    37     private Dictionary<Guid, DateTime> runningEngineDate;
    38     private const int RESULT_EXPIRY_TIME_MIN = 10;
    39     private const int RUNNING_JOB_EXPIRY_TIME_MIN = 10;
    40     private object bigLock;
     34    private Database database;
     35
     36    private static readonly string dbFile = AppDomain.CurrentDomain.BaseDirectory + "/enginestore.db3";
     37    private static readonly string connectionString = "Data Source=\"" + dbFile + "\";Pooling=False";
     38
     39    private int waitingJobs;
    4140    public int WaitingJobs {
    4241      get {
    43         return waitingEngines.Count;
     42        return waitingJobs;
    4443      }
    4544    }
    46 
     45    private int runningJobs;
    4746    public int RunningJobs {
    4847      get {
    49         return runningEngines.Count;
     48        return runningJobs;
    5049      }
    5150    }
    52 
     51    private int results;
    5352    public int WaitingResults {
    5453      get {
    55         return results.Count;
     54        return results;
    5655      }
    5756    }
    5857
    5958    public EngineStore() {
    60       engineList = new List<Guid>();
    61       waitingEngines = new Dictionary<Guid, byte[]>();
    62       runningEngines = new Dictionary<Guid, byte[]>();
    6359      waitHandles = new Dictionary<Guid, ManualResetEvent>();
    64       results = new Dictionary<Guid, byte[]>();
    65       resultDate = new Dictionary<Guid, DateTime>();
    66       runningEngineDate = new Dictionary<Guid, DateTime>();
    67       bigLock = new object();
     60      DbProviderFactory fact;
     61      fact = DbProviderFactories.GetFactory("System.Data.SQLite");
     62      if(!System.IO.File.Exists(dbFile)) {
     63        database = new Database(connectionString);
     64        database.CreateNew();
     65      } else {
     66        database = new Database(connectionString);
     67      }
     68      database = new Database(connectionString);
    6869    }
    6970
     71    private object t = new object();
    7072    public bool TryTakeEngine(out Guid guid, out byte[] engine) {
    71       lock(bigLock) {
    72         if(engineList.Count == 0) {
    73           guid = Guid.Empty;
    74           engine = null;
     73      lock(t) {
     74        List<JobEntry> waitingJobs = database.GetWaitingJobs();
     75        if(waitingJobs.Count == 0) {
     76          guid = Guid.Empty; engine = null;
    7577          return false;
    7678        } else {
    77           guid = engineList[0];
    78           engineList.RemoveAt(0);
    79           engine = waitingEngines[guid];
    80           waitingEngines.Remove(guid);
    81           runningEngines[guid] = engine;
    82           runningEngineDate[guid] = DateTime.Now;
     79          JobEntry oldestEntry = waitingJobs.OrderBy(a => a.CreationTime).First();
     80          guid = oldestEntry.Guid;
     81          engine = oldestEntry.RawData;
     82          database.UpdateJobState(guid, HeuristicLab.Grid.JobState.Busy);
    8383          return true;
    8484        }
     
    8787
    8888    public void StoreResult(Guid guid, byte[] result) {
    89       lock(bigLock) {
    90         // clear old results
    91         List<Guid> expiredResults = FindExpiredResults(DateTime.Now.AddMinutes(-RESULT_EXPIRY_TIME_MIN));
    92         foreach(Guid expiredGuid in expiredResults) {
    93           results.Remove(expiredGuid);
    94           waitHandles.Remove(expiredGuid);
    95           resultDate.Remove(expiredGuid);
    96         }
    97         // add the new result
    98         runningEngines.Remove(guid);
    99         runningEngineDate.Remove(guid);
    100         results[guid] = result;
    101         resultDate[guid] = DateTime.Now;
    102         waitHandles[guid].Set();
    103       }
    104     }
    105 
    106     private List<Guid> FindExpiredResults(DateTime expirationDate) {
    107       List<Guid> expiredResults = new List<Guid>();
    108       foreach(Guid guid in results.Keys) {
    109         if(resultDate[guid] < expirationDate) {
    110           expiredResults.Add(guid);
    111         }
    112       }
    113       return expiredResults;
    114     }
    115     private List<Guid> FindExpiredJobs(DateTime expirationDate) {
    116       List<Guid> expiredJobs = new List<Guid>();
    117       foreach(Guid guid in runningEngines.Keys) {
    118         if(runningEngineDate[guid] < expirationDate) {
    119           expiredJobs.Add(guid);
    120         }
    121       }
    122       return expiredJobs;
     89      database.DeleteExpiredResults();
     90      // add the new result
     91      database.SetJobResult(guid, result);
     92      waitHandles[guid].Set();
    12393    }
    12494
    12595    internal void AddEngine(Guid guid, byte[] engine) {
    126       lock(bigLock) {
    127         engineList.Add(guid);
    128         waitingEngines.Add(guid, engine);
    129         waitHandles.Add(guid, new ManualResetEvent(false));
    130       }
     96      database.InsertJob(guid, HeuristicLab.Grid.JobState.Waiting, engine);
     97      waitHandles.Add(guid, new ManualResetEvent(false));
    13198    }
    13299
     
    136103
    137104    internal byte[] GetResult(Guid guid, int timeout) {
    138       lock(bigLock) {
    139         // result already available
    140         if(results.ContainsKey(guid)) {
    141           // if the wait-handle for this result is still alive then close and remove it
    142           if(waitHandles.ContainsKey(guid)) {
    143             ManualResetEvent waitHandle = waitHandles[guid];
    144             waitHandle.Close();
    145             waitHandles.Remove(guid);
    146           }
    147           byte[] result = results[guid];
    148           results.Remove(guid);
    149           return result;
     105      if(JobState(guid) == HeuristicLab.Grid.JobState.Finished) {
     106        ManualResetEvent waitHandle = waitHandles[guid];
     107        waitHandle.Close();
     108        waitHandles.Remove(guid);
     109        JobEntry entry = database.GetJob(guid);
     110        return entry.RawData;
     111      } else {
     112        // result not yet available, if there is also no wait-handle for that result then we will never have a result and can return null
     113        if(!waitHandles.ContainsKey(guid)) return null;
     114        // otherwise we have a wait-handle and can wait for the result
     115        ManualResetEvent waitHandle = waitHandles[guid];
     116        // wait
     117        if(waitHandle.WaitOne(timeout, true)) {
     118          // ok got the result in within the wait time => close and remove the wait-hande and return the result
     119          waitHandle.Close();
     120          waitHandles.Remove(guid);
     121          JobEntry entry = database.GetJob(guid);
     122          return entry.RawData;
    150123        } else {
    151           // result not yet available, if there is also no wait-handle for that result then we will never have a result and can return null
    152           if(!waitHandles.ContainsKey(guid)) return null;
    153           // otherwise we have a wait-handle and can wait for the result
    154           ManualResetEvent waitHandle = waitHandles[guid];
    155           // wait
    156           if(waitHandle.WaitOne(timeout, true)) {
    157             // ok got the result in within the wait time => close and remove the wait-hande and return the result
    158             waitHandle.Close();
    159             waitHandles.Remove(guid);
    160             byte[] result = results[guid];
    161             return result;
    162           } else {
    163             // no result yet, check for which jobs we waited too long and requeue those jobs
    164             List<Guid> expiredJobs = FindExpiredJobs(DateTime.Now.AddDays(-RUNNING_JOB_EXPIRY_TIME_MIN));
    165             foreach(Guid expiredGuid in expiredJobs) {
    166               engineList.Insert(0, expiredGuid);
    167               waitingEngines[expiredGuid] = runningEngines[expiredGuid];
    168               runningEngines.Remove(expiredGuid);
    169               runningEngineDate.Remove(expiredGuid);
    170             }
    171             return null;
    172           }
     124          // no result yet, check for which jobs we waited too long and requeue those jobs
     125          database.RestartExpiredActiveJobs();
     126          return null;
    173127        }
    174128      }
    175129    }
    176130
    177     internal void AbortEngine(Guid guid) {
    178       throw new NotImplementedException();
    179     }
    180 
    181131    internal JobState JobState(Guid guid) {
    182       lock(bigLock) {
    183         if(waitingEngines.ContainsKey(guid)) return HeuristicLab.Grid.JobState.Waiting;
    184         else if(waitHandles.ContainsKey(guid)) return HeuristicLab.Grid.JobState.Busy;
    185         else if(results.ContainsKey(guid)) return HeuristicLab.Grid.JobState.Finished;
    186         else return HeuristicLab.Grid.JobState.Unknown;
    187       }
     132      return database.GetJob(guid).Status;
    188133    }
    189134  }
  • trunk/sources/HeuristicLab.Grid/GridServer.cs

    r219 r500  
    5151      return engineStore.GetResult(guid, timeout);
    5252    }
    53 
    54     public void AbortEngine(Guid engine) {
    55       engineStore.AbortEngine(engine);
    56     }
    5753  }
    5854}
  • trunk/sources/HeuristicLab.Grid/HeuristicLab.Grid.csproj

    r440 r500  
    3939      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    4040    </Reference>
     41    <Reference Include="System.Data.SQLite, Version=1.0.51.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
     42      <SpecificVersion>False</SpecificVersion>
     43      <HintPath>..\HeuristicLab.SQLite\System.Data.SQLite.DLL</HintPath>
     44    </Reference>
    4145    <Reference Include="System.Drawing" />
    4246    <Reference Include="System.Runtime.Serialization">
     
    6064      <DependentUpon>ClientForm.cs</DependentUpon>
    6165    </Compile>
     66    <Compile Include="Database.cs" />
    6267    <Compile Include="EngineRunner.cs" />
    6368    <Compile Include="EngineStore.cs" />
     
    7277    <Compile Include="ProcessingEngine.cs" />
    7378    <Compile Include="Properties\AssemblyInfo.cs" />
     79    <Compile Include="JobEntry.cs" />
    7480    <Compile Include="ServerForm.cs">
    7581      <SubType>Form</SubType>
  • trunk/sources/HeuristicLab.Grid/IGridServer.cs

    r391 r500  
    4444    [OperationContract]
    4545    byte[] TryEndExecuteEngine(Guid engineGuid, int timeout);
    46     [OperationContract]
    47     void AbortEngine(Guid engineGuid);
    4846  }
    4947}
Note: See TracChangeset for help on using the changeset viewer.