index: cleanup and formalizing key formats into their own types

Change-Id: I36aaa74ee7a4349bb00c1ac06285d4c43f4c61bc
This commit is contained in:
Brad Fitzpatrick 2011-11-29 17:33:10 -05:00
parent f23aadf801
commit dd5726a4d1
4 changed files with 125 additions and 14 deletions

View File

@ -127,6 +127,30 @@ func New(s IndexStorage) *Index {
}
}
type prefixIter struct {
Iterator
prefix string
}
func (p *prefixIter) Next() bool {
v := p.Iterator.Next()
if v && !strings.HasPrefix(p.Key(), p.prefix) {
return false
}
return v
}
func (x *Index) queryPrefix(key *keyType, args ...interface{}) *prefixIter {
return x.queryPrefixString(key.Prefix(args...))
}
func (x *Index) queryPrefixString(prefix string) *prefixIter {
return &prefixIter{
prefix: prefix,
Iterator: x.s.Find(prefix),
}
}
func (x *Index) GetRecentPermanodes(dest chan *search.Result, owner *blobref.BlobRef, limit int) os.Error {
defer close(dest)
// TODO(bradfitz): this will need to be a context wrapper too, like storage
@ -141,13 +165,10 @@ func (x *Index) GetRecentPermanodes(dest chan *search.Result, owner *blobref.Blo
sent := 0
var seenPermanode dupSkipper
prefix := pipes("recpn", keyId, "")
it := x.s.Find(prefix)
it := x.queryPrefix(keyRecentPermanode, keyId)
defer it.Close()
for it.Next() {
if !strings.HasPrefix(it.Key(), prefix) {
break
}
permaStr := it.Value()
parts := strings.SplitN(it.Key(), "|", 4)
if len(parts) != 4 {
@ -191,12 +212,9 @@ func (x *Index) GetOwnerClaims(permaNode, owner *blobref.BlobRef) (cl search.Cla
return nil, err
}
prefix := pipes("claim", permaNode, keyId, "")
it := x.s.Find(prefix)
it := x.queryPrefixString(prefix)
defer it.Close()
for it.Next() {
if !strings.HasPrefix(it.Key(), prefix) {
break
}
keyPart := strings.Split(it.Key(), "|")
valPart := strings.Split(it.Value(), "|")
if len(keyPart) < 5 || len(valPart) < 3 {
@ -257,13 +275,10 @@ func (x *Index) PermanodeOfSignerAttrValue(signer *blobref.BlobRef, attr, val st
if err != nil {
return nil, err
}
prefix := pipes("signerattrvalue", keyId, urle(attr), urle(val), "")
it := x.s.Find(prefix)
it := x.queryPrefixString(pipes("signerattrvalue", keyId, urle(attr), urle(val), ""))
defer it.Close()
if it.Next() {
if strings.HasPrefix(it.Key(), prefix) {
return blobref.Parse(it.Value()), nil
}
return blobref.Parse(it.Value()), nil
}
return nil, os.ENOENT
}

View File

@ -0,0 +1,68 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package index
import (
"bytes"
"fmt"
)
type keyType struct {
name string
parts []keyPart
}
func (k *keyType) Prefix(args ...interface{}) string {
var buf bytes.Buffer
buf.WriteString(k.name)
for _, arg := range args {
buf.WriteString("|")
// TODO(bradfitz): verify the type matches
if s, ok := arg.(string); ok {
buf.WriteString(s)
} else {
buf.WriteString(arg.(fmt.Stringer).String())
}
}
buf.WriteString("|")
return buf.String()
}
type keyPart struct {
name string
typ partType
}
type partType int
const (
typeKeyId partType = iota // PGP key id
typeTime
typeReverseTime // time prepended with "rt" + each numeric digit reversed from '9'
typeBlobRef
)
var (
keyRecentPermanode = &keyType{
"recpn",
[]keyPart{
{"owner", typeKeyId},
{"modtime", typeReverseTime},
{"claim", typeBlobRef},
},
}
)

View File

@ -0,0 +1,27 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package index
import (
"testing"
)
func TestKeyPrefix(t *testing.T) {
if g, e := keyRecentPermanode.Prefix("ABC"), "recpn|ABC|"; g != e {
t.Errorf("recpn = %q; want %q", g, e)
}
}

View File

@ -121,6 +121,7 @@ func (ix *Index) populateClaim(br *blobref.BlobRef, ss *schema.Superset, sniffer
bm.Set("signerkeyid:"+vr.CamliSigner.String(), verifiedKeyId)
// TODO(bradfitz): use keyRecentPermanode here instead of pipes() with "recpn".
recentKey := pipes("recpn", verifiedKeyId, reverseTimeString(ss.ClaimDate), br)
bm.Set(recentKey, pnbr.String())