Merge lp:~mandel/ubuntuone-windows-installer/implement_db_port_manager into lp:ubuntuone-windows-installer/beta
- implement_db_port_manager
- Merge into beta
Proposed by
Manuel de la Peña
Status: | Merged |
---|---|
Approved by: | Vincenzo Di Somma |
Approved revision: | 49 |
Merged at revision: | 66 |
Proposed branch: | lp:~mandel/ubuntuone-windows-installer/implement_db_port_manager |
Merge into: | lp:ubuntuone-windows-installer/beta |
Prerequisite: | lp:~mandel/ubuntuone-windows-installer/implement_dotnet_ipc_events |
Diff against target: |
469 lines (+303/-4) 8 files modified
.bzrignore (+1/-0) src/Canonical.UbuntuOne.ProcessDispatcher.Tests/App.config (+50/-0) src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Canonical.UbuntuOne.ProcessDispatcher.Tests.csproj (+20/-0) src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Net/PortManagerFixture.cs (+15/-0) src/Canonical.UbuntuOne.ProcessDispatcher.Tests/SetUpClass.cs (+43/-0) src/Canonical.UbuntuOne.ProcessDispatcher/App.config (+9/-2) src/Canonical.UbuntuOne.ProcessDispatcher/Canonical.UbuntuOne.ProcessDispatcher.csproj (+8/-0) src/Canonical.UbuntuOne.ProcessDispatcher/Net/PortManager.cs (+157/-2) |
To merge this branch: | bzr merge lp:~mandel/ubuntuone-windows-installer/implement_db_port_manager |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincenzo Di Somma (community) | Approve | ||
Rick McBride (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
Provides an implementation of the port manager that stores the relation between a user and a port in a SQLite db. This allows to ensure that the same port is always used when assigned so that the system admin can allow exceptions in the Windows firewall (either the OS one or a 3 party one)
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2010-08-10 12:42:54 +0000 |
3 | +++ .bzrignore 2010-08-18 10:05:56 +0000 |
4 | @@ -27,3 +27,4 @@ |
5 | src/UbuntuOneClient.Tests/bin |
6 | src/UbuntuOneClient.Tests/obj |
7 | *.ReSharper |
8 | +test-results |
9 | |
10 | === added directory 'lib/SQLite' |
11 | === added file 'lib/SQLite/System.Data.SQLite.DLL' |
12 | Binary files lib/SQLite/System.Data.SQLite.DLL 1970-01-01 00:00:00 +0000 and lib/SQLite/System.Data.SQLite.DLL 2010-08-18 10:05:56 +0000 differ |
13 | === added file 'src/Canonical.UbuntuOne.ProcessDispatcher.Tests/App.config' |
14 | --- src/Canonical.UbuntuOne.ProcessDispatcher.Tests/App.config 1970-01-01 00:00:00 +0000 |
15 | +++ src/Canonical.UbuntuOne.ProcessDispatcher.Tests/App.config 2010-08-18 10:05:56 +0000 |
16 | @@ -0,0 +1,50 @@ |
17 | +<?xml version="1.0"?> |
18 | +<configuration> |
19 | + <configSections> |
20 | + <sectionGroup name="spring"> |
21 | + <section name="parsers" |
22 | + type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" /> |
23 | + <section name="context" |
24 | + type="Spring.Context.Support.ContextHandler, Spring.Core"/> |
25 | + <section name="objects" |
26 | + type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> |
27 | + </sectionGroup> |
28 | + <sectionGroup name="common"> |
29 | + <section name="logging" |
30 | + type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /> |
31 | + </sectionGroup> |
32 | + </configSections> |
33 | + |
34 | + <!-- logging configuration --> |
35 | + <common> |
36 | + <logging> |
37 | + <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net"> |
38 | + <!-- choices are INLINE, FILE, FILE-WATCH, EXTERNAL--> |
39 | + <!-- otherwise BasicConfigurer.Configure is used --> |
40 | + <!-- log4net configuration file is specified with key configFile--> |
41 | + <arg key="configType" |
42 | + value="FILE" /> |
43 | + <arg key="configFile" |
44 | + value="~/Config/log4net.config" /> |
45 | + </factoryAdapter> |
46 | + </logging> |
47 | + </common> |
48 | + |
49 | + <!-- Spring configuration --> |
50 | + <spring> |
51 | + <parsers> |
52 | + <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> |
53 | + </parsers> |
54 | + <context> |
55 | + <resource uri="config://spring/objects"/> |
56 | + </context> |
57 | + <objects xmlns="http://www.springframework.net" |
58 | + xmlns:db="http://www.springframework.net/database"> |
59 | + <!-- most internal objects definition is in the embeded objects.xml file here you will just find the db configuration --> |
60 | + <db:provider id="DbProvider" |
61 | + provider="SQLite-1.0.65" |
62 | + connectionString="Data Source=UbuntuOne.db;Version=3;FailIfMissing=False;Compress=True"/> |
63 | + </objects> |
64 | + </spring> |
65 | + <startup/> |
66 | +</configuration> |
67 | |
68 | === modified file 'src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Canonical.UbuntuOne.ProcessDispatcher.Tests.csproj' |
69 | --- src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Canonical.UbuntuOne.ProcessDispatcher.Tests.csproj 2010-08-18 10:05:56 +0000 |
70 | +++ src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Canonical.UbuntuOne.ProcessDispatcher.Tests.csproj 2010-08-18 10:05:56 +0000 |
71 | @@ -65,6 +65,7 @@ |
72 | <Compile Include="Protobuf\SyncDaemonMessageFactoryFixture.cs" /> |
73 | <Compile Include="Protobuf\SyncFolderMessageFactoryFixture.cs" /> |
74 | <Compile Include="Protobuf\SyncShareMessageFactoryFixture.cs" /> |
75 | + <Compile Include="SetUpClass.cs" /> |
76 | <Compile Include="SyncConfigurationServiceFixture.cs" /> |
77 | <Compile Include="SyncDaemonServiceFixture.cs" /> |
78 | <Compile Include="SyncFoldersServiceFixture.cs" /> |
79 | @@ -81,6 +82,10 @@ |
80 | </ProjectReference> |
81 | </ItemGroup> |
82 | <ItemGroup> |
83 | + <Reference Include="Common.Logging.Log4Net, Version=1.2.0.2, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL"> |
84 | + <SpecificVersion>False</SpecificVersion> |
85 | + <HintPath>..\..\lib\Spring.Net\Common.Logging.Log4Net.dll</HintPath> |
86 | + </Reference> |
87 | <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> |
88 | <SpecificVersion>False</SpecificVersion> |
89 | <HintPath>..\..\lib\log4net\log4net.dll</HintPath> |
90 | @@ -97,11 +102,23 @@ |
91 | <SpecificVersion>False</SpecificVersion> |
92 | <HintPath>..\..\lib\RhinoMocks\Rhino.Mocks.dll</HintPath> |
93 | </Reference> |
94 | + <Reference Include="Spring.Core, Version=1.3.0.20349, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL"> |
95 | + <SpecificVersion>False</SpecificVersion> |
96 | + <HintPath>..\..\lib\Spring.Net\Spring.Core.dll</HintPath> |
97 | + </Reference> |
98 | + <Reference Include="Spring.Data, Version=1.3.0.20349, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL"> |
99 | + <SpecificVersion>False</SpecificVersion> |
100 | + <HintPath>..\..\lib\Spring.Net\Spring.Data.dll</HintPath> |
101 | + </Reference> |
102 | <Reference Include="System" /> |
103 | <Reference Include="System.Core"> |
104 | <RequiredTargetFramework>3.5</RequiredTargetFramework> |
105 | </Reference> |
106 | <Reference Include="System.Data" /> |
107 | + <Reference Include="System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86"> |
108 | + <SpecificVersion>False</SpecificVersion> |
109 | + <HintPath>..\..\lib\SQLite\System.Data.SQLite.DLL</HintPath> |
110 | + </Reference> |
111 | <Reference Include="System.Xml" /> |
112 | </ItemGroup> |
113 | <ItemGroup> |
114 | @@ -121,6 +138,9 @@ |
115 | <Install>false</Install> |
116 | </BootstrapperPackage> |
117 | </ItemGroup> |
118 | + <ItemGroup> |
119 | + <None Include="App.config" /> |
120 | + </ItemGroup> |
121 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
122 | <ProjectExtensions> |
123 | <MonoDevelop> |
124 | |
125 | === modified file 'src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Net/PortManagerFixture.cs' |
126 | --- src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Net/PortManagerFixture.cs 2010-08-12 07:59:15 +0000 |
127 | +++ src/Canonical.UbuntuOne.ProcessDispatcher.Tests/Net/PortManagerFixture.cs 2010-08-18 10:05:56 +0000 |
128 | @@ -18,9 +18,12 @@ |
129 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> |
130 | */ |
131 | using Canonical.UbuntuOne.Common; |
132 | +using Canonical.UbuntuOne.Common.Container; |
133 | using Canonical.UbuntuOne.ProcessDispatcher.Net; |
134 | using NUnit.Framework; |
135 | using Rhino.Mocks; |
136 | +using Spring.Data.Common; |
137 | +using Spring.Data.Core; |
138 | |
139 | namespace Canonical.UbuntuOne.ProcessDispatcher.Tests.Net |
140 | { |
141 | @@ -33,6 +36,7 @@ |
142 | private IAuthentication _auth; |
143 | private PortManager _portManager; |
144 | private MockRepository _mocks; |
145 | + private IDbProvider _dbProvider; |
146 | |
147 | #endregion |
148 | |
149 | @@ -44,15 +48,26 @@ |
150 | _mocks = new MockRepository(); |
151 | _portFinder = _mocks.StrictMock<IPortFinder>(); |
152 | _auth = _mocks.StrictMock<IAuthentication>(); |
153 | + _dbProvider = ObjectsContainer.GetImplementationOf<IDbProvider>(); |
154 | _portManager = PortManager.Instance; |
155 | _portManager.Authentication = _auth; |
156 | _portManager.PortFinder = _portFinder; |
157 | + _portManager.DbProvider = _dbProvider; |
158 | } |
159 | |
160 | [TearDown] |
161 | public void TearDown() |
162 | { |
163 | _portManager.Clear(); |
164 | + // Clear the db |
165 | + var template = new AdoTemplate(_dbProvider); |
166 | + template.Execute( |
167 | + command => |
168 | + { |
169 | + command.CommandText = string.Format("DELETE FROM {0};", PortManager.UserPortsTableName); |
170 | + return command.ExecuteScalar(); |
171 | + } |
172 | + ); |
173 | } |
174 | |
175 | #endregion |
176 | |
177 | === added file 'src/Canonical.UbuntuOne.ProcessDispatcher.Tests/SetUpClass.cs' |
178 | --- src/Canonical.UbuntuOne.ProcessDispatcher.Tests/SetUpClass.cs 1970-01-01 00:00:00 +0000 |
179 | +++ src/Canonical.UbuntuOne.ProcessDispatcher.Tests/SetUpClass.cs 2010-08-18 10:05:56 +0000 |
180 | @@ -0,0 +1,43 @@ |
181 | +/* |
182 | + * Copyright 2010 Canonical Ltd. |
183 | + * |
184 | + * This file is part of UbuntuOne on Windows. |
185 | + * |
186 | + * UbuntuOne on Windows is free software: you can redistribute it and/or modify |
187 | + * it under the terms of the GNU Lesser General Public License version |
188 | + * as published by the Free Software Foundation. |
189 | + * |
190 | + * Ubuntu One on Windows is distributed in the hope that it will be useful, |
191 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
192 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
193 | + * GNU Lesser General Public License for more details. |
194 | + * |
195 | + * You should have received a copy of the GNU Lesser General Public License |
196 | + * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>. |
197 | + * |
198 | + * Authors: Manuel de la Peña <manuel.delapena@canonical.com> |
199 | + */ |
200 | +using Canonical.UbuntuOne.Common.Container; |
201 | +using NUnit.Framework; |
202 | + |
203 | +namespace Canonical.UbuntuOne.ProcessDispatcher.Tests |
204 | +{ |
205 | + /// <summary> |
206 | + /// Set up class ran before any test to be able to use the IoC from xml |
207 | + /// </summary> |
208 | + [SetUpFixture] |
209 | + public class SetUpClass |
210 | + { |
211 | + [SetUp] |
212 | + public void Setup() |
213 | + { |
214 | + ObjectsContainer.Initialize(new SpringContainer()); |
215 | + } |
216 | + |
217 | + [TearDown] |
218 | + public void TearDown() |
219 | + { |
220 | + ObjectsContainer.Clear(); |
221 | + } |
222 | + } |
223 | +} |
224 | |
225 | === modified file 'src/Canonical.UbuntuOne.ProcessDispatcher/App.config' |
226 | --- src/Canonical.UbuntuOne.ProcessDispatcher/App.config 2010-07-26 15:55:00 +0000 |
227 | +++ src/Canonical.UbuntuOne.ProcessDispatcher/App.config 2010-08-18 10:05:56 +0000 |
228 | @@ -32,11 +32,18 @@ |
229 | |
230 | <!-- Spring configuration --> |
231 | <spring> |
232 | + <parsers> |
233 | + <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> |
234 | + </parsers> |
235 | <context> |
236 | <resource uri="assembly://Canonical.UbuntuOne.ProcessDispatcher/Canonical.UbuntuOne.ProcessDispatcher/objects.xml" /> |
237 | </context> |
238 | - <objects xmlns="http://www.springframework.net"> |
239 | - <!-- most internal objects definition is in the embeded objects.xml file --> |
240 | + <objects xmlns="http://www.springframework.net" |
241 | + xmlns:db="http://www.springframework.net/database"> |
242 | + <!-- most internal objects definition is in the embeded objects.xml file here you will just find the db configuration --> |
243 | + <db:provider id="DbProvider" |
244 | + provider="SQLite-1.0.65" |
245 | + connectionString="Data Source=UbuntuOne.db;Version=3;FailIfMissing=False;Compress=True"/> |
246 | </objects> |
247 | </spring> |
248 | |
249 | |
250 | === modified file 'src/Canonical.UbuntuOne.ProcessDispatcher/Canonical.UbuntuOne.ProcessDispatcher.csproj' |
251 | --- src/Canonical.UbuntuOne.ProcessDispatcher/Canonical.UbuntuOne.ProcessDispatcher.csproj 2010-08-18 10:05:56 +0000 |
252 | +++ src/Canonical.UbuntuOne.ProcessDispatcher/Canonical.UbuntuOne.ProcessDispatcher.csproj 2010-08-18 10:05:56 +0000 |
253 | @@ -127,6 +127,14 @@ |
254 | <SpecificVersion>False</SpecificVersion> |
255 | <HintPath>..\..\lib\log4net\log4net.dll</HintPath> |
256 | </Reference> |
257 | + <Reference Include="Spring.Core, Version=1.3.0.20349, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL"> |
258 | + <SpecificVersion>False</SpecificVersion> |
259 | + <HintPath>..\..\lib\Spring.Net\Spring.Core.dll</HintPath> |
260 | + </Reference> |
261 | + <Reference Include="Spring.Data, Version=1.3.0.20349, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL"> |
262 | + <SpecificVersion>False</SpecificVersion> |
263 | + <HintPath>..\..\lib\Spring.Net\Spring.Data.dll</HintPath> |
264 | + </Reference> |
265 | <Reference Include="Spring.Services, Version=1.3.0.20214, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL"> |
266 | <SpecificVersion>False</SpecificVersion> |
267 | <HintPath>..\..\lib\Spring.Net\Spring.Services.dll</HintPath> |
268 | |
269 | === modified file 'src/Canonical.UbuntuOne.ProcessDispatcher/Net/PortManager.cs' |
270 | --- src/Canonical.UbuntuOne.ProcessDispatcher/Net/PortManager.cs 2010-08-12 07:59:15 +0000 |
271 | +++ src/Canonical.UbuntuOne.ProcessDispatcher/Net/PortManager.cs 2010-08-18 10:05:56 +0000 |
272 | @@ -17,14 +17,19 @@ |
273 | * |
274 | * Authors: Manuel de la Peña <manuel.delapena@canonical.com> |
275 | */ |
276 | +using System; |
277 | using System.Collections.Generic; |
278 | +using System.Data; |
279 | using Canonical.UbuntuOne.Common; |
280 | +using Spring.Data.Common; |
281 | +using Spring.Data.Core; |
282 | |
283 | namespace Canonical.UbuntuOne.ProcessDispatcher.Net |
284 | { |
285 | /// <summary> |
286 | /// Implementation of the IPortManager that keeps track of the ports assigned to the different users and ensures that |
287 | - /// there are correctly managed. |
288 | + /// there are correctly managed. The port manager create a sqlite db that will be used to ensure that a user |
289 | + /// allw |
290 | /// </summary> |
291 | internal class PortManager : IPortManager |
292 | { |
293 | @@ -67,6 +72,8 @@ |
294 | |
295 | private readonly object _dictionaryLock = new object(); |
296 | private readonly Dictionary<string, UserPorts> _ports; |
297 | + internal const string UserPortsTableName = "UserPorts"; |
298 | + private bool _usetTableExists; |
299 | |
300 | #endregion |
301 | |
302 | @@ -82,6 +89,12 @@ |
303 | /// </summary> |
304 | internal IPortFinder PortFinder { get; set; } |
305 | |
306 | + /// <summary> |
307 | + /// Gets and sets the provider that the port manager uses to store the relation between a user and the |
308 | + /// ports he use in the application. |
309 | + /// </summary> |
310 | + internal IDbProvider DbProvider { get; set; } |
311 | + |
312 | #endregion |
313 | |
314 | #region Helpers |
315 | @@ -93,11 +106,153 @@ |
316 | { |
317 | lock (_dictionaryLock) |
318 | { |
319 | - var userPorts = new UserPorts(PortFinder.GetFreePort(), PortFinder.GetFreePort()); |
320 | + // we check if the table exists, this can happe either the first time we start in the system |
321 | + // and the table does not exists or when we reboot and we lost the info of the flag. Ofcourse the |
322 | + // the table could have been drop at some point |
323 | + if(!_usetTableExists) |
324 | + { |
325 | + var reallyExists = UserPortsTableExists(); |
326 | + if(!reallyExists) |
327 | + { |
328 | + CreateUserPortsTable(); |
329 | + } |
330 | + _usetTableExists = true; |
331 | + } |
332 | + int dotNetPort; |
333 | + int pythonPort; |
334 | + // we try to get the data from the db |
335 | + if(!TryGetUserPortFromDb(Authentication.Username, out pythonPort, out dotNetPort)) |
336 | + { |
337 | + // we cannot get the ports, therefore we generate them. |
338 | + pythonPort = PortFinder.GetFreePort(); |
339 | + dotNetPort = PortFinder.GetFreePort(); |
340 | + // store the user ports in the db for the next time |
341 | + InserUserPortsInDb(Authentication.Username, pythonPort, dotNetPort); |
342 | + } |
343 | + var userPorts = new UserPorts(pythonPort, dotNetPort); |
344 | _ports.Add(Authentication.Username, userPorts); |
345 | } |
346 | } |
347 | |
348 | + |
349 | + /// <summary> |
350 | + /// Helper method that returns if the table that stores the user name and ports relation is |
351 | + /// present in the db. |
352 | + /// </summary> |
353 | + /// <returns>A boolean value stating if the UserPorts table is present in the db.</returns> |
354 | + private bool UserPortsTableExists() |
355 | + { |
356 | + // query the sqlite schema using and ado template |
357 | + var template = new AdoTemplate(DbProvider); |
358 | + var result = template.Execute( |
359 | + command => |
360 | + { |
361 | + command.CommandText = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=:tableName;"; |
362 | + var parameter = command.CreateParameter(); |
363 | + parameter.ParameterName = ":tableName"; |
364 | + parameter.Value = UserPortsTableName; |
365 | + command.Parameters.Add(parameter); |
366 | + var count = command.ExecuteScalar(); |
367 | + return (long)count != 0; |
368 | + } |
369 | + ); |
370 | + |
371 | + return (bool)result; |
372 | + } |
373 | + |
374 | + /// <summary> |
375 | + /// Helper method that will create the user porst table in the db when needed. |
376 | + /// </summary> |
377 | + private void CreateUserPortsTable() |
378 | + { |
379 | + // create the table using an ado template. |
380 | + var template = new AdoTemplate(DbProvider); |
381 | + template.ExecuteNonQuery( CommandType.Text, |
382 | + String.Format("CREATE TABLE IF NOT EXISTS {0}('Username' TEXT PRIMARY KEY, 'PythonPort' INT, 'DotNetPort' INT);", |
383 | + UserPortsTableName)); |
384 | + } |
385 | + |
386 | + /// <summary> |
387 | + /// Helper method that adds a new pair of ports for a user in the db. |
388 | + /// </summary> |
389 | + /// <param name="username">The name of the user whose ports we are going to insert.</param> |
390 | + /// <param name="pythonPort">The port to be used to talk to python.</param> |
391 | + /// <param name="dotNetPort">The port to be used to talk to dotNet.</param> |
392 | + private void InserUserPortsInDb(string username, int pythonPort, int dotNetPort) |
393 | + { |
394 | + var template = new AdoTemplate(DbProvider); |
395 | + template.Execute( |
396 | + command => |
397 | + { |
398 | + command.CommandText = String.Format( |
399 | + "INSERT INTO {0}(Username, PythonPort, DotNetPort) VALUES (:username, :pythonPort, :dotNetPort)", |
400 | + UserPortsTableName); |
401 | + var usernameParam = command.CreateParameter(); |
402 | + usernameParam.ParameterName = ":username"; |
403 | + usernameParam.Value = username; |
404 | + command.Parameters.Add(usernameParam); |
405 | + |
406 | + var pythonParam = command.CreateParameter(); |
407 | + pythonParam.ParameterName = ":pythonPort"; |
408 | + pythonParam.Value = pythonPort; |
409 | + command.Parameters.Add(pythonParam); |
410 | + |
411 | + var dotNetParam = command.CreateParameter(); |
412 | + dotNetParam.ParameterName = ":dotNetPort"; |
413 | + dotNetParam.Value = dotNetPort; |
414 | + command.Parameters.Add(dotNetParam); |
415 | + |
416 | + return command.ExecuteScalar(); |
417 | + } |
418 | + ); |
419 | + } |
420 | + |
421 | + /// <summary> |
422 | + /// Helper method that allows to retrieve the ports of a user from the db. If the data cannot be retrieved from |
423 | + /// the db. |
424 | + /// </summary> |
425 | + /// <param name="username">The username whose ports we want to retrieve.</param> |
426 | + /// <param name="pythonPort">Out parameter used to return the port used to talk with python.</param> |
427 | + /// <param name="dotNetPort">Out parameter used to return the port used to talk with dot net.</param> |
428 | + /// <returns>A boolean flag that indicates if the data could have been retrieved from the db.</returns> |
429 | + private bool TryGetUserPortFromDb(string username, out int pythonPort, out int dotNetPort) |
430 | + { |
431 | + // try to get the ports from the db, if it is not possible we return false |
432 | + var template = new AdoTemplate(DbProvider); |
433 | + try |
434 | + { |
435 | + var userPorts = (UserPorts)template.Execute( |
436 | + command => |
437 | + { |
438 | + command.CommandText = |
439 | + String.Format("SELECT PythonPort, DotNetPort FROM {0} WHERE Username=:username;", |
440 | + UserPortsTableName); |
441 | + var parameter = command.CreateParameter(); |
442 | + parameter.ParameterName = ":username"; |
443 | + parameter.Value = username; |
444 | + command.Parameters.Add(parameter); |
445 | + var reader = command.ExecuteReader(); |
446 | + while (reader.Read()) |
447 | + { |
448 | + return new UserPorts(System.Convert.ToInt32((long) reader["PythonPort"]), |
449 | + System.Convert.ToInt32((long) reader["DotNetPort"])); |
450 | + } |
451 | + return new UserPorts(-1, -1); |
452 | + } |
453 | + ); |
454 | + pythonPort = userPorts.PythonPort; |
455 | + dotNetPort = userPorts.DotNetPort; |
456 | + return false; |
457 | + } |
458 | + catch(Exception) |
459 | + { |
460 | + // an exception will be thrown if we cannot get the data from the db, therefore we return false |
461 | + pythonPort = -1; |
462 | + dotNetPort = -1; |
463 | + return false; |
464 | + } |
465 | + } |
466 | + |
467 | #endregion |
468 | |
469 | #region Constructors |
Looks good, tests pass. +1