Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2356)

Unified Diff: build_scheduler/go/db/memory.go

Issue 2226583003: Add build scheduler DB interface, dumb in-memory impl, cache (Closed) Base URL: https://skia.googlesource.com/buildbot@master
Patch Set: Fix import Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: build_scheduler/go/db/memory.go
diff --git a/build_scheduler/go/db/memory.go b/build_scheduler/go/db/memory.go
new file mode 100644
index 0000000000000000000000000000000000000000..f0e25cc24fadc2291137706b6039202438de696b
--- /dev/null
+++ b/build_scheduler/go/db/memory.go
@@ -0,0 +1,149 @@
+package db
+
+import (
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/satori/go.uuid"
+ "github.com/skia-dev/glog"
+)
+
+type BuildSlice []*Build
+
+func (s BuildSlice) Len() int { return len(s) }
+
+func (s BuildSlice) Less(i, j int) bool {
+ ts1, err := s[i].Created()
+ if err != nil {
+ glog.Errorf("Failed to parse CreatedTimestamp: %v", s[i])
+ }
+ ts2, err := s[j].Created()
+ if err != nil {
+ glog.Errorf("Failed to parse CreatedTimestamp: %v", s[j])
+ }
+ return ts1.Before(ts2)
+}
+
+func (s BuildSlice) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+type inMemoryDB struct {
+ builds map[string]*Build
+ buildsMtx sync.RWMutex
+ modBuilds map[string]map[string]*Build
+ modExpire map[string]time.Time
+ modMtx sync.RWMutex
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) Close() error {
+ return nil
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) GetBuildsFromDateRange(start, end time.Time) ([]*Build, error) {
+ db.buildsMtx.RLock()
+ defer db.buildsMtx.RUnlock()
+
+ rv := []*Build{}
+ // TODO(borenet): Binary search.
+ for _, b := range db.builds {
+ created, err := b.Created()
+ if err != nil {
+ return nil, err
+ }
+ if created.After(start) && created.Before(end) {
+ rv = append(rv, b)
dogben 2016/08/08 19:22:38 nit: Probably want to copy. (Or change the docs o
borenet 2016/08/08 19:51:18 Done.
+ }
+ }
+ sort.Sort(BuildSlice(rv))
+ return rv, nil
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) GetModifiedBuilds(id string) ([]*Build, error) {
+ db.modMtx.Lock()
+ defer db.modMtx.Unlock()
+ modifiedBuilds, ok := db.modBuilds[id]
+ if !ok {
+ return nil, ErrUnknownId
+ }
+ rv := make([]*Build, 0, len(modifiedBuilds))
+ for _, b := range modifiedBuilds {
+ rv = append(rv, b)
dogben 2016/08/08 19:22:39 nit: Probably want to copy.
borenet 2016/08/08 19:51:18 Done.
+ }
+ db.modExpire[id] = time.Now().Add(MODIFIED_BUILDS_TIMEOUT)
+ db.modBuilds[id] = map[string]*Build{}
+ sort.Sort(BuildSlice(rv))
+ return rv, nil
+}
+
+func (db *inMemoryDB) clearExpiredModifiedUsers() {
+ db.modMtx.Lock()
+ defer db.modMtx.Unlock()
+ for id, t := range db.modExpire {
+ if time.Now().After(t) {
+ delete(db.modBuilds, id)
+ delete(db.modExpire, id)
+ }
+ }
+}
+
+func (db *inMemoryDB) modify(b *Build) {
+ db.modMtx.Lock()
+ defer db.modMtx.Unlock()
+ for _, modBuilds := range db.modBuilds {
+ modBuilds[b.Id] = b.Copy()
+ }
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) PutBuild(build *Build) error {
+ db.buildsMtx.Lock()
+ defer db.buildsMtx.Unlock()
+
+ // TODO(borenet): Keep builds in a sorted slice.
+ db.builds[build.Id] = build
+ db.modify(build)
+ return nil
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) PutBuilds(builds []*Build) error {
+ for _, b := range builds {
+ if err := db.PutBuild(b); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// See docs for DB interface.
+func (db *inMemoryDB) StartTrackingModifiedBuilds() (string, error) {
+ db.modMtx.Lock()
+ defer db.modMtx.Unlock()
+ if len(db.modBuilds) >= MAX_MODIFIED_BUILDS_USERS {
+ return "", ErrTooManyUsers
+ }
+ id := uuid.NewV5(uuid.NewV1(), uuid.NewV4().String()).String()
+ db.modBuilds[id] = map[string]*Build{}
+ db.modExpire[id] = time.Now().Add(MODIFIED_BUILDS_TIMEOUT)
+ return id, nil
+}
+
+// NewInMemoryDB returns an extremely simple, inefficient, in-memory DB implementation.
+func NewInMemoryDB() DB {
+ db := &inMemoryDB{
+ builds: map[string]*Build{},
+ modBuilds: map[string]map[string]*Build{},
+ modExpire: map[string]time.Time{},
+ }
+ go func() {
+ for _ = range time.Tick(time.Minute) {
+ db.clearExpiredModifiedUsers()
+ }
+ }()
+ return db
+}

Powered by Google App Engine
This is Rietveld 408576698