func storeBlob(blob *Blob) error { // TODO(ortutay): in the case of a failed write, we need to garbage collect for _, block := range blob.Blocks { path := blockPath(block.ID) if _, err := os.Stat(path); err == nil { continue } func() { f, err := os.Create(path) defer f.Close() util.Ferr(err) _, err = f.Write(block.Data) util.Ferr(err) }() } // Write blob -> blocks mapping ids := blob.BlockIDs() d := util.GetOrCreateDB(blobToBlocksDB()) ser, err := json.Marshal(ids) util.Ferr(err) err = d.Write(blob.ID.String(), ser) util.Ferr(err) return nil }
func NewBlobFromDisk(id BlobID) (*Blob, error) { d := util.GetOrCreateDB(blobToBlocksDB()) idsSer, err := d.Read(id.String()) if idsSer == nil || len(idsSer) == 0 { return nil, fmt.Errorf("not found") } var ids []BlockID err = json.Unmarshal(idsSer, &ids) util.Ferr(err) var blocks []*Block for _, id := range ids { block, err := func() (*Block, error) { f, err := os.Open(blockPath(id)) defer f.Close() if err != nil { return nil, err } data, err := ioutil.ReadAll(f) if len(data) > BYTES_PER_BLOCK { log.Fatalf("too big block %v of size %v", id, len(data)) } block, err := NewBlock(data) util.Ferr(err) if block.ID != id { log.Fatalf("mismatched id's %v != %v", id, block.ID) } return block, nil }() if err != nil { return nil, err } blocks = append(blocks, block) } return NewBlob(blocks) }
func (c *Container) WriteNewBlobID(id BlobID) { d := util.GetOrCreateDB(containersDB()) c.BlobIDs = append(c.BlobIDs, id) blobIDsSer, err := json.Marshal(c) util.Ferr(err) err = d.Write(c.OwnerID.String(), blobIDsSer) util.Ferr(err) }
func setOcIDForCoin(coin string, ocID *msg.OcID) error { fmt.Printf("set oc ID for coin %v\n", coin) d := util.GetOrCreateDB(peerDBPath()) err := d.Write(coin, []byte(ocID.String())) util.Ferr(err) return nil }
func NewBlobFromReader(r io.Reader) (*Blob, error) { blocks := make([]*Block, 0) for { buf := make([]byte, BYTES_PER_BLOCK) n, err := r.Read(buf) if err != nil && n == 0 { break } if err != nil { return nil, err } block, err := NewBlock(buf[:n]) util.Ferr(err) util.Ferr(err) blocks = append(blocks, block) } return NewBlob(blocks) }
func NewContainerFromDisk(id msg.OcID) *Container { d := util.GetOrCreateDB(containersDB()) containerID := ocIDToContainerID(id) ser, _ := d.Read(id.String()) if ser == nil || len(ser) == 0 { return &Container{ID: containerID, OwnerID: id} } else { var container Container err := json.Unmarshal(ser, &container) util.Ferr(err) return &container } }
func NewBlob(blocks []*Block) (*Blob, error) { h := sha256.New() for _, block := range blocks { _, err := h.Write([]byte(block.Data)) util.Ferr(err) } b := h.Sum([]byte{}) id := hex.EncodeToString(b) blob := Blob{ ID: BlobID(id), Blocks: blocks, } return &blob, nil }
func blockPath(id BlockID) string { dir := util.ServiceDir(SERVICE_NAME) + "/blocks" err := util.MakeDir(dir) util.Ferr(err) return dir + "/" + id.String() }
func main() { goopt.Parse(nil) util.SetAppDir(*fAppDir) ocCred, err := cred.NewOcCredLoadOrCreate("") if err != nil { log.Fatal(err.Error()) } bConf, err := util.LoadBitcoindConf("") if err != nil { log.Fatal(err.Error()) } pvLower, err := msg.NewPaymentValueParseString(*fCoinsLower) if err != nil { log.Fatal(err) } pvUpper, err := msg.NewPaymentValueParseString(*fCoinsUpper) if err != nil { log.Fatal(err) } coins, err := cred.GetBtcCredInRange(pvLower.Amount, pvUpper.Amount, bConf) if err != nil { log.Fatal(err.Error()) } c := node.Client{ BtcConf: bConf, Cred: cred.Cred{ OcCred: *ocCred, BtcConf: bConf, Coins: *coins, }, } var body []byte if !termutil.Isatty(os.Stdin.Fd()) { var err error body, err = ioutil.ReadAll(os.Stdin) util.Ferr(err) } cmdArgs := make([]string, 0) for _, arg := range os.Args[1:] { if arg[0] != '-' { cmdArgs = append(cmdArgs, arg) } } if len(cmdArgs) == 0 { // TODO(ortutay): print usage info return } var req *msg.OcReq switch cmdArgs[0] { case "quote": qReq, err := makeQuoteReq(cmdArgs[1:]) if err != nil { log.Fatal(err.Error()) } resp := sendRequest(&c, qReq) if resp.Status == msg.OK { var pv msg.PaymentValue err := json.Unmarshal(resp.Body, &pv) if err != nil { panic(err) } fmt.Printf("\n%v%v\n", util.S2B(pv.Amount), pv.Currency) } case "call": req, err = makeReq(cmdArgs[1:], body) if err != nil { log.Fatal(err.Error()) } resp := sendRequest(&c, req) switch fmt.Sprintf("%v.%v", req.Service, req.Method) { case "payment.balance": { var br payment.BalanceResponse err := json.Unmarshal(resp.Body, &br) if err != nil { log.Fatalf("malformed response") } fmt.Printf("\nServer reports balance of %v%v (max allowed is %v%v)\n", util.S2B(br.Balance.Amount), br.Balance.Currency, util.S2B(br.MaxBalance.Amount), br.MaxBalance.Currency) } } case "pay": payBtc(&c, cmdArgs) case "listrep": sel := rep.Record{} if len(cmdArgs) > 1 { selJson := cmdArgs[1] err := json.Unmarshal([]byte(selJson), &sel) if err != nil { log.Fatal(err.Error()) } fmt.Printf("sel json: %v %v\n", selJson, sel) } err := rep.PrettyPrint(&sel) if err != nil { log.Fatal(err.Error()) } default: fmt.Printf("unrecognized command: %v", cmdArgs) } }