Free cookie consent management tool by TermsFeed Policy Generator

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

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

Worked on OKB user authentication (#1167)

File size: 7.2 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      using (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      }
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.