From 8e72abaab74e3cb206ad074635dce8ee28590818 Mon Sep 17 00:00:00 2001
From: Alex Vanin <alexey@nspcc.ru>
Date: Thu, 24 Dec 2020 14:22:55 +0300
Subject: [PATCH] [#281] service/audit: Make report structure threadsafe

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
---
 pkg/services/audit/report.go | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/pkg/services/audit/report.go b/pkg/services/audit/report.go
index c41d0c016..a7f369902 100644
--- a/pkg/services/audit/report.go
+++ b/pkg/services/audit/report.go
@@ -1,6 +1,8 @@
 package audit
 
 import (
+	"sync"
+
 	"github.com/nspcc-dev/neofs-api-go/pkg/audit"
 	"github.com/nspcc-dev/neofs-api-go/pkg/container"
 	"github.com/nspcc-dev/neofs-api-go/pkg/object"
@@ -8,6 +10,7 @@ import (
 
 // Report tracks the progress of auditing container data.
 type Report struct {
+	mu  sync.RWMutex
 	res *audit.Result
 }
 
@@ -30,26 +33,41 @@ func NewReport(cid *container.ID) *Report {
 
 // Result forms the structure of the data audit result.
 func (r *Report) Result() *audit.Result {
+	r.mu.RLock()
+	defer r.mu.RUnlock()
+
 	return r.res
 }
 
 // Complete completes audit report.
 func (r *Report) Complete() {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetComplete(true)
 }
 
 // PassedPoR updates list of passed storage groups.
 func (r *Report) PassedPoR(sg *object.ID) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetPassSG(append(r.res.PassSG(), sg))
 }
 
 // FailedPoR updates list of failed storage groups.
 func (r *Report) FailedPoR(sg *object.ID) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetFailSG(append(r.res.FailSG(), sg))
 }
 
 // SetPlacementCounters sets counters of compliance with placement.
 func (r *Report) SetPlacementCounters(hit, miss, fail uint32) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetHit(hit)
 	r.res.SetMiss(miss)
 	r.res.SetFail(fail)
@@ -57,12 +75,18 @@ func (r *Report) SetPlacementCounters(hit, miss, fail uint32) {
 
 // SetPDPResults sets lists of nodes according to their PDP results.
 func (r *Report) SetPDPResults(passed, failed [][]byte) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetPassNodes(passed)
 	r.res.SetFailNodes(failed)
 }
 
 // SetPoRCounters sets amounts of head requests and retries at PoR audit stage.
 func (r *Report) SetPoRCounters(requests, retries uint32) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
 	r.res.SetRequests(requests)
 	r.res.SetRetries(retries)
 }