diff pkg/octree/cache.go @ 725:e0437ec46798

Finished the octree cache. TODO: implement the deserialization.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sat, 22 Sep 2018 09:55:42 +0200
parents 6ab0c170e5b8
children 41c8dc61f38f
line wrap: on
line diff
--- a/pkg/octree/cache.go	Sat Sep 22 09:36:12 2018 +0200
+++ b/pkg/octree/cache.go	Sat Sep 22 09:55:42 2018 +0200
@@ -83,21 +83,68 @@
 
 	key := cacheKey{date, bottleneck}
 	entry := oc.entries[key]
+
+	var data []byte
+	var checksum string
+
 	if entry == nil {
 		// fetch from database
-		var data []byte
-		err := conn.QueryRowContext(ctx, fetchOctreeSQL, bottleneck, date).Scan(&data)
+		err := conn.QueryRowContext(
+			ctx, fetchOctreeSQL, bottleneck, date).Scan(&checksum, &data)
+		switch {
+		case err == sql.ErrNoRows:
+			return nil, nil
+		case err != nil:
+			return nil, err
+		}
+	} else {
+		// check if we are not outdated.
+		err := conn.QueryRowContext(
+			ctx, checkOctreeSQL, bottleneck, date, entry.checksum).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!
+		if data == nil { // we are still current
+			entry.access = time.Now()
+			return entry.tree, nil
+		}
+	}
+
+	tree, err := Deserialize(data)
+	if err != nil {
+		return nil, err
+	}
+
+	now := time.Now()
+
+	if entry != nil {
+		entry.tree = tree
+		entry.access = now
+		return tree, nil
 	}
 
-	return nil, nil
+	for len(oc.entries) >= maxCacheEntries {
+		// Evict the entry that is accessed the longest time ago.
+		var oldestKey cacheKey
+		oldest := now
+
+		for k, v := range oc.entries {
+			if v.access.Before(oldest) {
+				oldest = v.access
+				oldestKey = k
+			}
+		}
+		delete(oc.entries, oldestKey)
+	}
+
+	oc.entries[key] = &cacheEntry{
+		checksum: checksum,
+		tree:     tree,
+		access:   now,
+	}
+
+	return tree, nil
 }