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 (cs CalcService) calculate(req *msg.OcReq) (*msg.OcResp, error) { // TODO(ortutay): pull out payment verifcation logic work, err := Measure(req) if err != nil { log.Printf("server error: %v", err.Error()) return msg.NewRespError(msg.SERVER_ERROR), nil } pv, err := cs.paymentForWork(work, CALCULATE_METHOD) if err != nil { log.Printf("server error: %v", err.Error()) return msg.NewRespError(msg.SERVER_ERROR), nil } var submitTxn string if pv.Amount != 0 { fmt.Printf("want payment: %v, got payment: %v\n", pv, req.PaymentValue) if req.PaymentType == msg.NONE || req.PaymentValue == nil { return msg.NewRespError(msg.PAYMENT_REQUIRED), nil } if req.PaymentValue.Currency != pv.Currency { return msg.NewRespError(msg.CURRENCY_UNSUPPORTED), nil } if req.PaymentValue.Amount < pv.Amount { return msg.NewRespError(msg.TOO_LOW), nil } var repStatus rep.Status switch req.PaymentType { case msg.DEFER: // TODO(ortutay): check if we accept deferred payment for the request // TODO(ortutay): marking as success is pre-emptive; need to handle // failure case repStatus = rep.SUCCESS_UNPAID case msg.ATTACHED: if !btc.TxnIsValid(req.PaymentTxn, req.PaymentValue) { return msg.NewRespError(msg.INVALID_TXN), nil } submitTxn = req.PaymentTxn // TODO(ortutay): same note as above about pre-emptive success mark repStatus = rep.SUCCESS_PAID } rec := rep.Record{ Role: rep.SERVER, Service: SERVICE_NAME, Method: CALCULATE_METHOD, Timestamp: int(time.Now().Unix()), ID: req.ID, Status: repStatus, PaymentType: msg.DEFER, PaymentValue: pv, Perf: nil, } fmt.Printf("rep rec: %v\n", rec) id, err := rep.Put(&rec) if err != nil { return nil, fmt.Errorf("local database error: %v", err) } fmt.Printf("stored rep rec, %v %v\n", id, err) } var results []string for _, q := range req.Args { tokens := strings.Split(q, " ") var stack []float64 for _, token := range tokens { switch token { case "+": r := stack[len(stack)-1] + stack[len(stack)-2] stack = stack[0 : len(stack)-2] stack = append(stack, r) case "-": r := stack[len(stack)-2] - stack[len(stack)-1] stack = stack[0 : len(stack)-2] stack = append(stack, r) case "/": r := stack[len(stack)-2] / stack[len(stack)-1] stack = stack[0 : len(stack)-2] stack = append(stack, r) case "*": r := stack[len(stack)-1] * stack[len(stack)-2] stack = stack[0 : len(stack)-2] stack = append(stack, r) default: f, err := strconv.ParseFloat(token, 54) stack = append(stack, f) if err != nil { return nil, errors.New("didn't understand \"" + token + "\"") } } } if len(stack) != 1 { return nil, errors.New("invalid expression") } results = append(results, fmt.Sprintf("%v", stack[0])) } resp := msg.NewRespOk([]byte(strings.Join(results, " "))) if submitTxn != "" { _ = btc.SubmitTxn(submitTxn) } return resp, nil }