refresh su3 cache

This commit is contained in:
Matt Drollette
2014-12-11 08:24:06 -06:00
parent 9b88ec00f5
commit b7696f9be2
3 changed files with 130 additions and 18 deletions

View File

@@ -2,6 +2,8 @@ package reseed
import (
"crypto/rsa"
"fmt"
"hash/crc32"
"io/ioutil"
"log"
"math/rand"
@@ -10,6 +12,7 @@ import (
"os"
"path/filepath"
"regexp"
"time"
"github.com/MDrollette/go-i2p/su3"
)
@@ -29,20 +32,110 @@ type Reseeder interface {
Peer(r *http.Request) Peer
// create an Su3 file from the given seeds
CreateSu3(seeds Seeds) (*su3.Su3File, error)
// get signed su3 bytes for a peer
PeerSu3Bytes(peer Peer) ([]byte, error)
}
type ReseederImpl struct {
netdb NetDbProvider
SigningKey *rsa.PrivateKey
SignerId []byte
netdb NetDbProvider
su3s chan [][]byte
SigningKey *rsa.PrivateKey
SignerId []byte
NumRi int
RebuildInterval time.Duration
numSu3 int
}
func NewReseeder(netdb NetDbProvider) *ReseederImpl {
return &ReseederImpl{
netdb: netdb,
netdb: netdb,
su3s: make(chan [][]byte),
NumRi: 50,
RebuildInterval: 12 * time.Hour,
numSu3: 50,
}
}
func (rs *ReseederImpl) Start() chan bool {
// atomic swapper
go func() {
var m [][]byte
for {
select {
case m = <-rs.su3s:
case rs.su3s <- m:
}
}
}()
// init the cache
err := rs.rebuild()
if nil != err {
log.Println(err)
}
ticker := time.NewTicker(rs.RebuildInterval)
quit := make(chan bool)
go func() {
for {
select {
case <-ticker.C:
err := rs.rebuild()
if nil != err {
log.Println(err)
}
case <-quit:
ticker.Stop()
return
}
}
}()
return quit
}
func (rs *ReseederImpl) rebuild() error {
log.Println("Rebuilding SU3s...")
ris, err := rs.netdb.RouterInfos()
if nil != err {
return fmt.Errorf("Unable to get routerInfos: %s", err)
}
if rs.NumRi > len(ris) {
return fmt.Errorf("Not enough routerInfos.")
}
newSu3s := make([][]byte, rs.numSu3)
for i := 0; i < rs.numSu3; i++ {
var seeds Seeds
for _, z := range rand.Perm(rs.NumRi) {
seeds = append(seeds, ris[z])
}
gs, err := rs.CreateSu3(seeds)
if nil != err {
return err
}
newSu3s[i] = gs.Bytes()
}
rs.su3s <- newSu3s
log.Println("Done rebuilding.")
return nil
}
func (rs *ReseederImpl) PeerSu3Bytes(peer Peer) ([]byte, error) {
hashMod := int(crc32.ChecksumIEEE([]byte(peer))) % rs.numSu3
m := <-rs.su3s
defer func() { rs.su3s <- m }()
return m[hashMod], nil
}
func (rs *ReseederImpl) Seeds(p Peer) (Seeds, error) {
all, err := rs.netdb.RouterInfos()
if nil != err {