File `Storage.cs` has 546 lines of code (exceeds 250 allowed). Consider refactoring.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
using Optuna.Study;
using Optuna.Trial;
namespace Optuna.Storage.Journal
{
Class `JournalStorage` has 35 methods (exceeds 20 allowed). Consider refactoring.
public class JournalStorage : IOptunaStorage
{
private readonly Dictionary<int, Study.Study> _studies = new Dictionary<int, Study.Study>();
private readonly Dictionary<int, Trial.Trial> _trialCache = new Dictionary<int, Trial.Trial>();
private readonly Dictionary<string, int> _studyNameToIdIndex = new Dictionary<string, int>();
private readonly object _initLock = new object();
private readonly string _filePath;
private int _nextStudyId;
private int _trialId;
private bool _isInitialized;
private bool _isInitialing;
public JournalStorage(string path, bool createIfNotExist = false)
{
if (File.Exists(path) == false)
{
if (createIfNotExist == false)
{
throw new FileNotFoundException($"File not found: {path}");
}
else
{
File.Create(path).Close();
_isInitialized = true;
}
}
_filePath = path;
}
private void EnsureInitialized()
{
if (_isInitialized || _isInitialing)
{
return;
}
lock (_initLock)
{
if (_isInitialized || _isInitialing)
{
return;
}
_isInitialing = true;
LoadDataFromFile();
_isInitialized = true;
_isInitialing = false;
}
}
Method `LoadDataFromFile` has 29 lines of code (exceeds 25 allowed). Consider refactoring.
private void LoadDataFromFile()
{
const int BufferSize = 65536;
var jsonBatch = new List<string>(1000);
using (var fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, BufferSize))
{
using (var sr = new StreamReader(fs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
jsonBatch.Add(line);
if (jsonBatch.Count >= 1000)
{
ProcessJsonBatch(jsonBatch);
jsonBatch.Clear();
}
}
if (jsonBatch.Count > 0)
{
ProcessJsonBatch(jsonBatch);
}
}
BuildIndices();
}
}
private void BuildIndices()
{
foreach (Study.Study study in _studies.Values)
{
_studyNameToIdIndex[study.StudyName] = study.StudyId;
}
foreach (Study.Study study in _studies.Values)
{
foreach (Trial.Trial trial in study.Trials)
{
_trialCache[trial.TrialId] = trial;
}
}
}
private void ProcessJsonBatch(List<string> jsonBatch)
{
foreach (string json in jsonBatch)
{
var logObject = JObject.Parse(json);
var opCode = (JournalOperation)Enum.ToObject(typeof(JournalOperation), (int)logObject["op_code"]);
ProcessLogEntry(opCode, logObject);
}
}
Method `ProcessLogEntry` has a Cognitive Complexity of 52 (exceeds 20 allowed). Consider refactoring.
Method `ProcessLogEntry` has 139 lines of code (exceeds 25 allowed). Consider refactoring.
private void ProcessLogEntry(JournalOperation opCode, JObject logObject)
{
switch (opCode)
{
case JournalOperation.CreateStudy:
{
StudyDirection[] studyDirections = logObject["directions"].ToObject<StudyDirection[]>();
string studyName = logObject["study_name"].ToString();
CreateNewStudy(studyDirections, studyName);
break;
}
case JournalOperation.DeleteStudy:
{
int studyId = (int)logObject["study_id"];
DeleteStudy(studyId);
break;
}
Similar blocks of code found in 2 locations. Consider refactoring.
case JournalOperation.SetStudyUserAttr:
{
int studyId = (int)logObject["study_id"];
var userAttr = (JObject)logObject["user_attr"];
foreach (KeyValuePair<string, JToken> item in userAttr)
{
string[] values = item.Value.Select(v => v.ToString()).ToArray();
if (values == null || values.Length == 0)
{
values = new string[] { item.Value.ToString() };
}
SetStudyUserAttr(studyId, item.Key, values);
}
break;
}
Similar blocks of code found in 2 locations. Consider refactoring.
case JournalOperation.SetStudySystemAttr:
{
int studyId = (int)logObject["study_id"];
var systemAttr = (JObject)logObject["system_attr"];
foreach (KeyValuePair<string, JToken> item in systemAttr)
{
string[] values = item.Value.Select(v => v.ToString()).ToArray();
if (values == null || values.Length == 0)
{
values = new string[] { item.Value.ToString() };
}
SetStudySystemAttr(studyId, item.Key, values);
}
break;
}
case JournalOperation.CreateTrial:
{
int studyId = (int)logObject["study_id"];
Trial.Trial trial;
if (logObject["datetime_complete"] == null)
{
trial = new Trial.Trial();
JToken start = logObject["datetime_start"];
if (start != null && start.HasValues)
{
trial.DatetimeStart = (DateTime)start;
}
CreateNewTrial(studyId, trial);
}
else
{
Dictionary<string, object> trialParams = logObject["params"].ToObject<Dictionary<string, object>>();
var trialParamsWithType = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> item in trialParams)
{
switch (item.Value)
{
case double d:
trialParamsWithType[item.Key] = d;
break;
case string s:
trialParamsWithType[item.Key] = s;
break;
case int i:
trialParamsWithType[item.Key] = i;
break;
default:
trialParamsWithType[item.Key] = item.Value;
break;
}
}
var values = new List<double>();
foreach (JToken value in logObject["values"])
{
values.Add(value.ToObject<double>());
}
if (logObject["value"].Type != JTokenType.Null)
{
values.Add((double)logObject["value"]);
}
trial = new Trial.Trial
{
Values = values.ToArray(),
Params = trialParamsWithType,
State = (TrialState)Enum.ToObject(typeof(TrialState), (int)logObject["state"]),
DatetimeStart = (DateTime)logObject["datetime_start"],
DatetimeComplete = (DateTime)logObject["datetime_complete"],
};
CreateNewTrial(studyId, trial);
SetTrialSystemAttrFromJObject(trial.TrialId, (JObject)logObject["system_attrs"]);
SetTrialUserAttrFromJObject(trial.TrialId, (JObject)logObject["user_attrs"]);
}
break;
}
case JournalOperation.SetTrialParam:
{
int trialId = (int)logObject["trial_id"];
string paramName = (string)logObject["param_name"];
double paramValueInternal = (double)logObject["param_value_internal"];
SetTrailParam(trialId, paramName, paramValueInternal, null);
break;
}
case JournalOperation.SetTrialStateValues:
{
int trialId = (int)logObject["trial_id"];
double[] trialValues = logObject["values"].Select(v => v.ToObject<double>()).ToArray();
var trialState = (TrialState)Enum.ToObject(typeof(TrialState), (int)logObject["state"]);
SetTrialStateValue(trialId, trialState, trialValues);
break;
}
case JournalOperation.SetTrialIntermediateValue:
break;
Similar blocks of code found in 2 locations. Consider refactoring.
case JournalOperation.SetTrialUserAttr:
{
int trialId = (int)logObject["trial_id"];
var userAttr = (JObject)logObject["user_attr"];
SetTrialUserAttrFromJObject(trialId, userAttr);
break;
}
Similar blocks of code found in 2 locations. Consider refactoring.
case JournalOperation.SetTrialSystemAttr:
{
int trialId = (int)logObject["trial_id"];
var systemAttr = (JObject)logObject["system_attr"];
SetTrialSystemAttrFromJObject(trialId, systemAttr);
break;
}
}
}
Similar blocks of code found in 2 locations. Consider refactoring.
private void SetTrialSystemAttrFromJObject(int trialId, JObject systemAttr)
{
foreach (KeyValuePair<string, JToken> item in systemAttr)
{
string[] values = item.Value.Select(v => v.ToString()).ToArray();
if (values == null || values.Length == 0)
{
values = new string[] { item.Value.ToString() };
}
SetTrialSystemAttr(trialId, item.Key, values);
}
}
Similar blocks of code found in 2 locations. Consider refactoring.
private void SetTrialUserAttrFromJObject(int trialId, JObject userAttr)
{
foreach (KeyValuePair<string, JToken> item in userAttr)
{
string[] values = item.Value.Select(v => v.ToString()).ToArray();
if (values == null || values.Length == 0)
{
values = new string[] { item.Value.ToString() };
}
SetTrialUserAttr(trialId, item.Key, values);
}
}
public void CheckTrialIsUpdatable(int trialId, TrialState trialState)
{
throw new NotImplementedException();
}
public int CreateNewStudy(StudyDirection[] studyDirections, string studyName = "")
{
EnsureInitialized();
if (!_studyNameToIdIndex.ContainsKey(studyName))
{
var study = new Study.Study(this, _nextStudyId, studyName, studyDirections);
_studies.Add(_nextStudyId, study);
_studyNameToIdIndex[studyName] = _nextStudyId;
_nextStudyId++;
}
return _nextStudyId;
}
public int CreateNewTrial(int studyId, Trial.Trial templateTrial = null)
{
EnsureInitialized();
Trial.Trial trial = templateTrial ?? new Trial.Trial();
trial.TrialId = _trialId++;
trial.Number = _studies[studyId].Trials.Count;
_studies[studyId].Trials.Add(trial);
_trialCache[trial.TrialId] = trial;
return _trialId;
}
public void DeleteStudy(int studyId)
{
EnsureInitialized();
if (_studies.TryGetValue(studyId, out Study.Study study))
{
foreach (Trial.Trial trial in study.Trials)
{
_trialCache.Remove(trial.TrialId);
}
_studyNameToIdIndex.Remove(study.StudyName);
_studies.Remove(studyId);
}
}
public Study.Study[] GetAllStudies()
{
EnsureInitialized();
return _studies.Values.ToArray();
}
public Trial.Trial[] GetAllTrials(int studyId, bool deepcopy = true)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.Trials.ToArray();
}
public Trial.Trial GetBestTrial(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
var allTrials = study.Trials.Where(trial => trial.State == TrialState.COMPLETE).ToList();
if (allTrials.Count == 0)
{
return null;
}
StudyDirection[] directions = study.Directions;
if (directions.Length != 1)
{
throw new InvalidOperationException("Study is multi-objective.");
}
Identical blocks of code found in 2 locations. Consider refactoring.
if (directions[0] == StudyDirection.Maximize)
{
return allTrials.OrderByDescending(trial => trial.Values[0]).First();
}
else
{
return allTrials.OrderBy(trial => trial.Values[0]).First();
}
}
public int GetNTrials(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.Trials.Count;
}
public StudyDirection[] GetStudyDirections(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.Directions;
}
public int GetStudyIdFromName(string studyName)
{
EnsureInitialized();
if (_studyNameToIdIndex.TryGetValue(studyName, out int studyId))
{
return studyId;
}
throw new KeyNotFoundException($"Study with name '{studyName}' not found.");
}
Similar blocks of code found in 2 locations. Consider refactoring.
public string GetStudyNameFromId(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.StudyName;
}
Similar blocks of code found in 2 locations. Consider refactoring.
public Dictionary<string, object> GetStudySystemAttrs(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.SystemAttrs;
}
Similar blocks of code found in 2 locations. Consider refactoring.
public Dictionary<string, object> GetStudyUserAttrs(int studyId)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
return study.UserAttrs;
}
public Trial.Trial GetTrial(int trialId)
{
EnsureInitialized();
if (_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
return trial;
}
return _studies.Values.First(s => s.Trials.Any(t => t.TrialId == trialId))
.Trials.First(t => t.TrialId == trialId);
}
public int GetTrialIdFromStudyIdTrialNumber(int studyId, int trialNumber)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
Trial.Trial trial = study.Trials.FirstOrDefault(t => t.Number == trialNumber);
if (trial == null)
{
throw new KeyNotFoundException($"Trial with number '{trialNumber}' not found in study '{studyId}'.");
}
return trial.TrialId;
}
Similar blocks of code found in 2 locations. Consider refactoring.
public int GetTrialNumberFromId(int trialId)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID '{trialId}' not found.");
}
return trial.Number;
}
public double GetTrialParam(int trialId, string paramName)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
if (!trial.Params.TryGetValue(paramName, out object paramValue))
{
throw new KeyNotFoundException($"Parameter '{paramName}' not found in trial {trialId}.");
}
return (double)paramValue;
}
Similar blocks of code found in 3 locations. Consider refactoring.
public Dictionary<string, object> GetTrialParams(int trialId)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
return trial.Params.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Similar blocks of code found in 3 locations. Consider refactoring.
public Dictionary<string, object> GetTrialSystemAttrs(int trialId)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
return trial.SystemAttrs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Similar blocks of code found in 3 locations. Consider refactoring.
public Dictionary<string, object> GetTrialUserAttrs(int trialId)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
return trial.UserAttrs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
public void RemoveSession()
{
throw new NotImplementedException();
}
Similar blocks of code found in 4 locations. Consider refactoring.
public void SetStudySystemAttr(int studyId, string key, object value)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
study.SystemAttrs[key] = value;
}
Similar blocks of code found in 4 locations. Consider refactoring.
public void SetStudyUserAttr(int studyId, string key, object value)
{
EnsureInitialized();
if (!_studies.TryGetValue(studyId, out Study.Study study))
{
throw new KeyNotFoundException($"Study with ID '{studyId}' not found.");
}
study.UserAttrs[key] = value;
}
public void SetTrailParam(int trialId, string paramName, double paramValueInternal, object distribution)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
trial.Params[paramName] = paramValueInternal;
}
public void SetTrialIntermediateValue(int trialId, int intermediateStep, double intermediateValue)
{
throw new NotImplementedException();
}
public bool SetTrialStateValue(int trialId, TrialState state, double[] values = null)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
trial.State = state;
if (values != null)
{
trial.Values = values;
}
return true;
}
Similar blocks of code found in 4 locations. Consider refactoring.
public void SetTrialSystemAttr(int trialId, string key, object value)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
trial.SystemAttrs[key] = value;
}
Similar blocks of code found in 4 locations. Consider refactoring.
public void SetTrialUserAttr(int trialId, string key, object value)
{
EnsureInitialized();
if (!_trialCache.TryGetValue(trialId, out Trial.Trial trial))
{
throw new KeyNotFoundException($"Trial with ID {trialId} not found.");
}
trial.UserAttrs[key] = value;
}
}
}