Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Command.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System.Text;
4 using SiliconStudio.Core;
5 using SiliconStudio.Core.Storage;
6 using SiliconStudio.Core.Serialization;
7 using SiliconStudio.Core.Serialization.Assets;
8 using System;
9 using System.Collections.Generic;
10 using System.IO;
11 using System.Reflection;
12 using System.Threading;
13 using System.Threading.Tasks;
14 
15 namespace SiliconStudio.BuildEngine
16 {
17  [DataContract(Inherited = true)]
18  public abstract class Command
19  {
20  /// <summary>
21  /// The command cache version, should be bumped when binary serialization format changes (so that cache gets invalidated)
22  /// </summary>
23  protected const int CommandCacheVersion = 1;
24 
25  /// <summary>
26  /// Title (short description) of the command
27  /// </summary>
28  public abstract string Title { get; }
29 
30  /// <summary>
31  /// List every tag created by the command. The first item of each entry is the <see cref="TagSymbol.Name"/> of the <see cref="TagSymbol"/>, The second item is the pattern or a description of the <see cref="TagSymbol.RealName"/>
32  /// </summary>
33  [DataMemberIgnore]
34  public virtual IEnumerable<Tuple<string, string>> TagList { get { yield break; } }
35 
36  /// <summary>
37  /// Safeguard to ensure inheritance will always call base.PreCommand
38  /// </summary>
39  internal bool BasePreCommandCalled = false;
40 
41  /// <summary>
42  /// Safeguard to ensure inheritance will always call base.PostCommand
43  /// </summary>
44  internal bool BasePostCommandCalled = false;
45 
46  /// <summary>
47  /// Cancellation Token. Must be checked frequently by the <see cref="DoCommandOverride"/> implementation in order to interrupt the command while running
48  /// </summary>
49  protected internal CancellationToken CancellationToken;
50 
51  /// <summary>
52  /// List
53  /// </summary>
54  protected internal Dictionary<string, TagSymbol> TagSymbols = new Dictionary<string, TagSymbol>();
55 
56  /// <summary>
57  /// The method to override containing the actual command code. It is called by the <see cref="DoCommand"/> function
58  /// </summary>
59  /// <param name="commandContext"></param>
60  protected abstract Task<ResultStatus> DoCommandOverride(ICommandContext commandContext);
61 
62  /// <summary>
63  /// The method that indirectly call <see cref="DoCommandOverride"/> to execute the actual command code.
64  /// It is called by the current <see cref="Builder"/> when the command is triggered
65  /// </summary>
66  /// <param name="commandContext"></param>
68  {
69  if (CancellationToken.IsCancellationRequested)
70  return Task.FromResult(ResultStatus.Cancelled);
71 
72  return DoCommandOverride(commandContext);
73  }
74 
75  public virtual void PreCommand(ICommandContext commandContext)
76  {
77  // Safeguard, will throw an exception if a inherited command does not call base.PreCommand
78  BasePreCommandCalled = true;
79  }
80 
81  public virtual void PostCommand(ICommandContext commandContext, ResultStatus status)
82  {
83  // Safeguard, will throw an exception if a inherited command does not call base.PostCommand
84  BasePostCommandCalled = true;
85  }
86 
87  public Command Clone()
88  {
89  var copy = (Command)Activator.CreateInstance(GetType());
90  foreach (PropertyInfo property in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
91  {
92  if (property.GetSetMethod() != null)
93  {
94  var value = property.GetValue(this);
95  property.SetValue(copy, value);
96  }
97  }
98  return copy;
99  }
100 
101  /// <inheritdoc/>
102  public abstract override string ToString();
103 
104  /// <summary>
105  /// Gets the list of input files (that can be deduced without running the command, only from command parameters).
106  /// </summary>
107  /// <returns></returns>
109  {
110  yield break;
111  }
112 
113  /// <summary>
114  /// Check some conditions that determine if the command should be executed. This method may not be called if some previous check determinated that it already needs to be executed.
115  /// </summary>
116  /// <returns>true if the command should be executed</returns>
117  public virtual bool ShouldForceExecution()
118  {
119  return false;
120  }
121 
122  public virtual bool ShouldSpawnNewProcess()
123  {
124  return false;
125  }
126 
127  /// <summary>
128  /// Callback called by <see cref="Builder.CancelBuild"/>. It can be useful for commands in a blocking call that can be unblocked from here.
129  /// </summary>
130  public virtual void Cancel()
131  {
132  // Do nothing by default
133  }
134 
135  protected virtual void ComputeParameterHash(BinarySerializationWriter writer)
136  {
137  // Do nothing by default
138  }
139 
140  protected void ComputeInputFilesHash(BinarySerializationWriter writer, IPrepareContext prepareContext)
141  {
142  var inputFiles = GetInputFiles();
143  if (inputFiles == null)
144  return;
145 
146  foreach (var inputFile in inputFiles)
147  {
148  var hash = prepareContext.ComputeInputHash(inputFile.Type, inputFile.Path);
149  if (hash == ObjectId.Empty)
150  {
151  writer.NativeStream.WriteByte(0);
152  }
153  else
154  {
155  writer.NativeStream.Write((byte[])hash, 0, ObjectId.HashSize);
156  }
157  }
158  }
159 
160  public void ComputeCommandHash(Stream stream, IPrepareContext prepareContext)
161  {
162  var writer = new BinarySerializationWriter(stream);
163 
164  writer.Write(CommandCacheVersion);
165 
166  // Compute assembly hash
167  ComputeAssemblyHash(writer);
168 
169  // Compute parameters hash
170  ComputeParameterHash(writer);
171 
172  // Compute static input files hash (parameter dependent)
173  ComputeInputFilesHash(writer, prepareContext);
174  }
175 
176  protected virtual void ComputeAssemblyHash(BinarySerializationWriter writer)
177  {
178  // Use binary format version (bumping it forces everything to be reevaluated)
179  writer.Write(DataSerializer.BinaryFormatVersion);
180 
181  // Gets the hash of the assembly of the command
182  writer.Write(AssemblyHash.ComputeAssemblyHash(GetType().Assembly));
183  }
184 
185  protected TagSymbol RegisterTag(string name, Func<string> getValue)
186  {
187  var tagSymbol = new TagSymbol(name, getValue);
188  TagSymbols.Add(name, tagSymbol);
189  return tagSymbol;
190  }
191 
192  internal ObjectId ComputeCommandHash(IPrepareContext prepareContext)
193  {
194  var stream = new DigestStream(Stream.Null);
195 
196  ComputeCommandHash(stream, prepareContext);
197 
198  return stream.CurrentHash;
199  }
200  }
201 }
virtual void PreCommand(ICommandContext commandContext)
Definition: Command.cs:75
virtual bool ShouldSpawnNewProcess()
Definition: Command.cs:122
virtual void ComputeAssemblyHash(BinarySerializationWriter writer)
Definition: Command.cs:176
Task< ResultStatus > DoCommand(ICommandContext commandContext)
The method that indirectly call DoCommandOverride to execute the actual command code. It is called by the current Builder when the command is triggered
Definition: Command.cs:67
virtual void PostCommand(ICommandContext commandContext, ResultStatus status)
Definition: Command.cs:81
virtual void ComputeParameterHash(BinarySerializationWriter writer)
Definition: Command.cs:135
virtual bool ShouldForceExecution()
Check some conditions that determine if the command should be executed. This method may not be called...
Definition: Command.cs:117
Implements SerializationStream as a binary writer.
virtual void Cancel()
Callback called by Builder.CancelBuild. It can be useful for commands in a blocking call that can be ...
Definition: Command.cs:130
ResultStatus
Status of a command.
Definition: ResultStatus.cs:8
TagSymbol RegisterTag(string name, Func< string > getValue)
Definition: Command.cs:185
void ComputeCommandHash(Stream stream, IPrepareContext prepareContext)
Definition: Command.cs:160
virtual IEnumerable< ObjectUrl > GetInputFiles()
Gets the list of input files (that can be deduced without running the command, only from command para...
Definition: Command.cs:108
static readonly ObjectId Empty
Definition: ObjectId.cs:15
A hash to uniquely identify data.
Definition: ObjectId.cs:13
void ComputeInputFilesHash(BinarySerializationWriter writer, IPrepareContext prepareContext)
Definition: Command.cs:140