Example #1
0
// Fast path for blobpacked.
func fileInfoPacked(sh *search.Handler, src blob.Fetcher, req *http.Request, file blob.Ref) (packFileInfo fileInfo, ok bool) {
	if sh == nil {
		return fileInfo{whyNot: "no search"}, false
	}
	wf, ok := src.(blobserver.WholeRefFetcher)
	if !ok {
		return fileInfo{whyNot: "fetcher type"}, false
	}
	if req != nil && req.Header.Get("Range") != "" {
		// TODO: not handled yet. Maybe not even important,
		// considering rarity.
		return fileInfo{whyNot: "range header"}, false
	}
	des, err := sh.Describe(&search.DescribeRequest{BlobRef: file})
	if err != nil {
		log.Printf("ui: fileInfoPacked: skipping fast path due to error from search: %v", err)
		return fileInfo{whyNot: "search error"}, false
	}
	db, ok := des.Meta[file.String()]
	if !ok || db.File == nil {
		return fileInfo{whyNot: "search index doesn't know file"}, false
	}
	fi := db.File
	if !fi.WholeRef.Valid() {
		return fileInfo{whyNot: "no wholeref from search index"}, false
	}

	offset := int64(0)
	rc, wholeSize, err := wf.OpenWholeRef(fi.WholeRef, offset)
	if err == os.ErrNotExist {
		return fileInfo{whyNot: "WholeRefFetcher returned ErrNotexist"}, false
	}
	if wholeSize != fi.Size {
		log.Printf("ui: fileInfoPacked: OpenWholeRef size %d != index size %d; ignoring fast path", wholeSize, fi.Size)
		return fileInfo{whyNot: "WholeRefFetcher and index don't agree"}, false
	}
	if err != nil {
		log.Printf("ui: fileInfoPacked: skipping fast path due to error from WholeRefFetcher (%T): %v", src, err)
		return fileInfo{whyNot: "WholeRefFetcher error"}, false
	}
	return fileInfo{
		mime:  fi.MIMEType,
		name:  fi.FileName,
		size:  fi.Size,
		rs:    readerutil.NewFakeSeeker(rc, fi.Size-offset),
		close: rc.Close,
	}, true
}
Example #2
0
// InitHandler goes through all the other configured handlers to discover
// the publisher ones, and uses them to populate ui.publishRoots.
func (ui *UIHandler) InitHandler(hl blobserver.FindHandlerByTyper) error {
	// InitHandler is called after all handlers have been setup, so the bootstrap
	// of the camliRoot node for publishers in dev-mode is already done.
	searchPrefix, _, err := hl.FindHandlerByType("search")
	if err != nil {
		return errors.New("No search handler configured, which is necessary for the ui handler")
	}
	var sh *search.Handler
	htype, hi := hl.AllHandlers()
	if h, ok := hi[searchPrefix]; !ok {
		return errors.New("failed to find the \"search\" handler")
	} else {
		sh = h.(*search.Handler)
		ui.search = sh
	}
	camliRootQuery := func(camliRoot string) (*search.SearchResult, error) {
		return sh.Query(&search.SearchQuery{
			Limit: 1,
			Constraint: &search.Constraint{
				Permanode: &search.PermanodeConstraint{
					Attr:  "camliRoot",
					Value: camliRoot,
				},
			},
		})
	}
	for prefix, typ := range htype {
		if typ != "app" {
			continue
		}
		ah, ok := hi[prefix].(*app.Handler)
		if !ok {
			panic(fmt.Sprintf("UI: handler for %v has type \"app\" but is not app.Handler", prefix))
		}
		if ah.ProgramName() != "publisher" {
			continue
		}
		appConfig := ah.AppConfig()
		if appConfig == nil {
			log.Printf("UI: app handler for %v has no appConfig", prefix)
			continue
		}
		camliRoot, ok := appConfig["camliRoot"].(string)
		if !ok {
			log.Printf("UI: camliRoot in appConfig is %T, want string", appConfig["camliRoot"])
			continue
		}
		result, err := camliRootQuery(camliRoot)
		if err != nil {
			log.Printf("UI: could not find permanode for camliRoot %v: %v", camliRoot, err)
			continue
		}
		if len(result.Blobs) == 0 || !result.Blobs[0].Blob.Valid() {
			log.Printf("UI: no valid permanode for camliRoot %v", camliRoot)
			continue
		}
		if ui.publishRoots == nil {
			ui.publishRoots = make(map[string]*publishRoot)
		}
		ui.publishRoots[prefix] = &publishRoot{
			Name:      camliRoot,
			Prefix:    prefix,
			Permanode: result.Blobs[0].Blob,
		}
	}
	return nil
}