作者:splad
项目:camlistor
func TestHubFiring(t *testing.T) {
hub := &SimpleBlobHub{}
ch := make(chan *blobref.BlobRef)
bch := make(chan *blobref.BlobRef)
blob := blobref.Parse("sha1-0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
blobsame := blobref.Parse("sha1-0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
hub.NotifyBlobReceived(blob) // no-op
hub.RegisterListener(ch)
hub.RegisterBlobListener(blob, bch)
hub.NotifyBlobReceived(blobsame)
tmr1 := time.NewTimer(1e9)
select {
case <-tmr1.C:
t.Fatal("timer expired on receiving from ch")
case got := <-ch:
if !blob.Equal(got) {
t.Fatalf("got wrong blob")
}
}
select {
case <-tmr1.C:
t.Fatal("timer expired on receiving from bch")
case got := <-bch:
if !blob.Equal(got) {
t.Fatalf("got wrong blob")
}
}
tmr1.Stop()
}
作者:oria
项目:camlistor
// StaticSet returns the whole of the static set members of that directory
func (dr *DirReader) StaticSet() ([]*blobref.BlobRef, error) {
if dr.staticSet != nil {
return dr.staticSet, nil
}
staticSetBlobref := blobref.Parse(dr.ss.Entries)
if staticSetBlobref == nil {
return nil, fmt.Errorf("schema/filereader: Invalid blobref\n")
}
rsc, _, err := dr.fetcher.Fetch(staticSetBlobref)
if err != nil {
return nil, fmt.Errorf("schema/filereader: fetching schema blob %s: %v", staticSetBlobref, err)
}
ss, err := ParseSuperset(rsc)
if err != nil {
return nil, fmt.Errorf("schema/filereader: decoding schema blob %s: %v", staticSetBlobref, err)
}
if ss.Type != "static-set" {
return nil, fmt.Errorf("schema/filereader: expected \"static-set\" schema blob for %s, got %q", staticSetBlobref, ss.Type)
}
for _, s := range ss.Members {
member := blobref.Parse(s)
if member == nil {
return nil, fmt.Errorf("schema/filereader: invalid (static-set member) blobref\n")
}
dr.staticSet = append(dr.staticSet, member)
}
return dr.staticSet, nil
}
作者:t3rm1n4
项目:camlistor
func (x *Index) PathsOfSignerTarget(signer, target *blobref.BlobRef) (paths []*search.Path, err error) {
paths = []*search.Path{}
keyId, err := x.keyId(signer)
if err != nil {
if err == ErrNotFound {
err = nil
}
return
}
mostRecent := make(map[string]*search.Path)
maxClaimDates := make(map[string]string)
it := x.queryPrefix(keyPathBackward, keyId, target)
defer closeIterator(it, &err)
for it.Next() {
keyPart := strings.Split(it.Key(), "|")[1:]
valPart := strings.Split(it.Value(), "|")
if len(keyPart) < 3 || len(valPart) < 4 {
continue
}
claimRef := blobref.Parse(keyPart[2])
baseRef := blobref.Parse(valPart[1])
if claimRef == nil || baseRef == nil {
continue
}
claimDate := valPart[0]
active := valPart[2]
suffix := urld(valPart[3])
key := baseRef.String() + "/" + suffix
if claimDate > maxClaimDates[key] {
maxClaimDates[key] = claimDate
if active == "Y" {
mostRecent[key] = &search.Path{
Claim: claimRef,
ClaimDate: claimDate,
Base: baseRef,
Suffix: suffix,
Target: target,
}
} else {
delete(mostRecent, key)
}
}
}
for _, v := range mostRecent {
paths = append(paths, v)
}
return paths, nil
}
作者:hagn
项目:camlistor
// fromHTTP panics with an httputil value on failure
func (r *WithAttrRequest) fromHTTP(req *http.Request) {
r.Signer = blobref.Parse(req.FormValue("signer"))
r.Value = req.FormValue("value")
fuzzy := req.FormValue("fuzzy") // exact match if empty
fuzzyMatch := false
if fuzzy != "" {
lowered := strings.ToLower(fuzzy)
if lowered == "true" || lowered == "t" {
fuzzyMatch = true
}
}
r.Attr = req.FormValue("attr") // all attributes if empty
if r.Attr == "" { // and force fuzzy in that case.
fuzzyMatch = true
}
r.Fuzzy = fuzzyMatch
r.ThumbnailSize = thumbnailSize(req)
max := req.FormValue("max")
if max != "" {
maxR, err := strconv.Atoi(max)
if err != nil {
panic(httputil.InvalidParameterError("max"))
}
r.N = maxR
}
r.N = r.n()
}
作者:propp
项目:camlistor
// MustGetBlobRef returns a non-nil BlobRef from req, as given by param.
// If it doesn't, it panics with a value understood by Recover or RecoverJSON.
func MustGetBlobRef(req *http.Request, param string) *blobref.BlobRef {
br := blobref.Parse(MustGet(req, param))
if br == nil {
panic(InvalidParameterError(param))
}
return br
}
作者:robry
项目:camlistor
func newHandlerFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, error) {
indexPrefix := conf.RequiredString("index") // TODO: add optional help tips here?
ownerBlobStr := conf.RequiredString("owner")
devBlockStartupPrefix := conf.OptionalString("devBlockStartupOn", "")
if err := conf.Validate(); err != nil {
return nil, err
}
if devBlockStartupPrefix != "" {
_, err := ld.GetHandler(devBlockStartupPrefix)
if err != nil {
return nil, fmt.Errorf("search handler references bogus devBlockStartupOn handler %s: %v", devBlockStartupPrefix, err)
}
}
indexHandler, err := ld.GetHandler(indexPrefix)
if err != nil {
return nil, fmt.Errorf("search config references unknown handler %q", indexPrefix)
}
indexer, ok := indexHandler.(Index)
if !ok {
return nil, fmt.Errorf("search config references invalid indexer %q (actually a %T)", indexPrefix, indexHandler)
}
ownerBlobRef := blobref.Parse(ownerBlobStr)
if ownerBlobRef == nil {
return nil, fmt.Errorf("search 'owner' has malformed blobref %q; expecting e.g. sha1-xxxxxxxxxxxx",
ownerBlobStr)
}
return &Handler{
index: indexer,
owner: ownerBlobRef,
}, nil
}
作者:splad
项目:camlistor
// Given a described blob, optionally follows a camliContent and
// returns the file's schema blobref and its fileinfo (if found).
func (pr *publishRequest) fileSchemaRefFromBlob(des *search.DescribedBlob) (fileref *blobref.BlobRef, fileinfo *search.FileInfo, ok bool) {
if des == nil {
http.NotFound(pr.rw, pr.req)
return
}
if des.Permanode != nil {
// TODO: get "forceMime" attr out of the permanode? or
// fileName content-disposition?
if cref := des.Permanode.Attr.Get("camliContent"); cref != "" {
cbr := blobref.Parse(cref)
if cbr == nil {
http.Error(pr.rw, "bogus camliContent", 500)
return
}
des = des.PeerBlob(cbr)
if des == nil {
http.Error(pr.rw, "camliContent not a peer in describe", 500)
return
}
}
}
if des.CamliType == "file" {
return des.BlobRef, des.File, true
}
http.Error(pr.rw, "failed to find fileSchemaRefFromBlob", 404)
return
}
作者:t3rm1n4
项目:camlistor
func (x *Index) GetOwnerClaims(permaNode, owner *blobref.BlobRef) (cl search.ClaimList, err error) {
keyId, err := x.keyId(owner)
if err == ErrNotFound {
err = nil
return
}
if err != nil {
return nil, err
}
prefix := pipes("claim", permaNode, keyId, "")
it := x.queryPrefixString(prefix)
defer closeIterator(it, &err)
for it.Next() {
keyPart := strings.Split(it.Key(), "|")
valPart := strings.Split(it.Value(), "|")
if len(keyPart) < 5 || len(valPart) < 3 {
continue
}
claimRef := blobref.Parse(keyPart[4])
if claimRef == nil {
continue
}
date, _ := time.Parse(time.RFC3339, keyPart[3])
cl = append(cl, &search.Claim{
BlobRef: claimRef,
Signer: owner,
Permanode: permaNode,
Date: date,
Type: urld(valPart[0]),
Attr: urld(valPart[1]),
Value: urld(valPart[2]),
})
}
return
}
作者:robry
项目:camlistor
func (ui *UIHandler) serveDownload(rw http.ResponseWriter, req *http.Request) {
if ui.root.Storage == nil {
http.Error(rw, "No BlobRoot configured", 500)
return
}
suffix := req.Header.Get("X-PrefixHandler-PathSuffix")
m := downloadPattern.FindStringSubmatch(suffix)
if m == nil {
httputil.ErrorRouting(rw, req)
return
}
fbr := blobref.Parse(m[1])
if fbr == nil {
http.Error(rw, "Invalid blobref", 400)
return
}
dh := &DownloadHandler{
Fetcher: ui.root.Storage,
Cache: ui.Cache,
}
dh.ServeHTTP(rw, req, fbr)
}
作者:t3rm1n4
项目:camlistor
// isDeleted returns whether br (a blobref or a claim) should be considered deleted.
func (x *Index) isDeleted(br *blobref.BlobRef) bool {
var err error
it := x.queryPrefix(keyDeleted, br)
defer closeIterator(it, &err)
for it.Next() {
// parts are ["deleted", br.String(), blobref-of-delete-claim].
// see keyDeleted in keys.go
parts := strings.SplitN(it.Key(), "|", 3)
if len(parts) != 3 {
continue
}
delClaimRef := blobref.Parse(parts[2])
if delClaimRef == nil {
panic(fmt.Errorf("invalid deleted claim for %v", parts[1]))
}
// The recursive call on the blobref of the delete claim
// checks that the claim itself was not deleted, in which case
// br is not considered deleted anymore.
// TODO(mpl): Each delete and undo delete adds a level of
// recursion so this could recurse far. is there a way to
// go faster in a worst case scenario?
return !x.isDeleted(delClaimRef)
}
return false
}
作者:splad
项目:camlistor
func (vr *VerifyRequest) ParsePayloadMap() bool {
vr.PayloadMap = make(map[string]interface{})
pm := vr.PayloadMap
if err := json.Unmarshal(vr.bpj, &pm); err != nil {
return vr.fail("parse error; payload JSON is invalid")
}
if _, hasVersion := pm["camliVersion"]; !hasVersion {
return vr.fail("missing 'camliVersion' in the JSON payload")
}
signer, hasSigner := pm["camliSigner"]
if !hasSigner {
return vr.fail("missing 'camliSigner' in the JSON payload")
}
if _, ok := signer.(string); !ok {
return vr.fail("invalid 'camliSigner' in the JSON payload")
}
vr.CamliSigner = blobref.Parse(signer.(string))
if vr.CamliSigner == nil {
return vr.fail("malformed 'camliSigner' blobref in the JSON payload")
}
return true
}
作者:robry
项目:camlistor
func (c *attrCmd) RunCommand(args []string) error {
if len(args) != 3 {
return errors.New("Attr takes 3 args: <permanode> <attr> <value>")
}
permanode, attr, value := args[0], args[1], args[2]
var err error
pn := blobref.Parse(permanode)
if pn == nil {
return fmt.Errorf("Error parsing blobref %q", permanode)
}
bb := schema.NewSetAttributeClaim(pn, attr, value)
if c.add {
if c.del {
return errors.New("Add and del options are exclusive")
}
bb = schema.NewAddAttributeClaim(pn, attr, value)
} else {
// TODO: del, which can make <value> be optional
if c.del {
return errors.New("del not yet implemented")
}
}
put, err := getUploader().UploadAndSignBlob(bb)
handleResult(bb.Type(), put, err)
return nil
}
作者:splad
项目:camlistor
// TODO(rh): tame copy/paste code from cammount
func main() {
client.AddFlags()
flag.Parse()
cacheDir, err := ioutil.TempDir("", "camlicache")
if err != nil {
log.Fatalf("Error creating temp cache directory: %v", err)
}
defer os.RemoveAll(cacheDir)
diskcache, err := localdisk.New(cacheDir)
if err != nil {
log.Fatalf("Error setting up local disk cache: %v", err)
}
if flag.NArg() != 1 {
log.Fatal("usage: camwebdav <blobref>")
}
br := blobref.Parse(flag.Arg(0))
if br == nil {
log.Fatalf("%s was not a valid blobref.", flag.Arg(0))
}
client := client.NewOrFail()
fetcher := cacher.NewCachingFetcher(diskcache, client)
f = fs.NewCamliFileSystem(fetcher, br)
http.HandleFunc("/", webdav)
err = http.ListenAndServe(*davaddr, nil)
if err != nil {
log.Fatalf("Error starting WebDAV server: %v", err)
}
}
作者:robry
项目:camlistor
func (ui *UIHandler) serveFileTree(rw http.ResponseWriter, req *http.Request) {
if ui.root.Storage == nil {
http.Error(rw, "No BlobRoot configured", 500)
return
}
suffix := req.Header.Get("X-PrefixHandler-PathSuffix")
m := treePattern.FindStringSubmatch(suffix)
if m == nil {
httputil.ErrorRouting(rw, req)
return
}
blobref := blobref.Parse(m[1])
if blobref == nil {
http.Error(rw, "Invalid blobref", 400)
return
}
fth := &FileTreeHandler{
Fetcher: ui.root.Storage,
file: blobref,
}
fth.ServeHTTP(rw, req)
}
作者:splad
项目:camlistor
func main() {
// Scans the arg list and sets up flags
debug := flag.Bool("debug", false, "print debugging messages.")
client.AddFlags()
flag.Parse()
errorf := func(msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, msg, args...)
os.Exit(2)
}
if n := flag.NArg(); n < 1 || n > 2 {
errorf("usage: cammount <mountpoint> [<root-blobref>]\n")
}
mountPoint := flag.Arg(0)
client := client.NewOrFail() // automatic from flags
cacheDir, err := ioutil.TempDir("", "camlicache")
if err != nil {
errorf("Error creating temp cache directory: %v\n", err)
}
defer os.RemoveAll(cacheDir)
diskcache, err := localdisk.New(cacheDir)
if err != nil {
errorf("Error setting up local disk cache: %v", err)
}
fetcher := cacher.NewCachingFetcher(diskcache, client)
var camfs *fs.CamliFileSystem
if flag.NArg() == 2 {
root := blobref.Parse(flag.Arg(1))
if root == nil {
errorf("Error parsing root blobref: %q\n", root)
}
var err error
camfs, err = fs.NewRootedCamliFileSystem(fetcher, root)
if err != nil {
errorf("Error creating root with %v: %v", root, err)
}
} else {
camfs = fs.NewCamliFileSystem(fetcher)
log.Printf("starting with fs %#v", camfs)
}
if *debug {
// TODO: set fs's logger
}
conn, err := fuse.Mount(mountPoint)
if err != nil {
log.Fatalf("Mount: %v", err)
}
err = conn.Serve(camfs)
if err != nil {
log.Fatalf("Serve: %v", err)
}
log.Printf("fuse process ending.")
}
作者:robry
项目:camlistor
func (sh *Handler) serveFiles(rw http.ResponseWriter, req *http.Request) {
ret := jsonMap()
defer httputil.ReturnJSON(rw, ret)
br := blobref.Parse(req.FormValue("wholedigest"))
if br == nil {
ret["error"] = "Missing or invalid 'wholedigest' param"
ret["errorType"] = "input"
return
}
files, err := sh.index.ExistingFileSchemas(br)
if err != nil {
ret["error"] = err.Error()
ret["errorType"] = "server"
return
}
strList := []string{}
for _, br := range files {
strList = append(strList, br.String())
}
ret["files"] = strList
return
}
作者:stunt
项目:camlistor
func (sto *appengineStorage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit int, wait time.Duration) error {
defer close(dest)
ctx := sto.ctx
if ctx == nil {
loan := ctxPool.Get()
defer loan.Return()
ctx = loan
}
prefix := sto.namespace + "|"
keyBegin := datastore.NewKey(ctx, memKind, prefix+after, 0, nil)
keyEnd := datastore.NewKey(ctx, memKind, sto.namespace+"~", 0, nil)
q := datastore.NewQuery(memKind).Limit(int(limit)).Filter("__key__>", keyBegin).Filter("__key__<", keyEnd)
it := q.Run(ctx)
var row memEnt
for {
key, err := it.Next(&row)
if err == datastore.Done {
break
}
if err != nil {
return err
}
dest <- blobref.SizedBlobRef{blobref.Parse(key.StringID()[len(prefix):]), row.Size}
}
return nil
}
作者:hagn
项目:camlistor
func (n *root) Lookup(name string, intr fuse.Intr) (fuse.Node, fuse.Error) {
switch name {
case ".quitquitquit":
log.Fatalf("Shutting down due to root .quitquitquit lookup.")
case "WELCOME.txt":
return staticFileNode("Welcome to CamlistoreFS.\n\nFor now you can only cd into a sha1-xxxx directory, if you know the blobref of a directory or a file.\n"), nil
case "recent":
return n.getRecentDir(), nil
case "tag", "date":
return notImplementDirNode{}, nil
case "roots":
return n.getRootsDir(), nil
case "sha1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx":
return notImplementDirNode{}, nil
case ".camli_fs_stats":
return statsDir{}, nil
case "mach_kernel", ".hidden", "._.":
// Just quiet some log noise on OS X.
return nil, fuse.ENOENT
}
br := blobref.Parse(name)
log.Printf("Root lookup of %q = %v", name, br)
if br != nil {
return &node{fs: n.fs, blobref: br}, nil
}
return nil, fuse.ENOENT
}
作者:stunt
项目:camlistor
func (s *storage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit int, wait time.Duration) error {
if wait != 0 {
panic("TODO: support wait in EnumerateBlobs")
}
defer close(dest)
iter := s.index.Find(after)
n := 0
for iter.Next() {
if iter.Key() == after {
continue
}
br := blobref.Parse(iter.Key())
if br == nil {
panic("Bogus encrypt index key: " + iter.Key())
}
plainSize, ok := parseMetaValuePlainSize(iter.Value())
if !ok {
panic("Bogus encrypt index value: " + iter.Value())
}
dest <- blobref.SizedBlobRef{br, plainSize}
n++
if limit != 0 && n >= limit {
break
}
}
return iter.Close()
}
作者:splad
项目:camlistor
func (sto *appengineStorage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit uint, waitSeconds int) os.Error {
defer close(dest)
if sto.ctx == nil {
return errNoContext
}
prefix := sto.namespace + "|"
keyBegin := datastore.NewKey(sto.ctx, memKind, prefix+after, 0, nil)
keyEnd := datastore.NewKey(sto.ctx, memKind, sto.namespace+"~", 0, nil)
q := datastore.NewQuery(memKind).Limit(int(limit)).Filter("__key__>", keyBegin).Filter("__key__<", keyEnd)
it := q.Run(sto.ctx)
var row memEnt
for {
key, err := it.Next(&row)
if err == datastore.Done {
break
}
if err != nil {
return err
}
size, err := row.size()
if err != nil {
return err
}
dest <- blobref.SizedBlobRef{blobref.Parse(key.StringID()[len(prefix):]), size}
}
return nil
}