Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.CEDMA.DB/Database.cs @ 380

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

improved contention problem by using ReaderWriterLock in the DB proxy and reducing the number of threads in the RunScheduler (ticket #189)

File size: 20.2 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.Linq;
27using HeuristicLab.CEDMA.DB.Interfaces;
28using System.ServiceModel;
29using System.Data;
30using System.Data.SQLite;
31using System.Data.Common;
32using System.Threading;
33
34namespace HeuristicLab.CEDMA.DB {
35  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
36  public class Database : IDatabase {
37    private string connectionString;
38    private ReaderWriterLockSlim rwLock;
39    public Database(string connectionString) {
40      this.connectionString = connectionString;
41      rwLock = new ReaderWriterLockSlim();
42    }
43
44    #region create empty database
45    public void CreateNew() {
46      rwLock.EnterWriteLock();
47      try {
48        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
49          cnn.Open();
50          using(DbTransaction t = cnn.BeginTransaction()) {
51            using(DbCommand cmd = cnn.CreateCommand()) {
52              cmd.CommandText = "CREATE TABLE Project (ID integer primary key autoincrement, Name text, Description text, CreationTime DateTime)";
53              cmd.Transaction = t;
54              cmd.ExecuteNonQuery();
55            }
56            using(DbCommand cmd = cnn.CreateCommand()) {
57              cmd.CommandText = "CREATE TABLE Agent (ID integer primary key autoincrement, ProjectId integer, Name text, Status text default 'Unknown', RawData Blob)";
58              cmd.Transaction = t;
59              cmd.ExecuteNonQuery();
60            }
61            using(DbCommand cmd = cnn.CreateCommand()) {
62              cmd.CommandText = "CREATE TABLE Run (ID integer primary key autoincrement, AgentId integer, CreationTime DateTime, StartTime DateTime, FinishedTime DateTime, Status text default 'Unknown', RawData Blob)";
63              cmd.Transaction = t;
64              cmd.ExecuteNonQuery();
65            }
66            using(DbCommand cmd = cnn.CreateCommand()) {
67              cmd.CommandText = "CREATE TABLE Result (ID integer primary key autoincrement, RunId integer, ResultId integer, CreationTime DateTime, RawData Blob)";
68              cmd.Transaction = t;
69              cmd.ExecuteNonQuery();
70            }
71            t.Commit();
72          }
73        }
74      } finally {
75        rwLock.ExitWriteLock();
76      }
77    }
78    #endregion
79
80    #region insert agent/run/result/sub-result
81    public long InsertAgent(string name, byte[] rawData) {
82      rwLock.EnterWriteLock();
83      try {
84        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
85          cnn.Open();
86          long id;
87          using(DbTransaction t = cnn.BeginTransaction()) {
88            using(DbCommand c = cnn.CreateCommand()) {
89              c.Transaction = t;
90              c.CommandText = "Insert into Agent (Name, RawData) values (@Name, @RawData); select last_insert_rowid()";
91              DbParameter nameParam = c.CreateParameter();
92              nameParam.ParameterName = "@Name";
93              nameParam.Value = name;
94              c.Parameters.Add(nameParam);
95              DbParameter dataParam = c.CreateParameter();
96              dataParam.ParameterName = "@RawData";
97              dataParam.Value = rawData;
98              c.Parameters.Add(dataParam);
99              id = (long)c.ExecuteScalar();
100            }
101            t.Commit();
102            return id;
103          }
104        }
105      } finally {
106        rwLock.ExitWriteLock();
107      }
108    }
109
110    public long InsertRun(long agentId, byte[] rawData) {
111      rwLock.EnterWriteLock();
112      try {
113        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
114          cnn.Open();
115          long id;
116          using(DbTransaction t = cnn.BeginTransaction()) {
117            using(DbCommand c = cnn.CreateCommand()) {
118              c.Transaction = t;
119              c.CommandText = "Insert into Run (AgentId, CreationTime, RawData) values (@AgentId, @CreationTime, @RawData); select last_insert_rowid()";
120              DbParameter agentIdParam = c.CreateParameter();
121              agentIdParam.ParameterName = "@AgentId";
122              agentIdParam.Value = agentId;
123              c.Parameters.Add(agentIdParam);
124              DbParameter creationParam = c.CreateParameter();
125              creationParam.ParameterName = "@CreationTime";
126              DateTime now = DateTime.Now;
127              creationParam.Value = now;
128              c.Parameters.Add(creationParam);
129              DbParameter rawDataParam = c.CreateParameter();
130              rawDataParam.ParameterName = "@RawData";
131              rawDataParam.Value = rawData;
132              c.Parameters.Add(rawDataParam);
133              id = (long)c.ExecuteScalar();
134            }
135            t.Commit();
136            return id;
137          }
138        }
139      } finally {
140        rwLock.ExitWriteLock();
141      }
142    }
143
144    public long InsertResult(long runId, byte[] rawData) {
145      rwLock.EnterWriteLock();
146      try {
147        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
148          cnn.Open();
149          long id;
150          using(DbTransaction t = cnn.BeginTransaction()) {
151            using(DbCommand c = cnn.CreateCommand()) {
152              c.Transaction = t;
153              c.CommandText = "Insert into Result (RunId, CreationTime, RawData) values (@RunId, @CreationTime, @RawData); select last_insert_rowid()";
154              DbParameter runIdParam = c.CreateParameter();
155              runIdParam.ParameterName = "@RunId";
156              runIdParam.Value = runId;
157              c.Parameters.Add(runIdParam);
158              DbParameter creationParam = c.CreateParameter();
159              creationParam.ParameterName = "@CreationTime";
160              DateTime now = DateTime.Now;
161              creationParam.Value = now;
162              c.Parameters.Add(creationParam);
163              DbParameter rawDataParam = c.CreateParameter();
164              rawDataParam.ParameterName = "@RawData";
165              rawDataParam.Value = rawData;
166              c.Parameters.Add(rawDataParam);
167              id = (long)c.ExecuteScalar();
168            }
169            t.Commit();
170            return id;
171          }
172        }
173      } finally {
174        rwLock.ExitWriteLock();
175      }
176    }
177
178    public long InsertSubResult(long resultId, byte[] rawData) {
179      rwLock.EnterWriteLock();
180      try {
181        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
182          cnn.Open();
183          long id;
184          using(DbTransaction t = cnn.BeginTransaction()) {
185            using(DbCommand c = cnn.CreateCommand()) {
186              c.Transaction = t;
187              c.CommandText = "Insert into Result (ResultId, CreationTime, RawData) values (@ResultId, @CreationTime, @RawData); select last_insert_rowid()";
188              DbParameter resultIdParam = c.CreateParameter();
189              resultIdParam.ParameterName = "@ResultId";
190              resultIdParam.Value = resultId;
191              c.Parameters.Add(resultIdParam);
192              DbParameter creationParam = c.CreateParameter();
193              creationParam.ParameterName = "@CreationTime";
194              DateTime now = DateTime.Now;
195              creationParam.Value = now;
196              c.Parameters.Add(creationParam);
197              DbParameter rawDataParam = c.CreateParameter();
198              rawDataParam.ParameterName = "@RawData";
199              rawDataParam.Value = rawData;
200              c.Parameters.Add(rawDataParam);
201              id = (long)c.ExecuteScalar();
202            }
203            t.Commit();
204            return id;
205          }
206        }
207      } finally {
208        rwLock.ExitWriteLock();
209      }
210    }
211    #endregion
212
213    #region update agent/run
214    public void UpdateAgent(long id, string name) {
215      rwLock.EnterWriteLock();
216      try {
217        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
218          cnn.Open();
219          using(SQLiteTransaction t = cnn.BeginTransaction()) {
220            using(SQLiteCommand c = cnn.CreateCommand()) {
221              c.Transaction = t;
222              c.CommandText = "Update Agent set Name=@Name where id=@Id";
223              DbParameter nameParam = c.CreateParameter();
224              DbParameter idParam = c.CreateParameter();
225              nameParam.ParameterName = "@Name";
226              nameParam.Value = name;
227              idParam.ParameterName = "@Id";
228              idParam.Value = id;
229              c.Parameters.Add(nameParam);
230              c.Parameters.Add(idParam);
231              c.ExecuteNonQuery();
232            }
233            t.Commit();
234          }
235        }
236      } finally {
237        rwLock.ExitWriteLock();
238      }
239    }
240
241    public void UpdateAgent(long id, ProcessStatus status) {
242      rwLock.EnterWriteLock();
243      try {
244        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
245          cnn.Open();
246          using(SQLiteTransaction t = cnn.BeginTransaction()) {
247            using(SQLiteCommand c = cnn.CreateCommand()) {
248              c.Transaction = t;
249              c.CommandText = "Update Agent set Status=@Status where id=@Id";
250              DbParameter statusParam = c.CreateParameter();
251              DbParameter idParam = c.CreateParameter();
252              statusParam.ParameterName = "@Status";
253              statusParam.Value = status;
254              idParam.ParameterName = "@Id";
255              idParam.Value = id;
256              c.Parameters.Add(statusParam);
257              c.Parameters.Add(idParam);
258              c.ExecuteNonQuery();
259            }
260            t.Commit();
261          }
262        }
263      } finally {
264        rwLock.ExitWriteLock();
265      }
266    }
267
268    public void UpdateAgent(long id, byte[] rawData) {
269      rwLock.EnterWriteLock();
270      try {
271        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
272          cnn.Open();
273          using(SQLiteTransaction t = cnn.BeginTransaction()) {
274            using(SQLiteCommand c = cnn.CreateCommand()) {
275              c.Transaction = t;
276              c.CommandText = "Update Agent set RawData=@RawData where id=@Id";
277              DbParameter rawDataParam = c.CreateParameter();
278              DbParameter idParam = c.CreateParameter();
279              rawDataParam.ParameterName = "@RawData";
280              rawDataParam.Value = rawData;
281              idParam.ParameterName = "@Id";
282              idParam.Value = id;
283              c.Parameters.Add(rawDataParam);
284              c.Parameters.Add(idParam);
285              c.ExecuteNonQuery();
286            }
287            t.Commit();
288          }
289        }
290      } finally {
291        rwLock.ExitWriteLock();
292      }
293    }
294
295    public void UpdateRunStart(long runId, DateTime startTime) {
296      rwLock.EnterWriteLock();
297      try {
298        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
299          cnn.Open();
300          using(SQLiteTransaction t = cnn.BeginTransaction()) {
301            using(SQLiteCommand c = cnn.CreateCommand()) {
302              c.Transaction = t;
303              c.CommandText = "Update Run set StartTime=@StartTime where id=@Id";
304              DbParameter startTimeParam = c.CreateParameter();
305              DbParameter idParam = c.CreateParameter();
306              startTimeParam.ParameterName = "@StartTime";
307              startTimeParam.Value = startTime;
308              idParam.ParameterName = "@Id";
309              idParam.Value = runId;
310              c.Parameters.Add(startTimeParam);
311              c.Parameters.Add(idParam);
312              c.ExecuteNonQuery();
313            }
314            t.Commit();
315          }
316        }
317      } finally {
318        rwLock.ExitWriteLock();
319      }
320    }
321
322    public void UpdateRunFinished(long runId, DateTime finishedTime) {
323      rwLock.EnterWriteLock();
324      try {
325        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
326          cnn.Open();
327          using(SQLiteTransaction t = cnn.BeginTransaction()) {
328            using(SQLiteCommand c = cnn.CreateCommand()) {
329              c.Transaction = t;
330              c.CommandText = "Update Run set FinishedTime=@FinishedTime where id=@Id";
331              DbParameter finishedTimeParam = c.CreateParameter();
332              DbParameter idParam = c.CreateParameter();
333              finishedTimeParam.ParameterName = "@FinishedTime";
334              finishedTimeParam.Value = finishedTime;
335              idParam.ParameterName = "@Id";
336              idParam.Value = runId;
337              c.Parameters.Add(finishedTimeParam);
338              c.Parameters.Add(idParam);
339              c.ExecuteNonQuery();
340            }
341            t.Commit();
342          }
343        }
344      } finally {
345        rwLock.ExitWriteLock();
346      }
347    }
348
349    public void UpdateRunStatus(long runId, ProcessStatus status) {
350      rwLock.EnterWriteLock();
351      try {
352        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
353          cnn.Open();
354          using(SQLiteTransaction t = cnn.BeginTransaction()) {
355            using(SQLiteCommand c = cnn.CreateCommand()) {
356              c.Transaction = t;
357              c.CommandText = "Update Run set Status=@Status where id=@Id";
358              DbParameter statusParam = c.CreateParameter();
359              DbParameter idParam = c.CreateParameter();
360              statusParam.ParameterName = "@Status";
361              statusParam.Value = status;
362              idParam.ParameterName = "@Id";
363              idParam.Value = runId;
364              c.Parameters.Add(statusParam);
365              c.Parameters.Add(idParam);
366              c.ExecuteNonQuery();
367            }
368            t.Commit();
369          }
370        }
371      } finally {
372        rwLock.ExitWriteLock();
373      }
374    }
375    #endregion
376
377    #region get agent/run/result/sub-result
378
379    public ICollection<AgentEntry> GetAgents(ProcessStatus status) {
380      rwLock.EnterReadLock();
381      List<AgentEntry> agents = new List<AgentEntry>();
382      try {
383        using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
384          cnn.Open();
385          SQLiteCommand c = cnn.CreateCommand();
386          c.CommandText = "Select id, name, status, rawdata from Agent where Status=@Status";
387          DbParameter statusParameter = c.CreateParameter();
388          statusParameter.ParameterName = "@Status";
389          statusParameter.Value = status;
390          c.Parameters.Add(statusParameter);
391
392          SQLiteDataReader r = c.ExecuteReader();
393          while(r.Read()) {
394            AgentEntry agent = new AgentEntry();
395            agent.Id = r.GetInt32(0);
396            agent.Name = r.GetString(1);
397            agent.Status = (ProcessStatus)Enum.Parse(typeof(ProcessStatus), r.GetString(2));
398            agent.RawData = (byte[])r.GetValue(3);
399            agents.Add(agent);
400          }
401        }
402      } finally {
403        rwLock.ExitReadLock();
404      }
405      return agents;
406    }
407
408    public ICollection<AgentEntry> GetAgents() {
409      rwLock.EnterReadLock();
410      List<AgentEntry> agents = new List<AgentEntry>();
411      try {
412        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
413          cnn.Open();
414          using(DbCommand c = cnn.CreateCommand()) {
415            c.CommandText = "Select id, name, status, rawdata from Agent";
416            using(DbDataReader r = c.ExecuteReader()) {
417              while(r.Read()) {
418                AgentEntry agent = new AgentEntry();
419                agent.Id = r.GetInt32(0);
420                agent.Name = r.GetString(1);
421                agent.Status = (ProcessStatus)Enum.Parse(typeof(ProcessStatus), r.GetString(2));
422                agent.RawData = (byte[])r.GetValue(3);
423                agents.Add(agent);
424              }
425            }
426          }
427        }
428      } finally {
429        rwLock.ExitReadLock();
430      }
431      return agents;
432    }
433
434    public ICollection<RunEntry> GetRuns() {
435      List<RunEntry> runs = new List<RunEntry>();
436      rwLock.EnterReadLock();
437      try {
438        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
439          cnn.Open();
440          using(DbCommand c = cnn.CreateCommand()) {
441            c.CommandText = "Select Id, AgentId, CreationTime, StartTime, FinishedTime, Status, Rawdata from Run";
442            using(DbDataReader r = c.ExecuteReader()) {
443              while(r.Read()) {
444                RunEntry run = new RunEntry();
445                run.Id = r.GetInt32(0);
446                run.AgentId = r.GetInt32(1);
447                run.CreationTime = r.GetDateTime(2);
448                run.StartTime = r.GetDateTime(3);
449                run.FinishedTime = r.GetDateTime(4);
450                run.Status = (ProcessStatus)Enum.Parse(typeof(ProcessStatus), r.GetString(5));
451                run.RawData = (byte[])r.GetValue(6);
452                runs.Add(run);
453              }
454            }
455          }
456        }
457      } finally {
458        rwLock.ExitReadLock();
459      }
460      return runs;
461    }
462
463    public ICollection<RunEntry> GetRuns(ProcessStatus status) {
464      List<RunEntry> runs = new List<RunEntry>();
465      rwLock.EnterReadLock();
466      try {
467        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
468          cnn.Open();
469          using(DbCommand c = cnn.CreateCommand()) {
470            c.CommandText = "Select Id, AgentId, CreationTime, StartTime, FinishedTime, Status, Rawdata from Run where Status=@Status";
471            DbParameter statusParameter = c.CreateParameter();
472            statusParameter.ParameterName = "@Status";
473            statusParameter.Value = status;
474            c.Parameters.Add(statusParameter);
475
476            using(DbDataReader r = c.ExecuteReader()) {
477              while(r.Read()) {
478                RunEntry run = new RunEntry();
479                run.Id = r.GetInt32(0);
480                run.AgentId = r.GetInt32(1);
481                run.CreationTime = r.GetDateTime(2);
482                run.StartTime = r.IsDBNull(3) ? null : new Nullable<DateTime>(r.GetDateTime(3));
483                run.FinishedTime = r.IsDBNull(4) ? null : new Nullable<DateTime>(r.GetDateTime(4));
484                run.Status = (ProcessStatus)Enum.Parse(typeof(ProcessStatus), r.GetString(5));
485                run.RawData = (byte[])r.GetValue(6);
486                runs.Add(run);
487              }
488            }
489          }
490        }
491      } finally {
492        rwLock.ExitReadLock();
493      }
494      return runs;
495    }
496
497    public ICollection<ResultEntry> GetResults(long runId) {
498      List<ResultEntry> results = new List<ResultEntry>();
499      rwLock.EnterReadLock();
500      try {
501        using(DbConnection cnn = new SQLiteConnection(connectionString)) {
502          cnn.Open();
503          using(DbCommand c = cnn.CreateCommand()) {
504            c.CommandText = "Select Id, RunId, CreationTime, Rawdata from Result";
505            using(DbDataReader r = c.ExecuteReader()) {
506              while(r.Read()) {
507                ResultEntry result = new ResultEntry();
508                result.Id = r.GetInt32(0);
509                result.RunId = r.GetInt32(1);
510                result.CreationTime = r.GetDateTime(2);
511                result.RawData = (byte[])r.GetValue(3);
512                results.Add(result);
513              }
514            }
515          }
516        }
517      } finally {
518        rwLock.ExitReadLock();
519      }
520      return results;
521    }
522
523    public ICollection<ResultEntry> GetSubResults(long resultId) {
524      throw new NotImplementedException();
525    }
526    #endregion
527  }
528}
Note: See TracBrowser for help on using the repository browser.