# HG changeset patch # User Sascha L. Teichmann # Date 1537547561 -7200 # Node ID 7eed7ff3142d575a4140a9368d5d1305787cdda3 # Parent 815f5e2ed9743c4ba4aedf9f9082139d0469a782 Started with model to load octrees from database. diff -r 815f5e2ed974 -r 7eed7ff3142d pkg/models/octree.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/models/octree.go Fri Sep 21 18:32:41 2018 +0200 @@ -0,0 +1,5 @@ +package models + +type Octree struct { + // TODO: Implement me! +} diff -r 815f5e2ed974 -r 7eed7ff3142d pkg/models/octreecache.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/models/octreecache.go Fri Sep 21 18:32:41 2018 +0200 @@ -0,0 +1,103 @@ +package models + +import ( + "context" + "database/sql" + "sync" + "time" +) + +type ( + octreeCacheKey struct { + date time.Time + bottleneck string + } + + octreeCacheEntry struct { + checksum string + tree *Octree + access time.Time + } + octreeCache struct { + sync.Mutex + entries map[octreeCacheKey]*octreeCacheEntry + } +) + +const ( + cleanupOctreeCacheSleep = 6 * time.Minute + maxOctreeCacheAge = 5 * time.Minute + maxOctreeCacheEntries = 4 +) + +const ( + fetchOctreeSQL = ` +SELECT checksum, octree_index +FROM waterway.octrees ot +JOIN waterway.sounding_results sr ON ot.sounding_result_id = sr.id +WHERE sr.bottleneck_id = $1 AND sr.date_info = $2::date +` + checkOctreeSQL = ` +SELECT CASE + WHEN checksum = $3 THEN NULL + ELSE ot.octree_index + END +FROM waterway.octrees ot +JOIN waterway.sounding_results sr ON ot.sounding_result_id = sr.id +WHERE sr.bottleneck_id = $1 AND sr.date_info = $2::date +` +) + +var OctreeCache = octreeCache{ + entries: map[octreeCacheKey]*octreeCacheEntry{}, +} + +func init() { + go OctreeCache.background() +} + +func (oc *octreeCache) background() { + for { + time.Sleep(cleanupOctreeCacheSleep) + oc.cleanup() + } +} + +func (oc *octreeCache) cleanup() { + oc.Lock() + defer oc.Unlock() + good := time.Now().Add(-maxOctreeCacheAge) + for k, v := range oc.entries { + if v.access.Before(good) { + delete(oc.entries, k) + } + } +} + +func (oc *octreeCache) Get( + bottleneck string, date time.Time, + conn *sql.Conn, ctx context.Context, +) (*Octree, error) { + oc.Lock() + defer oc.Unlock() + + key := octreeCacheKey{date, bottleneck} + entry := oc.entries[key] + if entry == nil { + // fetch from database + var data []byte + err := conn.QueryRowContext(ctx, fetchOctreeSQL, bottleneck, date).Scan(&data) + switch { + case err == sql.ErrNoRows: + return nil, nil + case err != nil: + return nil, err + } + // TODO: Deserialize! + } else { + // check if we are not outdated. + // TODO: Implement me! + } + + return nil, nil +}