Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Grid/Database.cs @ 505

Last change on this file since 505 was 505, checked in by gkronber, 16 years ago

improved SQL statement to reduce I/O load of the DB (ticket #197 Use SQLite backend to store waiting engines and results instead of in-memory dictionaries)

File size: 11.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using System.Data;
27using System.Data.SQLite;
28using System.Data.Common;
29using System.Threading;
30
31namespace HeuristicLab.Grid {
32  class Database {
33    private string connectionString;
34    private ReaderWriterLockSlim rwLock;
35    public Database(string connectionString) {
36      this.connectionString = connectionString;
37      rwLock = new ReaderWriterLockSlim();
38    }
39
40    #region create empty database
41    public void CreateNew() {
42      rwLock.EnterWriteLock();
43      try {
44        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
45          cnn.Open();
46          using(DbTransaction t = cnn.BeginTransaction()) {
47            using(DbCommand cmd = cnn.CreateCommand()) {
48              cmd.CommandText = "CREATE TABLE Job (ID integer primary key autoincrement, Guid text, Status text, CreationTime DateTime, StartTime DateTime, RawData blob)";
49              cmd.Transaction = t;
50              cmd.ExecuteNonQuery();
51            }
52            t.Commit();
53          }
54        }
55      } finally {
56        rwLock.ExitWriteLock();
57      }
58    }
59    #endregion
60
61    internal void InsertJob(Guid guid, JobState jobState, byte[] rawData) {
62      rwLock.EnterWriteLock();
63      try {
64        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
65          cnn.Open();
66          using(DbTransaction t = cnn.BeginTransaction()) {
67            using(DbCommand c = cnn.CreateCommand()) {
68              c.Transaction = t;
69              c.CommandText = "Insert into Job (Guid, Status, CreationTime, StartTime, RawData) values (@Guid, @Status, @CreationTime, @StartTime, @RawData)";
70              DbParameter guidParam = c.CreateParameter();
71              guidParam.ParameterName = "@Guid";
72              guidParam.Value = guid.ToString();
73              c.Parameters.Add(guidParam);
74              DbParameter statusParam = c.CreateParameter();
75              statusParam.ParameterName = "@Status";
76              statusParam.Value = jobState.ToString();
77              c.Parameters.Add(statusParam);
78              DbParameter creationParam = c.CreateParameter();
79              creationParam.ParameterName = "@CreationTime";
80              DateTime now = DateTime.Now;
81              creationParam.Value = now;
82              c.Parameters.Add(creationParam);
83              DbParameter startParam = c.CreateParameter();
84              startParam.ParameterName = "@StartTime";
85              if(jobState == JobState.Busy) startParam.Value = now;
86              else startParam.Value = null;
87              c.Parameters.Add(startParam);
88              DbParameter rawDataParam = c.CreateParameter();
89              rawDataParam.ParameterName = "@RawData";
90              rawDataParam.Value = rawData;
91              c.Parameters.Add(rawDataParam);
92              c.ExecuteNonQuery();
93            }
94            t.Commit();
95          }
96        }
97      } finally {
98        rwLock.ExitWriteLock();
99      }
100
101    }
102
103    internal JobEntry GetNextWaitingJob() {
104      rwLock.EnterUpgradeableReadLock();
105      try {
106        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
107          cnn.Open();
108          using(DbTransaction t = cnn.BeginTransaction()) {
109            DbCommand c = cnn.CreateCommand();
110            c.Transaction = t;
111            c.CommandText = "select guid,creationtime,starttime,rawdata from job, (select id from job where status=@Status order by creationtime limit 1) as next where job.id=next.id";
112            DbParameter statusParameter = c.CreateParameter();
113            statusParameter.ParameterName = "@Status";
114            statusParameter.Value = JobState.Waiting.ToString();
115            c.Parameters.Add(statusParameter);
116            DbDataReader r = c.ExecuteReader();
117            if(!r.HasRows) {
118              r.Close();
119              t.Commit();
120              return null;
121            }
122            r.Read();
123            JobEntry job = new JobEntry();
124            job.Status = JobState.Busy;
125            job.Guid = r.GetGuid(0);
126            job.CreationTime = r.GetDateTime(1);
127            job.StartTime = r.IsDBNull(2) ? null : new Nullable<DateTime>(r.GetDateTime(2));
128            job.RawData = (byte[])r.GetValue(3);
129            r.Close();
130            rwLock.EnterWriteLock();
131            try {
132              DbCommand updateCmd = cnn.CreateCommand();
133              updateCmd.Transaction = t;
134              updateCmd.CommandText = "Update job set Status=@Status where Guid=@Guid";
135              statusParameter = updateCmd.CreateParameter();
136              statusParameter.ParameterName = "@Status";
137              statusParameter.Value = JobState.Busy.ToString();
138              DbParameter guidParam = updateCmd.CreateParameter();
139              guidParam.ParameterName = "@Guid";
140              guidParam.Value = job.Guid.ToString();
141              updateCmd.Parameters.Add(statusParameter);
142              updateCmd.Parameters.Add(guidParam);
143              updateCmd.ExecuteNonQuery();
144            } finally {
145              rwLock.ExitWriteLock();
146            }
147            t.Commit();
148            return job;
149          }
150        }
151      } finally {
152        rwLock.ExitUpgradeableReadLock();
153      }
154    }
155
156    internal void SetJobResult(Guid guid, byte[] result) {
157      rwLock.EnterWriteLock();
158      try {
159        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
160          cnn.Open();
161          using(DbTransaction t = cnn.BeginTransaction()) {
162            using(DbCommand c = cnn.CreateCommand()) {
163              c.Transaction = t;
164              c.CommandText = "Update Job set Status=@Status, RawData=@RawData where Guid=@Guid";
165              DbParameter rawDataParam = c.CreateParameter();
166              DbParameter statusParam = c.CreateParameter();
167              DbParameter guidParam = c.CreateParameter();
168              rawDataParam.ParameterName = "@RawData";
169              rawDataParam.Value = result;
170              guidParam.ParameterName = "@Guid";
171              guidParam.Value = guid.ToString();
172              statusParam.ParameterName = "@Status";
173              statusParam.Value = JobState.Finished.ToString();
174              c.Parameters.Add(rawDataParam);
175              c.Parameters.Add(statusParam);
176              c.Parameters.Add(guidParam);
177              c.ExecuteNonQuery();
178            }
179            t.Commit();
180          }
181        }
182      } finally {
183        rwLock.ExitWriteLock();
184      }
185    }
186
187    internal void UpdateJobState(Guid guid, JobState jobState) {
188      rwLock.EnterWriteLock();
189      try {
190        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
191          cnn.Open();
192          using(DbTransaction t = cnn.BeginTransaction()) {
193            using(DbCommand c = cnn.CreateCommand()) {
194              c.Transaction = t;
195              c.CommandText = "Update Job set Status=@Status, StartTime=@StartTime where Guid=@Guid";
196              DbParameter statusParam = c.CreateParameter();
197              DbParameter startTimeParam = c.CreateParameter();
198              DbParameter guidParam = c.CreateParameter();
199              startTimeParam.ParameterName = "@StartTime";
200              if(jobState == JobState.Busy)
201                startTimeParam.Value = DateTime.Now;
202              else
203                startTimeParam.Value = null;
204              guidParam.ParameterName = "@Guid";
205              guidParam.Value = guid.ToString();
206              statusParam.ParameterName = "@Status";
207              statusParam.Value = jobState.ToString();
208              c.Parameters.Add(startTimeParam);
209              c.Parameters.Add(statusParam);
210              c.Parameters.Add(guidParam);
211              c.ExecuteNonQuery();
212            }
213            t.Commit();
214          }
215        }
216      } finally {
217        rwLock.ExitWriteLock();
218      }
219    }
220
221
222    internal JobEntry GetJob(Guid guid) {
223      rwLock.EnterReadLock();
224      try {
225        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
226          cnn.Open();
227          DbCommand c = cnn.CreateCommand();
228          c.CommandText = "Select Status, CreationTime, StartTime, Rawdata from Job where Guid=@Guid";
229          DbParameter guidParameter = c.CreateParameter();
230          guidParameter.ParameterName = "@Guid";
231          guidParameter.Value = guid.ToString();
232          c.Parameters.Add(guidParameter);
233          DbDataReader r = c.ExecuteReader();
234          if(r.HasRows) {
235            r.Read();
236            JobEntry job = new JobEntry();
237            job.Guid = guid;
238            job.Status = (JobState)Enum.Parse(typeof(JobState), r.GetString(0));
239            job.CreationTime = r.GetDateTime(1);
240            job.StartTime = r.IsDBNull(2) ? null : new Nullable<DateTime>(r.GetDateTime(2));
241            job.RawData = (byte[])r.GetValue(3);
242            return job;
243          }
244          r.Close();
245        }
246      } finally {
247        rwLock.ExitReadLock();
248      }
249      return null;
250    }
251
252    internal JobState GetJobState(Guid guid) {
253      rwLock.EnterReadLock();
254      try {
255        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
256          cnn.Open();
257          DbCommand c = cnn.CreateCommand();
258          c.CommandText = "Select Status from Job where Guid=@Guid";
259          DbParameter guidParameter = c.CreateParameter();
260          guidParameter.ParameterName = "@Guid";
261          guidParameter.Value = guid.ToString();
262          c.Parameters.Add(guidParameter);
263          DbDataReader r = c.ExecuteReader();
264          if(r.HasRows) {
265            r.Read();
266            return (JobState)Enum.Parse(typeof(JobState), r.GetString(0));
267          }
268          r.Close();
269        }
270      } finally {
271        rwLock.ExitReadLock();
272      }
273      return JobState.Unknown;
274    }
275
276    internal long GetJobCount(JobState status) {
277      rwLock.EnterReadLock();
278      try {
279        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
280          cnn.Open();
281          DbCommand c = cnn.CreateCommand();
282          c.CommandText = "Select Count(id) from Job where Status=@Status";
283          DbParameter stateParameter = c.CreateParameter();
284          stateParameter.ParameterName = "@Status";
285          stateParameter.Value = status.ToString();
286          c.Parameters.Add(stateParameter);
287          return (long)c.ExecuteScalar();
288        }
289      } finally {
290        rwLock.ExitReadLock();
291      }
292    }
293
294    /// <summary>
295    /// Does nothing right now (= running jobs that disappear are never restarted).
296    /// </summary>
297    internal void RestartExpiredActiveJobs() {
298    }
299
300    /// <summary>
301    /// Does nothing right now (= results are never deleted).
302    /// </summary>
303    internal void DeleteExpiredResults() {
304    }
305  }
306}
Note: See TracBrowser for help on using the repository browser.