Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Services.OKB/3.3/DataService.cs @ 4279

Last change on this file since 4279 was 4279, checked in by swagner, 14 years ago

Integrated OKB services (#1166)

File size: 7.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Data.Linq;
24using System.IO;
25using System.Linq;
26using System.ServiceModel;
27using HeuristicLab.Services.OKB.DataAccess;
28using log4net;
29
30namespace HeuristicLab.Services.OKB {
31
32  /// <summary>
33  /// Implementation of the <see cref="IDataService"/>.
34  /// </summary>
35  [ServiceBehavior(
36    InstanceContextMode = InstanceContextMode.PerSession,
37    IncludeExceptionDetailInFaults = true,
38    ConcurrencyMode = ConcurrencyMode.Multiple)]
39  class DataService : IDisposable, IDataService {
40
41    private enum Mode { Request, Submit, None };
42
43    private Mode mode = Mode.None;
44
45    private EntityType type;
46    private int id = -1;
47    private MemoryStream dataStream;
48
49    private Guid sessionID;
50    private static ILog logger = LogManager.GetLogger(typeof(DataService));
51
52    private void Log(string message, params object[] args) {
53      using (log4net.ThreadContext.Stacks["NDC"].Push(sessionID.ToString())) {
54        logger.Info(String.Format(message, args));
55      }
56    }
57
58    /// <summary>
59    /// Initializes a new instance of the <see cref="DataService"/> class.
60    /// </summary>
61    public DataService() {
62      sessionID = Guid.NewGuid();
63      Log("Instantiating new service");
64    }
65
66    private void EnsureInit() {
67      if (mode != Mode.None)
68        throw new FaultException(String.Format(
69          "Cannot service new request while processing another {0}-Operation", mode));
70    }
71
72    private byte[] GetData(EntityType type, int id) {
73      Log("loading data", type, id);
74      OKBDataContext okb = new OKBDataContext();
75      switch (type) {
76        case EntityType.Algorithm:
77          Algorithm algorithm = okb.Algorithms.Single(a => a.Id == id);
78          if (algorithm.AlgorithmData == null) {
79            algorithm.AlgorithmData = new AlgorithmData() {
80              AlgorithmId = algorithm.Id,
81              Data = new Binary(new byte[0])
82            };
83            okb.SubmitChanges();
84          }
85          return algorithm.AlgorithmData.Data.ToArray();
86          break;
87        case EntityType.Problem:
88          Problem problem = okb.Problems.Single(p => p.Id == id);
89          if (problem.ProblemData == null) {
90            problem.ProblemData = new ProblemData() {
91              ProblemId = problem.Id,
92              Data = new Binary(new byte[0])
93            };
94            okb.SubmitChanges();
95          }
96          return problem.ProblemData.Data.ToArray();
97          break;
98        default:
99          throw new FaultException("Unsupported EntityType");
100      }
101      okb.Dispose();
102    }
103
104    private void SetData(EntityType type, int id, byte[] data) {
105      Log("saving data", type, id, data.Length);
106      OKBDataContext okb = new OKBDataContext();
107      switch (type) {
108        case EntityType.Algorithm:
109          Algorithm algorithm = okb.Algorithms.Single(a => a.Id == id);
110          if (algorithm.AlgorithmData == null)
111            algorithm.AlgorithmData = new AlgorithmData() {
112              AlgorithmId = algorithm.Id,
113              Data = new Binary(new byte[0])
114            };
115          algorithm.AlgorithmData.Data = new Binary(data);
116          okb.SubmitChanges();
117          break;
118        case EntityType.Problem:
119          Problem problem = okb.Problems.Single(p => p.Id == id);
120          if (problem.ProblemData == null)
121            problem.ProblemData = new ProblemData() {
122              ProblemId = problem.Id,
123              Data = new Binary(new byte[0])
124            };
125          problem.ProblemData.Data = new Binary(data);
126          okb.SubmitChanges();
127          break;
128        default:
129          throw new FaultException("Unsupported EntityType");
130      }
131      okb.Dispose();
132    }
133
134    #region IDataService Members
135
136    /// <summary>
137    /// Request the specified <see cref="Algorithm"/> or <see cref="Problem"/>.
138    /// </summary>
139    /// <param name="type">The entity type.</param>
140    /// <param name="id">The entity id.</param>
141    /// <returns>The size of the data blob.</returns>
142    public int Request(EntityType type, int id) {
143      Log("requesting data", type, id);
144      EnsureInit();
145      dataStream = new MemoryStream(GetData(type, id));
146      mode = Mode.Request;
147      return (int)dataStream.Length;
148    }
149
150    /// <summary>
151    /// Gets the next chunk of bytes.
152    /// </summary>
153    /// <param name="size">The maximum number of bytes to transfer.</param>
154    /// <returns>An array of bytes.</returns>
155    public byte[] GetNextChunk(int size) {
156      if (dataStream == null || mode != Mode.Request)
157        throw new FaultException("No data has been prepared, call Request first");
158      byte[] chunk = new byte[Math.Min(size, dataStream.Length - dataStream.Position)];
159      dataStream.Read(chunk, 0, chunk.Length);
160      return chunk;
161    }
162
163    /// <summary>
164    /// Prepare submission of the specified <see cref="Algorithm"/> or <see cref="Problem"/>.
165    /// </summary>
166    /// <param name="type">The entity type.</param>
167    /// <param name="id">The entity id.</param>
168    public void Submit(EntityType type, int id) {
169      Log("Submitting", type, id);
170      EnsureInit();
171      GetData(type, id);
172      this.type = type;
173      this.id = id;
174      mode = Mode.Submit;
175      dataStream = new MemoryStream();
176    }
177
178    /// <summary>
179    /// Sets the next chunk of bytes.
180    /// </summary>
181    /// <param name="data">The data.</param>
182    public void SetNextChunk(byte[] data) {
183      dataStream.Write(data, 0, data.Length);
184    }
185
186    /// <summary>
187    /// Commits the transaction in case of an upload and closes
188    /// the connection.
189    /// </summary>
190    public void TransferDone() {
191      Log("commiting transfer");
192      if (mode == Mode.Submit)
193        SetData(type, id, dataStream.ToArray());
194      Dispose();
195    }
196
197    /// <summary>
198    /// Aborts the transfer.
199    /// </summary>
200    public void AbortTransfer() {
201      Dispose();
202    }
203
204    #endregion
205
206    #region IDisposable Members
207
208    /// <summary>
209    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
210    /// </summary>
211    public void Dispose() {
212      Log("disposing");
213      mode = Mode.None;
214      if (dataStream != null)
215        dataStream.Dispose();
216    }
217
218    #endregion
219  }
220}
Note: See TracBrowser for help on using the repository browser.