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 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 (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 ocIDForCoin(coin string) (*msg.OcID, error) { fmt.Printf("get oc ID for coin: %v\n", coin) d := util.GetOrCreateDB(peerDBPath()) v, _ := d.Read(coin) if v == nil || len(v) == 0 { return nil, nil } id := msg.OcID(v) return &id, nil }
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 (ss *StoreService) PeriodicWake() { now := time.Now().Unix() if ss.lastWake == 0 { ss.lastWake = now } period := int64(10) if now-ss.lastWake < period { return } ss.lastWake = now d := util.GetOrCreateDB(containersDB()) keys := d.Keys() for { key := <-keys if len(key) == 0 { break } bytesUsed := 0 id := msg.OcID(key) container := NewContainerFromDisk(id) seenBlocks := make(map[string]bool) for _, blobID := range container.BlobIDs { // TODO(ortutay): don't read blocks from disk just to find sizes blob, err := NewBlobFromDisk(blobID) if err != nil { continue } for _, block := range blob.Blocks { if _, ok := seenBlocks[block.ID.String()]; ok { continue } seenBlocks[block.ID.String()] = true bytesUsed += len(block.Data) } } costPv := costForBytesSeconds(bytesUsed, int(period)) fmt.Printf("bytes %v used by %v..., cost += %f %v\n", bytesUsed, id.String()[:8], util.S2B(costPv.Amount), costPv.Currency) rec := rep.Record{ Role: rep.SERVER, Service: SERVICE_NAME, Method: PUT_METHOD, Timestamp: int(now), ID: id, Status: rep.SUCCESS_UNPAID, PaymentValue: costPv, Perf: nil, } rep.Put(&rec) } }
func (p *Peer) readPaymentAddrs() []string { d := util.GetOrCreateDB(addrDBPath()) fmt.Printf("p: %v\n", p) addrsSer, _ := d.Read(p.ID.String()) if addrsSer == nil || len(addrsSer) == 0 { return []string{} } else { var addrs []string err := json.Unmarshal(addrsSer, &addrs) if err != nil { return []string{} } return addrs } }
func (p *Peer) PaymentAddr(maxToMake int, btcConf *util.BitcoindConf) (string, error) { if maxToMake == -1 { // TODO(ortutay): This is a parameter for testing. See if there is a better // solution. maxToMake = DEFAULT_MAX_TO_MAKE } d := util.GetOrCreateDB(addrDBPath()) addrsSer, _ := d.Read(p.ID.String()) fmt.Printf("read addrs: %v\n", addrsSer) if addrsSer == nil || len(addrsSer) == 0 { fmt.Printf("no addrs read, making...\n") var addrs []string for i := 0; i < maxToMake; i++ { btcAddr, err := p.fetchNewBtcAddr(btcConf) if err != nil { log.Printf("error while generating addresses: %v\n", err) return "", err } addrs = append(addrs, btcAddr) } ser, err := json.Marshal(addrs) if err != nil { return "", err } err = d.Write(p.ID.String(), ser) if err != nil { return "", err } fmt.Printf("generated addresses: %v ser: %v\n", addrs, string(ser)) addrsSer, _ = d.Read(p.ID.String()) } var addrs []string err := json.Unmarshal(addrsSer, &addrs) if err != nil { return "", err } if addrs == nil || len(addrs) == 0 { panic("unexpected empty list") } return addrs[rand.Int()%len(addrs)], nil }