mirror of
https://github.com/namecoin/ncdns
synced 2024-11-16 00:13:01 +00:00
Merge #97: Add stream isolation (except for namecoind)
06d6efb
backend: Stream-isolate LRU cache (JeremyRand)ed8fa68
Add plumbing for stream isolation (JeremyRand) Pull request description: This PR adds the plumbing for stream isolation (from madns to namecoin, without passing the stream ID to namecoind), and stream-isolates the LRU cache. A follow-up PR will pass the stream ID to namecoind; that's currently blocked on https://github.com/namecoin/ncdns/pull/103 . Prerequisites: - [x] Merge https://github.com/hlandau/madns/pull/4 - [x] Merge https://github.com/hlandau/madns/pull/5 - [x] Tag a madns release (with major version 2). - [x] Replace `madns.v1` dependency with `madns.v2`. - [x] Tag a madns release (with https://github.com/hlandau/madns/pull/5 included). ACKs for commit 06d6ef: Tree-SHA512: ee385454aef3b802899659db74bbeb28ec6555216f4a4ccfc6047c08f32272080b7f76f851e4b291204ab41525bbfae30e7cdc663b49595d7d5105744810c763
This commit is contained in:
commit
1e2eea58c7
@ -2,7 +2,7 @@ package backend
|
||||
|
||||
import "github.com/miekg/dns"
|
||||
import "github.com/golang/groupcache/lru"
|
||||
import "gopkg.in/hlandau/madns.v1/merr"
|
||||
import "gopkg.in/hlandau/madns.v2/merr"
|
||||
import "github.com/namecoin/ncdns/namecoin"
|
||||
import "github.com/namecoin/ncdns/util"
|
||||
import "github.com/namecoin/ncdns/ncdomain"
|
||||
@ -18,14 +18,13 @@ import "time"
|
||||
// Provides an abstract zone file for the Namecoin .bit TLD.
|
||||
type Backend struct {
|
||||
//s *Server
|
||||
nc namecoin.Conn
|
||||
cache lru.Cache // items are of type *Domain
|
||||
nc namecoin.Conn
|
||||
// caches map keys are stream isolation ID's; items are of type *Domain
|
||||
caches map[string]*lru.Cache
|
||||
cacheMutex sync.Mutex
|
||||
cfg Config
|
||||
}
|
||||
|
||||
const defaultMaxEntries = 100
|
||||
|
||||
var log, Log = xlog.New("ncdns.backend")
|
||||
|
||||
// Backend configuration.
|
||||
@ -35,7 +34,7 @@ type Config struct {
|
||||
// Timeout (in milliseconds) for Namecoin RPC requests
|
||||
NamecoinTimeout int
|
||||
|
||||
// Maximum entries to permit in name cache. If zero, a default value is used.
|
||||
// Maximum entries to permit in name cache.
|
||||
CacheMaxEntries int
|
||||
|
||||
// Nameservers to advertise at zone apex. The first is considered the primary.
|
||||
@ -68,10 +67,7 @@ func New(cfg *Config) (backend *Backend, err error) {
|
||||
//b.nc.Password = cfg.RPCPassword
|
||||
//b.nc.Server = cfg.RPCAddress
|
||||
|
||||
b.cache.MaxEntries = cfg.CacheMaxEntries
|
||||
if b.cache.MaxEntries == 0 {
|
||||
b.cache.MaxEntries = defaultMaxEntries
|
||||
}
|
||||
b.caches = make(map[string]*lru.Cache)
|
||||
|
||||
hostmaster, err := convertEmail(b.cfg.Hostmaster)
|
||||
if err != nil {
|
||||
@ -109,7 +105,7 @@ func convertEmail(email string) (string, error) {
|
||||
|
||||
// Do low-level queries against an abstract zone file. This is the per-query
|
||||
// entrypoint from madns.
|
||||
func (b *Backend) Lookup(qname string) (rrs []dns.RR, err error) {
|
||||
func (b *Backend) Lookup(qname, streamIsolationID string) (rrs []dns.RR, err error) {
|
||||
err = lookupReadyError()
|
||||
if err != nil {
|
||||
return
|
||||
@ -118,6 +114,7 @@ func (b *Backend) Lookup(qname string) (rrs []dns.RR, err error) {
|
||||
btx := &btx{}
|
||||
btx.b = b
|
||||
btx.qname = qname
|
||||
btx.streamIsolationID = streamIsolationID
|
||||
return btx.Do()
|
||||
}
|
||||
|
||||
@ -126,6 +123,8 @@ type btx struct {
|
||||
b *Backend
|
||||
qname string
|
||||
|
||||
streamIsolationID string
|
||||
|
||||
subname, basename, rootname string
|
||||
}
|
||||
|
||||
@ -269,7 +268,7 @@ func (tx *btx) doUserDomain() (rrs []dns.RR, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
d, err := tx.b.getNamecoinEntry(ncname)
|
||||
d, err := tx.b.getNamecoinEntry(ncname, tx.streamIsolationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -287,26 +286,31 @@ type domain struct {
|
||||
ncv *ncdomain.Value
|
||||
}
|
||||
|
||||
func (b *Backend) getNamecoinEntry(name string) (*domain, error) {
|
||||
d := b.getNamecoinEntryCache(name)
|
||||
func (b *Backend) getNamecoinEntry(name, streamIsolationID string) (*domain, error) {
|
||||
d := b.getNamecoinEntryCache(name, streamIsolationID)
|
||||
if d != nil {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
d, err := b.getNamecoinEntryLL(name)
|
||||
d, err := b.getNamecoinEntryLL(name, streamIsolationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.addNamecoinEntryToCache(name, d)
|
||||
b.addNamecoinEntryToCache(name, d, streamIsolationID)
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (b *Backend) getNamecoinEntryCache(name string) *domain {
|
||||
func (b *Backend) getNamecoinEntryCache(name, streamIsolationID string) *domain {
|
||||
b.cacheMutex.Lock()
|
||||
defer b.cacheMutex.Unlock()
|
||||
|
||||
if dd, ok := b.cache.Get(name); ok {
|
||||
cache, ok := b.caches[streamIsolationID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if dd, ok := cache.Get(name); ok {
|
||||
d := dd.(*domain)
|
||||
return d
|
||||
}
|
||||
@ -314,20 +318,28 @@ func (b *Backend) getNamecoinEntryCache(name string) *domain {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) addNamecoinEntryToCache(name string, d *domain) {
|
||||
func (b *Backend) addNamecoinEntryToCache(name string, d *domain, streamIsolationID string) {
|
||||
b.cacheMutex.Lock()
|
||||
defer b.cacheMutex.Unlock()
|
||||
|
||||
b.cache.Add(name, d)
|
||||
cache, ok := b.caches[streamIsolationID]
|
||||
if !ok {
|
||||
b.caches[streamIsolationID] = &lru.Cache{
|
||||
MaxEntries: b.cfg.CacheMaxEntries,
|
||||
}
|
||||
cache = b.caches[streamIsolationID]
|
||||
}
|
||||
|
||||
cache.Add(name, d)
|
||||
}
|
||||
|
||||
func (b *Backend) getNamecoinEntryLL(name string) (*domain, error) {
|
||||
v, err := b.resolveName(name)
|
||||
func (b *Backend) getNamecoinEntryLL(name, streamIsolationID string) (*domain, error) {
|
||||
v, err := b.resolveName(name, streamIsolationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d, err := b.jsonToDomain(name, v)
|
||||
d, err := b.jsonToDomain(name, v, streamIsolationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -335,7 +347,7 @@ func (b *Backend) getNamecoinEntryLL(name string) (*domain, error) {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (b *Backend) resolveName(name string) (jsonValue string, err error) {
|
||||
func (b *Backend) resolveName(name, streamIsolationID string) (jsonValue string, err error) {
|
||||
if fv, ok := b.cfg.FakeNames[name]; ok {
|
||||
if fv == "NX" {
|
||||
return "", merr.ErrNoSuchDomain
|
||||
@ -349,7 +361,7 @@ func (b *Backend) resolveName(name string) (jsonValue string, err error) {
|
||||
// Namecoin JSON-RPC seem sluggish sometimes.
|
||||
result := make(chan struct{}, 1)
|
||||
go func() {
|
||||
jsonValue, err = b.nc.Query(name)
|
||||
jsonValue, err = b.nc.Query(name, streamIsolationID)
|
||||
log.Errore(err, "failed to query namecoin")
|
||||
result <- struct{}{}
|
||||
}()
|
||||
@ -362,10 +374,14 @@ func (b *Backend) resolveName(name string) (jsonValue string, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) jsonToDomain(name, jsonValue string) (*domain, error) {
|
||||
func (b *Backend) jsonToDomain(name, jsonValue, streamIsolationID string) (*domain, error) {
|
||||
d := &domain{}
|
||||
|
||||
v := ncdomain.ParseValue(name, jsonValue, b.resolveExtraName, nil)
|
||||
resolveExtraIsolated := func(n string) (string, error) {
|
||||
return b.resolveExtraName(n, streamIsolationID)
|
||||
}
|
||||
|
||||
v := ncdomain.ParseValue(name, jsonValue, resolveExtraIsolated, nil)
|
||||
if v == nil {
|
||||
return nil, fmt.Errorf("couldn't parse value")
|
||||
}
|
||||
@ -375,8 +391,8 @@ func (b *Backend) jsonToDomain(name, jsonValue string) (*domain, error) {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (b *Backend) resolveExtraName(name string) (jsonValue string, err error) {
|
||||
return b.resolveName(name)
|
||||
func (b *Backend) resolveExtraName(name, streamIsolationID string) (jsonValue string, err error) {
|
||||
return b.resolveName(name, streamIsolationID)
|
||||
}
|
||||
|
||||
func (tx *btx) doUnderDomain(d *domain) (rrs []dns.RR, err error) {
|
||||
|
@ -4,7 +4,7 @@ package namecoin
|
||||
import (
|
||||
extratypes "github.com/hlandau/ncbtcjsontypes"
|
||||
"github.com/hlandauf/btcjson"
|
||||
"gopkg.in/hlandau/madns.v1/merr"
|
||||
"gopkg.in/hlandau/madns.v2/merr"
|
||||
|
||||
"expvar"
|
||||
"fmt"
|
||||
@ -57,9 +57,14 @@ func (nc *Conn) rpcSend(cmd btcjson.Cmd) (btcjson.Reply, error) {
|
||||
// Query the Namecoin daemon for a Namecoin domain (e.g. d/example).
|
||||
// If the domain exists, returns the value stored in Namecoin, which should be JSON.
|
||||
// Note that this will return domain data even if the domain is expired.
|
||||
func (nc *Conn) Query(name string) (v string, err error) {
|
||||
func (nc *Conn) Query(name string, streamIsolationID string) (v string, err error) {
|
||||
cQueryCalls.Add(1)
|
||||
|
||||
// TODO: Pass stream isolation ID to namecoind, and remove this error
|
||||
if streamIsolationID != "" {
|
||||
return "", fmt.Errorf("Stream isolation ID '%s' is not yet passed to namecoind", streamIsolationID)
|
||||
}
|
||||
|
||||
cmd, err := extratypes.NewNameShowCmd(newID(), name)
|
||||
if err != nil {
|
||||
//log.Info("NC NEWCMD ", err)
|
||||
|
@ -41,7 +41,7 @@ func translateValue(k, v string) (string, error) {
|
||||
|
||||
f = os.NewFile(uintptr(n), "-")
|
||||
} else if len(v) == 1 {
|
||||
return conn.Query(k)
|
||||
return conn.Query(k, "")
|
||||
} else {
|
||||
f, err = os.Open(v)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func dumpName(item *extratypes.NameFilterItem, conn namecoin.Conn,
|
||||
}
|
||||
|
||||
getNameFunc := func(k string) (string, error) {
|
||||
return conn.Query(k)
|
||||
return conn.Query(k, "")
|
||||
}
|
||||
|
||||
var errors []error
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"github.com/miekg/dns"
|
||||
"github.com/namecoin/ncdns/backend"
|
||||
"github.com/namecoin/ncdns/namecoin"
|
||||
"gopkg.in/hlandau/madns.v1"
|
||||
"gopkg.in/hlandau/madns.v2"
|
||||
)
|
||||
|
||||
var log, Log = xlog.New("ncdns.server")
|
||||
|
@ -140,7 +140,7 @@ func (ws *webServer) handleLookup(rw http.ResponseWriter, req *http.Request) {
|
||||
info.JSONValue = req.FormValue("value")
|
||||
info.Value = strings.Trim(info.JSONValue, " \t\r\n")
|
||||
if info.Value == "" {
|
||||
info.Value, info.ExistenceError = ws.s.namecoinConn.Query(info.NamecoinName)
|
||||
info.Value, info.ExistenceError = ws.s.namecoinConn.Query(info.NamecoinName, "")
|
||||
if info.ExistenceError != nil {
|
||||
return
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (ws *webServer) handleLookup(rw http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
func (ws *webServer) resolveFunc(name string) (string, error) {
|
||||
return ws.s.namecoinConn.Query(name)
|
||||
return ws.s.namecoinConn.Query(name, "")
|
||||
}
|
||||
|
||||
func (ws *webServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package util
|
||||
|
||||
import "strings"
|
||||
import "gopkg.in/hlandau/madns.v1/merr"
|
||||
import "gopkg.in/hlandau/madns.v2/merr"
|
||||
import "fmt"
|
||||
import "regexp"
|
||||
import "net/mail"
|
||||
|
@ -2,7 +2,7 @@ package util_test
|
||||
|
||||
import "testing"
|
||||
import "github.com/namecoin/ncdns/util"
|
||||
import "gopkg.in/hlandau/madns.v1/merr"
|
||||
import "gopkg.in/hlandau/madns.v2/merr"
|
||||
|
||||
type item struct {
|
||||
input string
|
||||
|
Loading…
Reference in New Issue
Block a user