Webcast on Parallel Computing

A couple of weeks ago, I did a webcast on Parallel Computing available on channel9 at http://channel9.msdn.com/posts/adebruyn/MSDN-Live-Meeting-Visual-Studio-2010-and-NET-4-Update

The presentation can  be downloaded at : ParallelComputing.pdf

In addition, you can also download my demos  :

ParallelismDemo.zip

ParallelismDemo2.zip


AZURE Roadshow at HOWEST - demos

Last week, I did a presentation on Windows Azure at HOWEST, University College West Flanders. As promised, my hands-on-labs of this session.

1. A file archive application to upload/download files into a database in the cloud.  This application consists out of a webpage (UploadFile.aspx) to upload files into a SQL Azure database, and a REST service to dowload your files as a stream. You can dowload the sources at : CodeArchiveService.zip

To get you up and running in the develoment fabric, first create a local database in SQL Server and add a table called CodeArchive. Modify the config files to point to your database.

CREATE TABLE [dbo].[ZipArchive](
[CodeName] [varchar](200) PRIMARY KEY CLUSTERED  NOT NULL,
[CodeBlob] [varbinary](max) NULL)
 

Next, to deploy into the cloud: create a database in SQL Azure, create a login and grant access to your database and create a table called CodeArchive (same as above). Now, change the config files to point to this database.

-- On the master database:
CREATE LOGIN <login> WITH password='<password>'

-- On your database:
CREATE USER <user> FROM LOGIN <login>
EXEC sp_addrolemember 'db_owner', '<user>'
 



2. A photo browser application :

  • Contains a synchronous Upload.aspx (storage right into SQL Azure) and an asynchronous UploadAsync.aspx (blob storage to store the image temporarily + queued messaging to send a message to a background workerrole)
  • Contains a workerrole for thumbnailing the image and saving both the image and the thumbnail  in SQL Azure
  • Contains a Silverlight photo browser app which talks to a WCF service to retrieve it's data (no rocket science here to be focused on Azure stuff as much as possible)

You can dowload the sources at : PhotoBookService.zip

Tables needed (both locally and in SQL Azure):

CREATE TABLE [Photo](
    [PhotoID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    [ThumbNailPhoto] [varbinary](max) NULL,
    [LargePhoto] [varbinary](max) NULL)
 

CREATE TABLE [Comment](
    [PhotoID] [int] NOT NULL,
    [CommentID] [int] IDENTITY(1,1) NOT NULL,
    [Comments] [varchar](1000) NULL,
 CONSTRAINT [PK_Comment_PhotoID_CommentID] PRIMARY KEY CLUSTERED 
(
    [PhotoID] ASC,
    [CommentID] ASC
))

ALTER TABLE [dbo].[Comment]  WITH CHECK ADD  CONSTRAINT [FK_Photo_Comment] FOREIGN KEY([PhotoID])
REFERENCES [dbo].[Photo] ([PhotoID])

ALTER TABLE [dbo].[Comment] CHECK CONSTRAINT [FK_Photo_Comment]

WCF Streaming

1. Configuring and Tracing

WCF can send messages in buffered mode and in streaming mode. The default is buffered mode, which means that the whole message needs to be transfered and received before the client can start processing it. When messages get too large to be send as one big blob and when those messages can’t be split in different message parts, streaming is your option. To use streaming (both on input and/or output parameters), define the parameters as type of stream (you should use the base class here, not a derived one like eg. FileStream), Message or IXmlSerializable. This should be the one and only parameter, no extra parameters are allowed !

Not all the bindings support streaming : you can use basicHttpBinding, NetTcpBinding, NetNamedPipeBinding and webHttpBinding. You can’t use wsHttpBinding : you can’t sign and/or encrypt messages without applying the algorithm on the complete message first, so streaming is no option here.

As example, let’s transfer an image both buffered and streamed. I’m going to use a REST service in order to use Internet Explorer as client application (which can show chunked data, i.e. showing the part of the image which has already been transferred).

[ServiceContract]
public interface IPicture
{
    [OperationContract]
    [WebGet(UriTemplate="/getpicture")]
    Stream GetPicture();
}

 

public class Picture : IPicture
{
    public System.IO.Stream GetPicture()
    {
        OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
        context.ContentType = "image/jpeg";

        return new TraceFileStream(@"E:\Downloads\image.jpg", FileMode.Open);
    }
}

 

To show a trace of the Read operations on the stream, I derived a class TraceFileStream from FileStream and added some tracing to it.

public class TraceFileStream : FileStream
{
    public TraceFileStream(string path, FileMode mode)
        : base(path, mode)
    {
    }
    public override void Write(byte[] array, int offset, int count)
    {
        Debug.WriteLine(string.Format("Writing {0} bytes to Filestream", count));
        base.Write(array, offset, count);
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        Debug.WriteLine(string.Format("Reading {0} bytes from Filestream", count));
        return base.Read(buffer, offset, count);
    }
}

 

Let’s configure buffered mode first:

<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="CustomWebBinding" transferMode="Buffered" />
      </webHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="CustomBehavior" name="Picture">
        <endpoint address="" behaviorConfiguration="WebEndpointBehavior"
          binding="webHttpBinding" bindingConfiguration="CustomWebBinding"
          contract="IPicture" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="WebEndpointBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
        <behavior name="CustomBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
 

By tracing the message, you will see that a buffer of 104270 bytes is send to the client.

Untitled

To send the same data in streamed mode, apply the following configuration change:

<webHttpBinding>
   <binding name="CustomWebBinding" transferMode="Streamed" />
</webHttpBinding>

 

Tracing now learns us that the data arrives chunked (see: Transfer-Encoding: Chunked)

Untitled

2. A  custom Stream class

When creating a class to read and/or write data from a stream, you shouldn’t care on how the data will be retrieved from the client: derive your implementation from Stream (or an existing Stream class).

As example, let’s create a class UpsideDownJpegStream which is a stream to an open a jpeg file, but the resulting image will be upside down in it.

public class UpsideDownJpegStream : Stream
{
    private MemoryStream outStream = null;

    public UpsideDownJpegStream(string filePath)
    {
        TraceFileStream inStream = new TraceFileStream(filePath, FileMode.Open);
        JpegBitmapDecoder decoder = new JpegBitmapDecoder(inStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        BitmapSource inSource = decoder.Frames[0];

        outStream = new TraceMemoryStream();
        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
        encoder.FlipHorizontal = true;
        encoder.FlipVertical = false;
        encoder.QualityLevel = 30;
        encoder.Rotation = Rotation.Rotate180;
        encoder.Frames.Add(BitmapFrame.Create(inSource));
        encoder.Save(outStream);
        outStream.Position = 0;
    }
    public override bool CanRead
    {
        get { return true; }
    }
    public override long Length
    {
        get { return outStream.Length; }
    }
    private long position = 0;
    public override long Position
    {
        get
        {
            return position;
        }
        set
        {
            position = value;
        }
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        Debug.WriteLine(string.Format("Reading {0} bytes from UpsideDownJpegStream", count));

        int countRead = outStream.Read(buffer,offset, count);
        Position = outStream.Position;
        
        return countRead;
    }
    public override void Close()
    {
        outStream.Close();
        base.Close();
    }
    protected override void Dispose(bool disposing)
    {
        outStream.Dispose();

        base.Dispose(disposing);
    }
   ...
}

As you notice, the Read() method provides access to our stream by passing a buffer and requesting for an amount of data at a certain offset. I use in here also trace classes (TraceFileStream,TraceMemoryStream) to trace what’s happening. Let’s add an extra call to the WCF service for it.

[ServiceContract]
public interface IPicture
{
    [OperationContract]
    [WebGet(UriTemplate = "/getreversepicture")]
    Stream GetReversePicture();
}

public class Picture : IPicture
{
    public Stream GetReversePicture()
    {
        OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
        context.ContentType = "image/jpeg";

        return new UpsideDownJpegStream(@"E:\Downloads\image.jpg");
    }
}

When running this, the picture will occur upside down (of course), and the trace output will be

Writing 20 bytes to MemoryStream                                    <== JpegBitmapEncoder writing to MemoryStream
Writing 4096 bytes to MemoryStream
Writing 4096 bytes to MemoryStream
Writing 4096 bytes to MemoryStream
Writing 4096 bytes to MemoryStream
Writing 4096 bytes to MemoryStream
Writing 1815 bytes to MemoryStream
Reading 256 bytes from UpsideDownJpegStream                         <== REST service reading UpsideDownJpegStream
Reading 256 bytes from MemoryStream                                 <== UpsideDownJpegStream reading MemoryStream
Reading 4096 bytes from UpsideDownJpegStream
Reading 4096 bytes from MemoryStream
Reading 65536 bytes from UpsideDownJpegStream
Reading 65536 bytes from MemoryStream
Reading 65536 bytes from UpsideDownJpegStream
Reading 65536 bytes from MemoryStream
 

3. Streaming video

Streaming movies works like explained above : open the movie as a FileStream, return the stream via WCF. To play it in a browser, apply the Content-Type: "video/x-ms-wmv". If you use the TraceFileStream class, you will see the traces of the call to the Read() method while playing the movie.

 
[OperationContract]
[WebGet(UriTemplate = "/getmovie")]
Stream GetMovie();

public Stream GetMovie()
{
    OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
    context.ContentType = "video/x-ms-wmv";
    return new TraceFileStream(@"E:\Downloads\movie.wmv", FileMode.Open);
}

IErrorHandler: A generic Fault Converter (1/2)

In WCF, methods communicate error information by means of SOAP faults. These SOAP faults are message types which are part of the metadata of your service contracts:  service operations declare the possible faults by using FaultContracts.

[ServiceContract] 
public interface IOrderMgrService 
{ 
    [OperationContract] 
    [FaultContract(typeof(Faulty))] 
    string GetData(int value); 
} 

[DataContract] 
public class Faulty 
{ 
    [DataMember] 
    public string ErrorMessage { get; set; } 
}

 

In .NET applications, errors are represented by Exception objects. So, to travel the exception from the server to the client, one needs to map Exception objects to SOAP faults.

The problem with this approach is of course : how do you map exceptions to faults. You are probably going to define multiple FaultContracts which you need to define on all the operation contracts. So first, every operation will contain a big try…catch statement to map existing .NET exceptions into faults. And secondly, an operation can only expose those faults that are applied in the contract.

public string GetData(int value) 
{ 
    try 
    { 
        int divider = 0; 
        int restult = value / divider; 
    } 
    catch (DivideByZeroException ex) 
    { 
        throw new FaultException<Faulty>(new Faulty() { ErrorMessage = ex.Message }, 
            "GetData failed"); 
    } 

    return string.Format("You entered: {0}", value); 
}
 

A generic solution for this is implementing an ErrorHandler: create a class that implements IErrorHandler and implement both HandleError and ProvideFault.

The ProvideFault() method is called by any exception - a CLR exception or a fault -  that occurs in your operation. The error property contains the exception that occurred, the fault property will contain a fault if the exception is already converted into a fault (so you can check wethether it is null or not).

HandleError() takes the exception : this is execute on a seperate thread. Definitely the right place to add logging or tracing.

public class MyErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
        return false; 
    } 

    public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault) 
    { 
       if (fault != null) 
           return; 

       if (error.GetType()== typeof(DivideByZeroException)) 
       { 
           FaultException<Faulty> f = new FaultException<Faulty>(new Faulty() { ErrorMessage = error.Message }, 
               "GetData failed"); 

           fault = Message.CreateMessage( 
                   version, 
                   f.CreateMessageFault(), 
                   f.Action); 
       } 
    }
    ...
 

An ErrorHandler is installed as a ServiceBehavior by registering it per ChannelDispatcher. The easiest way is to make your ErrorHander class an attribute and implement the IServiceBehavior interface on it.

public class MyErrorHandler : Attribute, IErrorHandler, IServiceBehavior 
{
   ...
 

The ApplyDispatchBehavior method passes a reference to the service host, which you can use to iterate over the different ChannelDispatchers in order to add your ErrorHander to the ErrorHandlers collection.

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
  System.ServiceModel.ServiceHostBase serviceHostBase) 
{ 
  foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers) 
  { 
    disp.ErrorHandlers.Add(this); 
  } 
}


Extensions to get attribute information

Checking attributes on classes can be done by getting the type of the class and executing GetCustomAttributes() on it. You just need to iterate over the resulting object[] to find what you are interested in.

To simplify this a bit more, I wrote a couple of extension methods :

    static public class AttributeExtensions
    {
        static public T FindAttribute<T>(this object obj)
            where T : Attribute
        {
            return obj.GetType().GetCustomAttributes(true)
                .Where(attr => attr.GetType() == typeof(T))
                .Select(attr => attr as T).FirstOrDefault();
        }

        static public List<Attribute> GetAttributes(this object obj)
        {
            return obj.GetType().GetCustomAttributes(true).ConvertAllItems(c => c as Attribute).ToList();
        }

        static private IEnumerable<TOutput> ConvertAllItems<TInput, TOutput>(this IEnumerable<TInput> e, 
            Converter<TInput, TOutput> op)
        {
            foreach (TInput item in e)
            {
                yield return op(item);
            }
        }
    }
 

So, on a Person class like this

    [DataContract(Namespace="http://www.u2u.be/demo/entities")]
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    Person p = new Person() { Name = "John Doe", Age = 77 } ;

You can now find the DataContractAttribute by:

    DataContractAttribute attribute = p.FindAttribute<DataContractAttribute>();
    Console.WriteLine(attribute != null ? attribute.Namespace : "Attribute not found");
 

Or, to retrieve the list of attributes:

    List<Attribute> lst = p.GetAttributes();

IErrorHandler: A generic Fault Converter (2/2)

My previous post IErrorHandler: A generic Fault Converter (1/2) describes how to build an ErrorHandler for WCF. The challenge is now to write a generic ErrorHander which can be configured to automatically convert exceptions into faults based upon a pre-defined list of converter methods. Converting an exception into a fault is one thing, but we need to be careful that we only return those faults that the operation contract defines (by means of FaultContract attributes)

Lets first focus on the implementation of the converter : we need a delegate definition for a method that takes any Exception as input and that converts this into a Fault. Faults are just classes that have a DataContract attribute (or even without when trusting on POCO support introduced in .NET 3.5 SP1). Since there isn’t any base class for FaultContracts, let’s define the type as generic.

public delegate TFault FaultConverter<TFault>(Exception e);



The converter maintains a Dictionary of exception types as keys and FaultConverter<TFault> delegates as values. We need to be able to add new converter methods and execute the converter method that suits the exception type.

public class ExceptionToFaultConverter
{
  private Dictionary<Type, Delegate> lst = new Dictionary<Type, Delegate>();

  public void AddConverter<TException, TFault>(FaultConverter<TFault> converter)
  {
    lst.Add(typeof(TException), converter);
  }

  public object Convert(Exception ex)
  {
    if (lst.ContainsKey(ex.GetType()))
    {
     return lst[ex.GetType()].DynamicInvoke(ex);
    }

    return null;
  }
}
 
Adding a converter just looks like this :
 
faultConverter.AddConverter<DivideByZeroException, Faulty>(e => new Faulty() { ErrorMessage = e.Message });

 

During ProvideFault(), theFautlConverter will convert the Exception info a fault (if any). Next thing to to is checking if we can return this fault for the current operation.

  public class MyErrorHandler : Attribute, IErrorHandler, IServiceBehavior
  {
    ExceptionToFaultConverter faultConverter =new ExceptionToFaultConverter();

    public MyErrorHandler()
    {
      faultConverter.AddConverter<DivideByZeroException, Faulty>(
        e => new Faulty() { ErrorMessage = e.Message }
        );
    }

    public bool HandleError(Exception error)
    {
      return false;
    }

    public void ProvideFault(Exception error, 
      System.ServiceModel.Channels.MessageVersion version, 
      ref System.ServiceModel.Channels.Message fault)
    {      
      ServiceDescription description = OperationContext.Current.Host.Description;      
      ServiceEndpoint endpoint = description.Endpoints.Find(OperationContext.Current.IncomingMessageHeaders.To);
      
      string operationName =OperationContext.Current.IncomingMessageHeaders.Action.Replace(
        endpoint.Contract.Namespace + endpoint.Contract.Name + "/", "");
      OperationDescription operation =endpoint.Contract.Operations.Find(operationName);

      object faulttype = faultConverter.Convert(error);
      if (faulttype == null)
          return;

      foreach (FaultDescription faultdescription in operation.Faults)
      {
          if (faultdescription.DetailType.IsAssignableFrom(faulttype.GetType()))
          {
              fault = Message.CreateMessage(
                  version,
                  FaultCode.CreateSenderFaultCode(
                          faultdescription.Name, 
                          faultdescription.Namespace),
                  faulttype.ToString(),
                  faulttype,
                  faultdescription.Action);
              break;
          }
      }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase, 
      System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
      System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase)
    {
      foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)
      {
        disp.ErrorHandlers.Add(this);
      }
    }

    public void Validate(ServiceDescription serviceDescription, 
      System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }
  }


Receive the U2U Newsletter. Submit your email address:
 
 


 


Search

rss  RSS

Categories

Tags

None

    Recent posts

    Blogroll