| package cache |
| |
| import ( |
| "time" |
| |
| "github.com/moby/buildkit/cache/metadata" |
| "github.com/moby/buildkit/client" |
| "github.com/pkg/errors" |
| bolt "go.etcd.io/bbolt" |
| ) |
| |
| const sizeUnknown int64 = -1 |
| const keySize = "snapshot.size" |
| const keyEqualMutable = "cache.equalMutable" |
| const keyCachePolicy = "cache.cachePolicy" |
| const keyDescription = "cache.description" |
| const keyCreatedAt = "cache.createdAt" |
| const keyLastUsedAt = "cache.lastUsedAt" |
| const keyUsageCount = "cache.usageCount" |
| const keyLayerType = "cache.layerType" |
| const keyRecordType = "cache.recordType" |
| |
| const keyDeleted = "cache.deleted" |
| |
| func setDeleted(si *metadata.StorageItem) error { |
| v, err := metadata.NewValue(true) |
| if err != nil { |
| return errors.Wrap(err, "failed to create size value") |
| } |
| si.Update(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyDeleted, v) |
| }) |
| return nil |
| } |
| |
| func getDeleted(si *metadata.StorageItem) bool { |
| v := si.Get(keyDeleted) |
| if v == nil { |
| return false |
| } |
| var deleted bool |
| if err := v.Unmarshal(&deleted); err != nil { |
| return false |
| } |
| return deleted |
| } |
| |
| func setSize(si *metadata.StorageItem, s int64) error { |
| v, err := metadata.NewValue(s) |
| if err != nil { |
| return errors.Wrap(err, "failed to create size value") |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keySize, v) |
| }) |
| return nil |
| } |
| |
| func getSize(si *metadata.StorageItem) int64 { |
| v := si.Get(keySize) |
| if v == nil { |
| return sizeUnknown |
| } |
| var size int64 |
| if err := v.Unmarshal(&size); err != nil { |
| return sizeUnknown |
| } |
| return size |
| } |
| |
| func getEqualMutable(si *metadata.StorageItem) string { |
| v := si.Get(keyEqualMutable) |
| if v == nil { |
| return "" |
| } |
| var str string |
| if err := v.Unmarshal(&str); err != nil { |
| return "" |
| } |
| return str |
| } |
| |
| func setEqualMutable(si *metadata.StorageItem, s string) error { |
| v, err := metadata.NewValue(s) |
| if err != nil { |
| return errors.Wrapf(err, "failed to create %s meta value", keyEqualMutable) |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyEqualMutable, v) |
| }) |
| return nil |
| } |
| |
| func clearEqualMutable(si *metadata.StorageItem) error { |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyEqualMutable, nil) |
| }) |
| return nil |
| } |
| |
| func queueCachePolicy(si *metadata.StorageItem, p cachePolicy) error { |
| v, err := metadata.NewValue(p) |
| if err != nil { |
| return errors.Wrap(err, "failed to create cachePolicy value") |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyCachePolicy, v) |
| }) |
| return nil |
| } |
| |
| func getCachePolicy(si *metadata.StorageItem) cachePolicy { |
| v := si.Get(keyCachePolicy) |
| if v == nil { |
| return cachePolicyDefault |
| } |
| var p cachePolicy |
| if err := v.Unmarshal(&p); err != nil { |
| return cachePolicyDefault |
| } |
| return p |
| } |
| |
| func queueDescription(si *metadata.StorageItem, descr string) error { |
| v, err := metadata.NewValue(descr) |
| if err != nil { |
| return errors.Wrap(err, "failed to create description value") |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyDescription, v) |
| }) |
| return nil |
| } |
| |
| func GetDescription(si *metadata.StorageItem) string { |
| v := si.Get(keyDescription) |
| if v == nil { |
| return "" |
| } |
| var str string |
| if err := v.Unmarshal(&str); err != nil { |
| return "" |
| } |
| return str |
| } |
| |
| func queueCreatedAt(si *metadata.StorageItem, tm time.Time) error { |
| v, err := metadata.NewValue(tm.UnixNano()) |
| if err != nil { |
| return errors.Wrap(err, "failed to create createdAt value") |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyCreatedAt, v) |
| }) |
| return nil |
| } |
| |
| func GetCreatedAt(si *metadata.StorageItem) time.Time { |
| v := si.Get(keyCreatedAt) |
| if v == nil { |
| return time.Time{} |
| } |
| var tm int64 |
| if err := v.Unmarshal(&tm); err != nil { |
| return time.Time{} |
| } |
| return time.Unix(tm/1e9, tm%1e9) |
| } |
| |
| func getLastUsed(si *metadata.StorageItem) (int, *time.Time) { |
| v := si.Get(keyUsageCount) |
| if v == nil { |
| return 0, nil |
| } |
| var usageCount int |
| if err := v.Unmarshal(&usageCount); err != nil { |
| return 0, nil |
| } |
| v = si.Get(keyLastUsedAt) |
| if v == nil { |
| return usageCount, nil |
| } |
| var lastUsedTs int64 |
| if err := v.Unmarshal(&lastUsedTs); err != nil || lastUsedTs == 0 { |
| return usageCount, nil |
| } |
| tm := time.Unix(lastUsedTs/1e9, lastUsedTs%1e9) |
| return usageCount, &tm |
| } |
| |
| func updateLastUsed(si *metadata.StorageItem) error { |
| count, _ := getLastUsed(si) |
| count++ |
| |
| v, err := metadata.NewValue(count) |
| if err != nil { |
| return errors.Wrap(err, "failed to create usageCount value") |
| } |
| v2, err := metadata.NewValue(time.Now().UnixNano()) |
| if err != nil { |
| return errors.Wrap(err, "failed to create lastUsedAt value") |
| } |
| return si.Update(func(b *bolt.Bucket) error { |
| if err := si.SetValue(b, keyUsageCount, v); err != nil { |
| return err |
| } |
| return si.SetValue(b, keyLastUsedAt, v2) |
| }) |
| } |
| |
| func SetLayerType(m withMetadata, value string) error { |
| v, err := metadata.NewValue(value) |
| if err != nil { |
| return errors.Wrap(err, "failed to create layertype value") |
| } |
| m.Metadata().Queue(func(b *bolt.Bucket) error { |
| return m.Metadata().SetValue(b, keyLayerType, v) |
| }) |
| return m.Metadata().Commit() |
| } |
| |
| func GetLayerType(m withMetadata) string { |
| v := m.Metadata().Get(keyLayerType) |
| if v == nil { |
| return "" |
| } |
| var str string |
| if err := v.Unmarshal(&str); err != nil { |
| return "" |
| } |
| return str |
| } |
| |
| func GetRecordType(m withMetadata) client.UsageRecordType { |
| v := m.Metadata().Get(keyRecordType) |
| if v == nil { |
| return "" |
| } |
| var str string |
| if err := v.Unmarshal(&str); err != nil { |
| return "" |
| } |
| return client.UsageRecordType(str) |
| } |
| |
| func SetRecordType(m withMetadata, value client.UsageRecordType) error { |
| if err := queueRecordType(m.Metadata(), value); err != nil { |
| return err |
| } |
| return m.Metadata().Commit() |
| } |
| |
| func queueRecordType(si *metadata.StorageItem, value client.UsageRecordType) error { |
| v, err := metadata.NewValue(value) |
| if err != nil { |
| return errors.Wrap(err, "failed to create recordtype value") |
| } |
| si.Queue(func(b *bolt.Bucket) error { |
| return si.SetValue(b, keyRecordType, v) |
| }) |
| return nil |
| } |