DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
ConnectionClient.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Data;
21 
23 using Deveel.Data.Protocol;
24 using Deveel.Data.Sql;
26 
27 using IsolationLevel = Deveel.Data.Transactions.IsolationLevel;
28 
29 namespace Deveel.Data.Client {
30  internal class ConnectionClient : IDisposable {
31  public DeveelDbConnectionStringBuilder Settings { get; private set; }
32 
34 
35  public IClientConnector Connector { get; private set; }
36 
37  private bool OwnsConnector { get; set; }
38 
39  public IMessageProcessor Processor { get; private set; }
40 
41  private IDictionary<string, object> serverMetadata;
42 
44  Settings = settings;
45  }
46 
48  if (connector == null)
49  throw new ArgumentNullException("connector");
50 
51  Settings = settings;
52  Connector = connector;
53  Processor = connector.CreateProcessor();
54  OwnsConnector = false;
55  }
56 
58  Dispose(false);
59  }
60 
61  public bool IsClosed { get; private set; }
62 
63  public string ServerVersion { get; private set; }
64 
66  throw new NotSupportedException();
67  }
68 
70  if (Connector != null)
71  return Connector;
72 
73  IConfiguration configuration = null;
74 
75  /*
76  TODO:
77  if (IsInMemory(Settings.DataSource) && controlDatabase == null) {
78  if (controlSystem == null)
79  controlSystem = CreateEmbeddedControlSystem();
80 
81  // TODO: handle the case the connection string does not specify a database name
82  var databaseName = Settings.Database;
83  if (String.IsNullOrEmpty(databaseName))
84  throw new InvalidOperationException();
85 
86  Configuration = new Configuration(controlSystem.Config);
87  Configuration.DatabaseName(databaseName);
88 
89  var defaultSchema = Settings.Schema;
90  if (!String.IsNullOrEmpty(defaultSchema))
91  Configuration.DefaultSchema(defaultSchema);
92 
93  controlDatabase = controlSystem.ControlDatabase(databaseName);
94  } else if (IsInFileSystem(Settings) && controlDatabase == null) {
95  if (controlSystem == null)
96  controlSystem = CreateEmbeddedControlSystem();
97 
98  // TODO: handle the case the connection string does not specify a database name
99  var databaseName = Settings.Database;
100  if (String.IsNullOrEmpty(databaseName))
101  throw new InvalidOperationException();
102 
103  Configuration = new Configuration(controlSystem.Config);
104  Configuration.StorageSystem(ConfigDefaultValues.FileStorageSystem);
105 
106  var dbPath = settings.DataSource;
107  if (String.Equals(dbPath, "local", StringComparison.OrdinalIgnoreCase))
108  dbPath = settings.Path;
109  if (String.IsNullOrEmpty(dbPath))
110  dbPath = databaseName;
111 
112  Configuration.DatabasePath(dbPath);
113 
114  var defaultSchema = settings.Schema;
115  if (!String.IsNullOrEmpty(defaultSchema))
116  Configuration.DefaultSchema(defaultSchema);
117 
118 
119  controlDatabase = controlSystem.ControlDatabase(databaseName);
120  } else if (controlDatabase == null) {
121  return CreateNetworkConnector();
122  }
123 
124  if (controlDatabase != null)
125  return CreateLocalDatabaseConnector(Configuration);
126 
127  throw new InvalidOperationException("Unable to create a connector to the database");
128  */
129 
130  throw new NotImplementedException();
131  }
132 
133  private IMessage SendMessage(IMessage message) {
134  var envelope = Connector.CreateEnvelope(serverMetadata, message);
135  var response = Processor.ProcessMessage(envelope);
136  if (response == null)
137  throw new InvalidOperationException("The processor returned no response.");
138 
139  if (response.Error != null)
140  throw new DeveelDbServerException(response.Error.ErrorMessage, response.Error.ErrorClass, response.Error.ErrorCode);
141 
142  serverMetadata = response.Metadata;
143  return response.Message;
144  }
145 
147  var properties = new Dictionary<string, object>();
148  var en = ((IDictionary)Settings).GetEnumerator();
149  while (en.MoveNext()) {
150  var current = en.Entry;
151  properties.Add((string)current.Key, current.Value);
152  }
153 
154  return Connector.MakeEndPoint(properties);
155  }
156 
157  public void Connect() {
158  if (Connector == null) {
159  Connector = CreateConnector();
160  Processor = Connector.CreateProcessor();
161  }
162 
163  remoteEndPoint = MakeRemoteEndPoint();
164 
165  var request = new ConnectRequest(Connector.LocalEndPoint, remoteEndPoint) {
166  DatabaseName = Settings.Database,
167  Timeout = Settings.QueryTimeout,
168  IgnoreIdentifiersCase = Settings.IgnoreIdentifiersCase,
169  ParameterStyle = Settings.ParameterStyle,
170  AutoCommit = Settings.AutoCommit
171  };
172 
173  var response = SendMessage(request) as ConnectResponse;
174  if (response == null)
175  throw new ProtocolException("The returned message is invalid");
176 
177  if (!response.Opened)
178  throw new DeveelDbServerException("Was not able to open the connection on the server.", -1, -1);
179 
180  if (response.IsEncryted)
181  Connector.SetEncrypton(response.EncryptionData);
182 
183  IsClosed = false;
184  ServerVersion = response.Version;
185  }
186 
187  public void Disconnect() {
188  try {
189  var response = SendMessage(new CloseRequest())
191 
192  if (response == null)
193  throw new InvalidOperationException();
194 
195  if (!response.State)
196  throw new DeveelDbServerException("Unable to close the connection on the server.", -1, -1);
197  } finally {
198  IsClosed = true;
199  }
200  }
201 
202  public bool Authenticate() {
203  var response = SendMessage(new AuthenticateRequest(Settings.Schema, Settings.UserName, Settings.Password))
205 
206  if (response == null)
207  throw new InvalidOperationException();
208 
209  return response.Authenticated;
210  }
211 
212  public IQueryResponse[] ExecuteQuery(int commitId, SqlQuery query) {
213  var response = SendMessage(new QueryExecuteRequest(commitId, query))
215 
216  if (response == null)
217  throw new InvalidOperationException();
218 
219  return response.QueryResponse;
220  }
221 
222  public QueryResultPart GetResultPart(int resultId, int rowIndex, int count) {
223  var response = SendMessage(new QueryResultPartRequest(resultId, rowIndex, count))
225 
226  if (response == null)
227  throw new InvalidOperationException();
228 
229  return response.Part;
230  }
231 
232  public void DisposeResult(int resultId) {
233  var response = SendMessage(new DisposeResultRequest(resultId))
235 
236  if (response == null)
237  throw new InvalidOperationException();
238 
239  if (!response.State)
240  throw new DeveelDbServerException(null, -1, -1);
241  }
242 
243  public int BeginTransaction(System.Data.IsolationLevel isolationLevel) {
244  var isolation = MapIsolationLevel(isolationLevel);
245  return BeginTransaction(isolation);
246  }
247 
248  private IsolationLevel MapIsolationLevel(System.Data.IsolationLevel isolationLevel) {
249  if (isolationLevel == System.Data.IsolationLevel.Serializable)
250  return IsolationLevel.Serializable;
251  if (isolationLevel == System.Data.IsolationLevel.Snapshot)
252  return IsolationLevel.Snapshot;
253  if (isolationLevel == System.Data.IsolationLevel.ReadCommitted)
254  return IsolationLevel.ReadCommitted;
255  if (isolationLevel == System.Data.IsolationLevel.ReadUncommitted)
256  return IsolationLevel.ReadUncommitted;
257 
258  throw new NotSupportedException(String.Format("Isolation Level '{0}' not supported by DeveelDB", isolationLevel));
259  }
260 
261  public int BeginTransaction(IsolationLevel isolationLevel) {
262  var response = SendMessage(new BeginRequest(isolationLevel))
263  as BeginResponse;
264 
265  if (response == null)
266  throw new InvalidOperationException();
267 
268  return response.CommitId;
269  }
270 
271  public void CommitTransaction(int transactionId) {
272  var response = SendMessage(new CommitRequest(transactionId))
274 
275  if (response == null)
276  throw new InvalidOperationException();
277 
278  if (!response.State)
279  throw new DeveelDbServerException("Unable to commit the transaction on the server.", -1, -1);
280  }
281 
282  public void RollbackTransaction(int transactionId) {
283  var response = SendMessage(new RollbackRequest(transactionId))
285 
286  if (response == null)
287  throw new InvalidOperationException();
288 
289  if (!response.State)
290  throw new DeveelDbServerException("Unable to rollback the transaction on the server.", -1, -1);
291 
292  }
293 
294  public void DisposeLargeObject(long objId) {
295  var response = SendMessage(new LargeObjectDisposeRequest(objId))
297 
298  if (response == null)
299  throw new InvalidOperationException();
300 
301  if (!response.State)
302  throw new InvalidOperationException("Unable to dispose the large object on the server.");
303  }
304 
305  public void Dispose() {
306  Dispose(true);
307  GC.SuppressFinalize(this);
308  }
309 
310  private void Dispose(bool disposing) {
311  if (disposing) {
312  if (OwnsConnector && Connector != null) {
313  Connector.Dispose();
314  }
315  }
316 
317  Connector = null;
318  }
319  }
320 }
IMessageProcessor CreateProcessor()
This processes _queries from a client and dispatches the _queries to the database.
Definition: Processor.cs:41
int BeginTransaction(System.Data.IsolationLevel isolationLevel)
IDictionary< string, object > serverMetadata
The response to a command executed via the IDatabaseInterface.ExecuteQuery method in the IDatabaseInt...
void CommitTransaction(int transactionId)
IMessage SendMessage(IMessage message)
ConnectionClient(IClientConnector connector, DeveelDbConnectionStringBuilder settings)
IQueryResponse[] ExecuteQuery(int commitId, SqlQuery query)
IsolationLevel MapIsolationLevel(System.Data.IsolationLevel isolationLevel)
Defines the contract for the configuration node of a component within the system or of the system its...
QueryResultPart GetResultPart(int resultId, int rowIndex, int count)
int BeginTransaction(IsolationLevel isolationLevel)
ConnectionClient(DeveelDbConnectionStringBuilder settings)
void RollbackTransaction(int transactionId)