4
4
// Created by: Denis Krjuchkov
5
5
// Created: 2009.08.20
6
6
7
- using System ;
8
7
using System . Collections . Generic ;
9
8
using System . Linq ;
10
9
using System . Threading ;
@@ -17,7 +16,7 @@ namespace Xtensive.Orm.Providers
17
16
internal sealed class BatchingCommandProcessor : CommandProcessor , ISqlTaskProcessor
18
17
{
19
18
private readonly int batchSize ;
20
- private readonly Queue < SqlTask > tasks ;
19
+ private Queue < SqlTask > tasks ;
21
20
22
21
void ISqlTaskProcessor . ProcessTask ( SqlLoadTask task , CommandProcessorContext context )
23
22
{
@@ -61,8 +60,17 @@ public override void ExecuteTasks(CommandProcessorContext context)
61
60
_ = ExecuteBatch ( batchSize , null , context ) ;
62
61
}
63
62
64
- while ( ! context . AllowPartialExecution && context . ProcessingTasks . Count > 0 ) {
65
- _ = ExecuteBatch ( context . ProcessingTasks . Count , null , context ) ;
63
+ var allowPartialExecution = context . AllowPartialExecution ;
64
+ while ( context . ProcessingTasks . Count > 0 ) {
65
+ if ( allowPartialExecution ) {
66
+ //re-register task
67
+ RegisterTask ( context . ProcessingTasks . Dequeue ( ) ) ;
68
+ }
69
+ else {
70
+ _ = context . ProcessingTasks . Count > batchSize
71
+ ? ExecuteBatch ( batchSize , null , context )
72
+ : ExecuteBatch ( context . ProcessingTasks . Count , null , context ) ;
73
+ }
66
74
}
67
75
}
68
76
@@ -74,8 +82,17 @@ public override async Task ExecuteTasksAsync(CommandProcessorContext context, Ca
74
82
_ = await ExecuteBatchAsync ( batchSize , null , context , token ) . ConfigureAwait ( false ) ;
75
83
}
76
84
77
- while ( ! context . AllowPartialExecution && context . ProcessingTasks . Count > 0 ) {
78
- _ = await ExecuteBatchAsync ( context . ProcessingTasks . Count , null , context , token ) . ConfigureAwait ( false ) ;
85
+ var allowPartialExecution = context . AllowPartialExecution ;
86
+ while ( context . ProcessingTasks . Count > 0 ) {
87
+ if ( allowPartialExecution ) {
88
+ //re-register task
89
+ RegisterTask ( context . ProcessingTasks . Dequeue ( ) ) ;
90
+ }
91
+ else {
92
+ _ = await ( ( context . ProcessingTasks . Count > batchSize )
93
+ ? ExecuteBatchAsync ( batchSize , null , context , token )
94
+ : ExecuteBatchAsync ( context . ProcessingTasks . Count , null , context , token ) ) ;
95
+ }
79
96
}
80
97
}
81
98
@@ -88,8 +105,9 @@ public override IEnumerator<Tuple> ExecuteTasksWithReader(QueryRequest request,
88
105
_ = ExecuteBatch ( batchSize , null , context ) ;
89
106
}
90
107
91
- for ( ; ; ) {
92
- var result = ExecuteBatch ( context . ProcessingTasks . Count , request , context ) ;
108
+ for ( ; ; ) {
109
+ var currentBatchSize = ( context . ProcessingTasks . Count > batchSize ) ? batchSize : context . ProcessingTasks . Count ;
110
+ var result = ExecuteBatch ( currentBatchSize , request , context ) ;
93
111
if ( result != null && context . ProcessingTasks . Count == 0 ) {
94
112
return result . AsReaderOf ( request ) ;
95
113
}
@@ -106,7 +124,8 @@ public override async Task<IEnumerator<Tuple>> ExecuteTasksWithReaderAsync(Query
106
124
}
107
125
108
126
for ( ; ; ) {
109
- var result = await ExecuteBatchAsync ( context . ProcessingTasks . Count , request , context , token ) . ConfigureAwait ( false ) ;
127
+ var currentBatchSize = ( context . ProcessingTasks . Count > batchSize ) ? batchSize : context . ProcessingTasks . Count ;
128
+ var result = await ExecuteBatchAsync ( currentBatchSize , request , context , token ) . ConfigureAwait ( false ) ;
110
129
if ( result != null && context . ProcessingTasks . Count == 0 ) {
111
130
return result . AsReaderOf ( request ) ;
112
131
}
@@ -117,21 +136,20 @@ public override async Task<IEnumerator<Tuple>> ExecuteTasksWithReaderAsync(Query
117
136
118
137
private Command ExecuteBatch ( int numberOfTasks , QueryRequest lastRequest , CommandProcessorContext context )
119
138
{
120
- if ( numberOfTasks == 0 && lastRequest == null ) {
139
+ if ( numberOfTasks == 0 && lastRequest == null ) {
121
140
return null ;
122
141
}
123
142
124
- var tasksToProcess = context . ProcessingTasks ;
125
-
126
143
AllocateCommand ( context ) ;
127
144
128
145
var shouldReturnReader = false ;
146
+ var tasksToProcess = context . ProcessingTasks ;
129
147
try {
130
148
while ( numberOfTasks > 0 && tasksToProcess . Count > 0 ) {
131
149
var task = tasksToProcess . Peek ( ) ;
132
150
context . CurrentTask = task ;
133
151
task . ProcessWith ( this , context ) ;
134
- if ( context . CurrentTask == null ) {
152
+ if ( context . CurrentTask == null ) {
135
153
numberOfTasks -- ;
136
154
_ = tasksToProcess . Dequeue ( ) ;
137
155
}
@@ -148,15 +166,18 @@ private Command ExecuteBatch(int numberOfTasks, QueryRequest lastRequest, Comman
148
166
}
149
167
}
150
168
151
- if ( context . ActiveCommand . Count == 0 ) {
169
+ if ( context . ActiveCommand . Count == 0 ) {
152
170
return null ;
153
171
}
172
+
154
173
var hasQueryTasks = context . ActiveTasks . Count > 0 ;
174
+
155
175
if ( ! hasQueryTasks && ! shouldReturnReader ) {
156
176
_ = context . ActiveCommand . ExecuteNonQuery ( ) ;
157
177
return null ;
158
178
}
159
179
context . ActiveCommand . ExecuteReader ( ) ;
180
+
160
181
if ( hasQueryTasks ) {
161
182
var currentQueryTask = 0 ;
162
183
while ( currentQueryTask < context . ActiveTasks . Count ) {
@@ -182,15 +203,14 @@ private Command ExecuteBatch(int numberOfTasks, QueryRequest lastRequest, Comman
182
203
183
204
private async Task < Command > ExecuteBatchAsync ( int numberOfTasks , QueryRequest lastRequest , CommandProcessorContext context , CancellationToken token )
184
205
{
185
- if ( numberOfTasks == 0 && lastRequest == null ) {
206
+ if ( numberOfTasks == 0 && lastRequest == null ) {
186
207
return null ;
187
208
}
188
209
189
- var tasksToProcess = context . ProcessingTasks ;
190
-
191
210
AllocateCommand ( context ) ;
192
211
193
212
var shouldReturnReader = false ;
213
+ var tasksToProcess = context . ProcessingTasks ;
194
214
try {
195
215
while ( numberOfTasks > 0 && tasksToProcess . Count > 0 ) {
196
216
var task = tasksToProcess . Peek ( ) ;
@@ -212,9 +232,10 @@ private async Task<Command> ExecuteBatchAsync(int numberOfTasks, QueryRequest la
212
232
}
213
233
}
214
234
215
- if ( context . ActiveCommand . Count == 0 ) {
235
+ if ( context . ActiveCommand . Count == 0 ) {
216
236
return null ;
217
237
}
238
+
218
239
var hasQueryTasks = context . ActiveTasks . Count > 0 ;
219
240
if ( ! hasQueryTasks && ! shouldReturnReader ) {
220
241
_ = await context . ActiveCommand . ExecuteNonQueryAsync ( token ) . ConfigureAwait ( false ) ;
@@ -259,7 +280,7 @@ private void ExecuteUnbatchedTask(SqlPersistTask task)
259
280
var sequence = Factory . CreatePersistParts ( task ) ;
260
281
foreach ( var part in sequence ) {
261
282
using ( var command = Factory . CreateCommand ( ) ) {
262
- ValidateCommandParameters ( part ) ;
283
+ ValidateCommandPartParameters ( part ) ;
263
284
command . AddPart ( part ) ;
264
285
var affectedRowsCount = command . ExecuteNonQuery ( ) ;
265
286
if ( affectedRowsCount == 0 ) {
@@ -273,19 +294,15 @@ private void ExecuteUnbatchedTask(SqlPersistTask task)
273
294
private void PutTasksForExecution ( CommandProcessorContext context )
274
295
{
275
296
if ( context . AllowPartialExecution ) {
276
- context . ProcessingTasks = new Queue < SqlTask > ( ) ;
277
- var batchesCount = ( int ) tasks . Count / batchSize ;
278
- if ( batchesCount == 0 ) {
279
- return ;
280
- }
281
- context . ProcessingTasks = new Queue < SqlTask > ( ) ;
282
- while ( context . ProcessingTasks . Count < batchesCount * batchSize ) {
297
+ var processingTasksCount = tasks . Count / batchSize * batchSize ;
298
+ context . ProcessingTasks = new Queue < SqlTask > ( processingTasksCount ) ;
299
+ while ( context . ProcessingTasks . Count < processingTasksCount ) {
283
300
context . ProcessingTasks . Enqueue ( tasks . Dequeue ( ) ) ;
284
301
}
285
302
}
286
303
else {
287
- context . ProcessingTasks = new Queue < SqlTask > ( tasks ) ;
288
- tasks . Clear ( ) ;
304
+ context . ProcessingTasks = tasks ;
305
+ tasks = new Queue < SqlTask > ( batchSize ) ;
289
306
}
290
307
}
291
308
@@ -304,13 +321,6 @@ private bool PendCommandParts(Command currentCommand, ICollection<CommandPart> p
304
321
: true ;
305
322
}
306
323
307
- private void ValidateCommandParameters ( CommandPart commandPart )
308
- {
309
- if ( GetCommandExecutionBehavior ( new [ ] { commandPart } , 0 ) == ExecutionBehavior . TooLargeForAnyCommand ) {
310
- throw new ParametersLimitExceededException ( commandPart . Parameters . Count , MaxQueryParameterCount ) ;
311
- }
312
- }
313
-
314
324
private static string GetParameterPrefix ( CommandProcessorContext context ) =>
315
325
string . Format ( "p{0}_" , context . ActiveCommand . Count + 1 ) ;
316
326
0 commit comments