@@ -284,6 +284,43 @@ public int getMaxSessions() {
284
284
}
285
285
}
286
286
287
+ /**
288
+ * Safely parse an integer value for max-sessions with validation and logging. Guards against
289
+ * NumberFormatException and ensures the value is positive.
290
+ *
291
+ * @param value the string value to parse
292
+ * @param defaultValue the default value to use if parsing fails or value is invalid
293
+ * @param context descriptive context for logging (e.g., "driver config", "node config")
294
+ * @return a valid positive integer, or the default value if parsing fails
295
+ */
296
+ private static int parseMaxSessionsSafely (String value , int defaultValue , String context ) {
297
+ if (value == null || value .trim ().isEmpty ()) {
298
+ LOG .log (
299
+ Level .WARNING ,
300
+ "Max-sessions value is null or empty for {0}, using default: {1}" ,
301
+ new Object [] {context , defaultValue });
302
+ return defaultValue ;
303
+ }
304
+
305
+ try {
306
+ int parsedValue = Integer .parseInt (value .trim ());
307
+ if (parsedValue <= 0 ) {
308
+ LOG .log (
309
+ Level .WARNING ,
310
+ "Max-sessions value {0} is not positive for {1}, using default: {2}" ,
311
+ new Object [] {parsedValue , context , defaultValue });
312
+ return defaultValue ;
313
+ }
314
+ return parsedValue ;
315
+ } catch (NumberFormatException e ) {
316
+ LOG .log (
317
+ Level .WARNING ,
318
+ "Invalid max-sessions value ''{0}'' for {1}, using default: {2}. Error: {3}" ,
319
+ new Object [] {value , context , defaultValue , e .getMessage ()});
320
+ return defaultValue ;
321
+ }
322
+ }
323
+
287
324
/**
288
325
* Calculate the actual max-sessions per driver config based on the current configuration. This
289
326
* method ensures consistency between getMaxSessions() and actual session allocation.
@@ -323,8 +360,10 @@ private Map<String, Integer> calculateActualMaxSessionsPerDriverConfig() {
323
360
for (Map <String , String > configMap : configList ) {
324
361
String displayName = configMap .get ("display-name" );
325
362
int driverMaxSessions =
326
- Integer .parseInt (
327
- configMap .getOrDefault ("max-sessions" , String .valueOf (nodeMaxSessions )));
363
+ parseMaxSessionsSafely (
364
+ configMap .get ("max-sessions" ),
365
+ nodeMaxSessions ,
366
+ "driver config '" + displayName + "'" );
328
367
result .put (displayName , driverMaxSessions );
329
368
}
330
369
} else {
@@ -342,7 +381,11 @@ private Map<String, Integer> calculateActualMaxSessionsPerDriverConfig() {
342
381
343
382
// Check if driver config has explicit max-sessions within allowed range
344
383
if (configMap .containsKey ("max-sessions" )) {
345
- int explicitMaxSessions = Integer .parseInt (configMap .get ("max-sessions" ));
384
+ int explicitMaxSessions =
385
+ parseMaxSessionsSafely (
386
+ configMap .get ("max-sessions" ),
387
+ sessionsPerDriverConfig ,
388
+ "driver config '" + displayName + "' explicit max-sessions" );
346
389
if (explicitMaxSessions >= 1 && explicitMaxSessions <= sessionsPerDriverConfig ) {
347
390
driverMaxSessions = explicitMaxSessions ;
348
391
}
@@ -427,14 +470,37 @@ private Map<WebDriverInfo, Integer> calculateOptimizedCpuDistribution(List<WebDr
427
470
// Then distribute remaining cores among flexible drivers
428
471
if (flexibleDrivers .size () > 0 && remainingCores > 0 ) {
429
472
int sessionsPerFlexibleDriver = Math .max (1 , remainingCores / flexibleDrivers .size ());
430
- for (WebDriverInfo info : flexibleDrivers ) {
431
- sessionsPerDriver .put (info , sessionsPerFlexibleDriver );
473
+ int remainderCores = remainingCores % flexibleDrivers .size ();
474
+
475
+ // Distribute base sessions to all flexible drivers
476
+ for (int i = 0 ; i < flexibleDrivers .size (); i ++) {
477
+ WebDriverInfo info = flexibleDrivers .get (i );
478
+ int sessions = sessionsPerFlexibleDriver ;
479
+
480
+ // Distribute remainder cores to the first 'remainderCores' drivers
481
+ if (i < remainderCores ) {
482
+ sessions ++;
483
+ }
484
+
485
+ sessionsPerDriver .put (info , sessions );
432
486
}
487
+
488
+ LOG .log (
489
+ Level .FINE ,
490
+ "Distributed {0} cores among {1} flexible drivers: {2} base sessions each, "
491
+ + "{3} drivers get +1 extra session" ,
492
+ new Object [] {
493
+ remainingCores , flexibleDrivers .size (), sessionsPerFlexibleDriver , remainderCores
494
+ });
433
495
} else if (flexibleDrivers .size () > 0 ) {
434
496
// No remaining cores, give each flexible driver 1 session
435
497
for (WebDriverInfo info : flexibleDrivers ) {
436
498
sessionsPerDriver .put (info , 1 );
437
499
}
500
+ LOG .log (
501
+ Level .FINE ,
502
+ "No remaining cores available, assigning 1 session to each of {0} flexible drivers" ,
503
+ flexibleDrivers .size ());
438
504
}
439
505
440
506
return sessionsPerDriver ;
0 commit comments