From b29e1c163f3cc88037f301c1cc1d71c7707ee64f Mon Sep 17 00:00:00 2001 From: Ben Morrison Date: Tue, 21 May 2019 16:04:10 -0400 Subject: review of db functions --- cache.go | 90 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 28 deletions(-) (limited to 'cache.go') diff --git a/cache.go b/cache.go index 253de98..be3d7d3 100644 --- a/cache.go +++ b/cache.go @@ -10,18 +10,20 @@ import ( "github.com/syndtr/goleveldb/leveldb" ) -// checks if it's time to refresh the cache or not +// Checks whether it's time to refresh +// the cache. func checkCacheTime() bool { return time.Since(confObj.lastCache) > confObj.cacheInterval } -// checks if it's time to push the cache to the database +// Checks whether it's time to push +// the cache to the database func checkDBtime() bool { return time.Since(confObj.lastPush) > confObj.dbInterval } -// launched by init as a goroutine to constantly watch -// for the update interval to pass +// Launched by init as a goroutine to constantly watch +// for the update interval to pass. func cacheAndPush() { for { if checkCacheTime() { @@ -35,9 +37,11 @@ func cacheAndPush() { } } -// refreshes the cache +// Refreshes the cache. func refreshCache() { + // Iterate over the registry and + // update each individual user. for k := range twtxtCache.Reg { err := twtxtCache.UpdateUser(k) if err != nil { @@ -46,6 +50,9 @@ func refreshCache() { } } + // Re-scrape all the remote registries + // to see if they have any new users + // to add locally. for _, v := range remoteRegistries.List { err := twtxtCache.ScrapeRemoteRegistry(v) if err != nil { @@ -57,40 +64,46 @@ func refreshCache() { confObj.mu.Unlock() } -// pushes the registry's cache data to a local -// database for safe keeping +// Pushes the registry's cache data to a local +// database for safe keeping. func pushDatabase() error { + // Acquire the database from the aether. + // goleveldb is concurrency-safe, so we + // can immediately push it back into the + // channel for other functions to use. db := <-dbChan - twtxtCache.Mu.RLock() + dbChan <- db - // create a batch write job so it can + // Create a batch write job so it can // be done at one time rather than - // per value + // per entry. + twtxtCache.Mu.RLock() var dbBasket *leveldb.Batch for k, v := range twtxtCache.Reg { - dbBasket.Put([]byte(k+".Nick"), []byte(v.Nick)) - dbBasket.Put([]byte(k+".URL"), []byte(v.URL)) - dbBasket.Put([]byte(k+".IP"), []byte(v.IP)) - dbBasket.Put([]byte(k+".Date"), []byte(v.Date)) + dbBasket.Put([]byte(k+"*Nick"), []byte(v.Nick)) + dbBasket.Put([]byte(k+"*URL"), []byte(v.URL)) + dbBasket.Put([]byte(k+"*IP"), []byte(v.IP)) + dbBasket.Put([]byte(k+"*Date"), []byte(v.Date)) for i, e := range v.Status { - dbBasket.Put([]byte(k+".Status."+i.String()), []byte(e)) + rfc := i.Format(time.RFC3339) + dbBasket.Put([]byte(k+"*Status*"+rfc), []byte(e)) } } + twtxtCache.Mu.RUnlock() - // save our list of remote registries to scrape + // Save our list of remote registries to scrape. for k, v := range remoteRegistries.List { - dbBasket.Put([]byte("remote."+string(k)), []byte(v)) + dbBasket.Put([]byte("remote*"+string(k)), []byte(v)) } - // execute the batch job + // Execute the batch job. if err := db.Write(dbBasket, nil); err != nil { return err } - twtxtCache.Mu.RUnlock() - dbChan <- db - - // update the last push time + // Update the last push time for + // our timer/watch function to + // reference. confObj.mu.Lock() confObj.lastPush = time.Now() confObj.mu.Unlock() @@ -98,29 +111,42 @@ func pushDatabase() error { return nil } -// pulls registry data from the DB on startup +// Pulls registry data from the DB on startup. +// Iterates over the database one entry at a time. func pullDatabase() { + // Acquire the database from the aether. + // goleveldb is concurrency-safe, so we + // can immediately push it back into the + // channel for other functions to use. db := <-dbChan + dbChan <- db iter := db.NewIterator(nil, nil) + // Read the database key-by-key for iter.Next() { key := iter.Key() val := iter.Value() - split := strings.Split(string(key), ".") + split := strings.Split(string(key), "*") urls := string(split[0]) field := string(split[1]) - data := registry.NewUserData() + // Start with an empty Data struct. If + // there's already one in the cache, pull + // it and use it instead. + data := registry.NewUserData() twtxtCache.Mu.RLock() if _, ok := twtxtCache.Reg[urls]; ok { data = twtxtCache.Reg[urls] } twtxtCache.Mu.RUnlock() - ref := reflect.ValueOf(data).Elem() + // Use reflection to find the right field + // in the Data struct. Once found, assign + // the value and break so the DB iteration + // can continue. if field != "Status" && urls != "remote" { for i := 0; i < ref.NumField(); i++ { @@ -132,6 +158,9 @@ func pullDatabase() { } } else if field == "Status" && urls != "remote" { + // If we're looking at a Status entry in the DB, + // parse the time then add it to the TimeMap under + // data.Status thetime, err := time.Parse("RFC3339", split[2]) if err != nil { log.Printf("%v\n", err) @@ -139,11 +168,18 @@ func pullDatabase() { data.Status[thetime] = string(val) } else { + // The third and final possibility is + // if we've come across an entry for + // a remote twtxt registry to scrape. + // If so, add it to our list. remoteRegistries.Mu.Lock() remoteRegistries.List = append(remoteRegistries.List, string(val)) remoteRegistries.Mu.Unlock() + continue } + // Push the data struct (back) into + // the cache. twtxtCache.Mu.Lock() twtxtCache.Reg[urls] = data twtxtCache.Mu.Unlock() @@ -154,6 +190,4 @@ func pullDatabase() { if err != nil { log.Printf("Error while pulling DB into registry cache: %v\n", err) } - - dbChan <- db } -- cgit 1.4.1-2-gfad0