diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index d1aafa3d..be860830 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -18,6 +18,7 @@ import ( var ( objectPhyCounterKey = []byte("phy_counter") objectLogicCounterKey = []byte("logic_counter") + objectUserCounterKey = []byte("user_counter") ) type objectType uint8 @@ -31,18 +32,13 @@ const ( // ObjectCounters groups object counter // according to metabase state. type ObjectCounters struct { - logic uint64 - phy uint64 + Logic uint64 + Phy uint64 + User uint64 } -// Logic returns logical object counter. -func (o ObjectCounters) Logic() uint64 { - return o.logic -} - -// Phy returns physical object counter. -func (o ObjectCounters) Phy() uint64 { - return o.phy +func (o ObjectCounters) IsZero() bool { + return o.Phy == 0 && o.Logic == 0 && o.User == 0 } // ObjectCounters returns object counters that metabase has @@ -63,12 +59,17 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { if b != nil { data := b.Get(objectPhyCounterKey) if len(data) == 8 { - cc.phy = binary.LittleEndian.Uint64(data) + cc.Phy = binary.LittleEndian.Uint64(data) } data = b.Get(objectLogicCounterKey) if len(data) == 8 { - cc.logic = binary.LittleEndian.Uint64(data) + cc.Logic = binary.LittleEndian.Uint64(data) + } + + data = b.Get(objectUserCounterKey) + if len(data) == 8 { + cc.User = binary.LittleEndian.Uint64(data) } } @@ -79,8 +80,7 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { } type ContainerCounters struct { - Logical map[cid.ID]uint64 - Physical map[cid.ID]uint64 + Counts map[cid.ID]ObjectCounters } // ContainerCounters returns object counters for each container @@ -103,8 +103,7 @@ func (db *DB) ContainerCounters(ctx context.Context) (ContainerCounters, error) defer span.End() cc := ContainerCounters{ - Logical: make(map[cid.ID]uint64), - Physical: make(map[cid.ID]uint64), + Counts: make(map[cid.ID]ObjectCounters), } lastKey := make([]byte, cidSize) @@ -158,16 +157,11 @@ func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) if err != nil { return err } - phy, logic, err := parseContainerCounterValue(value) + ent, err := parseContainerCounterValue(value) if err != nil { return err } - if phy > 0 { - cc.Physical[cnrID] = phy - } - if logic > 0 { - cc.Logical[cnrID] = logic - } + cc.Counts[cnrID] = ent counter++ if counter == batchSize { @@ -253,22 +247,23 @@ func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounte } func (*DB) editContainerCounterValue(b *bbolt.Bucket, key []byte, delta ObjectCounters, inc bool) error { - var phyValue, logicValue uint64 + var entity ObjectCounters var err error data := b.Get(key) if len(data) > 0 { - phyValue, logicValue, err = parseContainerCounterValue(data) + entity, err = parseContainerCounterValue(data) if err != nil { return err } } - phyValue = nextValue(phyValue, delta.phy, inc) - logicValue = nextValue(logicValue, delta.logic, inc) - if phyValue > 0 || logicValue > 0 { - value := containerCounterValue(phyValue, logicValue) - return b.Put(key, value) + entity.Phy = nextValue(entity.Phy, delta.Phy, inc) + entity.Logic = nextValue(entity.Logic, delta.Logic, inc) + entity.User = nextValue(entity.User, delta.User, inc) + if entity.IsZero() { + return b.Delete(key) } - return b.Delete(key) + value := containerCounterValue(entity) + return b.Put(key, value) } func nextValue(existed, delta uint64, inc bool) uint64 { @@ -290,7 +285,7 @@ func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID) error { key := make([]byte, cidSize) cnrID.Encode(key) - return db.editContainerCounterValue(b, key, ObjectCounters{logic: 1, phy: 1}, true) + return db.editContainerCounterValue(b, key, ObjectCounters{Logic: 1, Phy: 1}, true) } // syncCounter updates object counters according to metabase state: @@ -304,9 +299,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { if err != nil { return fmt.Errorf("could not get shard info bucket: %w", err) } - shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && len(shardInfoB.Get(objectLogicCounterKey)) == 8 - containerCounterInitialized := tx.Bucket(containerCounterBucketName) != nil - if !force && shardObjectCounterInitialized && containerCounterInitialized { + shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && + len(shardInfoB.Get(objectLogicCounterKey)) == 8 && + len(shardInfoB.Get(objectUserCounterKey)) == 8 + containerObjectCounterInitialized := containerObjectCounterInitialized(tx) + if !force && shardObjectCounterInitialized && containerObjectCounterInitialized { // the counters are already inited return nil } @@ -325,11 +322,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { err = iteratePhyObjects(tx, func(cnr cid.ID, obj oid.ID) error { if v, ok := counters[cnr]; ok { - v.phy++ + v.Phy++ counters[cnr] = v } else { counters[cnr] = ObjectCounters{ - phy: 1, + Phy: 1, } } @@ -340,11 +337,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { // and not covered with a tombstone if inGraveyardWithKey(addressKey(addr, key), graveyardBKT, garbageBKT) == 0 { if v, ok := counters[cnr]; ok { - v.logic++ + v.Logic++ counters[cnr] = v } else { counters[cnr] = ObjectCounters{ - logic: 1, + Logic: 1, } } } @@ -361,13 +358,15 @@ func syncCounter(tx *bbolt.Tx, force bool) error { func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, containerCounterB *bbolt.Bucket) error { var phyTotal uint64 var logicTotal uint64 + var userTotal uint64 key := make([]byte, cidSize) for cnrID, count := range counters { - phyTotal += count.phy - logicTotal += count.logic + phyTotal += count.Phy + logicTotal += count.Logic + userTotal += count.User cnrID.Encode(key) - value := containerCounterValue(count.phy, count.logic) + value := containerCounterValue(count) err := containerCounterB.Put(key, value) if err != nil { return fmt.Errorf("could not update phy container object counter: %w", err) @@ -389,13 +388,22 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container return fmt.Errorf("could not update logic object counter: %w", err) } + userData := make([]byte, 8) + binary.LittleEndian.PutUint64(userData, userTotal) + + err = shardInfoB.Put(objectUserCounterKey, userData) + if err != nil { + return fmt.Errorf("could not update user object counter: %w", err) + } + return nil } -func containerCounterValue(phy, logic uint64) []byte { - res := make([]byte, 16) - binary.LittleEndian.PutUint64(res, phy) - binary.LittleEndian.PutUint64(res[8:], logic) +func containerCounterValue(entity ObjectCounters) []byte { + res := make([]byte, 24) + binary.LittleEndian.PutUint64(res, entity.Phy) + binary.LittleEndian.PutUint64(res[8:], entity.Logic) + binary.LittleEndian.PutUint64(res[16:], entity.User) return res } @@ -411,9 +419,30 @@ func parseContainerCounterKey(buf []byte) (cid.ID, error) { } // parseContainerCounterValue return phy, logic values. -func parseContainerCounterValue(buf []byte) (uint64, uint64, error) { - if len(buf) != 16 { - return 0, 0, fmt.Errorf("invalid value length") +func parseContainerCounterValue(buf []byte) (ObjectCounters, error) { + if len(buf) != 24 { + return ObjectCounters{}, fmt.Errorf("invalid value length") } - return binary.LittleEndian.Uint64(buf), binary.LittleEndian.Uint64(buf[8:]), nil + return ObjectCounters{ + Phy: binary.LittleEndian.Uint64(buf), + Logic: binary.LittleEndian.Uint64(buf[8:16]), + User: binary.LittleEndian.Uint64(buf[16:]), + }, nil +} + +func containerObjectCounterInitialized(tx *bbolt.Tx) bool { + b := tx.Bucket(containerCounterBucketName) + if b == nil { + return false + } + k, v := b.Cursor().First() + if k == nil && v == nil { + return true + } + _, err := parseContainerCounterKey(k) + if err != nil { + return false + } + _, err = parseContainerCounterValue(v) + return err == nil } diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 51062f1f..27d0b37a 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -24,13 +24,13 @@ func TestCounters(t *testing.T) { db := newDB(t) c, err := db.ObjectCounters() require.NoError(t, err) - require.Zero(t, c.Phy()) - require.Zero(t, c.Logic()) + require.Zero(t, c.Phy) + require.Zero(t, c.Logic) + require.Zero(t, c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Zero(t, len(cc.Physical)) - require.Zero(t, len(cc.Logical)) + require.Zero(t, len(cc.Counts)) }) t.Run("put", func(t *testing.T) { @@ -42,29 +42,30 @@ func TestCounters(t *testing.T) { } var prm meta.PutPrm - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for i := 0; i < objCount; i++ { prm.SetObject(oo[i]) cnrID, _ := oo[i].ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + c := meta.ObjectCounters{} + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } _, err := db.Put(context.Background(), prm) require.NoError(t, err) - c, err := db.ObjectCounters() + c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -73,12 +74,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } var prm meta.DeletePrm @@ -92,29 +94,23 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i), c.Phy()) - require.Equal(t, uint64(i), c.Logic()) + require.Equal(t, uint64(i), c.Phy) + require.Equal(t, uint64(i), c.Logic) cnrID, _ := oo[i].ContainerID() - if v, ok := expPhy[cnrID]; ok { - if v == 1 { - delete(expPhy, cnrID) + if v, ok := exp[cnrID]; ok { + v.Phy-- + v.Logic-- + if v.IsZero() { + delete(exp, cnrID) } else { - expPhy[cnrID]-- - } - } - if v, ok := expLog[cnrID]; ok { - if v == 1 { - delete(expLog, cnrID) - } else { - expLog[cnrID]-- + exp[cnrID] = v } } cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -123,12 +119,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } inhumedObjs := make([]oid.Address, objCount/2) @@ -142,11 +139,12 @@ func TestCounters(t *testing.T) { } for _, addr := range inhumedObjs { - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -162,14 +160,13 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) }) t.Run("put_split", func(t *testing.T) { @@ -177,8 +174,7 @@ func TestCounters(t *testing.T) { db := newDB(t) parObj := testutil.GenerateObject() - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) // put objects and check that parent info // does not affect the counter @@ -189,20 +185,21 @@ func TestCounters(t *testing.T) { } cnrID, _ := o.ContainerID() - expLog[cnrID]++ - expPhy[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } require.NoError(t, putBig(db, o)) c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -211,12 +208,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } // delete objects that have parent info @@ -228,21 +226,15 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount-i-1), c.Phy()) - require.Equal(t, uint64(objCount-i-1), c.Logic()) + require.Equal(t, uint64(objCount-i-1), c.Phy) - if v, ok := expPhy[addr.Container()]; ok { - if v == 1 { - delete(expPhy, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + v.Phy-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expPhy[addr.Container()]-- - } - } - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) - } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -253,12 +245,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } inhumedObjs := make([]oid.Address, objCount/2) @@ -272,11 +265,12 @@ func TestCounters(t *testing.T) { } for _, addr := range inhumedObjs { - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -291,14 +285,13 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) }) } @@ -320,25 +313,25 @@ func TestCounters_Expired(t *testing.T) { oo[i] = putWithExpiration(t, db, objectSDK.TypeRegular, epoch+1) } - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, addr := range oo { - expPhy[addr.Container()]++ - expLog[addr.Container()]++ + exp[addr.Container()] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } // 1. objects are available and counters are correct c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) for _, o := range oo { _, err := metaGet(db, o, true) @@ -352,14 +345,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) for _, o := range oo { _, err := metaGet(db, o, true) @@ -381,22 +373,22 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)-1), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)-1), c.Logic) - if v, ok := expLog[oo[0].Container()]; ok { - if v == 1 { - delete(expLog, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expLog[oo[0].Container()]-- + exp[oo[0].Container()] = v } } cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) // 4. `Delete` an object with GCMark should decrease the // phy counter but does not affect the logic counter (after @@ -409,11 +401,12 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Zero(t, deleteRes.AvailableObjectsRemoved()) - if v, ok := expPhy[oo[0].Container()]; ok { - if v == 1 { - delete(expPhy, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Phy-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expPhy[oo[0].Container()]-- + exp[oo[0].Container()] = v } } @@ -421,14 +414,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) // 5 `Delete` an expired object (like it would the control // service do) should decrease both counters despite the @@ -440,19 +432,13 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), deleteRes.AvailableObjectsRemoved()) - if v, ok := expLog[oo[0].Container()]; ok { - if v == 1 { - delete(expLog, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Phy-- + v.Logic-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expLog[oo[0].Container()]-- - } - } - - if v, ok := expPhy[oo[0].Container()]; ok { - if v == 1 { - delete(expPhy, oo[0].Container()) - } else { - expPhy[oo[0].Container()]-- + exp[oo[0].Container()] = v } } @@ -460,14 +446,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK.Object { @@ -491,8 +476,8 @@ func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) } return oo diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 5acd7116..a2100f36 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -139,11 +139,11 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) if removed { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.phy++ + v.Phy++ res.removedByCnrID[addrs[i].Container()] = v } else { res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - phy: 1, + Phy: 1, } } @@ -153,11 +153,11 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) if available { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.logic++ + v.Logic++ res.removedByCnrID[addrs[i].Container()] = v } else { res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - logic: 1, + Logic: 1, } } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index cf792199..2a9adff3 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -82,11 +82,11 @@ func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64) { }) i.availableInhumed++ if v, ok := i.inhumedByCnrID[containerID]; ok { - v.logic++ + v.Logic++ i.inhumedByCnrID[containerID] = v } else { i.inhumedByCnrID[containerID] = ObjectCounters{ - logic: 1, + Logic: 1, } } } @@ -251,10 +251,10 @@ func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { inhumedbyCnr := make(map[cid.ID]ObjectCounters) for _, dd := range res.deletionDetails { if v, ok := inhumedbyCnr[dd.CID]; ok { - v.logic++ + v.Logic++ inhumedbyCnr[dd.CID] = v } else { - inhumedbyCnr[dd.CID] = ObjectCounters{logic: 1} + inhumedbyCnr[dd.CID] = ObjectCounters{Logic: 1} } inhumedCount++ } diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 749229cc..f08af6fc 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -347,8 +347,8 @@ func TestRefillMetabase(t *testing.T) { c, err := sh.metaBase.ObjectCounters() require.NoError(t, err) - phyBefore := c.Phy() - logicalBefore := c.Logic() + phyBefore := c.Phy + logicalBefore := c.Logic err = sh.Close() require.NoError(t, err) @@ -382,8 +382,8 @@ func TestRefillMetabase(t *testing.T) { c, err = sh.metaBase.ObjectCounters() require.NoError(t, err) - require.Equal(t, phyBefore, c.Phy()) - require.Equal(t, logicalBefore, c.Logic()) + require.Equal(t, phyBefore, c.Phy) + require.Equal(t, logicalBefore, c.Logic) checkAllObjs(true) checkObj(object.AddressOf(tombObj), tombObj) diff --git a/pkg/local_object_storage/shard/count.go b/pkg/local_object_storage/shard/count.go index abed5278..b3bc6a30 100644 --- a/pkg/local_object_storage/shard/count.go +++ b/pkg/local_object_storage/shard/count.go @@ -27,5 +27,5 @@ func (s *Shard) LogicalObjectsCount(ctx context.Context) (uint64, error) { if err != nil { return 0, err } - return cc.Logic(), nil + return cc.Logic, nil } diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 1e9bbf9f..138009a7 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -178,8 +178,6 @@ func TestCounters(t *testing.T) { oo[i] = testutil.GenerateObject() } - cc := meta.ContainerCounters{Logical: make(map[cid.ID]uint64), Physical: make(map[cid.ID]uint64)} - t.Run("defaults", func(t *testing.T) { require.Zero(t, mm.getObjectCounter(physical)) require.Zero(t, mm.getObjectCounter(logical)) @@ -200,15 +198,16 @@ func TestCounters(t *testing.T) { var totalPayload int64 expectedLogicalSizes := make(map[string]int64) - expectedLogCC := make(map[cid.ID]uint64) - expectedPhyCC := make(map[cid.ID]uint64) + expected := make(map[cid.ID]meta.ObjectCounters) for i := range oo { cnr, _ := oo[i].ContainerID() oSize := int64(oo[i].PayloadSize()) expectedLogicalSizes[cnr.EncodeToString()] += oSize totalPayload += oSize - expectedLogCC[cnr]++ - expectedPhyCC[cnr]++ + expected[cnr] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } var prm PutPrm @@ -227,8 +226,7 @@ func TestCounters(t *testing.T) { cc, err := sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) t.Run("inhume_GC", func(t *testing.T) { var prm InhumePrm @@ -244,9 +242,13 @@ func TestCounters(t *testing.T) { require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) - expectedLogCC[cid]-- - if expectedLogCC[cid] == 0 { - delete(expectedLogCC, cid) + if v, ok := expected[cid]; ok { + v.Logic-- + if v.IsZero() { + delete(expected, cid) + } else { + expected[cid] = v + } } } @@ -257,8 +259,7 @@ func TestCounters(t *testing.T) { cc, err := sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) oo = oo[inhumedNumber:] }) @@ -281,9 +282,13 @@ func TestCounters(t *testing.T) { require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) - expectedLogCC[cid]-- - if expectedLogCC[cid] == 0 { - delete(expectedLogCC, cid) + if v, ok := expected[cid]; ok { + v.Logic-- + if v.IsZero() { + delete(expected, cid) + } else { + expected[cid] = v + } } } @@ -294,8 +299,7 @@ func TestCounters(t *testing.T) { cc, err = sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) oo = oo[inhumedNumber:] }) @@ -322,14 +326,14 @@ func TestCounters(t *testing.T) { cnr, _ := oo[i].ContainerID() expectedLogicalSizes[cnr.EncodeToString()] -= int64(removedPayload) - expectedLogCC[cnr]-- - if expectedLogCC[cnr] == 0 { - delete(expectedLogCC, cnr) - } - - expectedPhyCC[cnr]-- - if expectedPhyCC[cnr] == 0 { - delete(expectedPhyCC, cnr) + if v, ok := expected[cnr]; ok { + v.Logic-- + v.Phy-- + if v.IsZero() { + delete(expected, cnr) + } else { + expected[cnr] = v + } } } require.Equal(t, expectedLogicalSizes, mm.containerSizes()) @@ -337,8 +341,7 @@ func TestCounters(t *testing.T) { cc, err = sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) }) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index ff437d7e..853a87b9 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -395,6 +395,8 @@ const ( // counter type (excludes objects that are // stored but unavailable). logical = "logic" + // user is an available small or big regular object. + user = "user" ) func (s *Shard) updateMetrics(ctx context.Context) { @@ -411,8 +413,9 @@ func (s *Shard) updateMetrics(ctx context.Context) { return } - s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy()) - s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic()) + s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy) + s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic) + s.cfg.metricsWriter.SetObjectCounter(user, cc.User) cnrList, err := s.metaBase.Containers(ctx) if err != nil { @@ -441,11 +444,10 @@ func (s *Shard) updateMetrics(ctx context.Context) { s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) return } - for contID, count := range contCount.Physical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count) - } - for contID, count := range contCount.Logical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count) + for contID, count := range contCount.Counts { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count.Phy) + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), user, count.User) } } @@ -472,8 +474,9 @@ func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) } for cnrID, count := range byCnr { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy()) - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic()) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) } }