diff --git a/pkg/mining/miner.go b/pkg/mining/miner.go index fc13de8..6658b7c 100644 --- a/pkg/mining/miner.go +++ b/pkg/mining/miner.go @@ -27,7 +27,7 @@ import ( type LogBuffer struct { lines []string maxLines int - mu sync.RWMutex + mutex sync.RWMutex } // buffer := NewLogBuffer(500) @@ -44,8 +44,8 @@ const maxLineLength = 2000 // cmd.Stdout = lb // satisfies io.Writer; timestamps and ring-buffers each line func (lb *LogBuffer) Write(p []byte) (n int, err error) { - lb.mu.Lock() - defer lb.mu.Unlock() + lb.mutex.Lock() + defer lb.mutex.Unlock() // Split input into lines text := string(p) @@ -76,8 +76,8 @@ func (lb *LogBuffer) Write(p []byte) (n int, err error) { // lines := lb.GetLines() // response.Logs = lines[max(0, len(lines)-100):] func (lb *LogBuffer) GetLines() []string { - lb.mu.RLock() - defer lb.mu.RUnlock() + lb.mutex.RLock() + defer lb.mutex.RUnlock() result := make([]string, len(lb.lines)) copy(result, lb.lines) return result @@ -85,8 +85,8 @@ func (lb *LogBuffer) GetLines() []string { // lb.Clear() // called on miner Stop() to release memory func (lb *LogBuffer) Clear() { - lb.mu.Lock() - defer lb.mu.Unlock() + lb.mutex.Lock() + defer lb.mutex.Unlock() lb.lines = lb.lines[:0] } @@ -102,7 +102,7 @@ type BaseMiner struct { Running bool `json:"running"` ConfigPath string `json:"configPath"` API *API `json:"api"` - mu sync.RWMutex + mutex sync.RWMutex cmd *exec.Cmd stdinPipe io.WriteCloser `json:"-"` HashrateHistory []HashratePoint `json:"hashrateHistory"` @@ -118,8 +118,8 @@ func (b *BaseMiner) GetType() string { // name := miner.GetName() // e.g. "xmrig-randomx" or "tt-miner-kawpow" func (b *BaseMiner) GetName() string { - b.mu.RLock() - defer b.mu.RUnlock() + b.mutex.RLock() + defer b.mutex.RUnlock() return b.Name } @@ -138,17 +138,17 @@ func (b *BaseMiner) GetPath() string { // binary := miner.GetBinaryPath() // e.g. "/home/user/.local/share/lethean-desktop/miners/xmrig/xmrig" func (b *BaseMiner) GetBinaryPath() string { - b.mu.RLock() - defer b.mu.RUnlock() + b.mutex.RLock() + defer b.mutex.RUnlock() return b.MinerBinary } // if err := miner.Stop(); err != nil { log.Warn("stop failed", ...) } func (b *BaseMiner) Stop() error { - b.mu.Lock() + b.mutex.Lock() if !b.Running || b.cmd == nil { - b.mu.Unlock() + b.mutex.Unlock() return ErrMinerNotRunning(b.Name) } @@ -165,7 +165,7 @@ func (b *BaseMiner) Stop() error { // Mark as not running immediately to prevent concurrent Stop() calls b.Running = false b.cmd = nil - b.mu.Unlock() + b.mutex.Unlock() // Try graceful shutdown with SIGTERM first (Unix only) if runtime.GOOS != "windows" { @@ -201,10 +201,10 @@ const stdinWriteTimeout = 5 * time.Second // if err := miner.WriteStdin("h"); err != nil { /* miner not running */ } func (b *BaseMiner) WriteStdin(input string) error { - b.mu.RLock() + b.mutex.RLock() stdinPipe := b.stdinPipe running := b.Running - b.mu.RUnlock() + b.mutex.RUnlock() if !running || stdinPipe == nil { return ErrMinerNotRunning(b.Name) @@ -417,8 +417,8 @@ func (b *BaseMiner) CheckInstallation() (*InstallationDetails, error) { // points := miner.GetHashrateHistory() // low-res (24h) + high-res (5min) points in chronological order func (b *BaseMiner) GetHashrateHistory() []HashratePoint { - b.mu.RLock() - defer b.mu.RUnlock() + b.mutex.RLock() + defer b.mutex.RUnlock() combinedHistory := make([]HashratePoint, 0, len(b.LowResHashrateHistory)+len(b.HashrateHistory)) combinedHistory = append(combinedHistory, b.LowResHashrateHistory...) combinedHistory = append(combinedHistory, b.HashrateHistory...) @@ -427,31 +427,31 @@ func (b *BaseMiner) GetHashrateHistory() []HashratePoint { // miner.AddHashratePoint(HashratePoint{Timestamp: time.Now(), Hashrate: 1234.5}) func (b *BaseMiner) AddHashratePoint(point HashratePoint) { - b.mu.Lock() - defer b.mu.Unlock() + b.mutex.Lock() + defer b.mutex.Unlock() b.HashrateHistory = append(b.HashrateHistory, point) } // n := miner.GetHighResHistoryLength() // 0..30 points (last 5 min at 10s resolution) func (b *BaseMiner) GetHighResHistoryLength() int { - b.mu.RLock() - defer b.mu.RUnlock() + b.mutex.RLock() + defer b.mutex.RUnlock() return len(b.HashrateHistory) } // n := miner.GetLowResHistoryLength() // 0..1440 points (last 24h at 1min resolution) func (b *BaseMiner) GetLowResHistoryLength() int { - b.mu.RLock() - defer b.mu.RUnlock() + b.mutex.RLock() + defer b.mutex.RUnlock() return len(b.LowResHashrateHistory) } // lines := miner.GetLogs() // response.Logs = lines[max(0, len(lines)-100):] func (b *BaseMiner) GetLogs() []string { - b.mu.RLock() + b.mutex.RLock() logBuffer := b.LogBuffer - b.mu.RUnlock() + b.mutex.RUnlock() if logBuffer == nil { return []string{} @@ -461,8 +461,8 @@ func (b *BaseMiner) GetLogs() []string { // ReduceHashrateHistory aggregates and trims hashrate data. func (b *BaseMiner) ReduceHashrateHistory(now time.Time) { - b.mu.Lock() - defer b.mu.Unlock() + b.mutex.Lock() + defer b.mutex.Unlock() if !b.LastLowResAggregation.IsZero() && now.Sub(b.LastLowResAggregation) < LowResolutionInterval { return diff --git a/pkg/mining/ttminer.go b/pkg/mining/ttminer.go index 84bcfd9..ad272fa 100644 --- a/pkg/mining/ttminer.go +++ b/pkg/mining/ttminer.go @@ -173,11 +173,11 @@ func (m *TTMiner) CheckInstallation() (*InstallationDetails, error) { } // Update shared fields under lock - m.mu.Lock() + m.mutex.Lock() m.MinerBinary = binaryPath m.Path = filepath.Dir(binaryPath) m.Version = version - m.mu.Unlock() + m.mutex.Unlock() return &InstallationDetails{ IsInstalled: true, diff --git a/pkg/mining/ttminer_start.go b/pkg/mining/ttminer_start.go index 7b49806..2317e97 100644 --- a/pkg/mining/ttminer_start.go +++ b/pkg/mining/ttminer_start.go @@ -15,9 +15,9 @@ import ( // Start launches the TT-Miner with the given configuration. func (m *TTMiner) Start(config *Config) error { // Check installation BEFORE acquiring lock (CheckInstallation takes its own locks) - m.mu.RLock() + m.mutex.RLock() needsInstallCheck := m.MinerBinary == "" - m.mu.RUnlock() + m.mutex.RUnlock() if needsInstallCheck { if _, err := m.CheckInstallation(); err != nil { @@ -25,8 +25,8 @@ func (m *TTMiner) Start(config *Config) error { } } - m.mu.Lock() - defer m.mu.Unlock() + m.mutex.Lock() + defer m.mutex.Unlock() if m.Running { return errors.New("miner is already running") @@ -100,13 +100,13 @@ func (m *TTMiner) Start(config *Config) error { } } - m.mu.Lock() + m.mutex.Lock() // Only clear if this is still the same command (not restarted) if m.cmd == cmd { m.Running = false m.cmd = nil } - m.mu.Unlock() + m.mutex.Unlock() if err != nil { logging.Debug("TT-Miner exited with error", logging.Fields{"error": err}) } else { diff --git a/pkg/mining/ttminer_stats.go b/pkg/mining/ttminer_stats.go index 752f78a..be199c3 100644 --- a/pkg/mining/ttminer_stats.go +++ b/pkg/mining/ttminer_stats.go @@ -8,13 +8,13 @@ import ( // GetStats retrieves performance metrics from the TT-Miner API. func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) { // Read state under RLock, then release before HTTP call - m.mu.RLock() + m.mutex.RLock() if !m.Running { - m.mu.RUnlock() + m.mutex.RUnlock() return nil, errors.New("miner is not running") } if m.API == nil || m.API.ListenPort == 0 { - m.mu.RUnlock() + m.mutex.RUnlock() return nil, errors.New("miner API not configured or port is zero") } config := HTTPStatsConfig{ @@ -22,7 +22,7 @@ func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) { Port: m.API.ListenPort, Endpoint: "/summary", } - m.mu.RUnlock() + m.mutex.RUnlock() // Create request with context and timeout reqCtx, cancel := context.WithTimeout(ctx, statsTimeout) @@ -35,9 +35,9 @@ func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) { } // Store the full summary in the miner struct (requires lock) - m.mu.Lock() + m.mutex.Lock() m.FullStats = &summary - m.mu.Unlock() + m.mutex.Unlock() // Calculate total hashrate from all GPUs var totalHashrate float64 diff --git a/pkg/mining/xmrig.go b/pkg/mining/xmrig.go index a9b7472..b7a42d9 100644 --- a/pkg/mining/xmrig.go +++ b/pkg/mining/xmrig.go @@ -173,9 +173,9 @@ func (m *XMRigMiner) CheckInstallation() (*InstallationDetails, error) { } // Get the config path using the helper (use instance name if set) - m.mu.RLock() + m.mutex.RLock() instanceName := m.Name - m.mu.RUnlock() + m.mutex.RUnlock() configPath, err := getXMRigConfigPath(instanceName) if err != nil { @@ -184,11 +184,11 @@ func (m *XMRigMiner) CheckInstallation() (*InstallationDetails, error) { } // Update shared fields under lock - m.mu.Lock() + m.mutex.Lock() m.MinerBinary = binaryPath m.Path = filepath.Dir(binaryPath) m.Version = version - m.mu.Unlock() + m.mutex.Unlock() return &InstallationDetails{ IsInstalled: true, diff --git a/pkg/mining/xmrig_start.go b/pkg/mining/xmrig_start.go index c141783..7ebff0a 100644 --- a/pkg/mining/xmrig_start.go +++ b/pkg/mining/xmrig_start.go @@ -18,9 +18,9 @@ import ( // if err := miner.Start(&mining.Config{Algo: "rx/0", Pool: "pool.lthn.io:3333"}); err != nil { return err } func (m *XMRigMiner) Start(config *Config) error { // Check installation BEFORE acquiring lock (CheckInstallation takes its own locks) - m.mu.RLock() + m.mutex.RLock() needsInstallCheck := m.MinerBinary == "" - m.mu.RUnlock() + m.mutex.RUnlock() if needsInstallCheck { if _, err := m.CheckInstallation(); err != nil { @@ -28,8 +28,8 @@ func (m *XMRigMiner) Start(config *Config) error { } } - m.mu.Lock() - defer m.mu.Unlock() + m.mutex.Lock() + defer m.mutex.Unlock() if m.Running { return errors.New("miner is already running") @@ -139,13 +139,13 @@ func (m *XMRigMiner) Start(config *Config) error { } } - m.mu.Lock() + m.mutex.Lock() // Only clear if this is still the same command (not restarted) if m.cmd == cmd { m.Running = false m.cmd = nil } - m.mu.Unlock() + m.mutex.Unlock() }() return nil diff --git a/pkg/mining/xmrig_stats.go b/pkg/mining/xmrig_stats.go index b116e8b..54a58dc 100644 --- a/pkg/mining/xmrig_stats.go +++ b/pkg/mining/xmrig_stats.go @@ -12,13 +12,13 @@ const statsTimeout = 5 * time.Second // GetStats retrieves the performance statistics from the running XMRig miner. func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) { // Read state under RLock, then release before HTTP call - m.mu.RLock() + m.mutex.RLock() if !m.Running { - m.mu.RUnlock() + m.mutex.RUnlock() return nil, errors.New("miner is not running") } if m.API == nil || m.API.ListenPort == 0 { - m.mu.RUnlock() + m.mutex.RUnlock() return nil, errors.New("miner API not configured or port is zero") } config := HTTPStatsConfig{ @@ -26,7 +26,7 @@ func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) Port: m.API.ListenPort, Endpoint: "/2/summary", } - m.mu.RUnlock() + m.mutex.RUnlock() // Create request with context and timeout reqCtx, cancel := context.WithTimeout(ctx, statsTimeout) @@ -39,9 +39,9 @@ func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) } // Store the full summary in the miner struct (requires lock) - m.mu.Lock() + m.mutex.Lock() m.FullStats = &summary - m.mu.Unlock() + m.mutex.Unlock() var hashrate int if len(summary.Hashrate.Total) > 0 {