// Implement io.ReaderAt func (f *FileHandle) ReadAt(p []byte, off int64) (n int, err error) { end := int64(len(p)) + off if end >= f.length { end = f.length } u, err := f.randomUrl() if err != nil { return 0, err } req, err := http.NewRequest("GET", u, nil) if err != nil { return 0, err } req.Header.Set("Range", fmt.Sprintf("bytes=%v-%v", off, end-1)) res, err := http.DefaultClient.Do(req) if err != nil { return 0, err } defer res.Body.Close() exp := 206 if off == 0 && end == f.length { exp = 200 } if res.StatusCode != exp { return 0, httputil.HTTPErrorf(res, "Unexpected http response: %S\n%B") } n, err = io.ReadFull(res.Body, p) if err == io.ErrUnexpectedEOF { err = io.EOF } return n, err }
func (c *bitfogClient) decodeURL(u string) (map[string]bitfog.FileData, error) { rv := map[string]bitfog.FileData{} resp, err := c.client.Get(u) if err != nil { return rv, err } if resp.StatusCode != 200 { return rv, httputil.HTTPErrorf(resp, "Error fetching %v - %S\n%B", u) } defer resp.Body.Close() d := json.NewDecoder(resp.Body) for { fd := bitfog.FileData{} err = d.Decode(&fd) switch err { default: return rv, fmt.Errorf("error decoding %v: %v", u, err) case nil: rv[fd.Name] = fd case io.EOF: return rv, nil } } }
// Implement io.WriterTo func (f *FileHandle) WriteTo(w io.Writer) (int64, error) { u, err := f.randomUrl() if err != nil { return 0, err } req, err := http.NewRequest("GET", u, nil) if err != nil { return 0, err } if f.off > 0 { req.Header.Set("Range", fmt.Sprintf("bytes=%v-%v", f.off, f.length-1)) } res, err := http.DefaultClient.Do(req) if err != nil { return 0, err } defer res.Body.Close() if res.StatusCode != 200 { return 0, httputil.HTTPErrorf(res, "Unexpected http response: %S\n%B") } n, err := io.Copy(w, res.Body) f.off += n return n, err }
func sendOne(u, k string, body []byte) { resp, err := http.DefaultClient.Post(u+"?ts="+k, "application/json", bytes.NewReader(body)) maybeFatal(err) defer resp.Body.Close() if resp.StatusCode >= 300 || resp.StatusCode < 200 { log.Fatal(httputil.HTTPErrorf(resp, "error on %v: %S -- %B", k)) } }
func httpCopy(dest, src string) error { sres, err := http.Get(src) if err != nil { return err } defer sres.Body.Close() if sres.StatusCode != 200 { return httputil.HTTPErrorf(sres, "error copying from %v: S\n%B", src) } dres, err := http.Post(dest, sres.Header.Get("Content-Type"), sres.Body) if err != nil { return err } defer dres.Body.Close() if dres.StatusCode != 201 { return httputil.HTTPErrorf(dres, "Error posting result to %v: %S\n%B", dest) } return nil }
// Compact the given database. func (s *SerieslyDB) Compact() error { u := s.URL().String() + "/_compact" req, err := http.NewRequest("POST", u, nil) if err != nil { return err } res, err := s.s.client.Do(req) if err != nil { return err } res.Body.Close() if res.StatusCode != 200 { return httputil.HTTPErrorf(res, "error compacting: %S -- %B") } return nil }
// Delete destroys a database. func (s *Seriesly) Delete(db string) error { u := *s.u u.Path = "/" + db req, err := http.NewRequest("DELETE", u.String(), nil) if err != nil { return err } res, err := s.client.Do(req) if err != nil { return err } defer res.Body.Close() if res.StatusCode != 200 { return httputil.HTTPErrorf(res, "Error deleting DB: %S -- %B") } return nil }
// Find out what nodes contain the given blobs. func (c Client) GetBlobInfos(oids ...string) (map[string]BlobInfo, error) { u := c.URLFor("/.cbfs/blob/info/") form := url.Values{"blob": oids} res, err := http.PostForm(u, form) if err != nil { return nil, err } defer res.Body.Close() if res.StatusCode != 200 { return nil, httputil.HTTPErrorf(res, "error fetching blob info: %S\n%B") } d := json.NewDecoder(res.Body) rv := map[string]BlobInfo{} err = d.Decode(&rv) return rv, err }
func rmFile(u string) error { if *rmbakNoop { return nil } req, err := http.NewRequest("DELETE", u, nil) if err != nil { return err } res, err := http.DefaultClient.Do(req) if err != nil { return err } res.Body.Close() if res.StatusCode != 204 && res.StatusCode != 404 { return httputil.HTTPErrorf(res, "Unexpeced Stats deleting %v: %S\n%B") } return nil }
func (c Client) Rm(fn string) error { u := c.URLFor(fn) req, err := http.NewRequest("DELETE", u, nil) if err != nil { return err } res, err := http.DefaultClient.Do(req) if err != nil { return err } res.Body.Close() if res.StatusCode == 404 { return Missing } if res.StatusCode != 204 { return httputil.HTTPErrorf(res, "unexpected status deleting %v: %S\n%B, u") } return nil }
// List the contents below the given location. func (c Client) ListDepth(ustr string, depth int) (ListResult, error) { result := ListResult{} inputUrl := *c.pu for strings.HasPrefix(ustr, "/") { ustr = ustr[1:] } inputUrl.Path = "/.cbfs/list/" + ustr for strings.HasSuffix(inputUrl.Path, "/") { inputUrl.Path = inputUrl.Path[:len(inputUrl.Path)-1] } if inputUrl.Path == "/.cbfs/list" { inputUrl.Path = "/.cbfs/list/" } inputUrl.RawQuery = fmt.Sprintf("includeMeta=true&depth=%d", depth) req, err := http.NewRequest("GET", inputUrl.String(), nil) if err != nil { return result, err } res, err := http.DefaultClient.Do(req) if err != nil { return result, err } defer res.Body.Close() switch res.StatusCode { case 404: return result, fourOhFour case 200: // ok default: return result, httputil.HTTPErrorf(res, "error in request to %v: %S\n%B", inputUrl) } d := json.NewDecoder(res.Body) err = d.Decode(&result) return result, err }
func restoreFile(base, path string, data interface{}) error { if *restoreNoop { log.Printf("NOOP would restore %v", path) return nil } fileMetaBytes, err := json.Marshal(data) if err != nil { return err } u := cbfstool.ParseURL(base) u.Path = fmt.Sprintf("/.cbfs/backup/restore/%v", path) req, err := http.NewRequest("POST", u.String(), bytes.NewReader(fileMetaBytes)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("X-CBFS-Expiration", strconv.Itoa(*restoreExpire)) res, err := http.DefaultClient.Do(req) cbfstool.MaybeFatal(err, "Error executing POST to %v - %v", u, err) defer res.Body.Close() switch { case res.StatusCode == 201: log.Printf("Restored %v", path) // OK case res.StatusCode == 409 && !*restoreForce: // OK default: return httputil.HTTPErrorf(res, "restore error on %v - %Sv\n%B", path) } return nil }
func (c *bitfogClient) downloadFile(src, dest string) error { resp, err := c.client.Get(src) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return httputil.HTTPErrorf(resp, "error getting %v - %S\n%B", src) } f, err := c.fs.Create(dest) if err != nil { c.fs.MkdirAll(filepath.Dir(dest), 0777) f, err = c.fs.Create(dest) if err != nil { return err } } defer f.Close() _, err = io.Copy(f, resp.Body) return err }