#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Data.Linq;
using System.IO;
using System.Linq;
using System.ServiceModel;
using HeuristicLab.Services.OKB.DataAccess;
namespace HeuristicLab.Services.OKB {
///
/// Implementation of the .
///
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)]
class DataService : IDisposable, IDataService {
private enum Mode { Request, Submit, None };
private Mode mode = Mode.None;
private EntityType type;
private int id = -1;
private MemoryStream dataStream;
private void EnsureInit() {
if (mode != Mode.None)
throw new FaultException(String.Format("Cannot service new request while processing another {0}-Operation.", mode));
}
private byte[] GetData(EntityType type, int id) {
using (OKBDataContext okb = new OKBDataContext()) {
switch (type) {
case EntityType.Algorithm:
Algorithm algorithm = okb.Algorithms.Single(a => a.Id == id);
if (algorithm.AlgorithmData == null) {
algorithm.AlgorithmData = new AlgorithmData() {
AlgorithmId = algorithm.Id,
Data = new Binary(new byte[0])
};
okb.SubmitChanges();
}
return algorithm.AlgorithmData.Data.ToArray();
case EntityType.Problem:
Problem problem = okb.Problems.Single(p => p.Id == id);
if (problem.ProblemData == null) {
problem.ProblemData = new ProblemData() {
ProblemId = problem.Id,
Data = new Binary(new byte[0])
};
okb.SubmitChanges();
}
return problem.ProblemData.Data.ToArray();
default:
throw new FaultException("Unsupported EntityType.");
}
}
}
private void SetData(EntityType type, int id, byte[] data) {
using (OKBDataContext okb = new OKBDataContext()) {
switch (type) {
case EntityType.Algorithm:
Algorithm algorithm = okb.Algorithms.Single(a => a.Id == id);
if (algorithm.AlgorithmData == null)
algorithm.AlgorithmData = new AlgorithmData() {
AlgorithmId = algorithm.Id,
Data = new Binary(new byte[0])
};
algorithm.AlgorithmData.Data = new Binary(data);
okb.SubmitChanges();
break;
case EntityType.Problem:
Problem problem = okb.Problems.Single(p => p.Id == id);
if (problem.ProblemData == null)
problem.ProblemData = new ProblemData() {
ProblemId = problem.Id,
Data = new Binary(new byte[0])
};
problem.ProblemData.Data = new Binary(data);
okb.SubmitChanges();
break;
default:
throw new FaultException("Unsupported EntityType.");
}
}
}
#region IDataService Members
///
/// Request the specified or .
///
/// The entity type.
/// The entity id.
/// The size of the data blob.
public int Request(EntityType type, int id) {
EnsureInit();
dataStream = new MemoryStream(GetData(type, id));
mode = Mode.Request;
return (int)dataStream.Length;
}
///
/// Gets the next chunk of bytes.
///
/// The maximum number of bytes to transfer.
/// An array of bytes.
public byte[] GetNextChunk(int size) {
if (dataStream == null || mode != Mode.Request)
throw new FaultException("No data has been prepared, call Request first.");
byte[] chunk = new byte[Math.Min(size, dataStream.Length - dataStream.Position)];
dataStream.Read(chunk, 0, chunk.Length);
return chunk;
}
///
/// Prepare submission of the specified or .
///
/// The entity type.
/// The entity id.
public void Submit(EntityType type, int id) {
EnsureInit();
GetData(type, id);
this.type = type;
this.id = id;
mode = Mode.Submit;
dataStream = new MemoryStream();
}
///
/// Sets the next chunk of bytes.
///
/// The data.
public void SetNextChunk(byte[] data) {
dataStream.Write(data, 0, data.Length);
}
///
/// Commits the transaction in case of an upload and closes
/// the connection.
///
public void TransferDone() {
if (mode == Mode.Submit)
SetData(type, id, dataStream.ToArray());
Dispose();
}
///
/// Aborts the transfer.
///
public void AbortTransfer() {
Dispose();
}
#endregion
#region IDisposable Members
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose() {
mode = Mode.None;
if (dataStream != null)
dataStream.Dispose();
}
#endregion
}
}