This commit is contained in:
Wenbiao Zheng 2018-06-04 16:21:56 +00:00 committed by GitHub
commit 66777dbabd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 2099 additions and 2099 deletions

View file

@ -38,12 +38,12 @@ type DirectoryString struct {
Value string Value string
} }
func (self *DirectoryString) String() string { func (s *DirectoryString) String() string {
return self.Value return s.Value
} }
func (self *DirectoryString) Set(value string) error { func (s *DirectoryString) Set(value string) error {
self.Value = expandPath(value) s.Value = expandPath(value)
return nil return nil
} }
@ -55,12 +55,12 @@ type DirectoryFlag struct {
Usage string Usage string
} }
func (self DirectoryFlag) String() string { func (f DirectoryFlag) String() string {
fmtString := "%s %v\t%v" fmtString := "%s %v\t%v"
if len(self.Value.Value) > 0 { if len(f.Value.Value) > 0 {
fmtString = "%s \"%v\"\t%v" fmtString = "%s \"%v\"\t%v"
} }
return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value.Value, f.Usage)
} }
func eachName(longName string, fn func(string)) { func eachName(longName string, fn func(string)) {
@ -73,9 +73,9 @@ func eachName(longName string, fn func(string)) {
// called by cli library, grabs variable from environment (if in env) // called by cli library, grabs variable from environment (if in env)
// and adds variable to flag set for parsing. // and adds variable to flag set for parsing.
func (self DirectoryFlag) Apply(set *flag.FlagSet) { func (f DirectoryFlag) Apply(set *flag.FlagSet) {
eachName(self.Name, func(name string) { eachName(f.Name, func(name string) {
set.Var(&self.Value, self.Name, self.Usage) set.Var(&f.Value, f.Name, f.Usage)
}) })
} }
@ -207,12 +207,12 @@ func prefixedNames(fullName string) (prefixed string) {
return return
} }
func (self DirectoryFlag) GetName() string { func (f DirectoryFlag) GetName() string {
return self.Name return f.Name
} }
func (self *DirectoryFlag) Set(value string) { func (f *DirectoryFlag) Set(value string) {
self.Value.Value = value f.Value.Value = value
} }
// Expands a file path // Expands a file path

View file

@ -35,32 +35,32 @@ func NewApi(ch func() *Chequebook) *Api {
return &Api{ch} return &Api{ch}
} }
func (self *Api) Balance() (string, error) { func (a *Api) Balance() (string, error) {
ch := self.chequebookf() ch := a.chequebookf()
if ch == nil { if ch == nil {
return "", errNoChequebook return "", errNoChequebook
} }
return ch.Balance().String(), nil return ch.Balance().String(), nil
} }
func (self *Api) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) { func (a *Api) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) {
ch := self.chequebookf() ch := a.chequebookf()
if ch == nil { if ch == nil {
return nil, errNoChequebook return nil, errNoChequebook
} }
return ch.Issue(beneficiary, amount) return ch.Issue(beneficiary, amount)
} }
func (self *Api) Cash(cheque *Cheque) (txhash string, err error) { func (a *Api) Cash(cheque *Cheque) (txhash string, err error) {
ch := self.chequebookf() ch := a.chequebookf()
if ch == nil { if ch == nil {
return "", errNoChequebook return "", errNoChequebook
} }
return ch.Cash(cheque) return ch.Cash(cheque)
} }
func (self *Api) Deposit(amount *big.Int) (txhash string, err error) { func (a *Api) Deposit(amount *big.Int) (txhash string, err error) {
ch := self.chequebookf() ch := a.chequebookf()
if ch == nil { if ch == nil {
return "", errNoChequebook return "", errNoChequebook
} }

View file

@ -75,8 +75,8 @@ type Cheque struct {
Sig []byte // signature Sign(Keccak256(contract, beneficiary, amount), prvKey) Sig []byte // signature Sign(Keccak256(contract, beneficiary, amount), prvKey)
} }
func (self *Cheque) String() string { func (c *Cheque) String() string {
return fmt.Sprintf("contract: %s, beneficiary: %s, amount: %v, signature: %x", self.Contract.Hex(), self.Beneficiary.Hex(), self.Amount, self.Sig) return fmt.Sprintf("contract: %s, beneficiary: %s, amount: %v, signature: %x", c.Contract.Hex(), c.Beneficiary.Hex(), c.Amount, c.Sig)
} }
type Params struct { type Params struct {
@ -109,12 +109,12 @@ type Chequebook struct {
log log.Logger // contextual logger with the contract address embedded log log.Logger // contextual logger with the contract address embedded
} }
func (self *Chequebook) String() string { func (c *Chequebook) String() string {
return fmt.Sprintf("contract: %s, owner: %s, balance: %v, signer: %x", self.contractAddr.Hex(), self.owner.Hex(), self.balance, self.prvKey.PublicKey) return fmt.Sprintf("contract: %s, owner: %s, balance: %v, signer: %x", c.contractAddr.Hex(), c.owner.Hex(), c.balance, c.prvKey.PublicKey)
} }
// NewChequebook creates a new Chequebook. // NewChequebook creates a new Chequebook.
func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.PrivateKey, backend Backend) (self *Chequebook, err error) { func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.PrivateKey, backend Backend) (c *Chequebook, err error) {
balance := new(big.Int) balance := new(big.Int)
sent := make(map[common.Address]*big.Int) sent := make(map[common.Address]*big.Int)
@ -128,7 +128,7 @@ func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.Priva
TransactOpts: *transactOpts, TransactOpts: *transactOpts,
} }
self = &Chequebook{ c = &Chequebook{
prvKey: prvKey, prvKey: prvKey,
balance: balance, balance: balance,
contractAddr: contractAddr, contractAddr: contractAddr,
@ -142,36 +142,36 @@ func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.Priva
} }
if (contractAddr != common.Address{}) { if (contractAddr != common.Address{}) {
self.setBalanceFromBlockChain() c.setBalanceFromBlockChain()
self.log.Trace("New chequebook initialised", "owner", self.owner, "balance", self.balance) c.log.Trace("New chequebook initialised", "owner", c.owner, "balance", c.balance)
} }
return return
} }
func (self *Chequebook) setBalanceFromBlockChain() { func (c *Chequebook) setBalanceFromBlockChain() {
balance, err := self.backend.BalanceAt(context.TODO(), self.contractAddr, nil) balance, err := c.backend.BalanceAt(context.TODO(), c.contractAddr, nil)
if err != nil { if err != nil {
log.Error("Failed to retrieve chequebook balance", "err", err) log.Error("Failed to retrieve chequebook balance", "err", err)
} else { } else {
self.balance.Set(balance) c.balance.Set(balance)
} }
} }
// LoadChequebook loads a chequebook from disk (file path). // LoadChequebook loads a chequebook from disk (file path).
func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend, checkBalance bool) (self *Chequebook, err error) { func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend, checkBalance bool) (c *Chequebook, err error) {
var data []byte var data []byte
data, err = ioutil.ReadFile(path) data, err = ioutil.ReadFile(path)
if err != nil { if err != nil {
return return
} }
self, _ = NewChequebook(path, common.Address{}, prvKey, backend) c, _ = NewChequebook(path, common.Address{}, prvKey, backend)
err = json.Unmarshal(data, self) err = json.Unmarshal(data, c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if checkBalance { if checkBalance {
self.setBalanceFromBlockChain() c.setBalanceFromBlockChain()
} }
log.Trace("Loaded chequebook from disk", "path", path) log.Trace("Loaded chequebook from disk", "path", path)
@ -187,19 +187,19 @@ type chequebookFile struct {
} }
// UnmarshalJSON deserialises a chequebook. // UnmarshalJSON deserialises a chequebook.
func (self *Chequebook) UnmarshalJSON(data []byte) error { func (c *Chequebook) UnmarshalJSON(data []byte) error {
var file chequebookFile var file chequebookFile
err := json.Unmarshal(data, &file) err := json.Unmarshal(data, &file)
if err != nil { if err != nil {
return err return err
} }
_, ok := self.balance.SetString(file.Balance, 10) _, ok := c.balance.SetString(file.Balance, 10)
if !ok { if !ok {
return fmt.Errorf("cumulative amount sent: unable to convert string to big integer: %v", file.Balance) return fmt.Errorf("cumulative amount sent: unable to convert string to big integer: %v", file.Balance)
} }
self.contractAddr = common.HexToAddress(file.Contract) c.contractAddr = common.HexToAddress(file.Contract)
for addr, sent := range file.Sent { for addr, sent := range file.Sent {
self.sent[common.HexToAddress(addr)], ok = new(big.Int).SetString(sent, 10) c.sent[common.HexToAddress(addr)], ok = new(big.Int).SetString(sent, 10)
if !ok { if !ok {
return fmt.Errorf("beneficiary %v cumulative amount sent: unable to convert string to big integer: %v", addr, sent) return fmt.Errorf("beneficiary %v cumulative amount sent: unable to convert string to big integer: %v", addr, sent)
} }
@ -208,14 +208,14 @@ func (self *Chequebook) UnmarshalJSON(data []byte) error {
} }
// MarshalJSON serialises a chequebook. // MarshalJSON serialises a chequebook.
func (self *Chequebook) MarshalJSON() ([]byte, error) { func (c *Chequebook) MarshalJSON() ([]byte, error) {
var file = &chequebookFile{ var file = &chequebookFile{
Balance: self.balance.String(), Balance: c.balance.String(),
Contract: self.contractAddr.Hex(), Contract: c.contractAddr.Hex(),
Owner: self.owner.Hex(), Owner: c.owner.Hex(),
Sent: make(map[string]string), Sent: make(map[string]string),
} }
for addr, sent := range self.sent { for addr, sent := range c.sent {
file.Sent[addr.Hex()] = sent.String() file.Sent[addr.Hex()] = sent.String()
} }
return json.Marshal(file) return json.Marshal(file)
@ -223,67 +223,67 @@ func (self *Chequebook) MarshalJSON() ([]byte, error) {
// Save persists the chequebook on disk, remembering balance, contract address and // Save persists the chequebook on disk, remembering balance, contract address and
// cumulative amount of funds sent for each beneficiary. // cumulative amount of funds sent for each beneficiary.
func (self *Chequebook) Save() (err error) { func (c *Chequebook) Save() (err error) {
data, err := json.MarshalIndent(self, "", " ") data, err := json.MarshalIndent(c, "", " ")
if err != nil { if err != nil {
return err return err
} }
self.log.Trace("Saving chequebook to disk", self.path) c.log.Trace("Saving chequebook to disk", c.path)
return ioutil.WriteFile(self.path, data, os.ModePerm) return ioutil.WriteFile(c.path, data, os.ModePerm)
} }
// Stop quits the autodeposit go routine to terminate // Stop quits the autodeposit go routine to terminate
func (self *Chequebook) Stop() { func (c *Chequebook) Stop() {
defer self.lock.Unlock() defer c.lock.Unlock()
self.lock.Lock() c.lock.Lock()
if self.quit != nil { if c.quit != nil {
close(self.quit) close(c.quit)
self.quit = nil c.quit = nil
} }
} }
// Issue creates a cheque signed by the chequebook owner's private key. The // Issue creates a cheque signed by the chequebook owner's private key. The
// signer commits to a contract (one that they own), a beneficiary and amount. // signer commits to a contract (one that they own), a beneficiary and amount.
func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *Cheque, err error) { func (c *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *Cheque, err error) {
defer self.lock.Unlock() defer c.lock.Unlock()
self.lock.Lock() c.lock.Lock()
if amount.Sign() <= 0 { if amount.Sign() <= 0 {
return nil, fmt.Errorf("amount must be greater than zero (%v)", amount) return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
} }
if self.balance.Cmp(amount) < 0 { if c.balance.Cmp(amount) < 0 {
err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, self.balance) err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, c.balance)
} else { } else {
var sig []byte var sig []byte
sent, found := self.sent[beneficiary] sent, found := c.sent[beneficiary]
if !found { if !found {
sent = new(big.Int) sent = new(big.Int)
self.sent[beneficiary] = sent c.sent[beneficiary] = sent
} }
sum := new(big.Int).Set(sent) sum := new(big.Int).Set(sent)
sum.Add(sum, amount) sum.Add(sum, amount)
sig, err = crypto.Sign(sigHash(self.contractAddr, beneficiary, sum), self.prvKey) sig, err = crypto.Sign(sigHash(c.contractAddr, beneficiary, sum), c.prvKey)
if err == nil { if err == nil {
ch = &Cheque{ ch = &Cheque{
Contract: self.contractAddr, Contract: c.contractAddr,
Beneficiary: beneficiary, Beneficiary: beneficiary,
Amount: sum, Amount: sum,
Sig: sig, Sig: sig,
} }
sent.Set(sum) sent.Set(sum)
self.balance.Sub(self.balance, amount) // subtract amount from balance c.balance.Sub(c.balance, amount) // subtract amount from balance
} }
} }
// auto deposit if threshold is set and balance is less then threshold // auto deposit if threshold is set and balance is less then threshold
// note this is called even if issuing cheque fails // note this is called even if issuing cheque fails
// so we reattempt depositing // so we reattempt depositing
if self.threshold != nil { if c.threshold != nil {
if self.balance.Cmp(self.threshold) < 0 { if c.balance.Cmp(c.threshold) < 0 {
send := new(big.Int).Sub(self.buffer, self.balance) send := new(big.Int).Sub(c.buffer, c.balance)
self.deposit(send) c.deposit(send)
} }
} }
@ -291,8 +291,8 @@ func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *
} }
// Cash is a convenience method to cash any cheque. // Cash is a convenience method to cash any cheque.
func (self *Chequebook) Cash(ch *Cheque) (txhash string, err error) { func (c *Chequebook) Cash(ch *Cheque) (txhash string, err error) {
return ch.Cash(self.session) return ch.Cash(c.session)
} }
// data to sign: contract address, beneficiary, cumulative amount of funds ever sent // data to sign: contract address, beneficiary, cumulative amount of funds ever sent
@ -309,73 +309,73 @@ func sigHash(contract, beneficiary common.Address, sum *big.Int) []byte {
} }
// Balance returns the current balance of the chequebook. // Balance returns the current balance of the chequebook.
func (self *Chequebook) Balance() *big.Int { func (c *Chequebook) Balance() *big.Int {
defer self.lock.Unlock() defer c.lock.Unlock()
self.lock.Lock() c.lock.Lock()
return new(big.Int).Set(self.balance) return new(big.Int).Set(c.balance)
} }
// Owner returns the owner account of the chequebook. // Owner returns the owner account of the chequebook.
func (self *Chequebook) Owner() common.Address { func (c *Chequebook) Owner() common.Address {
return self.owner return c.owner
} }
// Address returns the on-chain contract address of the chequebook. // Address returns the on-chain contract address of the chequebook.
func (self *Chequebook) Address() common.Address { func (c *Chequebook) Address() common.Address {
return self.contractAddr return c.contractAddr
} }
// Deposit deposits money to the chequebook account. // Deposit deposits money to the chequebook account.
func (self *Chequebook) Deposit(amount *big.Int) (string, error) { func (c *Chequebook) Deposit(amount *big.Int) (string, error) {
defer self.lock.Unlock() defer c.lock.Unlock()
self.lock.Lock() c.lock.Lock()
return self.deposit(amount) return c.deposit(amount)
} }
// deposit deposits amount to the chequebook account. // deposit deposits amount to the chequebook account.
// The caller must hold self.lock. // The caller must hold c.lock.
func (self *Chequebook) deposit(amount *big.Int) (string, error) { func (c *Chequebook) deposit(amount *big.Int) (string, error) {
// since the amount is variable here, we do not use sessions // since the amount is variable here, we do not use sessions
depositTransactor := bind.NewKeyedTransactor(self.prvKey) depositTransactor := bind.NewKeyedTransactor(c.prvKey)
depositTransactor.Value = amount depositTransactor.Value = amount
chbookRaw := &contract.ChequebookRaw{Contract: self.contract} chbookRaw := &contract.ChequebookRaw{Contract: c.contract}
tx, err := chbookRaw.Transfer(depositTransactor) tx, err := chbookRaw.Transfer(depositTransactor)
if err != nil { if err != nil {
self.log.Warn("Failed to fund chequebook", "amount", amount, "balance", self.balance, "target", self.buffer, "err", err) c.log.Warn("Failed to fund chequebook", "amount", amount, "balance", c.balance, "target", c.buffer, "err", err)
return "", err return "", err
} }
// assume that transaction is actually successful, we add the amount to balance right away // assume that transaction is actually successful, we add the amount to balance right away
self.balance.Add(self.balance, amount) c.balance.Add(c.balance, amount)
self.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", self.balance, "target", self.buffer) c.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", c.balance, "target", c.buffer)
return tx.Hash().Hex(), nil return tx.Hash().Hex(), nil
} }
// AutoDeposit (re)sets interval time and amount which triggers sending funds to the // AutoDeposit (re)sets interval time and amount which triggers sending funds to the
// chequebook. Contract backend needs to be set if threshold is not less than buffer, then // chequebook. Contract backend needs to be set if threshold is not less than buffer, then
// deposit will be triggered on every new cheque issued. // deposit will be triggered on every new cheque issued.
func (self *Chequebook) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) { func (c *Chequebook) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
defer self.lock.Unlock() defer c.lock.Unlock()
self.lock.Lock() c.lock.Lock()
self.threshold = threshold c.threshold = threshold
self.buffer = buffer c.buffer = buffer
self.autoDeposit(interval) c.autoDeposit(interval)
} }
// autoDeposit starts a goroutine that periodically sends funds to the chequebook // autoDeposit starts a goroutine that periodically sends funds to the chequebook
// contract caller holds the lock the go routine terminates if Chequebook.quit is closed. // contract caller holds the lock the go routine terminates if Chequebook.quit is closed.
func (self *Chequebook) autoDeposit(interval time.Duration) { func (c *Chequebook) autoDeposit(interval time.Duration) {
if self.quit != nil { if c.quit != nil {
close(self.quit) close(c.quit)
self.quit = nil c.quit = nil
} }
// if threshold >= balance autodeposit after every cheque issued // if threshold >= balance autodeposit after every cheque issued
if interval == time.Duration(0) || self.threshold != nil && self.buffer != nil && self.threshold.Cmp(self.buffer) >= 0 { if interval == time.Duration(0) || c.threshold != nil && c.buffer != nil && c.threshold.Cmp(c.buffer) >= 0 {
return return
} }
ticker := time.NewTicker(interval) ticker := time.NewTicker(interval)
self.quit = make(chan bool) c.quit = make(chan bool)
quit := self.quit quit := c.quit
go func() { go func() {
for { for {
@ -383,15 +383,15 @@ func (self *Chequebook) autoDeposit(interval time.Duration) {
case <-quit: case <-quit:
return return
case <-ticker.C: case <-ticker.C:
self.lock.Lock() c.lock.Lock()
if self.balance.Cmp(self.buffer) < 0 { if c.balance.Cmp(c.buffer) < 0 {
amount := new(big.Int).Sub(self.buffer, self.balance) amount := new(big.Int).Sub(c.buffer, c.balance)
txhash, err := self.deposit(amount) txhash, err := c.deposit(amount)
if err == nil { if err == nil {
self.txhash = txhash c.txhash = txhash
} }
} }
self.lock.Unlock() c.lock.Unlock()
} }
} }
}() }()
@ -409,21 +409,21 @@ func NewOutbox(chbook *Chequebook, beneficiary common.Address) *Outbox {
} }
// Issue creates cheque. // Issue creates cheque.
func (self *Outbox) Issue(amount *big.Int) (swap.Promise, error) { func (o *Outbox) Issue(amount *big.Int) (swap.Promise, error) {
return self.chequeBook.Issue(self.beneficiary, amount) return o.chequeBook.Issue(o.beneficiary, amount)
} }
// AutoDeposit enables auto-deposits on the underlying chequebook. // AutoDeposit enables auto-deposits on the underlying chequebook.
func (self *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) { func (o *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
self.chequeBook.AutoDeposit(interval, threshold, buffer) o.chequeBook.AutoDeposit(interval, threshold, buffer)
} }
// Stop helps satisfy the swap.OutPayment interface. // Stop helps satisfy the swap.OutPayment interface.
func (self *Outbox) Stop() {} func (o *Outbox) Stop() {}
// String implements fmt.Stringer. // String implements fmt.Stringer.
func (self *Outbox) String() string { func (o *Outbox) String() string {
return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", self.chequeBook.Address().Hex(), self.beneficiary.Hex(), self.chequeBook.Balance()) return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", o.chequeBook.Address().Hex(), o.beneficiary.Hex(), o.chequeBook.Balance())
} }
// Inbox can deposit, verify and cash cheques from a single contract to a single // Inbox can deposit, verify and cash cheques from a single contract to a single
@ -445,7 +445,7 @@ type Inbox struct {
// NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated // NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated
// from blockchain when first cheque is received. // from blockchain when first cheque is received.
func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address, signer *ecdsa.PublicKey, abigen bind.ContractBackend) (self *Inbox, err error) { func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address, signer *ecdsa.PublicKey, abigen bind.ContractBackend) (*Inbox, error) {
if signer == nil { if signer == nil {
return nil, fmt.Errorf("signer is null") return nil, fmt.Errorf("signer is null")
} }
@ -461,7 +461,7 @@ func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address
} }
sender := transactOpts.From sender := transactOpts.From
self = &Inbox{ inbox := &Inbox{
contract: contractAddr, contract: contractAddr,
beneficiary: beneficiary, beneficiary: beneficiary,
sender: sender, sender: sender,
@ -470,59 +470,59 @@ func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address
cashed: new(big.Int).Set(common.Big0), cashed: new(big.Int).Set(common.Big0),
log: log.New("contract", contractAddr), log: log.New("contract", contractAddr),
} }
self.log.Trace("New chequebook inbox initialized", "beneficiary", self.beneficiary, "signer", hexutil.Bytes(crypto.FromECDSAPub(signer))) inbox.log.Trace("New chequebook inbox initialized", "beneficiary", beneficiary, "signer", hexutil.Bytes(crypto.FromECDSAPub(signer)))
return return inbox, nil
} }
func (self *Inbox) String() string { func (i *Inbox) String() string {
return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", self.contract.Hex(), self.beneficiary.Hex(), self.cheque.Amount) return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", i.contract.Hex(), i.beneficiary.Hex(), i.cheque.Amount)
} }
// Stop quits the autocash goroutine. // Stop quits the autocash goroutine.
func (self *Inbox) Stop() { func (i *Inbox) Stop() {
defer self.lock.Unlock() defer i.lock.Unlock()
self.lock.Lock() i.lock.Lock()
if self.quit != nil { if i.quit != nil {
close(self.quit) close(i.quit)
self.quit = nil i.quit = nil
} }
} }
// Cash attempts to cash the current cheque. // Cash attempts to cash the current cheque.
func (self *Inbox) Cash() (txhash string, err error) { func (i *Inbox) Cash() (txhash string, err error) {
if self.cheque != nil { if i.cheque != nil {
txhash, err = self.cheque.Cash(self.session) txhash, err = i.cheque.Cash(i.session)
self.log.Trace("Cashing in chequebook cheque", "amount", self.cheque.Amount, "beneficiary", self.beneficiary) i.log.Trace("Cashing in chequebook cheque", "amount", i.cheque.Amount, "beneficiary", i.beneficiary)
self.cashed = self.cheque.Amount i.cashed = i.cheque.Amount
} }
return return
} }
// AutoCash (re)sets maximum time and amount which triggers cashing of the last uncashed // AutoCash (re)sets maximum time and amount which triggers cashing of the last uncashed
// cheque if maxUncashed is set to 0, then autocash on receipt. // cheque if maxUncashed is set to 0, then autocash on receipt.
func (self *Inbox) AutoCash(cashInterval time.Duration, maxUncashed *big.Int) { func (i *Inbox) AutoCash(cashInterval time.Duration, maxUncashed *big.Int) {
defer self.lock.Unlock() defer i.lock.Unlock()
self.lock.Lock() i.lock.Lock()
self.maxUncashed = maxUncashed i.maxUncashed = maxUncashed
self.autoCash(cashInterval) i.autoCash(cashInterval)
} }
// autoCash starts a loop that periodically clears the last cheque // autoCash starts a loop that periodically clears the last cheque
// if the peer is trusted. Clearing period could be 24h or a week. // if the peer is trusted. Clearing period could be 24h or a week.
// The caller must hold self.lock. // The caller must hold i.lock.
func (self *Inbox) autoCash(cashInterval time.Duration) { func (i *Inbox) autoCash(cashInterval time.Duration) {
if self.quit != nil { if i.quit != nil {
close(self.quit) close(i.quit)
self.quit = nil i.quit = nil
} }
// if maxUncashed is set to 0, then autocash on receipt // if maxUncashed is set to 0, then autocash on receipt
if cashInterval == time.Duration(0) || self.maxUncashed != nil && self.maxUncashed.Sign() == 0 { if cashInterval == time.Duration(0) || i.maxUncashed != nil && i.maxUncashed.Sign() == 0 {
return return
} }
ticker := time.NewTicker(cashInterval) ticker := time.NewTicker(cashInterval)
self.quit = make(chan bool) i.quit = make(chan bool)
quit := self.quit quit := i.quit
go func() { go func() {
for { for {
@ -530,14 +530,14 @@ func (self *Inbox) autoCash(cashInterval time.Duration) {
case <-quit: case <-quit:
return return
case <-ticker.C: case <-ticker.C:
self.lock.Lock() i.lock.Lock()
if self.cheque != nil && self.cheque.Amount.Cmp(self.cashed) != 0 { if i.cheque != nil && i.cheque.Amount.Cmp(i.cashed) != 0 {
txhash, err := self.Cash() txhash, err := i.Cash()
if err == nil { if err == nil {
self.txhash = txhash i.txhash = txhash
} }
} }
self.lock.Unlock() i.lock.Unlock()
} }
} }
}() }()
@ -545,56 +545,56 @@ func (self *Inbox) autoCash(cashInterval time.Duration) {
// Receive is called to deposit the latest cheque to the incoming Inbox. // Receive is called to deposit the latest cheque to the incoming Inbox.
// The given promise must be a *Cheque. // The given promise must be a *Cheque.
func (self *Inbox) Receive(promise swap.Promise) (*big.Int, error) { func (i *Inbox) Receive(promise swap.Promise) (*big.Int, error) {
ch := promise.(*Cheque) ch := promise.(*Cheque)
defer self.lock.Unlock() defer i.lock.Unlock()
self.lock.Lock() i.lock.Lock()
var sum *big.Int var sum *big.Int
if self.cheque == nil { if i.cheque == nil {
// the sum is checked against the blockchain once a cheque is received // the sum is checked against the blockchain once a cheque is received
tally, err := self.session.Sent(self.beneficiary) tally, err := i.session.Sent(i.beneficiary)
if err != nil { if err != nil {
return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err) return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err)
} }
sum = tally sum = tally
} else { } else {
sum = self.cheque.Amount sum = i.cheque.Amount
} }
amount, err := ch.Verify(self.signer, self.contract, self.beneficiary, sum) amount, err := ch.Verify(i.signer, i.contract, i.beneficiary, sum)
var uncashed *big.Int var uncashed *big.Int
if err == nil { if err == nil {
self.cheque = ch i.cheque = ch
if self.maxUncashed != nil { if i.maxUncashed != nil {
uncashed = new(big.Int).Sub(ch.Amount, self.cashed) uncashed = new(big.Int).Sub(ch.Amount, i.cashed)
if self.maxUncashed.Cmp(uncashed) < 0 { if i.maxUncashed.Cmp(uncashed) < 0 {
self.Cash() i.Cash()
} }
} }
self.log.Trace("Received cheque in chequebook inbox", "amount", amount, "uncashed", uncashed) i.log.Trace("Received cheque in chequebook inbox", "amount", amount, "uncashed", uncashed)
} }
return amount, err return amount, err
} }
// Verify verifies cheque for signer, contract, beneficiary, amount, valid signature. // Verify verifies cheque for signer, contract, beneficiary, amount, valid signature.
func (self *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary common.Address, sum *big.Int) (*big.Int, error) { func (c *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary common.Address, sum *big.Int) (*big.Int, error) {
log.Trace("Verifying chequebook cheque", "cheque", self, "sum", sum) log.Trace("Verifying chequebook cheque", "cheque", c, "sum", sum)
if sum == nil { if sum == nil {
return nil, fmt.Errorf("invalid amount") return nil, fmt.Errorf("invalid amount")
} }
if self.Beneficiary != beneficiary { if c.Beneficiary != beneficiary {
return nil, fmt.Errorf("beneficiary mismatch: %v != %v", self.Beneficiary.Hex(), beneficiary.Hex()) return nil, fmt.Errorf("beneficiary mismatch: %v != %v", c.Beneficiary.Hex(), beneficiary.Hex())
} }
if self.Contract != contract { if c.Contract != contract {
return nil, fmt.Errorf("contract mismatch: %v != %v", self.Contract.Hex(), contract.Hex()) return nil, fmt.Errorf("contract mismatch: %v != %v", c.Contract.Hex(), contract.Hex())
} }
amount := new(big.Int).Set(self.Amount) amount := new(big.Int).Set(c.Amount)
if sum != nil { if sum != nil {
amount.Sub(amount, sum) amount.Sub(amount, sum)
if amount.Sign() <= 0 { if amount.Sign() <= 0 {
@ -602,7 +602,7 @@ func (self *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary com
} }
} }
pubKey, err := crypto.SigToPub(sigHash(self.Contract, beneficiary, self.Amount), self.Sig) pubKey, err := crypto.SigToPub(sigHash(c.Contract, beneficiary, c.Amount), c.Sig)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid signature: %v", err) return nil, fmt.Errorf("invalid signature: %v", err)
} }
@ -621,9 +621,9 @@ func sig2vrs(sig []byte) (v byte, r, s [32]byte) {
} }
// Cash cashes the cheque by sending an Ethereum transaction. // Cash cashes the cheque by sending an Ethereum transaction.
func (self *Cheque) Cash(session *contract.ChequebookSession) (string, error) { func (c *Cheque) Cash(session *contract.ChequebookSession) (string, error) {
v, r, s := sig2vrs(self.Sig) v, r, s := sig2vrs(c.Sig)
tx, err := session.Cash(self.Beneficiary, self.Amount, v, r, s) tx, err := session.Cash(c.Beneficiary, c.Amount, v, r, s)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -100,45 +100,45 @@ func ensNode(name string) common.Hash {
return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
} }
func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { func (e *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := self.Resolver(node) resolverAddr, err := e.Resolver(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend) resolver, err := contract.NewPublicResolver(resolverAddr, e.contractBackend)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &contract.PublicResolverSession{ return &contract.PublicResolverSession{
Contract: resolver, Contract: resolver,
TransactOpts: self.TransactOpts, TransactOpts: e.TransactOpts,
}, nil }, nil
} }
func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { func (e *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := self.Owner(node) registrarAddr, err := e.Owner(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend) registrar, err := contract.NewFIFSRegistrar(registrarAddr, e.contractBackend)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &contract.FIFSRegistrarSession{ return &contract.FIFSRegistrarSession{
Contract: registrar, Contract: registrar,
TransactOpts: self.TransactOpts, TransactOpts: e.TransactOpts,
}, nil }, nil
} }
// Resolve is a non-transactional call that returns the content hash associated with a name. // Resolve is a non-transactional call that returns the content hash associated with a name.
func (self *ENS) Resolve(name string) (common.Hash, error) { func (e *ENS) Resolve(name string) (common.Hash, error) {
node := ensNode(name) node := ensNode(name)
resolver, err := self.getResolver(node) resolver, err := e.getResolver(node)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -153,26 +153,26 @@ func (self *ENS) Resolve(name string) (common.Hash, error) {
// Register registers a new domain name for the caller, making them the owner of the new name. // Register registers a new domain name for the caller, making them the owner of the new name.
// Only works if the registrar for the parent domain implements the FIFS registrar protocol. // Only works if the registrar for the parent domain implements the FIFS registrar protocol.
func (self *ENS) Register(name string) (*types.Transaction, error) { func (e *ENS) Register(name string) (*types.Transaction, error) {
parentNode, label := ensParentNode(name) parentNode, label := ensParentNode(name)
registrar, err := self.getRegistrar(parentNode) registrar, err := e.getRegistrar(parentNode)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return registrar.Contract.Register(&self.TransactOpts, label, self.TransactOpts.From) return registrar.Contract.Register(&e.TransactOpts, label, e.TransactOpts.From)
} }
// SetContentHash sets the content hash associated with a name. Only works if the caller // SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContent` function. // owns the name, and the associated resolver implements a `setContent` function.
func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) { func (e *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
node := ensNode(name) node := ensNode(name)
resolver, err := self.getResolver(node) resolver, err := e.getResolver(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
opts := self.TransactOpts opts := e.TransactOpts
opts.GasLimit = 200000 opts.GasLimit = 200000
return resolver.Contract.SetContent(&opts, node, hash) return resolver.Contract.SetContent(&opts, node, hash)
} }

View file

@ -39,15 +39,15 @@ type Dump struct {
Accounts map[string]DumpAccount `json:"accounts"` Accounts map[string]DumpAccount `json:"accounts"`
} }
func (self *StateDB) RawDump() Dump { func (db *StateDB) RawDump() Dump {
dump := Dump{ dump := Dump{
Root: fmt.Sprintf("%x", self.trie.Hash()), Root: fmt.Sprintf("%x", db.trie.Hash()),
Accounts: make(map[string]DumpAccount), Accounts: make(map[string]DumpAccount),
} }
it := trie.NewIterator(self.trie.NodeIterator(nil)) it := trie.NewIterator(db.trie.NodeIterator(nil))
for it.Next() { for it.Next() {
addr := self.trie.GetKey(it.Key) addr := db.trie.GetKey(it.Key)
var data Account var data Account
if err := rlp.DecodeBytes(it.Value, &data); err != nil { if err := rlp.DecodeBytes(it.Value, &data); err != nil {
panic(err) panic(err)
@ -59,20 +59,20 @@ func (self *StateDB) RawDump() Dump {
Nonce: data.Nonce, Nonce: data.Nonce,
Root: common.Bytes2Hex(data.Root[:]), Root: common.Bytes2Hex(data.Root[:]),
CodeHash: common.Bytes2Hex(data.CodeHash), CodeHash: common.Bytes2Hex(data.CodeHash),
Code: common.Bytes2Hex(obj.Code(self.db)), Code: common.Bytes2Hex(obj.Code(db.db)),
Storage: make(map[string]string), Storage: make(map[string]string),
} }
storageIt := trie.NewIterator(obj.getTrie(self.db).NodeIterator(nil)) storageIt := trie.NewIterator(obj.getTrie(db.db).NodeIterator(nil))
for storageIt.Next() { for storageIt.Next() {
account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) account.Storage[common.Bytes2Hex(db.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
} }
dump.Accounts[common.Bytes2Hex(addr)] = account dump.Accounts[common.Bytes2Hex(addr)] = account
} }
return dump return dump
} }
func (self *StateDB) Dump() []byte { func (db *StateDB) Dump() []byte {
json, err := json.MarshalIndent(self.RawDump(), "", " ") json, err := json.MarshalIndent(db.RawDump(), "", " ")
if err != nil { if err != nil {
fmt.Println("dump err", err) fmt.Println("dump err", err)
} }

View file

@ -31,23 +31,23 @@ var emptyCodeHash = crypto.Keccak256(nil)
type Code []byte type Code []byte
func (self Code) String() string { func (c Code) String() string {
return string(self) //strings.Join(Disassemble(self), " ") return string(c) //strings.Join(Disassemble(c), " ")
} }
type Storage map[common.Hash]common.Hash type Storage map[common.Hash]common.Hash
func (self Storage) String() (str string) { func (s Storage) String() (str string) {
for key, value := range self { for key, value := range s {
str += fmt.Sprintf("%X : %X\n", key, value) str += fmt.Sprintf("%X : %X\n", key, value)
} }
return return
} }
func (self Storage) Copy() Storage { func (s Storage) Copy() Storage {
cpy := make(Storage) cpy := make(Storage)
for key, value := range self { for key, value := range s {
cpy[key] = value cpy[key] = value
} }
@ -126,14 +126,14 @@ func (c *stateObject) EncodeRLP(w io.Writer) error {
} }
// setError remembers the first non-nil error it is called with. // setError remembers the first non-nil error it is called with.
func (self *stateObject) setError(err error) { func (object *stateObject) setError(err error) {
if self.dbErr == nil { if object.dbErr == nil {
self.dbErr = err object.dbErr = err
} }
} }
func (self *stateObject) markSuicided() { func (object *stateObject) markSuicided() {
self.suicided = true object.suicided = true
} }
func (c *stateObject) touch() { func (c *stateObject) touch() {
@ -160,75 +160,75 @@ func (c *stateObject) getTrie(db Database) Trie {
} }
// GetState returns a value in account storage. // GetState returns a value in account storage.
func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { func (object *stateObject) GetState(db Database, key common.Hash) common.Hash {
value, exists := self.cachedStorage[key] value, exists := object.cachedStorage[key]
if exists { if exists {
return value return value
} }
// Load from DB in case it is missing. // Load from DB in case it is missing.
enc, err := self.getTrie(db).TryGet(key[:]) enc, err := object.getTrie(db).TryGet(key[:])
if err != nil { if err != nil {
self.setError(err) object.setError(err)
return common.Hash{} return common.Hash{}
} }
if len(enc) > 0 { if len(enc) > 0 {
_, content, _, err := rlp.Split(enc) _, content, _, err := rlp.Split(enc)
if err != nil { if err != nil {
self.setError(err) object.setError(err)
} }
value.SetBytes(content) value.SetBytes(content)
} }
self.cachedStorage[key] = value object.cachedStorage[key] = value
return value return value
} }
// SetState updates a value in account storage. // SetState updates a value in account storage.
func (self *stateObject) SetState(db Database, key, value common.Hash) { func (object *stateObject) SetState(db Database, key, value common.Hash) {
self.db.journal.append(storageChange{ object.db.journal.append(storageChange{
account: &self.address, account: &object.address,
key: key, key: key,
prevalue: self.GetState(db, key), prevalue: object.GetState(db, key),
}) })
self.setState(key, value) object.setState(key, value)
} }
func (self *stateObject) setState(key, value common.Hash) { func (object *stateObject) setState(key, value common.Hash) {
self.cachedStorage[key] = value object.cachedStorage[key] = value
self.dirtyStorage[key] = value object.dirtyStorage[key] = value
} }
// updateTrie writes cached storage modifications into the object's storage trie. // updateTrie writes cached storage modifications into the object's storage trie.
func (self *stateObject) updateTrie(db Database) Trie { func (object *stateObject) updateTrie(db Database) Trie {
tr := self.getTrie(db) tr := object.getTrie(db)
for key, value := range self.dirtyStorage { for key, value := range object.dirtyStorage {
delete(self.dirtyStorage, key) delete(object.dirtyStorage, key)
if (value == common.Hash{}) { if (value == common.Hash{}) {
self.setError(tr.TryDelete(key[:])) object.setError(tr.TryDelete(key[:]))
continue continue
} }
// Encoding []byte cannot fail, ok to ignore the error. // Encoding []byte cannot fail, ok to ignore the error.
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
self.setError(tr.TryUpdate(key[:], v)) object.setError(tr.TryUpdate(key[:], v))
} }
return tr return tr
} }
// UpdateRoot sets the trie root to the current root hash of // UpdateRoot sets the trie root to the current root hash of
func (self *stateObject) updateRoot(db Database) { func (object *stateObject) updateRoot(db Database) {
self.updateTrie(db) object.updateTrie(db)
self.data.Root = self.trie.Hash() object.data.Root = object.trie.Hash()
} }
// CommitTrie the storage trie of the object to dwb. // CommitTrie the storage trie of the object to dwb.
// This updates the trie root. // This updates the trie root.
func (self *stateObject) CommitTrie(db Database) error { func (object *stateObject) CommitTrie(db Database) error {
self.updateTrie(db) object.updateTrie(db)
if self.dbErr != nil { if object.dbErr != nil {
return self.dbErr return object.dbErr
} }
root, err := self.trie.Commit(nil) root, err := object.trie.Commit(nil)
if err == nil { if err == nil {
self.data.Root = root object.data.Root = root
} }
return err return err
} }
@ -257,32 +257,32 @@ func (c *stateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) c.SetBalance(new(big.Int).Sub(c.Balance(), amount))
} }
func (self *stateObject) SetBalance(amount *big.Int) { func (object *stateObject) SetBalance(amount *big.Int) {
self.db.journal.append(balanceChange{ object.db.journal.append(balanceChange{
account: &self.address, account: &object.address,
prev: new(big.Int).Set(self.data.Balance), prev: new(big.Int).Set(object.data.Balance),
}) })
self.setBalance(amount) object.setBalance(amount)
} }
func (self *stateObject) setBalance(amount *big.Int) { func (object *stateObject) setBalance(amount *big.Int) {
self.data.Balance = amount object.data.Balance = amount
} }
// Return the gas back to the origin. Used by the Virtual machine or Closures // Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *stateObject) ReturnGas(gas *big.Int) {} func (c *stateObject) ReturnGas(gas *big.Int) {}
func (self *stateObject) deepCopy(db *StateDB) *stateObject { func (object *stateObject) deepCopy(db *StateDB) *stateObject {
stateObject := newObject(db, self.address, self.data) stateObject := newObject(db, object.address, object.data)
if self.trie != nil { if object.trie != nil {
stateObject.trie = db.db.CopyTrie(self.trie) stateObject.trie = db.db.CopyTrie(object.trie)
} }
stateObject.code = self.code stateObject.code = object.code
stateObject.dirtyStorage = self.dirtyStorage.Copy() stateObject.dirtyStorage = object.dirtyStorage.Copy()
stateObject.cachedStorage = self.dirtyStorage.Copy() stateObject.cachedStorage = object.dirtyStorage.Copy()
stateObject.suicided = self.suicided stateObject.suicided = object.suicided
stateObject.dirtyCode = self.dirtyCode stateObject.dirtyCode = object.dirtyCode
stateObject.deleted = self.deleted stateObject.deleted = object.deleted
return stateObject return stateObject
} }
@ -296,64 +296,64 @@ func (c *stateObject) Address() common.Address {
} }
// Code returns the contract code associated with this object, if any. // Code returns the contract code associated with this object, if any.
func (self *stateObject) Code(db Database) []byte { func (object *stateObject) Code(db Database) []byte {
if self.code != nil { if object.code != nil {
return self.code return object.code
} }
if bytes.Equal(self.CodeHash(), emptyCodeHash) { if bytes.Equal(object.CodeHash(), emptyCodeHash) {
return nil return nil
} }
code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) code, err := db.ContractCode(object.addrHash, common.BytesToHash(object.CodeHash()))
if err != nil { if err != nil {
self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) object.setError(fmt.Errorf("can't load code hash %x: %v", object.CodeHash(), err))
} }
self.code = code object.code = code
return code return code
} }
func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { func (object *stateObject) SetCode(codeHash common.Hash, code []byte) {
prevcode := self.Code(self.db.db) prevcode := object.Code(object.db.db)
self.db.journal.append(codeChange{ object.db.journal.append(codeChange{
account: &self.address, account: &object.address,
prevhash: self.CodeHash(), prevhash: object.CodeHash(),
prevcode: prevcode, prevcode: prevcode,
}) })
self.setCode(codeHash, code) object.setCode(codeHash, code)
} }
func (self *stateObject) setCode(codeHash common.Hash, code []byte) { func (object *stateObject) setCode(codeHash common.Hash, code []byte) {
self.code = code object.code = code
self.data.CodeHash = codeHash[:] object.data.CodeHash = codeHash[:]
self.dirtyCode = true object.dirtyCode = true
} }
func (self *stateObject) SetNonce(nonce uint64) { func (object *stateObject) SetNonce(nonce uint64) {
self.db.journal.append(nonceChange{ object.db.journal.append(nonceChange{
account: &self.address, account: &object.address,
prev: self.data.Nonce, prev: object.data.Nonce,
}) })
self.setNonce(nonce) object.setNonce(nonce)
} }
func (self *stateObject) setNonce(nonce uint64) { func (object *stateObject) setNonce(nonce uint64) {
self.data.Nonce = nonce object.data.Nonce = nonce
} }
func (self *stateObject) CodeHash() []byte { func (object *stateObject) CodeHash() []byte {
return self.data.CodeHash return object.data.CodeHash
} }
func (self *stateObject) Balance() *big.Int { func (object *stateObject) Balance() *big.Int {
return self.data.Balance return object.data.Balance
} }
func (self *stateObject) Nonce() uint64 { func (object *stateObject) Nonce() uint64 {
return self.data.Nonce return object.data.Nonce
} }
// Never called, but must be present to allow stateObject to be used // Never called, but must be present to allow stateObject to be used
// as a vm.Account interface that also satisfies the vm.ContractRef // as a vm.Account interface that also satisfies the vm.ContractRef
// interface. Interfaces are awesome. // interface. Interfaces are awesome.
func (self *stateObject) Value() *big.Int { func (object *stateObject) Value() *big.Int {
panic("Value on stateObject should never be called") panic("Value on stateObject should never be called")
} }

View file

@ -101,103 +101,103 @@ func New(root common.Hash, db Database) (*StateDB, error) {
} }
// setError remembers the first non-nil error it is called with. // setError remembers the first non-nil error it is called with.
func (self *StateDB) setError(err error) { func (db *StateDB) setError(err error) {
if self.dbErr == nil { if db.dbErr == nil {
self.dbErr = err db.dbErr = err
} }
} }
func (self *StateDB) Error() error { func (db *StateDB) Error() error {
return self.dbErr return db.dbErr
} }
// Reset clears out all ephemeral state objects from the state db, but keeps // Reset clears out all ephemeral state objects from the state db, but keeps
// the underlying state trie to avoid reloading data for the next operations. // the underlying state trie to avoid reloading data for the next operations.
func (self *StateDB) Reset(root common.Hash) error { func (db *StateDB) Reset(root common.Hash) error {
tr, err := self.db.OpenTrie(root) tr, err := db.db.OpenTrie(root)
if err != nil { if err != nil {
return err return err
} }
self.trie = tr db.trie = tr
self.stateObjects = make(map[common.Address]*stateObject) db.stateObjects = make(map[common.Address]*stateObject)
self.stateObjectsDirty = make(map[common.Address]struct{}) db.stateObjectsDirty = make(map[common.Address]struct{})
self.thash = common.Hash{} db.thash = common.Hash{}
self.bhash = common.Hash{} db.bhash = common.Hash{}
self.txIndex = 0 db.txIndex = 0
self.logs = make(map[common.Hash][]*types.Log) db.logs = make(map[common.Hash][]*types.Log)
self.logSize = 0 db.logSize = 0
self.preimages = make(map[common.Hash][]byte) db.preimages = make(map[common.Hash][]byte)
self.clearJournalAndRefund() db.clearJournalAndRefund()
return nil return nil
} }
func (self *StateDB) AddLog(log *types.Log) { func (db *StateDB) AddLog(log *types.Log) {
self.journal.append(addLogChange{txhash: self.thash}) db.journal.append(addLogChange{txhash: db.thash})
log.TxHash = self.thash log.TxHash = db.thash
log.BlockHash = self.bhash log.BlockHash = db.bhash
log.TxIndex = uint(self.txIndex) log.TxIndex = uint(db.txIndex)
log.Index = self.logSize log.Index = db.logSize
self.logs[self.thash] = append(self.logs[self.thash], log) db.logs[db.thash] = append(db.logs[db.thash], log)
self.logSize++ db.logSize++
} }
func (self *StateDB) GetLogs(hash common.Hash) []*types.Log { func (db *StateDB) GetLogs(hash common.Hash) []*types.Log {
return self.logs[hash] return db.logs[hash]
} }
func (self *StateDB) Logs() []*types.Log { func (db *StateDB) Logs() []*types.Log {
var logs []*types.Log var logs []*types.Log
for _, lgs := range self.logs { for _, lgs := range db.logs {
logs = append(logs, lgs...) logs = append(logs, lgs...)
} }
return logs return logs
} }
// AddPreimage records a SHA3 preimage seen by the VM. // AddPreimage records a SHA3 preimage seen by the VM.
func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) { func (db *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
if _, ok := self.preimages[hash]; !ok { if _, ok := db.preimages[hash]; !ok {
self.journal.append(addPreimageChange{hash: hash}) db.journal.append(addPreimageChange{hash: hash})
pi := make([]byte, len(preimage)) pi := make([]byte, len(preimage))
copy(pi, preimage) copy(pi, preimage)
self.preimages[hash] = pi db.preimages[hash] = pi
} }
} }
// Preimages returns a list of SHA3 preimages that have been submitted. // Preimages returns a list of SHA3 preimages that have been submitted.
func (self *StateDB) Preimages() map[common.Hash][]byte { func (db *StateDB) Preimages() map[common.Hash][]byte {
return self.preimages return db.preimages
} }
func (self *StateDB) AddRefund(gas uint64) { func (db *StateDB) AddRefund(gas uint64) {
self.journal.append(refundChange{prev: self.refund}) db.journal.append(refundChange{prev: db.refund})
self.refund += gas db.refund += gas
} }
// Exist reports whether the given account address exists in the state. // Exist reports whether the given account address exists in the state.
// Notably this also returns true for suicided accounts. // Notably this also returns true for suicided accounts.
func (self *StateDB) Exist(addr common.Address) bool { func (db *StateDB) Exist(addr common.Address) bool {
return self.getStateObject(addr) != nil return db.getStateObject(addr) != nil
} }
// Empty returns whether the state object is either non-existent // Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0) // or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *StateDB) Empty(addr common.Address) bool { func (db *StateDB) Empty(addr common.Address) bool {
so := self.getStateObject(addr) so := db.getStateObject(addr)
return so == nil || so.empty() return so == nil || so.empty()
} }
// Retrieve the balance from the given address or 0 if object not found // Retrieve the balance from the given address or 0 if object not found
func (self *StateDB) GetBalance(addr common.Address) *big.Int { func (db *StateDB) GetBalance(addr common.Address) *big.Int {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.Balance() return stateObject.Balance()
} }
return common.Big0 return common.Big0
} }
func (self *StateDB) GetNonce(addr common.Address) uint64 { func (db *StateDB) GetNonce(addr common.Address) uint64 {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.Nonce() return stateObject.Nonce()
} }
@ -205,63 +205,63 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 {
return 0 return 0
} }
func (self *StateDB) GetCode(addr common.Address) []byte { func (db *StateDB) GetCode(addr common.Address) []byte {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.Code(self.db) return stateObject.Code(db.db)
} }
return nil return nil
} }
func (self *StateDB) GetCodeSize(addr common.Address) int { func (db *StateDB) GetCodeSize(addr common.Address) int {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return 0 return 0
} }
if stateObject.code != nil { if stateObject.code != nil {
return len(stateObject.code) return len(stateObject.code)
} }
size, err := self.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash())) size, err := db.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
if err != nil { if err != nil {
self.setError(err) db.setError(err)
} }
return size return size
} }
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash { func (db *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return common.Hash{} return common.Hash{}
} }
return common.BytesToHash(stateObject.CodeHash()) return common.BytesToHash(stateObject.CodeHash())
} }
func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash { func (db *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.GetState(self.db, bhash) return stateObject.GetState(db.db, bhash)
} }
return common.Hash{} return common.Hash{}
} }
// Database retrieves the low level database supporting the lower level trie ops. // Database retrieves the low level database supporting the lower level trie ops.
func (self *StateDB) Database() Database { func (db *StateDB) Database() Database {
return self.db return db.db
} }
// StorageTrie returns the storage trie of an account. // StorageTrie returns the storage trie of an account.
// The return value is a copy and is nil for non-existent accounts. // The return value is a copy and is nil for non-existent accounts.
func (self *StateDB) StorageTrie(addr common.Address) Trie { func (db *StateDB) StorageTrie(addr common.Address) Trie {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return nil return nil
} }
cpy := stateObject.deepCopy(self) cpy := stateObject.deepCopy(db)
return cpy.updateTrie(self.db) return cpy.updateTrie(db.db)
} }
func (self *StateDB) HasSuicided(addr common.Address) bool { func (db *StateDB) HasSuicided(addr common.Address) bool {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
return stateObject.suicided return stateObject.suicided
} }
@ -273,46 +273,46 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
*/ */
// AddBalance adds amount to the account associated with addr. // AddBalance adds amount to the account associated with addr.
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (db *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.AddBalance(amount) stateObject.AddBalance(amount)
} }
} }
// SubBalance subtracts amount from the account associated with addr. // SubBalance subtracts amount from the account associated with addr.
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (db *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SubBalance(amount) stateObject.SubBalance(amount)
} }
} }
func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) { func (db *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetBalance(amount) stateObject.SetBalance(amount)
} }
} }
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { func (db *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetNonce(nonce) stateObject.SetNonce(nonce)
} }
} }
func (self *StateDB) SetCode(addr common.Address, code []byte) { func (db *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code) stateObject.SetCode(crypto.Keccak256Hash(code), code)
} }
} }
func (self *StateDB) SetState(addr common.Address, key, value common.Hash) { func (db *StateDB) SetState(addr common.Address, key, value common.Hash) {
stateObject := self.GetOrNewStateObject(addr) stateObject := db.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetState(self.db, key, value) stateObject.SetState(db.db, key, value)
} }
} }
@ -321,12 +321,12 @@ func (self *StateDB) SetState(addr common.Address, key, value common.Hash) {
// //
// The account's state object is still available until the state is committed, // The account's state object is still available until the state is committed,
// getStateObject will return a non-nil account after Suicide. // getStateObject will return a non-nil account after Suicide.
func (self *StateDB) Suicide(addr common.Address) bool { func (db *StateDB) Suicide(addr common.Address) bool {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return false return false
} }
self.journal.append(suicideChange{ db.journal.append(suicideChange{
account: &addr, account: &addr,
prev: stateObject.suicided, prev: stateObject.suicided,
prevbalance: new(big.Int).Set(stateObject.Balance()), prevbalance: new(big.Int).Set(stateObject.Balance()),
@ -342,26 +342,26 @@ func (self *StateDB) Suicide(addr common.Address) bool {
// //
// updateStateObject writes the given object to the trie. // updateStateObject writes the given object to the trie.
func (self *StateDB) updateStateObject(stateObject *stateObject) { func (db *StateDB) updateStateObject(stateObject *stateObject) {
addr := stateObject.Address() addr := stateObject.Address()
data, err := rlp.EncodeToBytes(stateObject) data, err := rlp.EncodeToBytes(stateObject)
if err != nil { if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
} }
self.setError(self.trie.TryUpdate(addr[:], data)) db.setError(db.trie.TryUpdate(addr[:], data))
} }
// deleteStateObject removes the given object from the state trie. // deleteStateObject removes the given object from the state trie.
func (self *StateDB) deleteStateObject(stateObject *stateObject) { func (db *StateDB) deleteStateObject(stateObject *stateObject) {
stateObject.deleted = true stateObject.deleted = true
addr := stateObject.Address() addr := stateObject.Address()
self.setError(self.trie.TryDelete(addr[:])) db.setError(db.trie.TryDelete(addr[:]))
} }
// Retrieve a state object given by the address. Returns nil if not found. // Retrieve a state object given by the address. Returns nil if not found.
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { func (db *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects. // Prefer 'live' objects.
if obj := self.stateObjects[addr]; obj != nil { if obj := db.stateObjects[addr]; obj != nil {
if obj.deleted { if obj.deleted {
return nil return nil
} }
@ -369,9 +369,9 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
} }
// Load the object from the database. // Load the object from the database.
enc, err := self.trie.TryGet(addr[:]) enc, err := db.trie.TryGet(addr[:])
if len(enc) == 0 { if len(enc) == 0 {
self.setError(err) db.setError(err)
return nil return nil
} }
var data Account var data Account
@ -380,36 +380,36 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
return nil return nil
} }
// Insert into the live set. // Insert into the live set.
obj := newObject(self, addr, data) obj := newObject(db, addr, data)
self.setStateObject(obj) db.setStateObject(obj)
return obj return obj
} }
func (self *StateDB) setStateObject(object *stateObject) { func (db *StateDB) setStateObject(object *stateObject) {
self.stateObjects[object.Address()] = object db.stateObjects[object.Address()] = object
} }
// Retrieve a state object or create a new state object if nil. // Retrieve a state object or create a new state object if nil.
func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { func (db *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
stateObject := self.getStateObject(addr) stateObject := db.getStateObject(addr)
if stateObject == nil || stateObject.deleted { if stateObject == nil || stateObject.deleted {
stateObject, _ = self.createObject(addr) stateObject, _ = db.createObject(addr)
} }
return stateObject return stateObject
} }
// createObject creates a new state object. If there is an existing account with // createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value. // the given address, it is overwritten and returned as the second return value.
func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { func (db *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = self.getStateObject(addr) prev = db.getStateObject(addr)
newobj = newObject(self, addr, Account{}) newobj = newObject(db, addr, Account{})
newobj.setNonce(0) // sets the object to dirty newobj.setNonce(0) // sets the object to dirty
if prev == nil { if prev == nil {
self.journal.append(createObjectChange{account: &addr}) db.journal.append(createObjectChange{account: &addr})
} else { } else {
self.journal.append(resetObjectChange{prev: prev}) db.journal.append(resetObjectChange{prev: prev})
} }
self.setStateObject(newobj) db.setStateObject(newobj)
return newobj, prev return newobj, prev
} }
@ -423,8 +423,8 @@ func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObjec
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
// //
// Carrying over the balance ensures that Ether doesn't disappear. // Carrying over the balance ensures that Ether doesn't disappear.
func (self *StateDB) CreateAccount(addr common.Address) { func (db *StateDB) CreateAccount(addr common.Address) {
new, prev := self.createObject(addr) new, prev := db.createObject(addr)
if prev != nil { if prev != nil {
new.setBalance(prev.data.Balance) new.setBalance(prev.data.Balance)
} }
@ -453,29 +453,29 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common
// Copy creates a deep, independent copy of the state. // Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy. // Snapshots of the copied state cannot be applied to the copy.
func (self *StateDB) Copy() *StateDB { func (db *StateDB) Copy() *StateDB {
self.lock.Lock() db.lock.Lock()
defer self.lock.Unlock() defer db.lock.Unlock()
// Copy all the basic fields, initialize the memory ones // Copy all the basic fields, initialize the memory ones
state := &StateDB{ state := &StateDB{
db: self.db, db: db.db,
trie: self.db.CopyTrie(self.trie), trie: db.db.CopyTrie(db.trie),
stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), stateObjects: make(map[common.Address]*stateObject, len(db.journal.dirties)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), stateObjectsDirty: make(map[common.Address]struct{}, len(db.journal.dirties)),
refund: self.refund, refund: db.refund,
logs: make(map[common.Hash][]*types.Log, len(self.logs)), logs: make(map[common.Hash][]*types.Log, len(db.logs)),
logSize: self.logSize, logSize: db.logSize,
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
journal: newJournal(), journal: newJournal(),
} }
// Copy the dirty states, logs, and preimages // Copy the dirty states, logs, and preimages
for addr := range self.journal.dirties { for addr := range db.journal.dirties {
// As documented [here](https://github.com/ethereum/go-ethereum/pull/16485#issuecomment-380438527), // As documented [here](https://github.com/ethereum/go-ethereum/pull/16485#issuecomment-380438527),
// and in the Finalise-method, there is a case where an object is in the journal but not // and in the Finalise-method, there is a case where an object is in the journal but not
// in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for // in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for
// nil // nil
if object, exist := self.stateObjects[addr]; exist { if object, exist := db.stateObjects[addr]; exist {
state.stateObjects[addr] = object.deepCopy(state) state.stateObjects[addr] = object.deepCopy(state)
state.stateObjectsDirty[addr] = struct{}{} state.stateObjectsDirty[addr] = struct{}{}
} }
@ -483,53 +483,53 @@ func (self *StateDB) Copy() *StateDB {
// Above, we don't copy the actual journal. This means that if the copy is copied, the // Above, we don't copy the actual journal. This means that if the copy is copied, the
// loop above will be a no-op, since the copy's journal is empty. // loop above will be a no-op, since the copy's journal is empty.
// Thus, here we iterate over stateObjects, to enable copies of copies // Thus, here we iterate over stateObjects, to enable copies of copies
for addr := range self.stateObjectsDirty { for addr := range db.stateObjectsDirty {
if _, exist := state.stateObjects[addr]; !exist { if _, exist := state.stateObjects[addr]; !exist {
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) state.stateObjects[addr] = db.stateObjects[addr].deepCopy(state)
state.stateObjectsDirty[addr] = struct{}{} state.stateObjectsDirty[addr] = struct{}{}
} }
} }
for hash, logs := range self.logs { for hash, logs := range db.logs {
state.logs[hash] = make([]*types.Log, len(logs)) state.logs[hash] = make([]*types.Log, len(logs))
copy(state.logs[hash], logs) copy(state.logs[hash], logs)
} }
for hash, preimage := range self.preimages { for hash, preimage := range db.preimages {
state.preimages[hash] = preimage state.preimages[hash] = preimage
} }
return state return state
} }
// Snapshot returns an identifier for the current revision of the state. // Snapshot returns an identifier for the current revision of the state.
func (self *StateDB) Snapshot() int { func (db *StateDB) Snapshot() int {
id := self.nextRevisionId id := db.nextRevisionId
self.nextRevisionId++ db.nextRevisionId++
self.validRevisions = append(self.validRevisions, revision{id, self.journal.length()}) db.validRevisions = append(db.validRevisions, revision{id, db.journal.length()})
return id return id
} }
// RevertToSnapshot reverts all state changes made since the given revision. // RevertToSnapshot reverts all state changes made since the given revision.
func (self *StateDB) RevertToSnapshot(revid int) { func (db *StateDB) RevertToSnapshot(revid int) {
// Find the snapshot in the stack of valid snapshots. // Find the snapshot in the stack of valid snapshots.
idx := sort.Search(len(self.validRevisions), func(i int) bool { idx := sort.Search(len(db.validRevisions), func(i int) bool {
return self.validRevisions[i].id >= revid return db.validRevisions[i].id >= revid
}) })
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid { if idx == len(db.validRevisions) || db.validRevisions[idx].id != revid {
panic(fmt.Errorf("revision id %v cannot be reverted", revid)) panic(fmt.Errorf("revision id %v cannot be reverted", revid))
} }
snapshot := self.validRevisions[idx].journalIndex snapshot := db.validRevisions[idx].journalIndex
// Replay the journal to undo changes and remove invalidated snapshots // Replay the journal to undo changes and remove invalidated snapshots
self.journal.revert(self, snapshot) db.journal.revert(db, snapshot)
self.validRevisions = self.validRevisions[:idx] db.validRevisions = db.validRevisions[:idx]
} }
// GetRefund returns the current value of the refund counter. // GetRefund returns the current value of the refund counter.
func (self *StateDB) GetRefund() uint64 { func (db *StateDB) GetRefund() uint64 {
return self.refund return db.refund
} }
// Finalise finalises the state by removing the self destructed objects // Finalise finalises the state by removing the db destructed objects
// and clears the journal as well as the refunds. // and clears the journal as well as the refunds.
func (s *StateDB) Finalise(deleteEmptyObjects bool) { func (s *StateDB) Finalise(deleteEmptyObjects bool) {
for addr := range s.journal.dirties { for addr := range s.journal.dirties {
@ -566,10 +566,10 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
// Prepare sets the current transaction hash and index and block hash which is // Prepare sets the current transaction hash and index and block hash which is
// used when the EVM emits new state logs. // used when the EVM emits new state logs.
func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { func (db *StateDB) Prepare(thash, bhash common.Hash, ti int) {
self.thash = thash db.thash = thash
self.bhash = bhash db.bhash = bhash
self.txIndex = ti db.txIndex = ti
} }
func (s *StateDB) clearJournalAndRefund() { func (s *StateDB) clearJournalAndRefund() {

View file

@ -392,10 +392,10 @@ type Blocks []*Block
type BlockBy func(b1, b2 *Block) bool type BlockBy func(b1, b2 *Block) bool
func (self BlockBy) Sort(blocks Blocks) { func (by BlockBy) Sort(blocks Blocks) {
bs := blockSorter{ bs := blockSorter{
blocks: blocks, blocks: blocks,
by: self, by: by,
} }
sort.Sort(bs) sort.Sort(bs)
} }
@ -405,10 +405,10 @@ type blockSorter struct {
by func(b1, b2 *Block) bool by func(b1, b2 *Block) bool
} }
func (self blockSorter) Len() int { return len(self.blocks) } func (b blockSorter) Len() int { return len(b.blocks) }
func (self blockSorter) Swap(i, j int) { func (b blockSorter) Swap(i, j int) {
self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i] b.blocks[i], b.blocks[j] = b.blocks[j], b.blocks[i]
} }
func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } func (b blockSorter) Less(i, j int) bool { return b.by(b.blocks[i], b.blocks[j]) }
func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 } func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 }

View file

@ -23,18 +23,18 @@ type Generic struct {
Fn func(data interface{}) Fn func(data interface{})
} }
// self = registered, f = incoming // g = registered, f = incoming
func (self Generic) Compare(f Filter) bool { func (g Generic) Compare(f Filter) bool {
var strMatch, dataMatch = true, true var strMatch, dataMatch = true, true
filter := f.(Generic) filter := f.(Generic)
if (len(self.Str1) > 0 && filter.Str1 != self.Str1) || if (len(g.Str1) > 0 && filter.Str1 != g.Str1) ||
(len(self.Str2) > 0 && filter.Str2 != self.Str2) || (len(g.Str2) > 0 && filter.Str2 != g.Str2) ||
(len(self.Str3) > 0 && filter.Str3 != self.Str3) { (len(g.Str3) > 0 && filter.Str3 != g.Str3) {
strMatch = false strMatch = false
} }
for k := range self.Data { for k := range g.Data {
if _, ok := filter.Data[k]; !ok { if _, ok := filter.Data[k]; !ok {
return false return false
} }
@ -43,6 +43,6 @@ func (self Generic) Compare(f Filter) bool {
return strMatch && dataMatch return strMatch && dataMatch
} }
func (self Generic) Trigger(data interface{}) { func (g Generic) Trigger(data interface{}) {
self.Fn(data) g.Fn(data)
} }

View file

@ -89,16 +89,16 @@ func NewClientManager(rcTarget, maxSimReq, maxRcSum uint64) *ClientManager {
return cm return cm
} }
func (self *ClientManager) Stop() { func (cm *ClientManager) Stop() {
self.lock.Lock() cm.lock.Lock()
defer self.lock.Unlock() defer cm.lock.Unlock()
// signal any waiting accept routines to return false // signal any waiting accept routines to return false
self.nodes = make(map[*cmNode]struct{}) cm.nodes = make(map[*cmNode]struct{})
close(self.resumeQueue) close(cm.resumeQueue)
} }
func (self *ClientManager) addNode(cnode *ClientNode) *cmNode { func (cm *ClientManager) addNode(cnode *ClientNode) *cmNode {
time := mclock.Now() time := mclock.Now()
node := &cmNode{ node := &cmNode{
node: cnode, node: cnode,
@ -106,28 +106,28 @@ func (self *ClientManager) addNode(cnode *ClientNode) *cmNode {
finishRecharge: time, finishRecharge: time,
rcWeight: 1, rcWeight: 1,
} }
self.lock.Lock() cm.lock.Lock()
defer self.lock.Unlock() defer cm.lock.Unlock()
self.nodes[node] = struct{}{} cm.nodes[node] = struct{}{}
self.update(mclock.Now()) cm.update(mclock.Now())
return node return node
} }
func (self *ClientManager) removeNode(node *cmNode) { func (cm *ClientManager) removeNode(node *cmNode) {
self.lock.Lock() cm.lock.Lock()
defer self.lock.Unlock() defer cm.lock.Unlock()
time := mclock.Now() time := mclock.Now()
self.stop(node, time) cm.stop(node, time)
delete(self.nodes, node) delete(cm.nodes, node)
self.update(time) cm.update(time)
} }
// recalc sumWeight // recalc sumWeight
func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) { func (cm *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
var sumWeight, rcSum uint64 var sumWeight, rcSum uint64
for node := range self.nodes { for node := range cm.nodes {
rc := node.recharging rc := node.recharging
node.update(time) node.update(time)
if rc && !node.recharging { if rc && !node.recharging {
@ -138,44 +138,44 @@ func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
} }
rcSum += uint64(node.rcValue) rcSum += uint64(node.rcValue)
} }
self.sumWeight = sumWeight cm.sumWeight = sumWeight
self.rcSumValue = rcSum cm.rcSumValue = rcSum
return return
} }
func (self *ClientManager) update(time mclock.AbsTime) { func (cm *ClientManager) update(time mclock.AbsTime) {
for { for {
firstTime := time firstTime := time
for node := range self.nodes { for node := range cm.nodes {
if node.recharging && node.finishRecharge < firstTime { if node.recharging && node.finishRecharge < firstTime {
firstTime = node.finishRecharge firstTime = node.finishRecharge
} }
} }
if self.updateNodes(firstTime) { if cm.updateNodes(firstTime) {
for node := range self.nodes { for node := range cm.nodes {
if node.recharging { if node.recharging {
node.set(node.serving, self.simReqCnt, self.sumWeight) node.set(node.serving, cm.simReqCnt, cm.sumWeight)
} }
} }
} else { } else {
self.time = time cm.time = time
return return
} }
} }
} }
func (self *ClientManager) canStartReq() bool { func (cm *ClientManager) canStartReq() bool {
return self.simReqCnt < self.maxSimReq && self.rcSumValue < self.maxRcSum return cm.simReqCnt < cm.maxSimReq && cm.rcSumValue < cm.maxRcSum
} }
func (self *ClientManager) queueProc() { func (cm *ClientManager) queueProc() {
for rc := range self.resumeQueue { for rc := range cm.resumeQueue {
for { for {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
self.lock.Lock() cm.lock.Lock()
self.update(mclock.Now()) cm.update(mclock.Now())
cs := self.canStartReq() cs := cm.canStartReq()
self.lock.Unlock() cm.lock.Unlock()
if cs { if cs {
break break
} }
@ -184,41 +184,41 @@ func (self *ClientManager) queueProc() {
} }
} }
func (self *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool { func (cm *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool {
self.lock.Lock() cm.lock.Lock()
defer self.lock.Unlock() defer cm.lock.Unlock()
self.update(time) cm.update(time)
if !self.canStartReq() { if !cm.canStartReq() {
resume := make(chan bool) resume := make(chan bool)
self.lock.Unlock() cm.lock.Unlock()
self.resumeQueue <- resume cm.resumeQueue <- resume
<-resume <-resume
self.lock.Lock() cm.lock.Lock()
if _, ok := self.nodes[node]; !ok { if _, ok := cm.nodes[node]; !ok {
return false // reject if node has been removed or manager has been stopped return false // reject if node has been removed or manager has been stopped
} }
} }
self.simReqCnt++ cm.simReqCnt++
node.set(true, self.simReqCnt, self.sumWeight) node.set(true, cm.simReqCnt, cm.sumWeight)
node.startValue = node.rcValue node.startValue = node.rcValue
self.update(self.time) cm.update(cm.time)
return true return true
} }
func (self *ClientManager) stop(node *cmNode, time mclock.AbsTime) { func (cm *ClientManager) stop(node *cmNode, time mclock.AbsTime) {
if node.serving { if node.serving {
self.update(time) cm.update(time)
self.simReqCnt-- cm.simReqCnt--
node.set(false, self.simReqCnt, self.sumWeight) node.set(false, cm.simReqCnt, cm.sumWeight)
self.update(time) cm.update(time)
} }
} }
func (self *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) { func (cm *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) {
self.lock.Lock() cm.lock.Lock()
defer self.lock.Unlock() defer cm.lock.Unlock()
self.stop(node, time) cm.stop(node, time)
return uint64(node.rcValue), uint64(node.rcValue - node.startValue) return uint64(node.rcValue), uint64(node.rcValue - node.startValue)
} }

View file

@ -1174,15 +1174,15 @@ type NodeInfo struct {
} }
// NodeInfo retrieves some protocol metadata about the running host node. // NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *NodeInfo { func (pm *ProtocolManager) NodeInfo() *NodeInfo {
head := self.blockchain.CurrentHeader() head := pm.blockchain.CurrentHeader()
hash := head.Hash() hash := head.Hash()
return &NodeInfo{ return &NodeInfo{
Network: self.networkId, Network: pm.networkId,
Difficulty: self.blockchain.GetTd(hash, head.Number.Uint64()), Difficulty: pm.blockchain.GetTd(hash, head.Number.Uint64()),
Genesis: self.blockchain.Genesis().Hash(), Genesis: pm.blockchain.Genesis().Hash(),
Config: self.blockchain.Config(), Config: pm.blockchain.Config(),
Head: hash, Head: hash,
} }
} }

View file

@ -50,47 +50,47 @@ func NewLesTxRelay(ps *peerSet, reqDist *requestDistributor) *LesTxRelay {
return r return r
} }
func (self *LesTxRelay) registerPeer(p *peer) { func (relay *LesTxRelay) registerPeer(p *peer) {
self.lock.Lock() relay.lock.Lock()
defer self.lock.Unlock() defer relay.lock.Unlock()
self.peerList = self.ps.AllPeers() relay.peerList = relay.ps.AllPeers()
} }
func (self *LesTxRelay) unregisterPeer(p *peer) { func (relay *LesTxRelay) unregisterPeer(p *peer) {
self.lock.Lock() relay.lock.Lock()
defer self.lock.Unlock() defer relay.lock.Unlock()
self.peerList = self.ps.AllPeers() relay.peerList = relay.ps.AllPeers()
} }
// send sends a list of transactions to at most a given number of peers at // send sends a list of transactions to at most a given number of peers at
// once, never resending any particular transaction to the same peer twice // once, never resending any particular transaction to the same peer twice
func (self *LesTxRelay) send(txs types.Transactions, count int) { func (relay *LesTxRelay) send(txs types.Transactions, count int) {
sendTo := make(map[*peer]types.Transactions) sendTo := make(map[*peer]types.Transactions)
self.peerStartPos++ // rotate the starting position of the peer list relay.peerStartPos++ // rotate the starting position of the peer list
if self.peerStartPos >= len(self.peerList) { if relay.peerStartPos >= len(relay.peerList) {
self.peerStartPos = 0 relay.peerStartPos = 0
} }
for _, tx := range txs { for _, tx := range txs {
hash := tx.Hash() hash := tx.Hash()
ltr, ok := self.txSent[hash] ltr, ok := relay.txSent[hash]
if !ok { if !ok {
ltr = &ltrInfo{ ltr = &ltrInfo{
tx: tx, tx: tx,
sentTo: make(map[*peer]struct{}), sentTo: make(map[*peer]struct{}),
} }
self.txSent[hash] = ltr relay.txSent[hash] = ltr
self.txPending[hash] = struct{}{} relay.txPending[hash] = struct{}{}
} }
if len(self.peerList) > 0 { if len(relay.peerList) > 0 {
cnt := count cnt := count
pos := self.peerStartPos pos := relay.peerStartPos
for { for {
peer := self.peerList[pos] peer := relay.peerList[pos]
if _, ok := ltr.sentTo[peer]; !ok { if _, ok := ltr.sentTo[peer]; !ok {
sendTo[peer] = append(sendTo[peer], tx) sendTo[peer] = append(sendTo[peer], tx)
ltr.sentTo[peer] = struct{}{} ltr.sentTo[peer] = struct{}{}
@ -100,10 +100,10 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) {
break // sent it to the desired number of peers break // sent it to the desired number of peers
} }
pos++ pos++
if pos == len(self.peerList) { if pos == len(relay.peerList) {
pos = 0 pos = 0
} }
if pos == self.peerStartPos { if pos == relay.peerStartPos {
break // tried all available peers break // tried all available peers
} }
} }
@ -130,46 +130,46 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) {
return func() { peer.SendTxs(reqID, cost, ll) } return func() { peer.SendTxs(reqID, cost, ll) }
}, },
} }
self.reqDist.queue(rq) relay.reqDist.queue(rq)
} }
} }
func (self *LesTxRelay) Send(txs types.Transactions) { func (relay *LesTxRelay) Send(txs types.Transactions) {
self.lock.Lock() relay.lock.Lock()
defer self.lock.Unlock() defer relay.lock.Unlock()
self.send(txs, 3) relay.send(txs, 3)
} }
func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { func (relay *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
self.lock.Lock() relay.lock.Lock()
defer self.lock.Unlock() defer relay.lock.Unlock()
for _, hash := range mined { for _, hash := range mined {
delete(self.txPending, hash) delete(relay.txPending, hash)
} }
for _, hash := range rollback { for _, hash := range rollback {
self.txPending[hash] = struct{}{} relay.txPending[hash] = struct{}{}
} }
if len(self.txPending) > 0 { if len(relay.txPending) > 0 {
txs := make(types.Transactions, len(self.txPending)) txs := make(types.Transactions, len(relay.txPending))
i := 0 i := 0
for hash := range self.txPending { for hash := range relay.txPending {
txs[i] = self.txSent[hash].tx txs[i] = relay.txSent[hash].tx
i++ i++
} }
self.send(txs, 1) relay.send(txs, 1)
} }
} }
func (self *LesTxRelay) Discard(hashes []common.Hash) { func (relay *LesTxRelay) Discard(hashes []common.Hash) {
self.lock.Lock() relay.lock.Lock()
defer self.lock.Unlock() defer relay.lock.Unlock()
for _, hash := range hashes { for _, hash := range hashes {
delete(self.txSent, hash) delete(relay.txSent, hash)
delete(self.txPending, hash) delete(relay.txPending, hash)
} }
} }

View file

@ -116,45 +116,45 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
} }
// addTrustedCheckpoint adds a trusted checkpoint to the blockchain // addTrustedCheckpoint adds a trusted checkpoint to the blockchain
func (self *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) { func (bc *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) {
if self.odr.ChtIndexer() != nil { if bc.odr.ChtIndexer() != nil {
StoreChtRoot(self.chainDb, cp.sectionIdx, cp.sectionHead, cp.chtRoot) StoreChtRoot(bc.chainDb, cp.sectionIdx, cp.sectionHead, cp.chtRoot)
self.odr.ChtIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead) bc.odr.ChtIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
} }
if self.odr.BloomTrieIndexer() != nil { if bc.odr.BloomTrieIndexer() != nil {
StoreBloomTrieRoot(self.chainDb, cp.sectionIdx, cp.sectionHead, cp.bloomTrieRoot) StoreBloomTrieRoot(bc.chainDb, cp.sectionIdx, cp.sectionHead, cp.bloomTrieRoot)
self.odr.BloomTrieIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead) bc.odr.BloomTrieIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
} }
if self.odr.BloomIndexer() != nil { if bc.odr.BloomIndexer() != nil {
self.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead) bc.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
} }
log.Info("Added trusted checkpoint", "chain", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead) log.Info("Added trusted checkpoint", "bc", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead)
} }
func (self *LightChain) getProcInterrupt() bool { func (bc *LightChain) getProcInterrupt() bool {
return atomic.LoadInt32(&self.procInterrupt) == 1 return atomic.LoadInt32(&bc.procInterrupt) == 1
} }
// Odr returns the ODR backend of the chain // Odr returns the ODR backend of the chain
func (self *LightChain) Odr() OdrBackend { func (bc *LightChain) Odr() OdrBackend {
return self.odr return bc.odr
} }
// loadLastState loads the last known chain state from the database. This method // loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held. // assumes that the chain manager mutex is held.
func (self *LightChain) loadLastState() error { func (bc *LightChain) loadLastState() error {
if head := rawdb.ReadHeadHeaderHash(self.chainDb); head == (common.Hash{}) { if head := rawdb.ReadHeadHeaderHash(bc.chainDb); head == (common.Hash{}) {
// Corrupt or empty database, init from scratch // Corrupt or empty database, init from scratch
self.Reset() bc.Reset()
} else { } else {
if header := self.GetHeaderByHash(head); header != nil { if header := bc.GetHeaderByHash(head); header != nil {
self.hc.SetCurrentHeader(header) bc.hc.SetCurrentHeader(header)
} }
} }
// Issue a status log and return // Issue a status log and return
header := self.hc.CurrentHeader() header := bc.hc.CurrentHeader()
headerTd := self.GetTd(header.Hash(), header.Number.Uint64()) headerTd := bc.GetTd(header.Hash(), header.Number.Uint64())
log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd) log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd)
return nil return nil
@ -171,8 +171,8 @@ func (bc *LightChain) SetHead(head uint64) {
} }
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
func (self *LightChain) GasLimit() uint64 { func (bc *LightChain) GasLimit() uint64 {
return self.hc.CurrentHeader().GasLimit return bc.hc.CurrentHeader().GasLimit
} }
// Reset purges the entire blockchain, restoring it to its genesis state. // Reset purges the entire blockchain, restoring it to its genesis state.
@ -183,7 +183,7 @@ func (bc *LightChain) Reset() {
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the // ResetWithGenesisBlock purges the entire blockchain, restoring it to the
// specified genesis state. // specified genesis state.
func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
// Dump the entire block chain and purge the caches // Dump the entire block bc and purge the caches
bc.SetHead(0) bc.SetHead(0)
bc.mu.Lock() bc.mu.Lock()
@ -215,42 +215,42 @@ func (bc *LightChain) State() (*state.StateDB, error) {
// GetBody retrieves a block body (transactions and uncles) from the database // GetBody retrieves a block body (transactions and uncles) from the database
// or ODR service by hash, caching it if found. // or ODR service by hash, caching it if found.
func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) { func (bc *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) {
// Short circuit if the body's already in the cache, retrieve otherwise // Short circuit if the body's already in the cache, retrieve otherwise
if cached, ok := self.bodyCache.Get(hash); ok { if cached, ok := bc.bodyCache.Get(hash); ok {
body := cached.(*types.Body) body := cached.(*types.Body)
return body, nil return body, nil
} }
number := self.hc.GetBlockNumber(hash) number := bc.hc.GetBlockNumber(hash)
if number == nil { if number == nil {
return nil, errors.New("unknown block") return nil, errors.New("unknown block")
} }
body, err := GetBody(ctx, self.odr, hash, *number) body, err := GetBody(ctx, bc.odr, hash, *number)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Cache the found body for next time and return // Cache the found body for next time and return
self.bodyCache.Add(hash, body) bc.bodyCache.Add(hash, body)
return body, nil return body, nil
} }
// GetBodyRLP retrieves a block body in RLP encoding from the database or // GetBodyRLP retrieves a block body in RLP encoding from the database or
// ODR service by hash, caching it if found. // ODR service by hash, caching it if found.
func (self *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) { func (bc *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) {
// Short circuit if the body's already in the cache, retrieve otherwise // Short circuit if the body's already in the cache, retrieve otherwise
if cached, ok := self.bodyRLPCache.Get(hash); ok { if cached, ok := bc.bodyRLPCache.Get(hash); ok {
return cached.(rlp.RawValue), nil return cached.(rlp.RawValue), nil
} }
number := self.hc.GetBlockNumber(hash) number := bc.hc.GetBlockNumber(hash)
if number == nil { if number == nil {
return nil, errors.New("unknown block") return nil, errors.New("unknown block")
} }
body, err := GetBodyRLP(ctx, self.odr, hash, *number) body, err := GetBodyRLP(ctx, bc.odr, hash, *number)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Cache the found body for next time and return // Cache the found body for next time and return
self.bodyRLPCache.Add(hash, body) bc.bodyRLPCache.Add(hash, body)
return body, nil return body, nil
} }
@ -263,38 +263,38 @@ func (bc *LightChain) HasBlock(hash common.Hash, number uint64) bool {
// GetBlock retrieves a block from the database or ODR service by hash and number, // GetBlock retrieves a block from the database or ODR service by hash and number,
// caching it if found. // caching it if found.
func (self *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) { func (bc *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) {
// Short circuit if the block's already in the cache, retrieve otherwise // Short circuit if the block's already in the cache, retrieve otherwise
if block, ok := self.blockCache.Get(hash); ok { if block, ok := bc.blockCache.Get(hash); ok {
return block.(*types.Block), nil return block.(*types.Block), nil
} }
block, err := GetBlock(ctx, self.odr, hash, number) block, err := GetBlock(ctx, bc.odr, hash, number)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Cache the found block for next time and return // Cache the found block for next time and return
self.blockCache.Add(block.Hash(), block) bc.blockCache.Add(block.Hash(), block)
return block, nil return block, nil
} }
// GetBlockByHash retrieves a block from the database or ODR service by hash, // GetBlockByHash retrieves a block from the database or ODR service by hash,
// caching it if found. // caching it if found.
func (self *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (bc *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
number := self.hc.GetBlockNumber(hash) number := bc.hc.GetBlockNumber(hash)
if number == nil { if number == nil {
return nil, errors.New("unknown block") return nil, errors.New("unknown block")
} }
return self.GetBlock(ctx, hash, *number) return bc.GetBlock(ctx, hash, *number)
} }
// GetBlockByNumber retrieves a block from the database or ODR service by // GetBlockByNumber retrieves a block from the database or ODR service by
// number, caching it (associated with its hash) if found. // number, caching it (associated with its hash) if found.
func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) { func (bc *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) {
hash, err := GetCanonicalHash(ctx, self.odr, number) hash, err := GetCanonicalHash(ctx, bc.odr, number)
if hash == (common.Hash{}) || err != nil { if hash == (common.Hash{}) || err != nil {
return nil, err return nil, err
} }
return self.GetBlock(ctx, hash, number) return bc.GetBlock(ctx, hash, number)
} }
// Stop stops the blockchain service. If any imports are currently in progress // Stop stops the blockchain service. If any imports are currently in progress
@ -312,31 +312,31 @@ func (bc *LightChain) Stop() {
// Rollback is designed to remove a chain of links from the database that aren't // Rollback is designed to remove a chain of links from the database that aren't
// certain enough to be valid. // certain enough to be valid.
func (self *LightChain) Rollback(chain []common.Hash) { func (bc *LightChain) Rollback(chain []common.Hash) {
self.mu.Lock() bc.mu.Lock()
defer self.mu.Unlock() defer bc.mu.Unlock()
for i := len(chain) - 1; i >= 0; i-- { for i := len(chain) - 1; i >= 0; i-- {
hash := chain[i] hash := chain[i]
if head := self.hc.CurrentHeader(); head.Hash() == hash { if head := bc.hc.CurrentHeader(); head.Hash() == hash {
self.hc.SetCurrentHeader(self.GetHeader(head.ParentHash, head.Number.Uint64()-1)) bc.hc.SetCurrentHeader(bc.GetHeader(head.ParentHash, head.Number.Uint64()-1))
} }
} }
} }
// postChainEvents iterates over the events generated by a chain insertion and // postChainEvents iterates over the events generated by a chain insertion and
// posts them into the event feed. // posts them into the event feed.
func (self *LightChain) postChainEvents(events []interface{}) { func (chain *LightChain) postChainEvents(events []interface{}) {
for _, event := range events { for _, event := range events {
switch ev := event.(type) { switch ev := event.(type) {
case core.ChainEvent: case core.ChainEvent:
if self.CurrentHeader().Hash() == ev.Hash { if chain.CurrentHeader().Hash() == ev.Hash {
self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block}) chain.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
} }
self.chainFeed.Send(ev) chain.chainFeed.Send(ev)
case core.ChainSideEvent: case core.ChainSideEvent:
self.chainSideFeed.Send(ev) chain.chainSideFeed.Send(ev)
} }
} }
} }
@ -352,28 +352,28 @@ func (self *LightChain) postChainEvents(events []interface{}) {
// //
// In the case of a light chain, InsertHeaderChain also creates and posts light // In the case of a light chain, InsertHeaderChain also creates and posts light
// chain events when necessary. // chain events when necessary.
func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { func (bc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
start := time.Now() start := time.Now()
if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil { if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
return i, err return i, err
} }
// Make sure only one thread manipulates the chain at once // Make sure only one thread manipulates the chain at once
self.chainmu.Lock() bc.chainmu.Lock()
defer func() { defer func() {
self.chainmu.Unlock() bc.chainmu.Unlock()
time.Sleep(time.Millisecond * 10) // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation time.Sleep(time.Millisecond * 10) // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation
}() }()
self.wg.Add(1) bc.wg.Add(1)
defer self.wg.Done() defer bc.wg.Done()
var events []interface{} var events []interface{}
whFunc := func(header *types.Header) error { whFunc := func(header *types.Header) error {
self.mu.Lock() bc.mu.Lock()
defer self.mu.Unlock() defer bc.mu.Unlock()
status, err := self.hc.WriteHeader(header) status, err := bc.hc.WriteHeader(header)
switch status { switch status {
case core.CanonStatTy: case core.CanonStatTy:
@ -386,39 +386,39 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
} }
return err return err
} }
i, err := self.hc.InsertHeaderChain(chain, whFunc, start) i, err := bc.hc.InsertHeaderChain(chain, whFunc, start)
self.postChainEvents(events) bc.postChainEvents(events)
return i, err return i, err
} }
// CurrentHeader retrieves the current head header of the canonical chain. The // CurrentHeader retrieves the current head header of the canonical chain. The
// header is retrieved from the HeaderChain's internal cache. // header is retrieved from the HeaderChain's internal cache.
func (self *LightChain) CurrentHeader() *types.Header { func (bc *LightChain) CurrentHeader() *types.Header {
return self.hc.CurrentHeader() return bc.hc.CurrentHeader()
} }
// GetTd retrieves a block's total difficulty in the canonical chain from the // GetTd retrieves a block's total difficulty in the canonical chain from the
// database by hash and number, caching it if found. // database by hash and number, caching it if found.
func (self *LightChain) GetTd(hash common.Hash, number uint64) *big.Int { func (bc *LightChain) GetTd(hash common.Hash, number uint64) *big.Int {
return self.hc.GetTd(hash, number) return bc.hc.GetTd(hash, number)
} }
// GetTdByHash retrieves a block's total difficulty in the canonical chain from the // GetTdByHash retrieves a block's total difficulty in the canonical chain from the
// database by hash, caching it if found. // database by hash, caching it if found.
func (self *LightChain) GetTdByHash(hash common.Hash) *big.Int { func (bc *LightChain) GetTdByHash(hash common.Hash) *big.Int {
return self.hc.GetTdByHash(hash) return bc.hc.GetTdByHash(hash)
} }
// GetHeader retrieves a block header from the database by hash and number, // GetHeader retrieves a block header from the database by hash and number,
// caching it if found. // caching it if found.
func (self *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header { func (bc *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header {
return self.hc.GetHeader(hash, number) return bc.hc.GetHeader(hash, number)
} }
// GetHeaderByHash retrieves a block header from the database by hash, caching it if // GetHeaderByHash retrieves a block header from the database by hash, caching it if
// found. // found.
func (self *LightChain) GetHeaderByHash(hash common.Hash) *types.Header { func (bc *LightChain) GetHeaderByHash(hash common.Hash) *types.Header {
return self.hc.GetHeaderByHash(hash) return bc.hc.GetHeaderByHash(hash)
} }
// HasHeader checks if a block header is present in the database or not, caching // HasHeader checks if a block header is present in the database or not, caching
@ -429,43 +429,43 @@ func (bc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given // GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// hash, fetching towards the genesis block. // hash, fetching towards the genesis block.
func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { func (bc *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
return self.hc.GetBlockHashesFromHash(hash, max) return bc.hc.GetBlockHashesFromHash(hash, max)
} }
// GetHeaderByNumber retrieves a block header from the database by number, // GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found. // caching it (associated with its hash) if found.
func (self *LightChain) GetHeaderByNumber(number uint64) *types.Header { func (bc *LightChain) GetHeaderByNumber(number uint64) *types.Header {
return self.hc.GetHeaderByNumber(number) return bc.hc.GetHeaderByNumber(number)
} }
// GetHeaderByNumberOdr retrieves a block header from the database or network // GetHeaderByNumberOdr retrieves a block header from the database or network
// by number, caching it (associated with its hash) if found. // by number, caching it (associated with its hash) if found.
func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) { func (bc *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) {
if header := self.hc.GetHeaderByNumber(number); header != nil { if header := bc.hc.GetHeaderByNumber(number); header != nil {
return header, nil return header, nil
} }
return GetHeaderByNumber(ctx, self.odr, number) return GetHeaderByNumber(ctx, bc.odr, number)
} }
// Config retrieves the header chain's chain configuration. // Config retrieves the header chain's chain configuration.
func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() } func (bc *LightChain) Config() *params.ChainConfig { return bc.hc.Config() }
func (self *LightChain) SyncCht(ctx context.Context) bool { func (bc *LightChain) SyncCht(ctx context.Context) bool {
if self.odr.ChtIndexer() == nil { if bc.odr.ChtIndexer() == nil {
return false return false
} }
headNum := self.CurrentHeader().Number.Uint64() headNum := bc.CurrentHeader().Number.Uint64()
chtCount, _, _ := self.odr.ChtIndexer().Sections() chtCount, _, _ := bc.odr.ChtIndexer().Sections()
if headNum+1 < chtCount*CHTFrequencyClient { if headNum+1 < chtCount*CHTFrequencyClient {
num := chtCount*CHTFrequencyClient - 1 num := chtCount*CHTFrequencyClient - 1
header, err := GetHeaderByNumber(ctx, self.odr, num) header, err := GetHeaderByNumber(ctx, bc.odr, num)
if header != nil && err == nil { if header != nil && err == nil {
self.mu.Lock() bc.mu.Lock()
if self.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { if bc.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() {
self.hc.SetCurrentHeader(header) bc.hc.SetCurrentHeader(header)
} }
self.mu.Unlock() bc.mu.Unlock()
return true return true
} }
} }
@ -474,38 +474,38 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
// LockChain locks the chain mutex for reading so that multiple canonical hashes can be // LockChain locks the chain mutex for reading so that multiple canonical hashes can be
// retrieved while it is guaranteed that they belong to the same version of the chain // retrieved while it is guaranteed that they belong to the same version of the chain
func (self *LightChain) LockChain() { func (bc *LightChain) LockChain() {
self.chainmu.RLock() bc.chainmu.RLock()
} }
// UnlockChain unlocks the chain mutex // UnlockChain unlocks the chain mutex
func (self *LightChain) UnlockChain() { func (bc *LightChain) UnlockChain() {
self.chainmu.RUnlock() bc.chainmu.RUnlock()
} }
// SubscribeChainEvent registers a subscription of ChainEvent. // SubscribeChainEvent registers a subscription of ChainEvent.
func (self *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { func (bc *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return self.scope.Track(self.chainFeed.Subscribe(ch)) return bc.scope.Track(bc.chainFeed.Subscribe(ch))
} }
// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
func (self *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { func (bc *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return self.scope.Track(self.chainHeadFeed.Subscribe(ch)) return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
} }
// SubscribeChainSideEvent registers a subscription of ChainSideEvent. // SubscribeChainSideEvent registers a subscription of ChainSideEvent.
func (self *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { func (bc *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return self.scope.Track(self.chainSideFeed.Subscribe(ch)) return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
} }
// SubscribeLogsEvent implements the interface of filters.Backend // SubscribeLogsEvent implements the interface of filters.Backend
// LightChain does not send logs events, so return an empty subscription. // LightChain does not send logs events, so return an empty subscription.
func (self *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { func (bc *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
return self.scope.Track(new(event.Feed).Subscribe(ch)) return bc.scope.Track(new(event.Feed).Subscribe(ch))
} }
// SubscribeRemovedLogsEvent implements the interface of filters.Backend // SubscribeRemovedLogsEvent implements the interface of filters.Backend
// LightChain does not send core.RemovedLogsEvent, so return an empty subscription. // LightChain does not send core.RemovedLogsEvent, so return an empty subscription.
func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { func (bc *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return self.scope.Track(new(event.Feed).Subscribe(ch)) return bc.scope.Track(new(event.Feed).Subscribe(ch))
} }

View file

@ -388,73 +388,73 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// add validates a new transaction and sets its state pending if processable. // add validates a new transaction and sets its state pending if processable.
// It also updates the locally stored nonce if necessary. // It also updates the locally stored nonce if necessary.
func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error { func (pool *TxPool) add(ctx context.Context, tx *types.Transaction) error {
hash := tx.Hash() hash := tx.Hash()
if self.pending[hash] != nil { if pool.pending[hash] != nil {
return fmt.Errorf("Known transaction (%x)", hash[:4]) return fmt.Errorf("Known transaction (%x)", hash[:4])
} }
err := self.validateTx(ctx, tx) err := pool.validateTx(ctx, tx)
if err != nil { if err != nil {
return err return err
} }
if _, ok := self.pending[hash]; !ok { if _, ok := pool.pending[hash]; !ok {
self.pending[hash] = tx pool.pending[hash] = tx
nonce := tx.Nonce() + 1 nonce := tx.Nonce() + 1
addr, _ := types.Sender(self.signer, tx) addr, _ := types.Sender(pool.signer, tx)
if nonce > self.nonce[addr] { if nonce > pool.nonce[addr] {
self.nonce[addr] = nonce pool.nonce[addr] = nonce
} }
// Notify the subscribers. This event is posted in a goroutine // Notify the subscribers. This event is posted in a goroutine
// because it's possible that somewhere during the post "Remove transaction" // because it's possible that somewhere during the post "Remove transaction"
// gets called which will then wait for the global tx pool lock and deadlock. // gets called which will then wait for the global tx pool lock and deadlock.
go self.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}}) go pool.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}})
} }
// Print a log message if low enough level is set // Print a log message if low enough level is set
log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(self.signer, tx); return from }}, "to", tx.To()) log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(pool.signer, tx); return from }}, "to", tx.To())
return nil return nil
} }
// Add adds a transaction to the pool if valid and passes it to the tx relay // Add adds a transaction to the pool if valid and passes it to the tx relay
// backend // backend
func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error { func (pool *TxPool) Add(ctx context.Context, tx *types.Transaction) error {
self.mu.Lock() pool.mu.Lock()
defer self.mu.Unlock() defer pool.mu.Unlock()
data, err := rlp.EncodeToBytes(tx) data, err := rlp.EncodeToBytes(tx)
if err != nil { if err != nil {
return err return err
} }
if err := self.add(ctx, tx); err != nil { if err := pool.add(ctx, tx); err != nil {
return err return err
} }
//fmt.Println("Send", tx.Hash()) //fmt.Println("Send", tx.Hash())
self.relay.Send(types.Transactions{tx}) pool.relay.Send(types.Transactions{tx})
self.chainDb.Put(tx.Hash().Bytes(), data) pool.chainDb.Put(tx.Hash().Bytes(), data)
return nil return nil
} }
// AddTransactions adds all valid transactions to the pool and passes them to // AddTransactions adds all valid transactions to the pool and passes them to
// the tx relay backend // the tx relay backend
func (self *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { func (pool *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) {
self.mu.Lock() pool.mu.Lock()
defer self.mu.Unlock() defer pool.mu.Unlock()
var sendTx types.Transactions var sendTx types.Transactions
for _, tx := range txs { for _, tx := range txs {
if err := self.add(ctx, tx); err == nil { if err := pool.add(ctx, tx); err == nil {
sendTx = append(sendTx, tx) sendTx = append(sendTx, tx)
} }
} }
if len(sendTx) > 0 { if len(sendTx) > 0 {
self.relay.Send(sendTx) pool.relay.Send(sendTx)
} }
} }
@ -470,13 +470,13 @@ func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
// GetTransactions returns all currently processable transactions. // GetTransactions returns all currently processable transactions.
// The returned slice may be modified by the caller. // The returned slice may be modified by the caller.
func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { func (pool *TxPool) GetTransactions() (txs types.Transactions, err error) {
self.mu.RLock() pool.mu.RLock()
defer self.mu.RUnlock() defer pool.mu.RUnlock()
txs = make(types.Transactions, len(self.pending)) txs = make(types.Transactions, len(pool.pending))
i := 0 i := 0
for _, tx := range self.pending { for _, tx := range pool.pending {
txs[i] = tx txs[i] = tx
i++ i++
} }
@ -485,14 +485,14 @@ func (self *TxPool) GetTransactions() (txs types.Transactions, err error) {
// Content retrieves the data content of the transaction pool, returning all the // Content retrieves the data content of the transaction pool, returning all the
// pending as well as queued transactions, grouped by account and nonce. // pending as well as queued transactions, grouped by account and nonce.
func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
self.mu.RLock() pool.mu.RLock()
defer self.mu.RUnlock() defer pool.mu.RUnlock()
// Retrieve all the pending transactions and sort by account and by nonce // Retrieve all the pending transactions and sort by account and by nonce
pending := make(map[common.Address]types.Transactions) pending := make(map[common.Address]types.Transactions)
for _, tx := range self.pending { for _, tx := range pool.pending {
account, _ := types.Sender(self.signer, tx) account, _ := types.Sender(pool.signer, tx)
pending[account] = append(pending[account], tx) pending[account] = append(pending[account], tx)
} }
// There are no queued transactions in a light pool, just return an empty map // There are no queued transactions in a light pool, just return an empty map
@ -501,18 +501,18 @@ func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common
} }
// RemoveTransactions removes all given transactions from the pool. // RemoveTransactions removes all given transactions from the pool.
func (self *TxPool) RemoveTransactions(txs types.Transactions) { func (pool *TxPool) RemoveTransactions(txs types.Transactions) {
self.mu.Lock() pool.mu.Lock()
defer self.mu.Unlock() defer pool.mu.Unlock()
var hashes []common.Hash var hashes []common.Hash
for _, tx := range txs { for _, tx := range txs {
//self.RemoveTx(tx.Hash()) //pool.RemoveTx(tx.Hash())
hash := tx.Hash() hash := tx.Hash()
delete(self.pending, hash) delete(pool.pending, hash)
self.chainDb.Delete(hash[:]) pool.chainDb.Delete(hash[:])
hashes = append(hashes, hash) hashes = append(hashes, hash)
} }
self.relay.Discard(hashes) pool.relay.Discard(hashes)
} }
// RemoveTx removes the transaction with the given hash from the pool. // RemoveTx removes the transaction with the given hash from the pool.

View file

@ -36,19 +36,19 @@ type testTxRelay struct {
send, discard, mined chan int send, discard, mined chan int
} }
func (self *testTxRelay) Send(txs types.Transactions) { func (relay *testTxRelay) Send(txs types.Transactions) {
self.send <- len(txs) relay.send <- len(txs)
} }
func (self *testTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { func (relay *testTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) {
m := len(mined) m := len(mined)
if m != 0 { if m != 0 {
self.mined <- m relay.mined <- m
} }
} }
func (self *testTxRelay) Discard(hashes []common.Hash) { func (relay *testTxRelay) Discard(hashes []common.Hash) {
self.discard <- len(hashes) relay.discard <- len(hashes)
} }
const poolTestTxs = 1000 const poolTestTxs = 1000

View file

@ -49,70 +49,70 @@ func NewCpuAgent(chain consensus.ChainReader, engine consensus.Engine) *CpuAgent
return miner return miner
} }
func (self *CpuAgent) Work() chan<- *Work { return self.workCh } func (agent *CpuAgent) Work() chan<- *Work { return agent.workCh }
func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch } func (agent *CpuAgent) SetReturnCh(ch chan<- *Result) { agent.returnCh = ch }
func (self *CpuAgent) Stop() { func (agent *CpuAgent) Stop() {
if !atomic.CompareAndSwapInt32(&self.isMining, 1, 0) { if !atomic.CompareAndSwapInt32(&agent.isMining, 1, 0) {
return // agent already stopped return // agent already stopped
} }
self.stop <- struct{}{} agent.stop <- struct{}{}
done: done:
// Empty work channel // Empty work channel
for { for {
select { select {
case <-self.workCh: case <-agent.workCh:
default: default:
break done break done
} }
} }
} }
func (self *CpuAgent) Start() { func (agent *CpuAgent) Start() {
if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) { if !atomic.CompareAndSwapInt32(&agent.isMining, 0, 1) {
return // agent already started return // agent already started
} }
go self.update() go agent.update()
} }
func (self *CpuAgent) update() { func (agent *CpuAgent) update() {
out: out:
for { for {
select { select {
case work := <-self.workCh: case work := <-agent.workCh:
self.mu.Lock() agent.mu.Lock()
if self.quitCurrentOp != nil { if agent.quitCurrentOp != nil {
close(self.quitCurrentOp) close(agent.quitCurrentOp)
} }
self.quitCurrentOp = make(chan struct{}) agent.quitCurrentOp = make(chan struct{})
go self.mine(work, self.quitCurrentOp) go agent.mine(work, agent.quitCurrentOp)
self.mu.Unlock() agent.mu.Unlock()
case <-self.stop: case <-agent.stop:
self.mu.Lock() agent.mu.Lock()
if self.quitCurrentOp != nil { if agent.quitCurrentOp != nil {
close(self.quitCurrentOp) close(agent.quitCurrentOp)
self.quitCurrentOp = nil agent.quitCurrentOp = nil
} }
self.mu.Unlock() agent.mu.Unlock()
break out break out
} }
} }
} }
func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { func (agent *CpuAgent) mine(work *Work, stop <-chan struct{}) {
if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil { if result, err := agent.engine.Seal(agent.chain, work.Block, stop); result != nil {
log.Info("Successfully sealed new block", "number", result.Number(), "hash", result.Hash()) log.Info("Successfully sealed new block", "number", result.Number(), "hash", result.Hash())
self.returnCh <- &Result{work, result} agent.returnCh <- &Result{work, result}
} else { } else {
if err != nil { if err != nil {
log.Warn("Block sealing failed", "err", err) log.Warn("Block sealing failed", "err", err)
} }
self.returnCh <- nil agent.returnCh <- nil
} }
} }
func (self *CpuAgent) GetHashRate() int64 { func (agent *CpuAgent) GetHashRate() int64 {
if pow, ok := self.engine.(consensus.PoW); ok { if pow, ok := agent.engine.(consensus.PoW); ok {
return int64(pow.Hashrate()) return int64(pow.Hashrate())
} }
return 0 return 0

View file

@ -75,25 +75,25 @@ func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine con
// It's entered once and as soon as `Done` or `Failed` has been broadcasted the events are unregistered and // It's entered once and as soon as `Done` or `Failed` has been broadcasted the events are unregistered and
// the loop is exited. This to prevent a major security vuln where external parties can DOS you with blocks // the loop is exited. This to prevent a major security vuln where external parties can DOS you with blocks
// and halt your mining operation for as long as the DOS continues. // and halt your mining operation for as long as the DOS continues.
func (self *Miner) update() { func (miner *Miner) update() {
events := self.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{}) events := miner.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
out: out:
for ev := range events.Chan() { for ev := range events.Chan() {
switch ev.Data.(type) { switch ev.Data.(type) {
case downloader.StartEvent: case downloader.StartEvent:
atomic.StoreInt32(&self.canStart, 0) atomic.StoreInt32(&miner.canStart, 0)
if self.Mining() { if miner.Mining() {
self.Stop() miner.Stop()
atomic.StoreInt32(&self.shouldStart, 1) atomic.StoreInt32(&miner.shouldStart, 1)
log.Info("Mining aborted due to sync") log.Info("Mining aborted due to sync")
} }
case downloader.DoneEvent, downloader.FailedEvent: case downloader.DoneEvent, downloader.FailedEvent:
shouldStart := atomic.LoadInt32(&self.shouldStart) == 1 shouldStart := atomic.LoadInt32(&miner.shouldStart) == 1
atomic.StoreInt32(&self.canStart, 1) atomic.StoreInt32(&miner.canStart, 1)
atomic.StoreInt32(&self.shouldStart, 0) atomic.StoreInt32(&miner.shouldStart, 0)
if shouldStart { if shouldStart {
self.Start(self.coinbase) miner.Start(miner.coinbase)
} }
// unsubscribe. we're only interested in this event once // unsubscribe. we're only interested in this event once
events.Unsubscribe() events.Unsubscribe()
@ -103,50 +103,50 @@ out:
} }
} }
func (self *Miner) Start(coinbase common.Address) { func (miner *Miner) Start(coinbase common.Address) {
atomic.StoreInt32(&self.shouldStart, 1) atomic.StoreInt32(&miner.shouldStart, 1)
self.SetEtherbase(coinbase) miner.SetEtherbase(coinbase)
if atomic.LoadInt32(&self.canStart) == 0 { if atomic.LoadInt32(&miner.canStart) == 0 {
log.Info("Network syncing, will start miner afterwards") log.Info("Network syncing, will start miner afterwards")
return return
} }
atomic.StoreInt32(&self.mining, 1) atomic.StoreInt32(&miner.mining, 1)
log.Info("Starting mining operation") log.Info("Starting mining operation")
self.worker.start() miner.worker.start()
self.worker.commitNewWork() miner.worker.commitNewWork()
} }
func (self *Miner) Stop() { func (miner *Miner) Stop() {
self.worker.stop() miner.worker.stop()
atomic.StoreInt32(&self.mining, 0) atomic.StoreInt32(&miner.mining, 0)
atomic.StoreInt32(&self.shouldStart, 0) atomic.StoreInt32(&miner.shouldStart, 0)
} }
func (self *Miner) Register(agent Agent) { func (miner *Miner) Register(agent Agent) {
if self.Mining() { if miner.Mining() {
agent.Start() agent.Start()
} }
self.worker.register(agent) miner.worker.register(agent)
} }
func (self *Miner) Unregister(agent Agent) { func (miner *Miner) Unregister(agent Agent) {
self.worker.unregister(agent) miner.worker.unregister(agent)
} }
func (self *Miner) Mining() bool { func (miner *Miner) Mining() bool {
return atomic.LoadInt32(&self.mining) > 0 return atomic.LoadInt32(&miner.mining) > 0
} }
func (self *Miner) HashRate() (tot int64) { func (miner *Miner) HashRate() (tot int64) {
if pow, ok := self.engine.(consensus.PoW); ok { if pow, ok := miner.engine.(consensus.PoW); ok {
tot += int64(pow.Hashrate()) tot += int64(pow.Hashrate())
} }
// do we care this might race? is it worth we're rewriting some // do we care this might race? is it worth we're rewriting some
// aspects of the worker/locking up agents so we can get an accurate // aspects of the worker/locking up agents so we can get an accurate
// hashrate? // hashrate?
for agent := range self.worker.agents { for agent := range miner.worker.agents {
if _, ok := agent.(*CpuAgent); !ok { if _, ok := agent.(*CpuAgent); !ok {
tot += agent.GetHashRate() tot += agent.GetHashRate()
} }
@ -154,17 +154,17 @@ func (self *Miner) HashRate() (tot int64) {
return return
} }
func (self *Miner) SetExtra(extra []byte) error { func (miner *Miner) SetExtra(extra []byte) error {
if uint64(len(extra)) > params.MaximumExtraDataSize { if uint64(len(extra)) > params.MaximumExtraDataSize {
return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize) return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize)
} }
self.worker.setExtra(extra) miner.worker.setExtra(extra)
return nil return nil
} }
// Pending returns the currently pending block and associated state. // Pending returns the currently pending block and associated state.
func (self *Miner) Pending() (*types.Block, *state.StateDB) { func (miner *Miner) Pending() (*types.Block, *state.StateDB) {
return self.worker.pending() return miner.worker.pending()
} }
// PendingBlock returns the currently pending block. // PendingBlock returns the currently pending block.
@ -172,11 +172,11 @@ func (self *Miner) Pending() (*types.Block, *state.StateDB) {
// Note, to access both the pending block and the pending state // Note, to access both the pending block and the pending state
// simultaneously, please use Pending(), as the pending state can // simultaneously, please use Pending(), as the pending state can
// change between multiple method calls // change between multiple method calls
func (self *Miner) PendingBlock() *types.Block { func (miner *Miner) PendingBlock() *types.Block {
return self.worker.pendingBlock() return miner.worker.pendingBlock()
} }
func (self *Miner) SetEtherbase(addr common.Address) { func (miner *Miner) SetEtherbase(addr common.Address) {
self.coinbase = addr miner.coinbase = addr
self.worker.setEtherbase(addr) miner.worker.setEtherbase(addr)
} }

View file

@ -51,7 +51,7 @@ const (
chainSideChanSize = 10 chainSideChanSize = 10
) )
// Agent can register themself with the worker // Agent can register themw with the worker
type Agent interface { type Agent interface {
Work() chan<- *Work Work() chan<- *Work
SetReturnCh(chan<- *Result) SetReturnCh(chan<- *Result)
@ -163,143 +163,143 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase com
return worker return worker
} }
func (self *worker) setEtherbase(addr common.Address) { func (w *worker) setEtherbase(addr common.Address) {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
self.coinbase = addr w.coinbase = addr
} }
func (self *worker) setExtra(extra []byte) { func (w *worker) setExtra(extra []byte) {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
self.extra = extra w.extra = extra
} }
func (self *worker) pending() (*types.Block, *state.StateDB) { func (w *worker) pending() (*types.Block, *state.StateDB) {
if atomic.LoadInt32(&self.mining) == 0 { if atomic.LoadInt32(&w.mining) == 0 {
// return a snapshot to avoid contention on currentMu mutex // return a snapshot to avoid contention on currentMu mutex
self.snapshotMu.RLock() w.snapshotMu.RLock()
defer self.snapshotMu.RUnlock() defer w.snapshotMu.RUnlock()
return self.snapshotBlock, self.snapshotState.Copy() return w.snapshotBlock, w.snapshotState.Copy()
} }
self.currentMu.Lock() w.currentMu.Lock()
defer self.currentMu.Unlock() defer w.currentMu.Unlock()
return self.current.Block, self.current.state.Copy() return w.current.Block, w.current.state.Copy()
} }
func (self *worker) pendingBlock() *types.Block { func (w *worker) pendingBlock() *types.Block {
if atomic.LoadInt32(&self.mining) == 0 { if atomic.LoadInt32(&w.mining) == 0 {
// return a snapshot to avoid contention on currentMu mutex // return a snapshot to avoid contention on currentMu mutex
self.snapshotMu.RLock() w.snapshotMu.RLock()
defer self.snapshotMu.RUnlock() defer w.snapshotMu.RUnlock()
return self.snapshotBlock return w.snapshotBlock
} }
self.currentMu.Lock() w.currentMu.Lock()
defer self.currentMu.Unlock() defer w.currentMu.Unlock()
return self.current.Block return w.current.Block
} }
func (self *worker) start() { func (w *worker) start() {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
atomic.StoreInt32(&self.mining, 1) atomic.StoreInt32(&w.mining, 1)
// spin up agents // spin up agents
for agent := range self.agents { for agent := range w.agents {
agent.Start() agent.Start()
} }
} }
func (self *worker) stop() { func (w *worker) stop() {
self.wg.Wait() w.wg.Wait()
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
if atomic.LoadInt32(&self.mining) == 1 { if atomic.LoadInt32(&w.mining) == 1 {
for agent := range self.agents { for agent := range w.agents {
agent.Stop() agent.Stop()
} }
} }
atomic.StoreInt32(&self.mining, 0) atomic.StoreInt32(&w.mining, 0)
atomic.StoreInt32(&self.atWork, 0) atomic.StoreInt32(&w.atWork, 0)
} }
func (self *worker) register(agent Agent) { func (w *worker) register(agent Agent) {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
self.agents[agent] = struct{}{} w.agents[agent] = struct{}{}
agent.SetReturnCh(self.recv) agent.SetReturnCh(w.recv)
} }
func (self *worker) unregister(agent Agent) { func (w *worker) unregister(agent Agent) {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
delete(self.agents, agent) delete(w.agents, agent)
agent.Stop() agent.Stop()
} }
func (self *worker) update() { func (w *worker) update() {
defer self.txsSub.Unsubscribe() defer w.txsSub.Unsubscribe()
defer self.chainHeadSub.Unsubscribe() defer w.chainHeadSub.Unsubscribe()
defer self.chainSideSub.Unsubscribe() defer w.chainSideSub.Unsubscribe()
for { for {
// A real event arrived, process interesting content // A real event arrived, process interesting content
select { select {
// Handle ChainHeadEvent // Handle ChainHeadEvent
case <-self.chainHeadCh: case <-w.chainHeadCh:
self.commitNewWork() w.commitNewWork()
// Handle ChainSideEvent // Handle ChainSideEvent
case ev := <-self.chainSideCh: case ev := <-w.chainSideCh:
self.uncleMu.Lock() w.uncleMu.Lock()
self.possibleUncles[ev.Block.Hash()] = ev.Block w.possibleUncles[ev.Block.Hash()] = ev.Block
self.uncleMu.Unlock() w.uncleMu.Unlock()
// Handle NewTxsEvent // Handle NewTxsEvent
case ev := <-self.txsCh: case ev := <-w.txsCh:
// Apply transactions to the pending state if we're not mining. // Apply transactions to the pending state if we're not mining.
// //
// Note all transactions received may not be continuous with transactions // Note all transactions received may not be continuous with transactions
// already included in the current mining block. These transactions will // already included in the current mining block. These transactions will
// be automatically eliminated. // be automatically eliminated.
if atomic.LoadInt32(&self.mining) == 0 { if atomic.LoadInt32(&w.mining) == 0 {
self.currentMu.Lock() w.currentMu.Lock()
txs := make(map[common.Address]types.Transactions) txs := make(map[common.Address]types.Transactions)
for _, tx := range ev.Txs { for _, tx := range ev.Txs {
acc, _ := types.Sender(self.current.signer, tx) acc, _ := types.Sender(w.current.signer, tx)
txs[acc] = append(txs[acc], tx) txs[acc] = append(txs[acc], tx)
} }
txset := types.NewTransactionsByPriceAndNonce(self.current.signer, txs) txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs)
self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase) w.current.commitTransactions(w.mux, txset, w.chain, w.coinbase)
self.updateSnapshot() w.updateSnapshot()
self.currentMu.Unlock() w.currentMu.Unlock()
} else { } else {
// If we're mining, but nothing is being processed, wake on new transactions // If we're mining, but nothing is being processed, wake on new transactions
if self.config.Clique != nil && self.config.Clique.Period == 0 { if w.config.Clique != nil && w.config.Clique.Period == 0 {
self.commitNewWork() w.commitNewWork()
} }
} }
// System stopped // System stopped
case <-self.txsSub.Err(): case <-w.txsSub.Err():
return return
case <-self.chainHeadSub.Err(): case <-w.chainHeadSub.Err():
return return
case <-self.chainSideSub.Err(): case <-w.chainSideSub.Err():
return return
} }
} }
} }
func (self *worker) wait() { func (w *worker) wait() {
for { for {
mustCommitNewWork := true mustCommitNewWork := true
for result := range self.recv { for result := range w.recv {
atomic.AddInt32(&self.atWork, -1) atomic.AddInt32(&w.atWork, -1)
if result == nil { if result == nil {
continue continue
@ -317,7 +317,7 @@ func (self *worker) wait() {
for _, log := range work.state.Logs() { for _, log := range work.state.Logs() {
log.BlockHash = block.Hash() log.BlockHash = block.Hash()
} }
stat, err := self.chain.WriteBlockWithState(block, work.receipts, work.state) stat, err := w.chain.WriteBlockWithState(block, work.receipts, work.state)
if err != nil { if err != nil {
log.Error("Failed writing block to chain", "err", err) log.Error("Failed writing block to chain", "err", err)
continue continue
@ -328,7 +328,7 @@ func (self *worker) wait() {
mustCommitNewWork = false mustCommitNewWork = false
} }
// Broadcast the block and announce chain insertion event // Broadcast the block and announce chain insertion event
self.mux.Post(core.NewMinedBlockEvent{Block: block}) w.mux.Post(core.NewMinedBlockEvent{Block: block})
var ( var (
events []interface{} events []interface{}
logs = work.state.Logs() logs = work.state.Logs()
@ -337,25 +337,25 @@ func (self *worker) wait() {
if stat == core.CanonStatTy { if stat == core.CanonStatTy {
events = append(events, core.ChainHeadEvent{Block: block}) events = append(events, core.ChainHeadEvent{Block: block})
} }
self.chain.PostChainEvents(events, logs) w.chain.PostChainEvents(events, logs)
// Insert the block into the set of pending ones to wait for confirmations // Insert the block into the set of pending ones to wait for confirmations
self.unconfirmed.Insert(block.NumberU64(), block.Hash()) w.unconfirmed.Insert(block.NumberU64(), block.Hash())
if mustCommitNewWork { if mustCommitNewWork {
self.commitNewWork() w.commitNewWork()
} }
} }
} }
} }
// push sends a new work task to currently live miner agents. // push sends a new work task to currently live miner agents.
func (self *worker) push(work *Work) { func (w *worker) push(work *Work) {
if atomic.LoadInt32(&self.mining) != 1 { if atomic.LoadInt32(&w.mining) != 1 {
return return
} }
for agent := range self.agents { for agent := range w.agents {
atomic.AddInt32(&self.atWork, 1) atomic.AddInt32(&w.atWork, 1)
if ch := agent.Work(); ch != nil { if ch := agent.Work(); ch != nil {
ch <- work ch <- work
} }
@ -363,14 +363,14 @@ func (self *worker) push(work *Work) {
} }
// makeCurrent creates a new environment for the current cycle. // makeCurrent creates a new environment for the current cycle.
func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error { func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
state, err := self.chain.StateAt(parent.Root()) state, err := w.chain.StateAt(parent.Root())
if err != nil { if err != nil {
return err return err
} }
work := &Work{ work := &Work{
config: self.config, config: w.config,
signer: types.NewEIP155Signer(self.config.ChainId), signer: types.NewEIP155Signer(w.config.ChainId),
state: state, state: state,
ancestors: set.New(), ancestors: set.New(),
family: set.New(), family: set.New(),
@ -380,7 +380,7 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
} }
// when 08 is processed ancestors contain 07 (quick block) // when 08 is processed ancestors contain 07 (quick block)
for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) { for _, ancestor := range w.chain.GetBlocksFromHash(parent.Hash(), 7) {
for _, uncle := range ancestor.Uncles() { for _, uncle := range ancestor.Uncles() {
work.family.Add(uncle.Hash()) work.family.Add(uncle.Hash())
} }
@ -390,20 +390,20 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
// Keep track of transactions which return errors so they can be removed // Keep track of transactions which return errors so they can be removed
work.tcount = 0 work.tcount = 0
self.current = work w.current = work
return nil return nil
} }
func (self *worker) commitNewWork() { func (w *worker) commitNewWork() {
self.mu.Lock() w.mu.Lock()
defer self.mu.Unlock() defer w.mu.Unlock()
self.uncleMu.Lock() w.uncleMu.Lock()
defer self.uncleMu.Unlock() defer w.uncleMu.Unlock()
self.currentMu.Lock() w.currentMu.Lock()
defer self.currentMu.Unlock() defer w.currentMu.Unlock()
tstart := time.Now() tstart := time.Now()
parent := self.chain.CurrentBlock() parent := w.chain.CurrentBlock()
tstamp := tstart.Unix() tstamp := tstart.Unix()
if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 { if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 {
@ -421,24 +421,24 @@ func (self *worker) commitNewWork() {
ParentHash: parent.Hash(), ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1), Number: num.Add(num, common.Big1),
GasLimit: core.CalcGasLimit(parent), GasLimit: core.CalcGasLimit(parent),
Extra: self.extra, Extra: w.extra,
Time: big.NewInt(tstamp), Time: big.NewInt(tstamp),
} }
// Only set the coinbase if we are mining (avoid spurious block rewards) // Only set the coinbase if we are mining (avoid spurious block rewards)
if atomic.LoadInt32(&self.mining) == 1 { if atomic.LoadInt32(&w.mining) == 1 {
header.Coinbase = self.coinbase header.Coinbase = w.coinbase
} }
if err := self.engine.Prepare(self.chain, header); err != nil { if err := w.engine.Prepare(w.chain, header); err != nil {
log.Error("Failed to prepare header for mining", "err", err) log.Error("Failed to prepare header for mining", "err", err)
return return
} }
// If we are care about TheDAO hard-fork check whether to override the extra-data or not // If we are care about TheDAO hard-fork check whether to override the extra-data or not
if daoBlock := self.config.DAOForkBlock; daoBlock != nil { if daoBlock := w.config.DAOForkBlock; daoBlock != nil {
// Check whether the block is among the fork extra-override range // Check whether the block is among the fork extra-override range
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 { if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
// Depending whether we support or oppose the fork, override differently // Depending whether we support or oppose the fork, override differently
if self.config.DAOForkSupport { if w.config.DAOForkSupport {
header.Extra = common.CopyBytes(params.DAOForkBlockExtra) header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
} else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) { } else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data
@ -446,34 +446,34 @@ func (self *worker) commitNewWork() {
} }
} }
// Could potentially happen if starting to mine in an odd state. // Could potentially happen if starting to mine in an odd state.
err := self.makeCurrent(parent, header) err := w.makeCurrent(parent, header)
if err != nil { if err != nil {
log.Error("Failed to create mining context", "err", err) log.Error("Failed to create mining context", "err", err)
return return
} }
// Create the current work task and check any fork transitions needed // Create the current work task and check any fork transitions needed
work := self.current work := w.current
if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 { if w.config.DAOForkSupport && w.config.DAOForkBlock != nil && w.config.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(work.state) misc.ApplyDAOHardFork(work.state)
} }
pending, err := self.eth.TxPool().Pending() pending, err := w.eth.TxPool().Pending()
if err != nil { if err != nil {
log.Error("Failed to fetch pending transactions", "err", err) log.Error("Failed to fetch pending transactions", "err", err)
return return
} }
txs := types.NewTransactionsByPriceAndNonce(self.current.signer, pending) txs := types.NewTransactionsByPriceAndNonce(w.current.signer, pending)
work.commitTransactions(self.mux, txs, self.chain, self.coinbase) work.commitTransactions(w.mux, txs, w.chain, w.coinbase)
// compute uncles for the new block. // compute uncles for the new block.
var ( var (
uncles []*types.Header uncles []*types.Header
badUncles []common.Hash badUncles []common.Hash
) )
for hash, uncle := range self.possibleUncles { for hash, uncle := range w.possibleUncles {
if len(uncles) == 2 { if len(uncles) == 2 {
break break
} }
if err := self.commitUncle(work, uncle.Header()); err != nil { if err := w.commitUncle(work, uncle.Header()); err != nil {
log.Trace("Bad uncle found and will be removed", "hash", hash) log.Trace("Bad uncle found and will be removed", "hash", hash)
log.Trace(fmt.Sprint(uncle)) log.Trace(fmt.Sprint(uncle))
@ -484,23 +484,23 @@ func (self *worker) commitNewWork() {
} }
} }
for _, hash := range badUncles { for _, hash := range badUncles {
delete(self.possibleUncles, hash) delete(w.possibleUncles, hash)
} }
// Create the new block to seal with the consensus engine // Create the new block to seal with the consensus engine
if work.Block, err = self.engine.Finalize(self.chain, header, work.state, work.txs, uncles, work.receipts); err != nil { if work.Block, err = w.engine.Finalize(w.chain, header, work.state, work.txs, uncles, work.receipts); err != nil {
log.Error("Failed to finalize block for sealing", "err", err) log.Error("Failed to finalize block for sealing", "err", err)
return return
} }
// We only care about logging if we're actually mining. // We only care about logging if we're actually mining.
if atomic.LoadInt32(&self.mining) == 1 { if atomic.LoadInt32(&w.mining) == 1 {
log.Info("Commit new mining work", "number", work.Block.Number(), "txs", work.tcount, "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart))) log.Info("Commit new mining work", "number", work.Block.Number(), "txs", work.tcount, "uncles", len(uncles), "elapsed", common.PrettyDuration(time.Since(tstart)))
self.unconfirmed.Shift(work.Block.NumberU64() - 1) w.unconfirmed.Shift(work.Block.NumberU64() - 1)
} }
self.push(work) w.push(work)
self.updateSnapshot() w.updateSnapshot()
} }
func (self *worker) commitUncle(work *Work, uncle *types.Header) error { func (w *worker) commitUncle(work *Work, uncle *types.Header) error {
hash := uncle.Hash() hash := uncle.Hash()
if work.uncles.Has(hash) { if work.uncles.Has(hash) {
return fmt.Errorf("uncle not unique") return fmt.Errorf("uncle not unique")
@ -515,17 +515,17 @@ func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
return nil return nil
} }
func (self *worker) updateSnapshot() { func (w *worker) updateSnapshot() {
self.snapshotMu.Lock() w.snapshotMu.Lock()
defer self.snapshotMu.Unlock() defer w.snapshotMu.Unlock()
self.snapshotBlock = types.NewBlock( w.snapshotBlock = types.NewBlock(
self.current.header, w.current.header,
self.current.txs, w.current.txs,
nil, nil,
self.current.receipts, w.current.receipts,
) )
self.snapshotState = self.current.state.Copy() w.snapshotState = w.current.state.Copy()
} }
func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsByPriceAndNonce, bc *core.BlockChain, coinbase common.Address) { func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsByPriceAndNonce, bc *core.BlockChain, coinbase common.Address) {

View file

@ -147,8 +147,8 @@ type Api struct {
} }
//the api constructor initialises //the api constructor initialises
func NewApi(dpa *storage.DPA, dns Resolver) (self *Api) { func NewApi(dpa *storage.DPA, dns Resolver) (api *Api) {
self = &Api{ api = &Api{
dpa: dpa, dpa: dpa,
dns: dns, dns: dns,
} }
@ -156,25 +156,25 @@ func NewApi(dpa *storage.DPA, dns Resolver) (self *Api) {
} }
// to be used only in TEST // to be used only in TEST
func (self *Api) Upload(uploadDir, index string) (hash string, err error) { func (api *Api) Upload(uploadDir, index string) (hash string, err error) {
fs := NewFileSystem(self) fs := NewFileSystem(api)
hash, err = fs.Upload(uploadDir, index) hash, err = fs.Upload(uploadDir, index)
return hash, err return hash, err
} }
// DPA reader API // DPA reader API
func (self *Api) Retrieve(key storage.Key) storage.LazySectionReader { func (api *Api) Retrieve(key storage.Key) storage.LazySectionReader {
return self.dpa.Retrieve(key) return api.dpa.Retrieve(key)
} }
func (self *Api) Store(data io.Reader, size int64, wg *sync.WaitGroup) (key storage.Key, err error) { func (api *Api) Store(data io.Reader, size int64, wg *sync.WaitGroup) (key storage.Key, err error) {
return self.dpa.Store(data, size, wg, nil) return api.dpa.Store(data, size, wg, nil)
} }
type ErrResolve error type ErrResolve error
// DNS Resolver // DNS Resolver
func (self *Api) Resolve(uri *URI) (storage.Key, error) { func (api *Api) Resolve(uri *URI) (storage.Key, error) {
apiResolveCount.Inc(1) apiResolveCount.Inc(1)
log.Trace(fmt.Sprintf("Resolving : %v", uri.Addr)) log.Trace(fmt.Sprintf("Resolving : %v", uri.Addr))
@ -188,7 +188,7 @@ func (self *Api) Resolve(uri *URI) (storage.Key, error) {
} }
// if DNS is not configured, check if the address is a hash // if DNS is not configured, check if the address is a hash
if self.dns == nil { if api.dns == nil {
if !isHash { if !isHash {
apiResolveFail.Inc(1) apiResolveFail.Inc(1)
return nil, fmt.Errorf("no DNS to resolve name: %q", uri.Addr) return nil, fmt.Errorf("no DNS to resolve name: %q", uri.Addr)
@ -197,7 +197,7 @@ func (self *Api) Resolve(uri *URI) (storage.Key, error) {
} }
// try and resolve the address // try and resolve the address
resolved, err := self.dns.Resolve(uri.Addr) resolved, err := api.dns.Resolve(uri.Addr)
if err == nil { if err == nil {
return resolved[:], nil return resolved[:], nil
} else if !isHash { } else if !isHash {
@ -208,18 +208,18 @@ func (self *Api) Resolve(uri *URI) (storage.Key, error) {
} }
// Put provides singleton manifest creation on top of dpa store // Put provides singleton manifest creation on top of dpa store
func (self *Api) Put(content, contentType string) (storage.Key, error) { func (api *Api) Put(content, contentType string) (storage.Key, error) {
apiPutCount.Inc(1) apiPutCount.Inc(1)
r := strings.NewReader(content) r := strings.NewReader(content)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
key, err := self.dpa.Store(r, int64(len(content)), wg, nil) key, err := api.dpa.Store(r, int64(len(content)), wg, nil)
if err != nil { if err != nil {
apiPutFail.Inc(1) apiPutFail.Inc(1)
return nil, err return nil, err
} }
manifest := fmt.Sprintf(`{"entries":[{"hash":"%v","contentType":"%s"}]}`, key, contentType) manifest := fmt.Sprintf(`{"entries":[{"hash":"%v","contentType":"%s"}]}`, key, contentType)
r = strings.NewReader(manifest) r = strings.NewReader(manifest)
key, err = self.dpa.Store(r, int64(len(manifest)), wg, nil) key, err = api.dpa.Store(r, int64(len(manifest)), wg, nil)
if err != nil { if err != nil {
apiPutFail.Inc(1) apiPutFail.Inc(1)
return nil, err return nil, err
@ -231,9 +231,9 @@ func (self *Api) Put(content, contentType string) (storage.Key, error) {
// Get uses iterative manifest retrieval and prefix matching // Get uses iterative manifest retrieval and prefix matching
// to resolve basePath to content using dpa retrieve // to resolve basePath to content using dpa retrieve
// it returns a section reader, mimeType, status and an error // it returns a section reader, mimeType, status and an error
func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionReader, mimeType string, status int, err error) { func (api *Api) Get(key storage.Key, path string) (reader storage.LazySectionReader, mimeType string, status int, err error) {
apiGetCount.Inc(1) apiGetCount.Inc(1)
trie, err := loadManifest(self.dpa, key, nil) trie, err := loadManifest(api.dpa, key, nil)
if err != nil { if err != nil {
apiGetNotFound.Inc(1) apiGetNotFound.Inc(1)
status = http.StatusNotFound status = http.StatusNotFound
@ -254,7 +254,7 @@ func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionRe
} else { } else {
mimeType = entry.ContentType mimeType = entry.ContentType
log.Trace(fmt.Sprintf("content lookup key: '%v' (%v)", key, mimeType)) log.Trace(fmt.Sprintf("content lookup key: '%v' (%v)", key, mimeType))
reader = self.dpa.Retrieve(key) reader = api.dpa.Retrieve(key)
} }
} else { } else {
status = http.StatusNotFound status = http.StatusNotFound
@ -265,10 +265,10 @@ func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionRe
return return
} }
func (self *Api) Modify(key storage.Key, path, contentHash, contentType string) (storage.Key, error) { func (api *Api) Modify(key storage.Key, path, contentHash, contentType string) (storage.Key, error) {
apiModifyCount.Inc(1) apiModifyCount.Inc(1)
quitC := make(chan bool) quitC := make(chan bool)
trie, err := loadManifest(self.dpa, key, quitC) trie, err := loadManifest(api.dpa, key, quitC)
if err != nil { if err != nil {
apiModifyFail.Inc(1) apiModifyFail.Inc(1)
return nil, err return nil, err
@ -291,7 +291,7 @@ func (self *Api) Modify(key storage.Key, path, contentHash, contentType string)
return trie.hash, nil return trie.hash, nil
} }
func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver bool) (storage.Key, string, error) { func (api *Api) AddFile(mhash, path, fname string, content []byte, nameresolver bool) (storage.Key, string, error) {
apiAddFileCount.Inc(1) apiAddFileCount.Inc(1)
uri, err := Parse("bzz:/" + mhash) uri, err := Parse("bzz:/" + mhash)
@ -299,7 +299,7 @@ func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver
apiAddFileFail.Inc(1) apiAddFileFail.Inc(1)
return nil, "", err return nil, "", err
} }
mkey, err := self.Resolve(uri) mkey, err := api.Resolve(uri)
if err != nil { if err != nil {
apiAddFileFail.Inc(1) apiAddFileFail.Inc(1)
return nil, "", err return nil, "", err
@ -318,7 +318,7 @@ func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver
ModTime: time.Now(), ModTime: time.Now(),
} }
mw, err := self.NewManifestWriter(mkey, nil) mw, err := api.NewManifestWriter(mkey, nil)
if err != nil { if err != nil {
apiAddFileFail.Inc(1) apiAddFileFail.Inc(1)
return nil, "", err return nil, "", err
@ -341,7 +341,7 @@ func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver
} }
func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (string, error) { func (api *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (string, error) {
apiRmFileCount.Inc(1) apiRmFileCount.Inc(1)
uri, err := Parse("bzz:/" + mhash) uri, err := Parse("bzz:/" + mhash)
@ -349,7 +349,7 @@ func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (strin
apiRmFileFail.Inc(1) apiRmFileFail.Inc(1)
return "", err return "", err
} }
mkey, err := self.Resolve(uri) mkey, err := api.Resolve(uri)
if err != nil { if err != nil {
apiRmFileFail.Inc(1) apiRmFileFail.Inc(1)
return "", err return "", err
@ -360,7 +360,7 @@ func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (strin
path = path[1:] path = path[1:]
} }
mw, err := self.NewManifestWriter(mkey, nil) mw, err := api.NewManifestWriter(mkey, nil)
if err != nil { if err != nil {
apiRmFileFail.Inc(1) apiRmFileFail.Inc(1)
return "", err return "", err
@ -382,7 +382,7 @@ func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (strin
return newMkey.String(), nil return newMkey.String(), nil
} }
func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, content []byte, oldKey storage.Key, offset int64, addSize int64, nameresolver bool) (storage.Key, string, error) { func (api *Api) AppendFile(mhash, path, fname string, existingSize int64, content []byte, oldKey storage.Key, offset int64, addSize int64, nameresolver bool) (storage.Key, string, error) {
apiAppendFileCount.Inc(1) apiAppendFileCount.Inc(1)
buffSize := offset + addSize buffSize := offset + addSize
@ -392,7 +392,7 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
buf := make([]byte, buffSize) buf := make([]byte, buffSize)
oldReader := self.Retrieve(oldKey) oldReader := api.Retrieve(oldKey)
io.ReadAtLeast(oldReader, buf, int(offset)) io.ReadAtLeast(oldReader, buf, int(offset))
newReader := bytes.NewReader(content) newReader := bytes.NewReader(content)
@ -406,7 +406,7 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
totalSize := int64(len(buf)) totalSize := int64(len(buf))
// TODO(jmozah): to append using pyramid chunker when it is ready // TODO(jmozah): to append using pyramid chunker when it is ready
//oldReader := self.Retrieve(oldKey) //oldReader := api.Retrieve(oldKey)
//newReader := bytes.NewReader(content) //newReader := bytes.NewReader(content)
//combinedReader := io.MultiReader(oldReader, newReader) //combinedReader := io.MultiReader(oldReader, newReader)
@ -415,7 +415,7 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
apiAppendFileFail.Inc(1) apiAppendFileFail.Inc(1)
return nil, "", err return nil, "", err
} }
mkey, err := self.Resolve(uri) mkey, err := api.Resolve(uri)
if err != nil { if err != nil {
apiAppendFileFail.Inc(1) apiAppendFileFail.Inc(1)
return nil, "", err return nil, "", err
@ -426,7 +426,7 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
path = path[1:] path = path[1:]
} }
mw, err := self.NewManifestWriter(mkey, nil) mw, err := api.NewManifestWriter(mkey, nil)
if err != nil { if err != nil {
apiAppendFileFail.Inc(1) apiAppendFileFail.Inc(1)
return nil, "", err return nil, "", err
@ -463,19 +463,19 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
} }
func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storage.Key, manifestEntryMap map[string]*manifestTrieEntry, err error) { func (api *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storage.Key, manifestEntryMap map[string]*manifestTrieEntry, err error) {
uri, err := Parse("bzz:/" + mhash) uri, err := Parse("bzz:/" + mhash)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
key, err = self.Resolve(uri) key, err = api.Resolve(uri)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
quitC := make(chan bool) quitC := make(chan bool)
rootTrie, err := loadManifest(self.dpa, key, quitC) rootTrie, err := loadManifest(api.dpa, key, quitC)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("can't load manifest %v: %v", key.String(), err) return nil, nil, fmt.Errorf("can't load manifest %v: %v", key.String(), err)
} }

View file

@ -64,9 +64,9 @@ type Config struct {
} }
//create a default config with all parameters to set to defaults //create a default config with all parameters to set to defaults
func NewDefaultConfig() (self *Config) { func NewDefaultConfig() (cfg *Config) {
self = &Config{ cfg = &Config{
StoreParams: storage.NewDefaultStoreParams(), StoreParams: storage.NewDefaultStoreParams(),
ChunkerParams: storage.NewChunkerParams(), ChunkerParams: storage.NewChunkerParams(),
HiveParams: network.NewDefaultHiveParams(), HiveParams: network.NewDefaultHiveParams(),
@ -89,11 +89,11 @@ func NewDefaultConfig() (self *Config) {
//some config params need to be initialized after the complete //some config params need to be initialized after the complete
//config building phase is completed (e.g. due to overriding flags) //config building phase is completed (e.g. due to overriding flags)
func (self *Config) Init(prvKey *ecdsa.PrivateKey) { func (cfg *Config) Init(prvKey *ecdsa.PrivateKey) {
address := crypto.PubkeyToAddress(prvKey.PublicKey) address := crypto.PubkeyToAddress(prvKey.PublicKey)
self.Path = filepath.Join(self.Path, "bzz-"+common.Bytes2Hex(address.Bytes())) cfg.Path = filepath.Join(cfg.Path, "bzz-"+common.Bytes2Hex(address.Bytes()))
err := os.MkdirAll(self.Path, os.ModePerm) err := os.MkdirAll(cfg.Path, os.ModePerm)
if err != nil { if err != nil {
log.Error(fmt.Sprintf("Error creating root swarm data directory: %v", err)) log.Error(fmt.Sprintf("Error creating root swarm data directory: %v", err))
return return
@ -103,11 +103,11 @@ func (self *Config) Init(prvKey *ecdsa.PrivateKey) {
pubkeyhex := common.ToHex(pubkey) pubkeyhex := common.ToHex(pubkey)
keyhex := crypto.Keccak256Hash(pubkey).Hex() keyhex := crypto.Keccak256Hash(pubkey).Hex()
self.PublicKey = pubkeyhex cfg.PublicKey = pubkeyhex
self.BzzKey = keyhex cfg.BzzKey = keyhex
self.Swap.Init(self.Contract, prvKey) cfg.Swap.Init(cfg.Contract, prvKey)
self.SyncParams.Init(self.Path) cfg.SyncParams.Init(cfg.Path)
self.HiveParams.Init(self.Path) cfg.HiveParams.Init(cfg.Path)
self.StoreParams.Init(self.Path) cfg.StoreParams.Init(cfg.Path)
} }

View file

@ -46,7 +46,7 @@ func NewFileSystem(api *Api) *FileSystem {
// TODO: localpath should point to a manifest // TODO: localpath should point to a manifest
// //
// DEPRECATED: Use the HTTP API instead // DEPRECATED: Use the HTTP API instead
func (self *FileSystem) Upload(lpath, index string) (string, error) { func (fs *FileSystem) Upload(lpath, index string) (string, error) {
var list []*manifestTrieEntry var list []*manifestTrieEntry
localpath, err := filepath.Abs(filepath.Clean(lpath)) localpath, err := filepath.Abs(filepath.Clean(lpath))
if err != nil { if err != nil {
@ -113,7 +113,7 @@ func (self *FileSystem) Upload(lpath, index string) (string, error) {
stat, _ := f.Stat() stat, _ := f.Stat()
var hash storage.Key var hash storage.Key
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
hash, err = self.api.dpa.Store(f, stat.Size(), wg, nil) hash, err = fs.api.dpa.Store(f, stat.Size(), wg, nil)
if hash != nil { if hash != nil {
list[i].Hash = hash.String() list[i].Hash = hash.String()
} }
@ -142,7 +142,7 @@ func (self *FileSystem) Upload(lpath, index string) (string, error) {
} }
trie := &manifestTrie{ trie := &manifestTrie{
dpa: self.api.dpa, dpa: fs.api.dpa,
} }
quitC := make(chan bool) quitC := make(chan bool)
for i, entry := range list { for i, entry := range list {
@ -173,7 +173,7 @@ func (self *FileSystem) Upload(lpath, index string) (string, error) {
// under localpath // under localpath
// //
// DEPRECATED: Use the HTTP API instead // DEPRECATED: Use the HTTP API instead
func (self *FileSystem) Download(bzzpath, localpath string) error { func (fs *FileSystem) Download(bzzpath, localpath string) error {
lpath, err := filepath.Abs(filepath.Clean(localpath)) lpath, err := filepath.Abs(filepath.Clean(localpath))
if err != nil { if err != nil {
return err return err
@ -188,7 +188,7 @@ func (self *FileSystem) Download(bzzpath, localpath string) error {
if err != nil { if err != nil {
return err return err
} }
key, err := self.api.Resolve(uri) key, err := fs.api.Resolve(uri)
if err != nil { if err != nil {
return err return err
} }
@ -199,7 +199,7 @@ func (self *FileSystem) Download(bzzpath, localpath string) error {
} }
quitC := make(chan bool) quitC := make(chan bool)
trie, err := loadManifest(self.api.dpa, key, quitC) trie, err := loadManifest(fs.api.dpa, key, quitC)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("fs.Download: loadManifestTrie error: %v", err)) log.Warn(fmt.Sprintf("fs.Download: loadManifestTrie error: %v", err))
return err return err
@ -244,7 +244,7 @@ func (self *FileSystem) Download(bzzpath, localpath string) error {
} }
go func(i int, entry *downloadListEntry) { go func(i int, entry *downloadListEntry) {
defer wg.Done() defer wg.Done()
err := retrieveToFile(quitC, self.api.dpa, entry.key, entry.path) err := retrieveToFile(quitC, fs.api.dpa, entry.key, entry.path)
if err != nil { if err != nil {
select { select {
case errC <- err: case errC <- err:

View file

@ -51,12 +51,12 @@ type RoundTripper struct {
Port string Port string
} }
func (self *RoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) { func (tripper *RoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {
host := self.Host host := tripper.Host
if len(host) == 0 { if len(host) == 0 {
host = "localhost" host = "localhost"
} }
url := fmt.Sprintf("http://%s:%s/%s:/%s/%s", host, self.Port, req.Proto, req.URL.Host, req.URL.Path) url := fmt.Sprintf("http://%s:%s/%s:/%s/%s", host, tripper.Port, req.Proto, req.URL.Host, req.URL.Path)
log.Info(fmt.Sprintf("roundtripper: proxying request '%s' to '%s'", req.RequestURI, url)) log.Info(fmt.Sprintf("roundtripper: proxying request '%s' to '%s'", req.RequestURI, url))
reqProxy, err := http.NewRequest(req.Method, url, req.Body) reqProxy, err := http.NewRequest(req.Method, url, req.Body)
if err != nil { if err != nil {

View file

@ -230,18 +230,18 @@ func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dp
return return
} }
func (self *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) { func (trie *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) {
self.hash = nil // trie modified, hash needs to be re-calculated on demand trie.hash = nil // trie modified, hash needs to be re-calculated on demand
if len(entry.Path) == 0 { if len(entry.Path) == 0 {
self.entries[256] = entry trie.entries[256] = entry
return return
} }
b := entry.Path[0] b := entry.Path[0]
oldentry := self.entries[b] oldentry := trie.entries[b]
if (oldentry == nil) || (oldentry.Path == entry.Path && oldentry.ContentType != ManifestType) { if (oldentry == nil) || (oldentry.Path == entry.Path && oldentry.ContentType != ManifestType) {
self.entries[b] = entry trie.entries[b] = entry
return return
} }
@ -251,7 +251,7 @@ func (self *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) {
} }
if (oldentry.ContentType == ManifestType) && (cpl == len(oldentry.Path)) { if (oldentry.ContentType == ManifestType) && (cpl == len(oldentry.Path)) {
if self.loadSubTrie(oldentry, quitC) != nil { if trie.loadSubTrie(oldentry, quitC) != nil {
return return
} }
entry.Path = entry.Path[cpl:] entry.Path = entry.Path[cpl:]
@ -263,21 +263,21 @@ func (self *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) {
commonPrefix := entry.Path[:cpl] commonPrefix := entry.Path[:cpl]
subtrie := &manifestTrie{ subtrie := &manifestTrie{
dpa: self.dpa, dpa: trie.dpa,
} }
entry.Path = entry.Path[cpl:] entry.Path = entry.Path[cpl:]
oldentry.Path = oldentry.Path[cpl:] oldentry.Path = oldentry.Path[cpl:]
subtrie.addEntry(entry, quitC) subtrie.addEntry(entry, quitC)
subtrie.addEntry(oldentry, quitC) subtrie.addEntry(oldentry, quitC)
self.entries[b] = newManifestTrieEntry(&ManifestEntry{ trie.entries[b] = newManifestTrieEntry(&ManifestEntry{
Path: commonPrefix, Path: commonPrefix,
ContentType: ManifestType, ContentType: ManifestType,
}, subtrie) }, subtrie)
} }
func (self *manifestTrie) getCountLast() (cnt int, entry *manifestTrieEntry) { func (trie *manifestTrie) getCountLast() (cnt int, entry *manifestTrieEntry) {
for _, e := range self.entries { for _, e := range trie.entries {
if e != nil { if e != nil {
cnt++ cnt++
entry = e entry = e
@ -286,27 +286,27 @@ func (self *manifestTrie) getCountLast() (cnt int, entry *manifestTrieEntry) {
return return
} }
func (self *manifestTrie) deleteEntry(path string, quitC chan bool) { func (trie *manifestTrie) deleteEntry(path string, quitC chan bool) {
self.hash = nil // trie modified, hash needs to be re-calculated on demand trie.hash = nil // trie modified, hash needs to be re-calculated on demand
if len(path) == 0 { if len(path) == 0 {
self.entries[256] = nil trie.entries[256] = nil
return return
} }
b := path[0] b := path[0]
entry := self.entries[b] entry := trie.entries[b]
if entry == nil { if entry == nil {
return return
} }
if entry.Path == path { if entry.Path == path {
self.entries[b] = nil trie.entries[b] = nil
return return
} }
epl := len(entry.Path) epl := len(entry.Path)
if (entry.ContentType == ManifestType) && (len(path) >= epl) && (path[:epl] == entry.Path) { if (entry.ContentType == ManifestType) && (len(path) >= epl) && (path[:epl] == entry.Path) {
if self.loadSubTrie(entry, quitC) != nil { if trie.loadSubTrie(entry, quitC) != nil {
return return
} }
entry.subtrie.deleteEntry(path[epl:], quitC) entry.subtrie.deleteEntry(path[epl:], quitC)
@ -317,13 +317,13 @@ func (self *manifestTrie) deleteEntry(path string, quitC chan bool) {
if lastentry != nil { if lastentry != nil {
lastentry.Path = entry.Path + lastentry.Path lastentry.Path = entry.Path + lastentry.Path
} }
self.entries[b] = lastentry trie.entries[b] = lastentry
} }
} }
} }
func (self *manifestTrie) recalcAndStore() error { func (trie *manifestTrie) recalcAndStore() error {
if self.hash != nil { if trie.hash != nil {
return nil return nil
} }
@ -331,7 +331,7 @@ func (self *manifestTrie) recalcAndStore() error {
buffer.WriteString(`{"entries":[`) buffer.WriteString(`{"entries":[`)
list := &Manifest{} list := &Manifest{}
for _, entry := range self.entries { for _, entry := range trie.entries {
if entry != nil { if entry != nil {
if entry.Hash == "" { // TODO: paralellize if entry.Hash == "" { // TODO: paralellize
err := entry.subtrie.recalcAndStore() err := entry.subtrie.recalcAndStore()
@ -352,22 +352,22 @@ func (self *manifestTrie) recalcAndStore() error {
sr := bytes.NewReader(manifest) sr := bytes.NewReader(manifest)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
key, err2 := self.dpa.Store(sr, int64(len(manifest)), wg, nil) key, err2 := trie.dpa.Store(sr, int64(len(manifest)), wg, nil)
wg.Wait() wg.Wait()
self.hash = key trie.hash = key
return err2 return err2
} }
func (self *manifestTrie) loadSubTrie(entry *manifestTrieEntry, quitC chan bool) (err error) { func (trie *manifestTrie) loadSubTrie(entry *manifestTrieEntry, quitC chan bool) (err error) {
if entry.subtrie == nil { if entry.subtrie == nil {
hash := common.Hex2Bytes(entry.Hash) hash := common.Hex2Bytes(entry.Hash)
entry.subtrie, err = loadManifest(self.dpa, hash, quitC) entry.subtrie, err = loadManifest(trie.dpa, hash, quitC)
entry.Hash = "" // might not match, should be recalculated entry.Hash = "" // might not match, should be recalculated
} }
return return
} }
func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) error { func (trie *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) error {
plen := len(prefix) plen := len(prefix)
var start, stop int var start, stop int
if plen == 0 { if plen == 0 {
@ -384,7 +384,7 @@ func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool,
return fmt.Errorf("aborted") return fmt.Errorf("aborted")
default: default:
} }
entry := self.entries[i] entry := trie.entries[i]
if entry != nil { if entry != nil {
epl := len(entry.Path) epl := len(entry.Path)
if entry.ContentType == ManifestType { if entry.ContentType == ManifestType {
@ -393,7 +393,7 @@ func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool,
l = epl l = epl
} }
if prefix[:l] == entry.Path[:l] { if prefix[:l] == entry.Path[:l] {
err := self.loadSubTrie(entry, quitC) err := trie.loadSubTrie(entry, quitC)
if err != nil { if err != nil {
return err return err
} }
@ -412,23 +412,23 @@ func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool,
return nil return nil
} }
func (self *manifestTrie) listWithPrefix(prefix string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) (err error) { func (trie *manifestTrie) listWithPrefix(prefix string, quitC chan bool, cb func(entry *manifestTrieEntry, suffix string)) (err error) {
return self.listWithPrefixInt(prefix, "", quitC, cb) return trie.listWithPrefixInt(prefix, "", quitC, cb)
} }
func (self *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *manifestTrieEntry, pos int) { func (trie *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *manifestTrieEntry, pos int) {
log.Trace(fmt.Sprintf("findPrefixOf(%s)", path)) log.Trace(fmt.Sprintf("findPrefixOf(%s)", path))
if len(path) == 0 { if len(path) == 0 {
return self.entries[256], 0 return trie.entries[256], 0
} }
//see if first char is in manifest entries //see if first char is in manifest entries
b := path[0] b := path[0]
entry = self.entries[b] entry = trie.entries[b]
if entry == nil { if entry == nil {
return self.entries[256], 0 return trie.entries[256], 0
} }
epl := len(entry.Path) epl := len(entry.Path)
@ -436,7 +436,7 @@ func (self *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *man
if len(path) <= epl { if len(path) <= epl {
if entry.Path[:len(path)] == path { if entry.Path[:len(path)] == path {
if entry.ContentType == ManifestType { if entry.ContentType == ManifestType {
err := self.loadSubTrie(entry, quitC) err := trie.loadSubTrie(entry, quitC)
if err == nil && entry.subtrie != nil { if err == nil && entry.subtrie != nil {
subentries := entry.subtrie.entries subentries := entry.subtrie.entries
for i := 0; i < len(subentries); i++ { for i := 0; i < len(subentries); i++ {
@ -457,7 +457,7 @@ func (self *manifestTrie) findPrefixOf(path string, quitC chan bool) (entry *man
log.Trace(fmt.Sprintf("entry.ContentType = %v", entry.ContentType)) log.Trace(fmt.Sprintf("entry.ContentType = %v", entry.ContentType))
//the subentry is a manifest, load subtrie //the subentry is a manifest, load subtrie
if entry.ContentType == ManifestType && (strings.Contains(entry.Path, path) || strings.Contains(path, entry.Path)) { if entry.ContentType == ManifestType && (strings.Contains(entry.Path, path) || strings.Contains(path, entry.Path)) {
err := self.loadSubTrie(entry, quitC) err := trie.loadSubTrie(entry, quitC)
if err != nil { if err != nil {
return nil, 0 return nil, 0
} }
@ -495,10 +495,10 @@ func RegularSlashes(path string) (res string) {
return return
} }
func (self *manifestTrie) getEntry(spath string) (entry *manifestTrieEntry, fullpath string) { func (trie *manifestTrie) getEntry(spath string) (entry *manifestTrieEntry, fullpath string) {
path := RegularSlashes(spath) path := RegularSlashes(spath)
var pos int var pos int
quitC := make(chan bool) quitC := make(chan bool)
entry, pos = self.findPrefixOf(path, quitC) entry, pos = trie.findPrefixOf(path, quitC)
return entry, path[:pos] return entry, path[:pos]
} }

View file

@ -41,8 +41,8 @@ func NewStorage(api *Api) *Storage {
// its content type // its content type
// //
// DEPRECATED: Use the HTTP API instead // DEPRECATED: Use the HTTP API instead
func (self *Storage) Put(content, contentType string) (string, error) { func (s *Storage) Put(content, contentType string) (string, error) {
key, err := self.api.Put(content, contentType) key, err := s.api.Put(content, contentType)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -57,16 +57,16 @@ func (self *Storage) Put(content, contentType string) (string, error) {
// size is resp.Size // size is resp.Size
// //
// DEPRECATED: Use the HTTP API instead // DEPRECATED: Use the HTTP API instead
func (self *Storage) Get(bzzpath string) (*Response, error) { func (s *Storage) Get(bzzpath string) (*Response, error) {
uri, err := Parse(path.Join("bzz:/", bzzpath)) uri, err := Parse(path.Join("bzz:/", bzzpath))
if err != nil { if err != nil {
return nil, err return nil, err
} }
key, err := self.api.Resolve(uri) key, err := s.api.Resolve(uri)
if err != nil { if err != nil {
return nil, err return nil, err
} }
reader, mimeType, status, err := self.api.Get(key, uri.Path) reader, mimeType, status, err := s.api.Get(key, uri.Path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -87,16 +87,16 @@ func (self *Storage) Get(bzzpath string) (*Response, error) {
// and merge on to it. creating an entry w conentType (mime) // and merge on to it. creating an entry w conentType (mime)
// //
// DEPRECATED: Use the HTTP API instead // DEPRECATED: Use the HTTP API instead
func (self *Storage) Modify(rootHash, path, contentHash, contentType string) (newRootHash string, err error) { func (s *Storage) Modify(rootHash, path, contentHash, contentType string) (newRootHash string, err error) {
uri, err := Parse("bzz:/" + rootHash) uri, err := Parse("bzz:/" + rootHash)
if err != nil { if err != nil {
return "", err return "", err
} }
key, err := self.api.Resolve(uri) key, err := s.api.Resolve(uri)
if err != nil { if err != nil {
return "", err return "", err
} }
key, err = self.api.Modify(key, path, contentHash, contentType) key, err = s.api.Modify(key, path, contentHash, contentType)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -29,18 +29,18 @@ func NewControl(api *Api, hive *network.Hive) *Control {
return &Control{api, hive} return &Control{api, hive}
} }
func (self *Control) BlockNetworkRead(on bool) { func (c *Control) BlockNetworkRead(on bool) {
self.hive.BlockNetworkRead(on) c.hive.BlockNetworkRead(on)
} }
func (self *Control) SyncEnabled(on bool) { func (c *Control) SyncEnabled(on bool) {
self.hive.SyncEnabled(on) c.hive.SyncEnabled(on)
} }
func (self *Control) SwapEnabled(on bool) { func (c *Control) SwapEnabled(on bool) {
self.hive.SwapEnabled(on) c.hive.SwapEnabled(on)
} }
func (self *Control) Hive() string { func (c *Control) Hive() string {
return self.hive.String() return c.hive.String()
} }

View file

@ -34,18 +34,18 @@ type MountInfo struct {
LatestManifest string LatestManifest string
} }
func (self *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) { func (fs *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) {
return nil, errNoFUSE return nil, errNoFUSE
} }
func (self *SwarmFS) Unmount(mountpoint string) (bool, error) { func (fs *SwarmFS) Unmount(mountpoint string) (bool, error) {
return false, errNoFUSE return false, errNoFUSE
} }
func (self *SwarmFS) Listmounts() ([]*MountInfo, error) { func (fs *SwarmFS) Listmounts() ([]*MountInfo, error) {
return nil, errNoFUSE return nil, errNoFUSE
} }
func (self *SwarmFS) Stop() error { func (fs *SwarmFS) Stop() error {
return nil return nil
} }

View file

@ -72,7 +72,7 @@ func NewMountInfo(mhash, mpoint string, sapi *api.Api) *MountInfo {
return newMountInfo return newMountInfo
} }
func (self *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) { func (s *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) {
if mountpoint == "" { if mountpoint == "" {
return nil, errEmptyMountPoint return nil, errEmptyMountPoint
@ -82,25 +82,25 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) {
return nil, err return nil, err
} }
self.swarmFsLock.Lock() s.swarmFsLock.Lock()
defer self.swarmFsLock.Unlock() defer s.swarmFsLock.Unlock()
noOfActiveMounts := len(self.activeMounts) noOfActiveMounts := len(s.activeMounts)
if noOfActiveMounts >= maxFuseMounts { if noOfActiveMounts >= maxFuseMounts {
return nil, errMaxMountCount return nil, errMaxMountCount
} }
if _, ok := self.activeMounts[cleanedMountPoint]; ok { if _, ok := s.activeMounts[cleanedMountPoint]; ok {
return nil, errAlreadyMounted return nil, errAlreadyMounted
} }
log.Info(fmt.Sprintf("Attempting to mount %s ", cleanedMountPoint)) log.Info(fmt.Sprintf("Attempting to mount %s ", cleanedMountPoint))
_, manifestEntryMap, err := self.swarmApi.BuildDirectoryTree(mhash, true) _, manifestEntryMap, err := s.swarmApi.BuildDirectoryTree(mhash, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
mi := NewMountInfo(mhash, cleanedMountPoint, self.swarmApi) mi := NewMountInfo(mhash, cleanedMountPoint, s.swarmApi)
dirTree := map[string]*SwarmDir{} dirTree := map[string]*SwarmDir{}
rootDir := NewSwarmDir("/", mi) rootDir := NewSwarmDir("/", mi)
@ -174,21 +174,21 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (*MountInfo, error) {
log.Info("Now serving swarm FUSE FS", "manifest", mhash, "mountpoint", cleanedMountPoint) log.Info("Now serving swarm FUSE FS", "manifest", mhash, "mountpoint", cleanedMountPoint)
} }
self.activeMounts[cleanedMountPoint] = mi s.activeMounts[cleanedMountPoint] = mi
return mi, nil return mi, nil
} }
func (self *SwarmFS) Unmount(mountpoint string) (*MountInfo, error) { func (s *SwarmFS) Unmount(mountpoint string) (*MountInfo, error) {
self.swarmFsLock.Lock() s.swarmFsLock.Lock()
defer self.swarmFsLock.Unlock() defer s.swarmFsLock.Unlock()
cleanedMountPoint, err := filepath.Abs(filepath.Clean(mountpoint)) cleanedMountPoint, err := filepath.Abs(filepath.Clean(mountpoint))
if err != nil { if err != nil {
return nil, err return nil, err
} }
mountInfo := self.activeMounts[cleanedMountPoint] mountInfo := s.activeMounts[cleanedMountPoint]
if mountInfo == nil || mountInfo.MountPoint != cleanedMountPoint { if mountInfo == nil || mountInfo.MountPoint != cleanedMountPoint {
return nil, fmt.Errorf("%s is not mounted", cleanedMountPoint) return nil, fmt.Errorf("%s is not mounted", cleanedMountPoint)
@ -204,7 +204,7 @@ func (self *SwarmFS) Unmount(mountpoint string) (*MountInfo, error) {
} }
mountInfo.fuseConnection.Close() mountInfo.fuseConnection.Close()
delete(self.activeMounts, cleanedMountPoint) delete(s.activeMounts, cleanedMountPoint)
succString := fmt.Sprintf("UnMounting %v succeeded", cleanedMountPoint) succString := fmt.Sprintf("UnMounting %v succeeded", cleanedMountPoint)
log.Info(succString) log.Info(succString)
@ -212,21 +212,21 @@ func (self *SwarmFS) Unmount(mountpoint string) (*MountInfo, error) {
return mountInfo, nil return mountInfo, nil
} }
func (self *SwarmFS) Listmounts() []*MountInfo { func (s *SwarmFS) Listmounts() []*MountInfo {
self.swarmFsLock.RLock() s.swarmFsLock.RLock()
defer self.swarmFsLock.RUnlock() defer s.swarmFsLock.RUnlock()
rows := make([]*MountInfo, 0, len(self.activeMounts)) rows := make([]*MountInfo, 0, len(s.activeMounts))
for _, mi := range self.activeMounts { for _, mi := range s.activeMounts {
rows = append(rows, mi) rows = append(rows, mi)
} }
return rows return rows
} }
func (self *SwarmFS) Stop() bool { func (s *SwarmFS) Stop() bool {
for mp := range self.activeMounts { for mp := range s.activeMounts {
mountInfo := self.activeMounts[mp] mountInfo := s.activeMounts[mp]
self.Unmount(mountInfo.MountPoint) s.Unmount(mountInfo.MountPoint)
} }
return true return true
} }

View file

@ -58,14 +58,14 @@ func NewDepo(hash storage.SwarmHasher, localStore, remoteStore storage.ChunkStor
// * back immediately as a deliveryRequest message // * back immediately as a deliveryRequest message
// * empty message just pings back for more (is this needed?) // * empty message just pings back for more (is this needed?)
// * strict signed sync states may be needed. // * strict signed sync states may be needed.
func (self *Depo) HandleUnsyncedKeysMsg(req *unsyncedKeysMsgData, p *peer) error { func (d *Depo) HandleUnsyncedKeysMsg(req *unsyncedKeysMsgData, p *peer) error {
unsynced := req.Unsynced unsynced := req.Unsynced
var missing []*syncRequest var missing []*syncRequest
var chunk *storage.Chunk var chunk *storage.Chunk
var err error var err error
for _, req := range unsynced { for _, req := range unsynced {
// skip keys that are found, // skip keys that are found,
chunk, err = self.localStore.Get(req.Key[:]) chunk, err = d.localStore.Get(req.Key[:])
if err != nil || chunk.SData == nil { if err != nil || chunk.SData == nil {
missing = append(missing, req) missing = append(missing, req)
} }
@ -88,7 +88,7 @@ func (self *Depo) HandleUnsyncedKeysMsg(req *unsyncedKeysMsgData, p *peer) error
// (remote peer is free to reprioritize) // (remote peer is free to reprioritize)
// * the message implies remote peer wants more, so trigger for // * the message implies remote peer wants more, so trigger for
// * new outgoing unsynced keys message is fired // * new outgoing unsynced keys message is fired
func (self *Depo) HandleDeliveryRequestMsg(req *deliveryRequestMsgData, p *peer) error { func (d *Depo) HandleDeliveryRequestMsg(req *deliveryRequestMsgData, p *peer) error {
deliver := req.Deliver deliver := req.Deliver
// queue the actual delivery of a chunk () // queue the actual delivery of a chunk ()
log.Trace(fmt.Sprintf("Depo.HandleDeliveryRequestMsg: received %v delivery requests: %v", len(deliver), deliver)) log.Trace(fmt.Sprintf("Depo.HandleDeliveryRequestMsg: received %v delivery requests: %v", len(deliver), deliver))
@ -96,7 +96,7 @@ func (self *Depo) HandleDeliveryRequestMsg(req *deliveryRequestMsgData, p *peer)
// TODO: look up in cache here or in deliveries // TODO: look up in cache here or in deliveries
// priorities are taken from the message so the remote party can // priorities are taken from the message so the remote party can
// reprioritise to at their leisure // reprioritise to at their leisure
// r = self.pullCached(sreq.Key) // pulls and deletes from cache // r = d.pullCached(sreq.Key) // pulls and deletes from cache
Push(p, sreq.Key, sreq.Priority) Push(p, sreq.Key, sreq.Priority)
} }
@ -108,10 +108,10 @@ func (self *Depo) HandleDeliveryRequestMsg(req *deliveryRequestMsgData, p *peer)
// the entrypoint for store requests coming from the bzz wire protocol // the entrypoint for store requests coming from the bzz wire protocol
// if key found locally, return. otherwise // if key found locally, return. otherwise
// remote is untrusted, so hash is verified and chunk passed on to NetStore // remote is untrusted, so hash is verified and chunk passed on to NetStore
func (self *Depo) HandleStoreRequestMsg(req *storeRequestMsgData, p *peer) { func (d *Depo) HandleStoreRequestMsg(req *storeRequestMsgData, p *peer) {
var islocal bool var islocal bool
req.from = p req.from = p
chunk, err := self.localStore.Get(req.Key) chunk, err := d.localStore.Get(req.Key)
switch { switch {
case err != nil: case err != nil:
log.Trace(fmt.Sprintf("Depo.handleStoreRequest: %v not found locally. create new chunk/request", req.Key)) log.Trace(fmt.Sprintf("Depo.handleStoreRequest: %v not found locally. create new chunk/request", req.Key))
@ -133,7 +133,7 @@ func (self *Depo) HandleStoreRequestMsg(req *storeRequestMsgData, p *peer) {
//return //return
} }
hasher := self.hashfunc() hasher := d.hashfunc()
hasher.Write(req.SData) hasher.Write(req.SData)
if !bytes.Equal(hasher.Sum(nil), req.Key) { if !bytes.Equal(hasher.Sum(nil), req.Key) {
// data does not validate, ignore // data does not validate, ignore
@ -150,12 +150,12 @@ func (self *Depo) HandleStoreRequestMsg(req *storeRequestMsgData, p *peer) {
chunk.Size = int64(binary.LittleEndian.Uint64(req.SData[0:8])) chunk.Size = int64(binary.LittleEndian.Uint64(req.SData[0:8]))
log.Trace(fmt.Sprintf("delivery of %v from %v", chunk, p)) log.Trace(fmt.Sprintf("delivery of %v from %v", chunk, p))
chunk.Source = p chunk.Source = p
self.netStore.Put(chunk) d.netStore.Put(chunk)
} }
// entrypoint for retrieve requests coming from the bzz wire protocol // entrypoint for retrieve requests coming from the bzz wire protocol
// checks swap balance - return if peer has no credit // checks swap balance - return if peer has no credit
func (self *Depo) HandleRetrieveRequestMsg(req *retrieveRequestMsgData, p *peer) { func (d *Depo) HandleRetrieveRequestMsg(req *retrieveRequestMsgData, p *peer) {
req.from = p req.from = p
// swap - record credit for 1 request // swap - record credit for 1 request
// note that only charge actual reqsearches // note that only charge actual reqsearches
@ -171,8 +171,8 @@ func (self *Depo) HandleRetrieveRequestMsg(req *retrieveRequestMsgData, p *peer)
// call storage.NetStore#Get which // call storage.NetStore#Get which
// blocks until local retrieval finished // blocks until local retrieval finished
// launches cloud retrieval // launches cloud retrieval
chunk, _ := self.netStore.Get(req.Key) chunk, _ := d.netStore.Get(req.Key)
req = self.strategyUpdateRequest(chunk.Req, req) req = d.strategyUpdateRequest(chunk.Req, req)
// check if we can immediately deliver // check if we can immediately deliver
if chunk.SData != nil { if chunk.SData != nil {
log.Trace(fmt.Sprintf("Depo.HandleRetrieveRequest: %v - content found, delivering...", req.Key.Log())) log.Trace(fmt.Sprintf("Depo.HandleRetrieveRequest: %v - content found, delivering...", req.Key.Log()))
@ -197,20 +197,20 @@ func (self *Depo) HandleRetrieveRequestMsg(req *retrieveRequestMsgData, p *peer)
} }
// add peer request the chunk and decides the timeout for the response if still searching // add peer request the chunk and decides the timeout for the response if still searching
func (self *Depo) strategyUpdateRequest(rs *storage.RequestStatus, origReq *retrieveRequestMsgData) (req *retrieveRequestMsgData) { func (d *Depo) strategyUpdateRequest(rs *storage.RequestStatus, origReq *retrieveRequestMsgData) (req *retrieveRequestMsgData) {
log.Trace(fmt.Sprintf("Depo.strategyUpdateRequest: key %v", origReq.Key.Log())) log.Trace(fmt.Sprintf("Depo.strategyUpdateRequest: key %v", origReq.Key.Log()))
// we do not create an alternative one // we do not create an alternative one
req = origReq req = origReq
if rs != nil { if rs != nil {
self.addRequester(rs, req) d.addRequester(rs, req)
req.setTimeout(self.searchTimeout(rs, req)) req.setTimeout(d.searchTimeout(rs, req))
} }
return return
} }
// decides the timeout promise sent with the immediate peers response to a retrieve request // decides the timeout promise sent with the immediate peers response to a retrieve request
// if timeout is explicitly set and expired // if timeout is explicitly set and expired
func (self *Depo) searchTimeout(rs *storage.RequestStatus, req *retrieveRequestMsgData) (timeout *time.Time) { func (d *Depo) searchTimeout(rs *storage.RequestStatus, req *retrieveRequestMsgData) (timeout *time.Time) {
reqt := req.getTimeout() reqt := req.getTimeout()
t := time.Now().Add(searchTimeout) t := time.Now().Add(searchTimeout)
if reqt != nil && reqt.Before(t) { if reqt != nil && reqt.Before(t) {
@ -225,7 +225,7 @@ adds a new peer to an existing open request
only add if less than requesterCount peers forwarded the same request id so far only add if less than requesterCount peers forwarded the same request id so far
note this is done irrespective of status (searching or found) note this is done irrespective of status (searching or found)
*/ */
func (self *Depo) addRequester(rs *storage.RequestStatus, req *retrieveRequestMsgData) { func (d *Depo) addRequester(rs *storage.RequestStatus, req *retrieveRequestMsgData) {
log.Trace(fmt.Sprintf("Depo.addRequester: key %v - add peer to req.Id %v", req.Key.Log(), req.Id)) log.Trace(fmt.Sprintf("Depo.addRequester: key %v - add peer to req.Id %v", req.Key.Log(), req.Id))
list := rs.Requesters[req.Id] list := rs.Requesters[req.Id]
rs.Requesters[req.Id] = append(list, req) rs.Requesters[req.Id] = append(list, req)

View file

@ -54,8 +54,8 @@ var searchTimeout = 3 * time.Second
// forwarding logic // forwarding logic
// logic propagating retrieve requests to peers given by the kademlia hive // logic propagating retrieve requests to peers given by the kademlia hive
func (self *forwarder) Retrieve(chunk *storage.Chunk) { func (f *forwarder) Retrieve(chunk *storage.Chunk) {
peers := self.hive.getPeers(chunk.Key, 0) peers := f.hive.getPeers(chunk.Key, 0)
log.Trace(fmt.Sprintf("forwarder.Retrieve: %v - received %d peers from KΛÐΞMLIΛ...", chunk.Key.Log(), len(peers))) log.Trace(fmt.Sprintf("forwarder.Retrieve: %v - received %d peers from KΛÐΞMLIΛ...", chunk.Key.Log(), len(peers)))
OUT: OUT:
for _, p := range peers { for _, p := range peers {
@ -87,7 +87,7 @@ OUT:
// requests to specific peers given by the kademlia hive // requests to specific peers given by the kademlia hive
// except for peers that the store request came from (if any) // except for peers that the store request came from (if any)
// delivery queueing taken care of by syncer // delivery queueing taken care of by syncer
func (self *forwarder) Store(chunk *storage.Chunk) { func (f *forwarder) Store(chunk *storage.Chunk) {
var n int var n int
msg := &storeRequestMsgData{ msg := &storeRequestMsgData{
Key: chunk.Key, Key: chunk.Key,
@ -97,7 +97,7 @@ func (self *forwarder) Store(chunk *storage.Chunk) {
if chunk.Source != nil { if chunk.Source != nil {
source = chunk.Source.(*peer) source = chunk.Source.(*peer)
} }
for _, p := range self.hive.getPeers(chunk.Key, 0) { for _, p := range f.hive.getPeers(chunk.Key, 0) {
log.Trace(fmt.Sprintf("forwarder.Store: %v %v", p, chunk)) log.Trace(fmt.Sprintf("forwarder.Store: %v %v", p, chunk))
if p.syncer != nil && (source == nil || p.Addr() != source.Addr()) { if p.syncer != nil && (source == nil || p.Addr() != source.Addr()) {
@ -109,7 +109,7 @@ func (self *forwarder) Store(chunk *storage.Chunk) {
} }
// once a chunk is found deliver it to its requesters unless timed out // once a chunk is found deliver it to its requesters unless timed out
func (self *forwarder) Deliver(chunk *storage.Chunk) { func (f *forwarder) Deliver(chunk *storage.Chunk) {
// iterate over request entries // iterate over request entries
for id, requesters := range chunk.Req.Requesters { for id, requesters := range chunk.Req.Requesters {
counter := requesterCount counter := requesterCount

View file

@ -92,8 +92,8 @@ func NewDefaultHiveParams() *HiveParams {
//this can only finally be set after all config options (file, cmd line, env vars) //this can only finally be set after all config options (file, cmd line, env vars)
//have been evaluated //have been evaluated
func (self *HiveParams) Init(path string) { func (hp *HiveParams) Init(path string) {
self.KadDbPath = filepath.Join(path, "bzz-peers.json") hp.KadDbPath = filepath.Join(path, "bzz-peers.json")
} }
func NewHive(addr common.Hash, params *HiveParams, swapEnabled, syncEnabled bool) *Hive { func NewHive(addr common.Hash, params *HiveParams, swapEnabled, syncEnabled bool) *Hive {
@ -108,53 +108,53 @@ func NewHive(addr common.Hash, params *HiveParams, swapEnabled, syncEnabled bool
} }
} }
func (self *Hive) SyncEnabled(on bool) { func (hive *Hive) SyncEnabled(on bool) {
self.syncEnabled = on hive.syncEnabled = on
} }
func (self *Hive) SwapEnabled(on bool) { func (hive *Hive) SwapEnabled(on bool) {
self.swapEnabled = on hive.swapEnabled = on
} }
func (self *Hive) BlockNetworkRead(on bool) { func (hive *Hive) BlockNetworkRead(on bool) {
self.blockRead = on hive.blockRead = on
} }
func (self *Hive) BlockNetworkWrite(on bool) { func (hive *Hive) BlockNetworkWrite(on bool) {
self.blockWrite = on hive.blockWrite = on
} }
// public accessor to the hive base address // public accessor to the hive base address
func (self *Hive) Addr() kademlia.Address { func (hive *Hive) Addr() kademlia.Address {
return self.addr return hive.addr
} }
// Start receives network info only at startup // Start receives network info only at startup
// listedAddr is a function to retrieve listening address to advertise to peers // listedAddr is a function to retrieve listening address to advertise to peers
// connectPeer is a function to connect to a peer based on its NodeID or enode URL // connectPeer is a function to connect to a peer based on its NodeID or enode URL
// there are called on the p2p.Server which runs on the node // there are called on the p2p.Server which runs on the node
func (self *Hive) Start(id discover.NodeID, listenAddr func() string, connectPeer func(string) error) (err error) { func (hive *Hive) Start(id discover.NodeID, listenAddr func() string, connectPeer func(string) error) (err error) {
self.toggle = make(chan bool) hive.toggle = make(chan bool)
self.more = make(chan bool) hive.more = make(chan bool)
self.quit = make(chan bool) hive.quit = make(chan bool)
self.id = id hive.id = id
self.listenAddr = listenAddr hive.listenAddr = listenAddr
err = self.kad.Load(self.path, nil) err = hive.kad.Load(hive.path, nil)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("Warning: error reading kaddb '%s' (skipping): %v", self.path, err)) log.Warn(fmt.Sprintf("Warning: error reading kaddb '%s' (skipping): %v", hive.path, err))
err = nil err = nil
} }
// this loop is doing bootstrapping and maintains a healthy table // this loop is doing bootstrapping and maintains a healthy table
go self.keepAlive() go hive.keepAlive()
go func() { go func() {
// whenever toggled ask kademlia about most preferred peer // whenever toggled ask kademlia about most preferred peer
for alive := range self.more { for alive := range hive.more {
if !alive { if !alive {
// receiving false closes the loop while allowing parallel routines // receiving false closes the loop while allowing parallel routines
// to attempt to write to more (remove Peer when shutting down) // to attempt to write to more (remove Peer when shutting down)
return return
} }
node, need, proxLimit := self.kad.Suggest() node, need, proxLimit := hive.kad.Suggest()
if node != nil && len(node.Url) > 0 { if node != nil && len(node.Url) > 0 {
log.Trace(fmt.Sprintf("call known bee %v", node.Url)) log.Trace(fmt.Sprintf("call known bee %v", node.Url))
@ -164,10 +164,10 @@ func (self *Hive) Start(id discover.NodeID, listenAddr func() string, connectPee
} }
if need { if need {
// a random peer is taken from the table // a random peer is taken from the table
peers := self.kad.FindClosest(kademlia.RandomAddressAt(self.addr, rand.Intn(self.kad.MaxProx)), 1) peers := hive.kad.FindClosest(kademlia.RandomAddressAt(hive.addr, rand.Intn(hive.kad.MaxProx)), 1)
if len(peers) > 0 { if len(peers) > 0 {
// a random address at prox bin 0 is sent for lookup // a random address at prox bin 0 is sent for lookup
randAddr := kademlia.RandomAddressAt(self.addr, proxLimit) randAddr := kademlia.RandomAddressAt(hive.addr, proxLimit)
req := &retrieveRequestMsgData{ req := &retrieveRequestMsgData{
Key: storage.Key(randAddr[:]), Key: storage.Key(randAddr[:]),
} }
@ -181,11 +181,11 @@ func (self *Hive) Start(id discover.NodeID, listenAddr func() string, connectPee
log.Info(fmt.Sprintf("no need for more bees")) log.Info(fmt.Sprintf("no need for more bees"))
} }
select { select {
case self.toggle <- need: case hive.toggle <- need:
case <-self.quit: case <-hive.quit:
return return
} }
log.Debug(fmt.Sprintf("queen's address: %v, population: %d (%d)", self.addr, self.kad.Count(), self.kad.DBCount())) log.Debug(fmt.Sprintf("queen's address: %v, population: %d (%d)", hive.addr, hive.kad.Count(), hive.kad.DBCount()))
} }
}() }()
return return
@ -193,60 +193,60 @@ func (self *Hive) Start(id discover.NodeID, listenAddr func() string, connectPee
// keepAlive is a forever loop // keepAlive is a forever loop
// in its awake state it periodically triggers connection attempts // in its awake state it periodically triggers connection attempts
// by writing to self.more until Kademlia Table is saturated // by writing to hive.more until Kademlia Table is saturated
// wake state is toggled by writing to self.toggle // wake state is toggled by writing to hive.toggle
// it restarts if the table becomes non-full again due to disconnections // it restarts if the table becomes non-full again due to disconnections
func (self *Hive) keepAlive() { func (hive *Hive) keepAlive() {
alarm := time.NewTicker(time.Duration(self.callInterval)).C alarm := time.NewTicker(time.Duration(hive.callInterval)).C
for { for {
peersNumGauge.Update(int64(self.kad.Count())) peersNumGauge.Update(int64(hive.kad.Count()))
select { select {
case <-alarm: case <-alarm:
if self.kad.DBCount() > 0 { if hive.kad.DBCount() > 0 {
select { select {
case self.more <- true: case hive.more <- true:
log.Debug(fmt.Sprintf("buzz wakeup")) log.Debug(fmt.Sprintf("buzz wakeup"))
default: default:
} }
} }
case need := <-self.toggle: case need := <-hive.toggle:
if alarm == nil && need { if alarm == nil && need {
alarm = time.NewTicker(time.Duration(self.callInterval)).C alarm = time.NewTicker(time.Duration(hive.callInterval)).C
} }
if alarm != nil && !need { if alarm != nil && !need {
alarm = nil alarm = nil
} }
case <-self.quit: case <-hive.quit:
return return
} }
} }
} }
func (self *Hive) Stop() error { func (hive *Hive) Stop() error {
// closing toggle channel quits the updateloop // closing toggle channel quits the updateloop
close(self.quit) close(hive.quit)
return self.kad.Save(self.path, saveSync) return hive.kad.Save(hive.path, saveSync)
} }
// called at the end of a successful protocol handshake // called at the end of a successful protocol handshake
func (self *Hive) addPeer(p *peer) error { func (hive *Hive) addPeer(p *peer) error {
addPeerCounter.Inc(1) addPeerCounter.Inc(1)
defer func() { defer func() {
select { select {
case self.more <- true: case hive.more <- true:
default: default:
} }
}() }()
log.Trace(fmt.Sprintf("hi new bee %v", p)) log.Trace(fmt.Sprintf("hi new bee %v", p))
err := self.kad.On(p, loadSync) err := hive.kad.On(p, loadSync)
if err != nil { if err != nil {
return err return err
} }
// self lookup (can be encoded as nil/zero key since peers addr known) + no id () // hive lookup (can be encoded as nil/zero key since peers addr known) + no id ()
// the most common way of saying hi in bzz is initiation of gossip // the most common way of saying hi in bzz is initiation of gossip
// let me know about anyone new from my hood , here is the storageradius // let me know about anyone new from my hood , here is the storageradius
// to send the 6 byte self lookup // to send the 6 byte hive lookup
// we do not record as request or forward it, just reply with peers // we do not record as request or forward it, just reply with peers
p.retrieve(&retrieveRequestMsgData{}) p.retrieve(&retrieveRequestMsgData{})
log.Trace(fmt.Sprintf("'whatsup wheresdaparty' sent to %v", p)) log.Trace(fmt.Sprintf("'whatsup wheresdaparty' sent to %v", p))
@ -255,33 +255,33 @@ func (self *Hive) addPeer(p *peer) error {
} }
// called after peer disconnected // called after peer disconnected
func (self *Hive) removePeer(p *peer) { func (hive *Hive) removePeer(p *peer) {
removePeerCounter.Inc(1) removePeerCounter.Inc(1)
log.Debug(fmt.Sprintf("bee %v removed", p)) log.Debug(fmt.Sprintf("bee %v removed", p))
self.kad.Off(p, saveSync) hive.kad.Off(p, saveSync)
select { select {
case self.more <- true: case hive.more <- true:
default: default:
} }
if self.kad.Count() == 0 { if hive.kad.Count() == 0 {
log.Debug(fmt.Sprintf("empty, all bees gone")) log.Debug(fmt.Sprintf("empty, all bees gone"))
} }
} }
// Retrieve a list of live peers that are closer to target than us // Retrieve a list of live peers that are closer to target than us
func (self *Hive) getPeers(target storage.Key, max int) (peers []*peer) { func (hive *Hive) getPeers(target storage.Key, max int) (peers []*peer) {
var addr kademlia.Address var addr kademlia.Address
copy(addr[:], target[:]) copy(addr[:], target[:])
for _, node := range self.kad.FindClosest(addr, max) { for _, node := range hive.kad.FindClosest(addr, max) {
peers = append(peers, node.(*peer)) peers = append(peers, node.(*peer))
} }
return return
} }
// disconnects all the peers // disconnects all the peers
func (self *Hive) DropAll() { func (hive *Hive) DropAll() {
log.Info(fmt.Sprintf("dropping all bees")) log.Info(fmt.Sprintf("dropping all bees"))
for _, node := range self.kad.FindClosest(kademlia.Address{}, 0) { for _, node := range hive.kad.FindClosest(kademlia.Address{}, 0) {
node.Drop() node.Drop()
} }
} }
@ -301,7 +301,7 @@ func newNodeRecord(addr *peerAddr) *kademlia.NodeRecord {
// called by the protocol when receiving peerset (for target address) // called by the protocol when receiving peerset (for target address)
// peersMsgData is converted to a slice of NodeRecords for Kademlia // peersMsgData is converted to a slice of NodeRecords for Kademlia
// this is to store all thats needed // this is to store all thats needed
func (self *Hive) HandlePeersMsg(req *peersMsgData, from *peer) { func (hive *Hive) HandlePeersMsg(req *peersMsgData, from *peer) {
var nrs []*kademlia.NodeRecord var nrs []*kademlia.NodeRecord
for _, p := range req.Peers { for _, p := range req.Peers {
if err := netutil.CheckRelayIP(from.remoteAddr.IP, p.IP); err != nil { if err := netutil.CheckRelayIP(from.remoteAddr.IP, p.IP); err != nil {
@ -310,7 +310,7 @@ func (self *Hive) HandlePeersMsg(req *peersMsgData, from *peer) {
} }
nrs = append(nrs, newNodeRecord(p)) nrs = append(nrs, newNodeRecord(p))
} }
self.kad.Add(nrs) hive.kad.Add(nrs)
} }
// peer wraps the protocol instance to represent a connected peer // peer wraps the protocol instance to represent a connected peer
@ -320,17 +320,17 @@ type peer struct {
} }
// protocol instance implements kademlia.Node interface (embedded peer) // protocol instance implements kademlia.Node interface (embedded peer)
func (self *peer) Addr() kademlia.Address { func (p *peer) Addr() kademlia.Address {
return self.remoteAddr.Addr return p.remoteAddr.Addr
} }
func (self *peer) Url() string { func (p *peer) Url() string {
return self.remoteAddr.String() return p.remoteAddr.String()
} }
// TODO take into account traffic // TODO take into account traffic
func (self *peer) LastActive() time.Time { func (p *peer) LastActive() time.Time {
return self.lastActive return p.lastActive
} }
// reads the serialised form of sync state persisted as the 'Meta' attribute // reads the serialised form of sync state persisted as the 'Meta' attribute
@ -370,19 +370,19 @@ func saveSync(record *kademlia.NodeRecord, node kademlia.Node) {
// the immediate response to a retrieve request, // the immediate response to a retrieve request,
// sends relevant peer data given by the kademlia hive to the requester // sends relevant peer data given by the kademlia hive to the requester
// TODO: remember peers sent for duration of the session, only new peers sent // TODO: remember peers sent for duration of the session, only new peers sent
func (self *Hive) peers(req *retrieveRequestMsgData) { func (hive *Hive) peers(req *retrieveRequestMsgData) {
if req != nil { if req != nil {
var addrs []*peerAddr var addrs []*peerAddr
if req.timeout == nil || time.Now().Before(*(req.timeout)) { if req.timeout == nil || time.Now().Before(*(req.timeout)) {
key := req.Key key := req.Key
// self lookup from remote peer // hive lookup from remote peer
if storage.IsZeroKey(key) { if storage.IsZeroKey(key) {
addr := req.from.Addr() addr := req.from.Addr()
key = storage.Key(addr[:]) key = storage.Key(addr[:])
req.Key = nil req.Key = nil
} }
// get peer addresses from hive // get peer addresses from hive
for _, peer := range self.getPeers(key, int(req.MaxPeers)) { for _, peer := range hive.getPeers(key, int(req.MaxPeers)) {
addrs = append(addrs, peer.remoteAddr) addrs = append(addrs, peer.remoteAddr)
} }
log.Debug(fmt.Sprintf("Hive sending %d peer addresses to %v. req.Id: %v, req.Key: %v", len(addrs), req.from, req.Id, req.Key.Log())) log.Debug(fmt.Sprintf("Hive sending %d peer addresses to %v. req.Id: %v, req.Key: %v", len(addrs), req.from, req.Id, req.Key.Log()))
@ -398,6 +398,6 @@ func (self *Hive) peers(req *retrieveRequestMsgData) {
} }
} }
func (self *Hive) String() string { func (hive *Hive) String() string {
return self.kad.String() return hive.kad.String()
} }

View file

@ -43,14 +43,14 @@ type NodeRecord struct {
node Node node Node
} }
func (self *NodeRecord) setSeen() { func (record *NodeRecord) setSeen() {
t := time.Now() t := time.Now()
self.Seen = t record.Seen = t
self.After = t record.After = t
} }
func (self *NodeRecord) String() string { func (record *NodeRecord) String() string {
return fmt.Sprintf("<%v>", self.Addr) return fmt.Sprintf("<%v>", record.Addr)
} }
// persisted node record database () // persisted node record database ()
@ -77,11 +77,11 @@ func newKadDb(addr Address, params *KadParams) *KadDb {
} }
} }
func (self *KadDb) findOrCreate(index int, a Address, url string) *NodeRecord { func (db *KadDb) findOrCreate(index int, a Address, url string) *NodeRecord {
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
record, found := self.index[a] record, found := db.index[a]
if !found { if !found {
record = &NodeRecord{ record = &NodeRecord{
Addr: a, Addr: a,
@ -89,8 +89,8 @@ func (self *KadDb) findOrCreate(index int, a Address, url string) *NodeRecord {
} }
log.Info(fmt.Sprintf("add new record %v to kaddb", record)) log.Info(fmt.Sprintf("add new record %v to kaddb", record))
// insert in kaddb // insert in kaddb
self.index[a] = record db.index[a] = record
self.Nodes[index] = append(self.Nodes[index], record) db.Nodes[index] = append(db.Nodes[index], record)
} else { } else {
log.Info(fmt.Sprintf("found record %v in kaddb", record)) log.Info(fmt.Sprintf("found record %v in kaddb", record))
} }
@ -102,26 +102,26 @@ func (self *KadDb) findOrCreate(index int, a Address, url string) *NodeRecord {
} }
// add adds node records to kaddb (persisted node record db) // add adds node records to kaddb (persisted node record db)
func (self *KadDb) add(nrs []*NodeRecord, proximityBin func(Address) int) { func (db *KadDb) add(nrs []*NodeRecord, proximityBin func(Address) int) {
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
var n int var n int
var nodes []*NodeRecord var nodes []*NodeRecord
for _, node := range nrs { for _, node := range nrs {
_, found := self.index[node.Addr] _, found := db.index[node.Addr]
if !found && node.Addr != self.Address { if !found && node.Addr != db.Address {
node.setSeen() node.setSeen()
self.index[node.Addr] = node db.index[node.Addr] = node
index := proximityBin(node.Addr) index := proximityBin(node.Addr)
dbcursor := self.cursors[index] dbcursor := db.cursors[index]
nodes = self.Nodes[index] nodes = db.Nodes[index]
// this is inefficient for allocation, need to just append then shift // this is inefficient for allocation, need to just append then shift
newnodes := make([]*NodeRecord, len(nodes)+1) newnodes := make([]*NodeRecord, len(nodes)+1)
copy(newnodes[:], nodes[:dbcursor]) copy(newnodes[:], nodes[:dbcursor])
newnodes[dbcursor] = node newnodes[dbcursor] = node
copy(newnodes[dbcursor+1:], nodes[dbcursor:]) copy(newnodes[dbcursor+1:], nodes[dbcursor:])
log.Trace(fmt.Sprintf("new nodes: %v, nodes: %v", newnodes, nodes)) log.Trace(fmt.Sprintf("new nodes: %v, nodes: %v", newnodes, nodes))
self.Nodes[index] = newnodes db.Nodes[index] = newnodes
n++ n++
} }
} }
@ -168,10 +168,10 @@ offline past peer)
The second argument returned names the first missing slot found The second argument returned names the first missing slot found
*/ */
func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRecord, need bool, proxLimit int) { func (db *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRecord, need bool, proxLimit int) {
// return nil, proxLimit indicates that all buckets are filled // return nil, proxLimit indicates that all buckets are filled
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
var interval time.Duration var interval time.Duration
var found bool var found bool
@ -185,7 +185,7 @@ func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRe
for rounds := 1; rounds <= maxBinSize; rounds++ { for rounds := 1; rounds <= maxBinSize; rounds++ {
ROUND: ROUND:
// iterate over rows from PO 0 upto MaxProx // iterate over rows from PO 0 upto MaxProx
for po, dbrow := range self.Nodes { for po, dbrow := range db.Nodes {
// if row has rounds connected peers, then take the next // if row has rounds connected peers, then take the next
if binSize(po) >= rounds { if binSize(po) >= rounds {
continue ROUND continue ROUND
@ -200,7 +200,7 @@ func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRe
// there is a missing slot - finding a node to connect to // there is a missing slot - finding a node to connect to
// select a node record from the relavant kaddb row (of identical prox order) // select a node record from the relavant kaddb row (of identical prox order)
ROW: ROW:
for cursor = self.cursors[po]; !found && count < len(dbrow); cursor = (cursor + 1) % len(dbrow) { for cursor = db.cursors[po]; !found && count < len(dbrow); cursor = (cursor + 1) % len(dbrow) {
count++ count++
node = dbrow[cursor] node = dbrow[cursor]
@ -217,10 +217,10 @@ func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRe
} }
delta = time.Since(node.Seen) delta = time.Since(node.Seen)
if delta < self.initialRetryInterval { if delta < db.initialRetryInterval {
delta = self.initialRetryInterval delta = db.initialRetryInterval
} }
if delta > self.purgeInterval { if delta > db.purgeInterval {
// remove node // remove node
purge[cursor] = true purge[cursor] = true
log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) unreachable since %v. Removed", node.Addr, po, cursor, node.Seen)) log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) unreachable since %v. Removed", node.Addr, po, cursor, node.Seen))
@ -230,15 +230,15 @@ func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRe
log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) ready to be tried. seen at %v (%v ago), scheduled at %v", node.Addr, po, cursor, node.Seen, delta, node.After)) log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) ready to be tried. seen at %v (%v ago), scheduled at %v", node.Addr, po, cursor, node.Seen, delta, node.After))
// scheduling next check // scheduling next check
interval = delta * time.Duration(self.connRetryExp) interval = delta * time.Duration(db.connRetryExp)
after = time.Now().Add(interval) after = time.Now().Add(interval)
log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) selected as candidate connection %v. seen at %v (%v ago), selectable since %v, retry after %v (in %v)", node.Addr, po, cursor, rounds, node.Seen, delta, node.After, after, interval)) log.Debug(fmt.Sprintf("kaddb record %v (PO%03d:%d) selected as candidate connection %v. seen at %v (%v ago), selectable since %v, retry after %v (in %v)", node.Addr, po, cursor, rounds, node.Seen, delta, node.After, after, interval))
node.After = after node.After = after
found = true found = true
} // ROW } // ROW
self.cursors[po] = cursor db.cursors[po] = cursor
self.delete(po, purge) db.delete(po, purge)
if found { if found {
return node, need, proxLimit return node, need, proxLimit
} }
@ -251,33 +251,33 @@ func (self *KadDb) findBest(maxBinSize int, binSize func(int) int) (node *NodeRe
// deletes the noderecords of a kaddb row corresponding to the indexes // deletes the noderecords of a kaddb row corresponding to the indexes
// caller must hold the dblock // caller must hold the dblock
// the call is unsafe, no index checks // the call is unsafe, no index checks
func (self *KadDb) delete(row int, purge []bool) { func (db *KadDb) delete(row int, purge []bool) {
var nodes []*NodeRecord var nodes []*NodeRecord
dbrow := self.Nodes[row] dbrow := db.Nodes[row]
for i, del := range purge { for i, del := range purge {
if i == self.cursors[row] { if i == db.cursors[row] {
//reset cursor //reset cursor
self.cursors[row] = len(nodes) db.cursors[row] = len(nodes)
} }
// delete the entry to be purged // delete the entry to be purged
if del { if del {
delete(self.index, dbrow[i].Addr) delete(db.index, dbrow[i].Addr)
continue continue
} }
// otherwise append to new list // otherwise append to new list
nodes = append(nodes, dbrow[i]) nodes = append(nodes, dbrow[i])
} }
self.Nodes[row] = nodes db.Nodes[row] = nodes
} }
// save persists kaddb on disk (written to file on path in json format. // save persists kaddb on disk (written to file on path in json format.
func (self *KadDb) save(path string, cb func(*NodeRecord, Node)) error { func (db *KadDb) save(path string, cb func(*NodeRecord, Node)) error {
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
var n int var n int
for _, b := range self.Nodes { for _, b := range db.Nodes {
for _, node := range b { for _, node := range b {
n++ n++
node.After = time.Now() node.After = time.Now()
@ -288,7 +288,7 @@ func (self *KadDb) save(path string, cb func(*NodeRecord, Node)) error {
} }
} }
data, err := json.MarshalIndent(self, "", " ") data, err := json.MarshalIndent(db, "", " ")
if err != nil { if err != nil {
return err return err
} }
@ -302,9 +302,9 @@ func (self *KadDb) save(path string, cb func(*NodeRecord, Node)) error {
} }
// Load(path) loads the node record database (kaddb) from file on path. // Load(path) loads the node record database (kaddb) from file on path.
func (self *KadDb) load(path string, cb func(*NodeRecord, Node) error) (err error) { func (db *KadDb) load(path string, cb func(*NodeRecord, Node) error) (err error) {
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
var data []byte var data []byte
data, err = ioutil.ReadFile(path) data, err = ioutil.ReadFile(path)
@ -312,13 +312,13 @@ func (self *KadDb) load(path string, cb func(*NodeRecord, Node) error) (err erro
return return
} }
err = json.Unmarshal(data, self) err = json.Unmarshal(data, db)
if err != nil { if err != nil {
return return
} }
var n int var n int
var purge []bool var purge []bool
for po, b := range self.Nodes { for po, b := range db.Nodes {
purge = make([]bool, len(b)) purge = make([]bool, len(b))
ROW: ROW:
for i, node := range b { for i, node := range b {
@ -333,9 +333,9 @@ func (self *KadDb) load(path string, cb func(*NodeRecord, Node) error) (err erro
if node.After.IsZero() { if node.After.IsZero() {
node.After = time.Now() node.After = time.Now()
} }
self.index[node.Addr] = node db.index[node.Addr] = node
} }
self.delete(po, purge) db.delete(po, purge)
} }
log.Info(fmt.Sprintf("loaded kaddb with %v nodes from %v", n, path)) log.Info(fmt.Sprintf("loaded kaddb with %v nodes from %v", n, path))
@ -343,8 +343,8 @@ func (self *KadDb) load(path string, cb func(*NodeRecord, Node) error) (err erro
} }
// accessor for KAD offline db count // accessor for KAD offline db count
func (self *KadDb) count() int { func (db *KadDb) count() int {
defer self.lock.Unlock() defer db.lock.Unlock()
self.lock.Lock() db.lock.Lock()
return len(self.index) return len(db.index)
} }

View file

@ -109,31 +109,31 @@ func New(addr Address, params *KadParams) *Kademlia {
} }
// accessor for KAD base address // accessor for KAD base address
func (self *Kademlia) Addr() Address { func (kad *Kademlia) Addr() Address {
return self.addr return kad.addr
} }
// accessor for KAD active node count // accessor for KAD active node count
func (self *Kademlia) Count() int { func (kad *Kademlia) Count() int {
defer self.lock.Unlock() defer kad.lock.Unlock()
self.lock.Lock() kad.lock.Lock()
return self.count return kad.count
} }
// accessor for KAD active node count // accessor for KAD active node count
func (self *Kademlia) DBCount() int { func (kad *Kademlia) DBCount() int {
return self.db.count() return kad.db.count()
} }
// On is the entry point called when a new nodes is added // On is the entry point called when a new nodes is added
// unsafe in that node is not checked to be already active node (to be called once) // unsafe in that node is not checked to be already active node (to be called once)
func (self *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error) { func (kad *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error) {
log.Debug(fmt.Sprintf("%v", self)) log.Debug(fmt.Sprintf("%v", kad))
defer self.lock.Unlock() defer kad.lock.Unlock()
self.lock.Lock() kad.lock.Lock()
index := self.proximityBin(node.Addr()) index := kad.proximityBin(node.Addr())
record := self.db.findOrCreate(index, node.Addr(), node.Url()) record := kad.db.findOrCreate(index, node.Addr(), node.Url())
if cb != nil { if cb != nil {
err = cb(record, node) err = cb(record, node)
@ -145,21 +145,21 @@ func (self *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error
} }
// insert in kademlia table of active nodes // insert in kademlia table of active nodes
bucket := self.buckets[index] bucket := kad.buckets[index]
// if bucket is full insertion replaces the worst node // if bucket is full insertion replaces the worst node
// TODO: give priority to peers with active traffic // TODO: give priority to peers with active traffic
if len(bucket) < self.BucketSize { // >= allows us to add peers beyond the bucketsize limitation if len(bucket) < kad.BucketSize { // >= allows us to add peers beyond the bucketsize limitation
self.buckets[index] = append(bucket, node) kad.buckets[index] = append(bucket, node)
bucketAddIndexCount[index].Inc(1) bucketAddIndexCount[index].Inc(1)
log.Debug(fmt.Sprintf("add node %v to table", node)) log.Debug(fmt.Sprintf("add node %v to table", node))
self.setProxLimit(index, true) kad.setProxLimit(index, true)
record.node = node record.node = node
self.count++ kad.count++
return nil return nil
} }
// always rotate peers // always rotate peers
idle := self.MaxIdleInterval idle := kad.MaxIdleInterval
var pos int var pos int
var replaced Node var replaced Node
for i, p := range bucket { for i, p := range bucket {
@ -174,41 +174,41 @@ func (self *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error
log.Debug(fmt.Sprintf("all peers wanted, PO%03d bucket full", index)) log.Debug(fmt.Sprintf("all peers wanted, PO%03d bucket full", index))
return fmt.Errorf("bucket full") return fmt.Errorf("bucket full")
} }
log.Debug(fmt.Sprintf("node %v replaced by %v (idle for %v > %v)", replaced, node, idle, self.MaxIdleInterval)) log.Debug(fmt.Sprintf("node %v replaced by %v (idle for %v > %v)", replaced, node, idle, kad.MaxIdleInterval))
replaced.Drop() replaced.Drop()
// actually replace in the row. When off(node) is called, the peer is no longer in the row // actually replace in the row. When off(node) is called, the peer is no longer in the row
bucket[pos] = node bucket[pos] = node
// there is no change in bucket cardinalities so no prox limit adjustment is needed // there is no change in bucket cardinalities so no prox limit adjustment is needed
record.node = node record.node = node
self.count++ kad.count++
return nil return nil
} }
// Off is the called when a node is taken offline (from the protocol main loop exit) // Off is the called when a node is taken offline (from the protocol main loop exit)
func (self *Kademlia) Off(node Node, cb func(*NodeRecord, Node)) (err error) { func (kad *Kademlia) Off(node Node, cb func(*NodeRecord, Node)) (err error) {
self.lock.Lock() kad.lock.Lock()
defer self.lock.Unlock() defer kad.lock.Unlock()
index := self.proximityBin(node.Addr()) index := kad.proximityBin(node.Addr())
bucketRmIndexCount[index].Inc(1) bucketRmIndexCount[index].Inc(1)
bucket := self.buckets[index] bucket := kad.buckets[index]
for i := 0; i < len(bucket); i++ { for i := 0; i < len(bucket); i++ {
if node.Addr() == bucket[i].Addr() { if node.Addr() == bucket[i].Addr() {
self.buckets[index] = append(bucket[:i], bucket[(i+1):]...) kad.buckets[index] = append(bucket[:i], bucket[(i+1):]...)
self.setProxLimit(index, false) kad.setProxLimit(index, false)
break break
} }
} }
record := self.db.index[node.Addr()] record := kad.db.index[node.Addr()]
// callback on remove // callback on remove
if cb != nil { if cb != nil {
cb(record, record.node) cb(record, record.node)
} }
record.node = nil record.node = nil
self.count-- kad.count--
log.Debug(fmt.Sprintf("remove node %v from table, population now is %v", node, self.count)) log.Debug(fmt.Sprintf("remove node %v from table, population now is %v", node, kad.count))
return return
} }
@ -218,39 +218,39 @@ func (self *Kademlia) Off(node Node, cb func(*NodeRecord, Node)) (err error) {
// 2) the sum of all items are the minimum possible but higher than ProxBinSize // 2) the sum of all items are the minimum possible but higher than ProxBinSize
// adjust Prox (proxLimit and proxSize after an insertion/removal of nodes) // adjust Prox (proxLimit and proxSize after an insertion/removal of nodes)
// caller holds the lock // caller holds the lock
func (self *Kademlia) setProxLimit(r int, on bool) { func (kad *Kademlia) setProxLimit(r int, on bool) {
// if the change is outside the core (PO lower) // if the change is outside the core (PO lower)
// and the change does not leave a bucket empty then // and the change does not leave a bucket empty then
// no adjustment needed // no adjustment needed
if r < self.proxLimit && len(self.buckets[r]) > 0 { if r < kad.proxLimit && len(kad.buckets[r]) > 0 {
return return
} }
// if on=a node was added, then r must be within prox limit so increment cardinality // if on=a node was added, then r must be within prox limit so increment cardinality
if on { if on {
self.proxSize++ kad.proxSize++
curr := len(self.buckets[self.proxLimit]) curr := len(kad.buckets[kad.proxLimit])
// if now core is big enough without the furthest bucket, then contract // if now core is big enough without the furthest bucket, then contract
// this can result in more than one bucket change // this can result in more than one bucket change
for self.proxSize >= self.ProxBinSize+curr && curr > 0 { for kad.proxSize >= kad.ProxBinSize+curr && curr > 0 {
self.proxSize -= curr kad.proxSize -= curr
self.proxLimit++ kad.proxLimit++
curr = len(self.buckets[self.proxLimit]) curr = len(kad.buckets[kad.proxLimit])
log.Trace(fmt.Sprintf("proxbin contraction (size: %v, limit: %v, bin: %v)", self.proxSize, self.proxLimit, r)) log.Trace(fmt.Sprintf("proxbin contraction (size: %v, limit: %v, bin: %v)", kad.proxSize, kad.proxLimit, r))
} }
return return
} }
// otherwise // otherwise
if r >= self.proxLimit { if r >= kad.proxLimit {
self.proxSize-- kad.proxSize--
} }
// expand core by lowering prox limit until hit zero or cover the empty bucket or reached target cardinality // expand core by lowering prox limit until hit zero or cover the empty bucket or reached target cardinality
for (self.proxSize < self.ProxBinSize || r < self.proxLimit) && for (kad.proxSize < kad.ProxBinSize || r < kad.proxLimit) &&
self.proxLimit > 0 { kad.proxLimit > 0 {
// //
self.proxLimit-- kad.proxLimit--
self.proxSize += len(self.buckets[self.proxLimit]) kad.proxSize += len(kad.buckets[kad.proxLimit])
log.Trace(fmt.Sprintf("proxbin expansion (size: %v, limit: %v, bin: %v)", self.proxSize, self.proxLimit, r)) log.Trace(fmt.Sprintf("proxbin expansion (size: %v, limit: %v, bin: %v)", kad.proxSize, kad.proxLimit, r))
} }
} }
@ -259,15 +259,15 @@ returns the list of nodes belonging to the same proximity bin
as the target. The most proximate bin will be the union of the bins between as the target. The most proximate bin will be the union of the bins between
proxLimit and MaxProx. proxLimit and MaxProx.
*/ */
func (self *Kademlia) FindClosest(target Address, max int) []Node { func (kad *Kademlia) FindClosest(target Address, max int) []Node {
self.lock.Lock() kad.lock.Lock()
defer self.lock.Unlock() defer kad.lock.Unlock()
r := nodesByDistance{ r := nodesByDistance{
target: target, target: target,
} }
po := self.proximityBin(target) po := kad.proximityBin(target)
index := po index := po
step := 1 step := 1
log.Trace(fmt.Sprintf("serving %v nodes at %v (PO%02d)", max, index, po)) log.Trace(fmt.Sprintf("serving %v nodes at %v (PO%02d)", max, index, po))
@ -284,17 +284,17 @@ func (self *Kademlia) FindClosest(target Address, max int) []Node {
var n int var n int
for index >= 0 { for index >= 0 {
// add entire bucket // add entire bucket
for _, p := range self.buckets[index] { for _, p := range kad.buckets[index] {
r.push(p, limit) r.push(p, limit)
n++ n++
} }
// terminate if index reached the bottom or enough peers > min // terminate if index reached the bottom or enough peers > min
log.Trace(fmt.Sprintf("add %v -> %v (PO%02d, PO%03d)", len(self.buckets[index]), n, index, po)) log.Trace(fmt.Sprintf("add %v -> %v (PO%02d, PO%03d)", len(kad.buckets[index]), n, index, po))
if n >= min && (step < 0 || max == 0) { if n >= min && (step < 0 || max == 0) {
break break
} }
// reach top most non-empty PO bucket, turn around // reach top most non-empty PO bucket, turn around
if index == self.MaxProx { if index == kad.MaxProx {
index = po index = po
step = -1 step = -1
} }
@ -304,15 +304,15 @@ func (self *Kademlia) FindClosest(target Address, max int) []Node {
return r.nodes return r.nodes
} }
func (self *Kademlia) Suggest() (*NodeRecord, bool, int) { func (kad *Kademlia) Suggest() (*NodeRecord, bool, int) {
defer self.lock.RUnlock() defer kad.lock.RUnlock()
self.lock.RLock() kad.lock.RLock()
return self.db.findBest(self.BucketSize, func(i int) int { return len(self.buckets[i]) }) return kad.db.findBest(kad.BucketSize, func(i int) int { return len(kad.buckets[i]) })
} }
// adds node records to kaddb (persisted node record db) // adds node records to kaddb (persisted node record db)
func (self *Kademlia) Add(nrs []*NodeRecord) { func (kad *Kademlia) Add(nrs []*NodeRecord) {
self.db.add(nrs, self.proximityBin) kad.db.add(nrs, kad.proximityBin)
} }
// nodesByDistance is a list of nodes, ordered by distance to target. // nodesByDistance is a list of nodes, ordered by distance to target.
@ -369,52 +369,52 @@ a guaranteed constant maximum limit on the number of hops needed to reach one
node from the other. node from the other.
*/ */
func (self *Kademlia) proximityBin(other Address) (ret int) { func (kad *Kademlia) proximityBin(other Address) (ret int) {
ret = proximity(self.addr, other) ret = proximity(kad.addr, other)
if ret > self.MaxProx { if ret > kad.MaxProx {
ret = self.MaxProx ret = kad.MaxProx
} }
return return
} }
// provides keyrange for chunk db iteration // provides keyrange for chunk db iteration
func (self *Kademlia) KeyRange(other Address) (start, stop Address) { func (kad *Kademlia) KeyRange(other Address) (start, stop Address) {
defer self.lock.RUnlock() defer kad.lock.RUnlock()
self.lock.RLock() kad.lock.RLock()
return KeyRange(self.addr, other, self.proxLimit) return KeyRange(kad.addr, other, kad.proxLimit)
} }
// save persists kaddb on disk (written to file on path in json format. // save persists kaddb on disk (written to file on path in json format.
func (self *Kademlia) Save(path string, cb func(*NodeRecord, Node)) error { func (kad *Kademlia) Save(path string, cb func(*NodeRecord, Node)) error {
return self.db.save(path, cb) return kad.db.save(path, cb)
} }
// Load(path) loads the node record database (kaddb) from file on path. // Load(path) loads the node record database (kaddb) from file on path.
func (self *Kademlia) Load(path string, cb func(*NodeRecord, Node) error) (err error) { func (kad *Kademlia) Load(path string, cb func(*NodeRecord, Node) error) (err error) {
return self.db.load(path, cb) return kad.db.load(path, cb)
} }
// kademlia table + kaddb table displayed with ascii // kademlia table + kaddb table displayed with ascii
func (self *Kademlia) String() string { func (kad *Kademlia) String() string {
defer self.lock.RUnlock() defer kad.lock.RUnlock()
self.lock.RLock() kad.lock.RLock()
defer self.db.lock.RUnlock() defer kad.db.lock.RUnlock()
self.db.lock.RLock() kad.db.lock.RLock()
var rows []string var rows []string
rows = append(rows, "=========================================================================") rows = append(rows, "=========================================================================")
rows = append(rows, fmt.Sprintf("%v KΛÐΞMLIΛ hive: queen's address: %v", time.Now().UTC().Format(time.UnixDate), self.addr.String()[:6])) rows = append(rows, fmt.Sprintf("%v KΛÐΞMLIΛ hive: queen's address: %v", time.Now().UTC().Format(time.UnixDate), kad.addr.String()[:6]))
rows = append(rows, fmt.Sprintf("population: %d (%d), proxLimit: %d, proxSize: %d", self.count, len(self.db.index), self.proxLimit, self.proxSize)) rows = append(rows, fmt.Sprintf("population: %d (%d), proxLimit: %d, proxSize: %d", kad.count, len(kad.db.index), kad.proxLimit, kad.proxSize))
rows = append(rows, fmt.Sprintf("MaxProx: %d, ProxBinSize: %d, BucketSize: %d", self.MaxProx, self.ProxBinSize, self.BucketSize)) rows = append(rows, fmt.Sprintf("MaxProx: %d, ProxBinSize: %d, BucketSize: %d", kad.MaxProx, kad.ProxBinSize, kad.BucketSize))
for i, bucket := range self.buckets { for i, bucket := range kad.buckets {
if i == self.proxLimit { if i == kad.proxLimit {
rows = append(rows, fmt.Sprintf("============ PROX LIMIT: %d ==========================================", i)) rows = append(rows, fmt.Sprintf("============ PROX LIMIT: %d ==========================================", i))
} }
row := []string{fmt.Sprintf("%03d", i), fmt.Sprintf("%2d", len(bucket))} row := []string{fmt.Sprintf("%03d", i), fmt.Sprintf("%2d", len(bucket))}
var k int var k int
c := self.db.cursors[i] c := kad.db.cursors[i]
for ; k < len(bucket); k++ { for ; k < len(bucket); k++ {
p := bucket[(c+k)%len(bucket)] p := bucket[(c+k)%len(bucket)]
row = append(row, p.Addr().String()[:6]) row = append(row, p.Addr().String()[:6])
@ -425,16 +425,16 @@ func (self *Kademlia) String() string {
for ; k < 4; k++ { for ; k < 4; k++ {
row = append(row, " ") row = append(row, " ")
} }
row = append(row, fmt.Sprintf("| %2d %2d", len(self.db.Nodes[i]), self.db.cursors[i])) row = append(row, fmt.Sprintf("| %2d %2d", len(kad.db.Nodes[i]), kad.db.cursors[i]))
for j, p := range self.db.Nodes[i] { for j, p := range kad.db.Nodes[i] {
row = append(row, p.Addr.String()[:6]) row = append(row, p.Addr.String()[:6])
if j == 3 { if j == 3 {
break break
} }
} }
rows = append(rows, strings.Join(row, " ")) rows = append(rows, strings.Join(row, " "))
if i == self.MaxProx { if i == kad.MaxProx {
} }
} }
rows = append(rows, "=========================================================================") rows = append(rows, "=========================================================================")
@ -442,12 +442,12 @@ func (self *Kademlia) String() string {
} }
//We have to build up the array of counters for each index //We have to build up the array of counters for each index
func (self *Kademlia) initMetricsVariables() { func (kad *Kademlia) initMetricsVariables() {
//create the arrays //create the arrays
bucketAddIndexCount = make([]metrics.Counter, self.MaxProx+1) bucketAddIndexCount = make([]metrics.Counter, kad.MaxProx+1)
bucketRmIndexCount = make([]metrics.Counter, self.MaxProx+1) bucketRmIndexCount = make([]metrics.Counter, kad.MaxProx+1)
//at each index create a metrics counter //at each index create a metrics counter
for i := 0; i < (self.KadParams.MaxProx + 1); i++ { for i := 0; i < (kad.KadParams.MaxProx + 1); i++ {
bucketAddIndexCount[i] = metrics.NewRegisteredCounter(fmt.Sprintf("network.kademlia.bucket.add.%d.index", i), nil) bucketAddIndexCount[i] = metrics.NewRegisteredCounter(fmt.Sprintf("network.kademlia.bucket.add.%d.index", i), nil)
bucketRmIndexCount[i] = metrics.NewRegisteredCounter(fmt.Sprintf("network.kademlia.bucket.rm.%d.index", i), nil) bucketRmIndexCount[i] = metrics.NewRegisteredCounter(fmt.Sprintf("network.kademlia.bucket.rm.%d.index", i), nil)
} }

View file

@ -272,31 +272,31 @@ func TestSaveLoad(t *testing.T) {
} }
} }
func (self *Kademlia) proxCheck(t *testing.T) bool { func (kad *Kademlia) proxCheck(t *testing.T) bool {
var sum int var sum int
for i, b := range self.buckets { for i, b := range kad.buckets {
l := len(b) l := len(b)
// if we are in the high prox multibucket // if we are in the high prox multibucket
if i >= self.proxLimit { if i >= kad.proxLimit {
sum += l sum += l
} else if l == 0 { } else if l == 0 {
t.Errorf("bucket %d empty, yet proxLimit is %d\n%v", len(b), self.proxLimit, self) t.Errorf("bucket %d empty, yet proxLimit is %d\n%v", len(b), kad.proxLimit, kad)
return false return false
} }
} }
// check if merged high prox bucket does not exceed size // check if merged high prox bucket does not exceed size
if sum > 0 { if sum > 0 {
if sum != self.proxSize { if sum != kad.proxSize {
t.Errorf("proxSize incorrect, expected %v, got %v", sum, self.proxSize) t.Errorf("proxSize incorrect, expected %v, got %v", sum, kad.proxSize)
return false return false
} }
last := len(self.buckets[self.proxLimit]) last := len(kad.buckets[kad.proxLimit])
if last > 0 && sum >= self.ProxBinSize+last { if last > 0 && sum >= kad.ProxBinSize+last {
t.Errorf("proxLimit %v incorrect, redundant non-empty bucket %d added to proxBin with %v (target %v)\n%v", self.proxLimit, last, sum-last, self.ProxBinSize, self) t.Errorf("proxLimit %v incorrect, redundant non-empty bucket %d added to proxBin with %v (target %v)\n%v", kad.proxLimit, last, sum-last, kad.ProxBinSize, kad)
return false return false
} }
if self.proxLimit > 0 && sum < self.ProxBinSize { if kad.proxLimit > 0 && sum < kad.ProxBinSize {
t.Errorf("proxLimit %v incorrect. proxSize %v is less than target %v, yet there is more peers", self.proxLimit, sum, self.ProxBinSize) t.Errorf("proxLimit %v incorrect. proxSize %v is less than target %v, yet there is more peers", kad.proxLimit, sum, kad.ProxBinSize)
return false return false
} }
} }

View file

@ -64,8 +64,8 @@ type statusMsgData struct {
NetworkId uint64 NetworkId uint64
} }
func (self *statusMsgData) String() string { func (data *statusMsgData) String() string {
return fmt.Sprintf("Status: Version: %v, ID: %v, Addr: %v, Swap: %v, NetworkId: %v", self.Version, self.ID, self.Addr, self.Swap, self.NetworkId) return fmt.Sprintf("Status: Version: %v, ID: %v, Addr: %v, Swap: %v, NetworkId: %v", data.Version, data.ID, data.Addr, data.Swap, data.NetworkId)
} }
/* /*
@ -86,18 +86,18 @@ type storeRequestMsgData struct {
from *peer // [not serialised] protocol registers the requester from *peer // [not serialised] protocol registers the requester
} }
func (self storeRequestMsgData) String() string { func (data storeRequestMsgData) String() string {
var from string var from string
if self.from == nil { if data.from == nil {
from = "self" from = "data"
} else { } else {
from = self.from.Addr().String() from = data.from.Addr().String()
} }
end := len(self.SData) end := len(data.SData)
if len(self.SData) > 10 { if len(data.SData) > 10 {
end = 10 end = 10
} }
return fmt.Sprintf("from: %v, Key: %v; ID: %v, requestTimeout: %v, storageTimeout: %v, SData %x", from, self.Key, self.Id, self.requestTimeout, self.storageTimeout, self.SData[:end]) return fmt.Sprintf("from: %v, Key: %v; ID: %v, requestTimeout: %v, storageTimeout: %v, SData %x", from, data.Key, data.Id, data.requestTimeout, data.storageTimeout, data.SData[:end])
} }
/* /*
@ -133,40 +133,40 @@ type retrieveRequestMsgData struct {
from *peer // from *peer //
} }
func (self *retrieveRequestMsgData) String() string { func (data *retrieveRequestMsgData) String() string {
var from string var from string
if self.from == nil { if data.from == nil {
from = "ourselves" from = "ourselves"
} else { } else {
from = self.from.Addr().String() from = data.from.Addr().String()
} }
var target []byte var target []byte
if len(self.Key) > 3 { if len(data.Key) > 3 {
target = self.Key[:4] target = data.Key[:4]
} }
return fmt.Sprintf("from: %v, Key: %x; ID: %v, MaxSize: %v, MaxPeers: %d", from, target, self.Id, self.MaxSize, self.MaxPeers) return fmt.Sprintf("from: %v, Key: %x; ID: %v, MaxSize: %v, MaxPeers: %d", from, target, data.Id, data.MaxSize, data.MaxPeers)
} }
// lookups are encoded by missing request ID // lookups are encoded by missing request ID
func (self *retrieveRequestMsgData) isLookup() bool { func (data *retrieveRequestMsgData) isLookup() bool {
return self.Id == 0 return data.Id == 0
} }
// sets timeout fields // sets timeout fields
func (self *retrieveRequestMsgData) setTimeout(t *time.Time) { func (data *retrieveRequestMsgData) setTimeout(t *time.Time) {
self.timeout = t data.timeout = t
if t != nil { if t != nil {
self.Timeout = uint64(t.UnixNano()) data.Timeout = uint64(t.UnixNano())
} else { } else {
self.Timeout = 0 data.Timeout = 0
} }
} }
func (self *retrieveRequestMsgData) getTimeout() (t *time.Time) { func (data *retrieveRequestMsgData) getTimeout() (t *time.Time) {
if self.Timeout > 0 && self.timeout == nil { if data.Timeout > 0 && data.timeout == nil {
timeout := time.Unix(int64(self.Timeout), 0) timeout := time.Unix(int64(data.Timeout), 0)
t = &timeout t = &timeout
self.timeout = t data.timeout = t
} }
return return
} }
@ -180,10 +180,10 @@ type peerAddr struct {
} }
// peerAddr pretty prints as enode // peerAddr pretty prints as enode
func (self *peerAddr) String() string { func (data *peerAddr) String() string {
var nodeid discover.NodeID var nodeid discover.NodeID
copy(nodeid[:], self.ID) copy(nodeid[:], data.ID)
return discover.NewNode(nodeid, self.IP, 0, self.Port).String() return discover.NewNode(nodeid, data.IP, 0, data.Port).String()
} }
/* /*
@ -199,7 +199,7 @@ the timeout or not.
NodeID serves as the owner of payment contracts and signer of proofs of transfer. NodeID serves as the owner of payment contracts and signer of proofs of transfer.
The Key is the target (if response to a retrieval request) or missing (zero value) The Key is the target (if response to a retrieval request) or missing (zero value)
peers address (hash of NodeID) if retrieval request was a self lookup. peers address (hash of NodeID) if retrieval request was a data lookup.
Peers message is requested by retrieval requests with a missing or zero value request ID Peers message is requested by retrieval requests with a missing or zero value request ID
*/ */
@ -213,26 +213,26 @@ type peersMsgData struct {
} }
// peers msg pretty printer // peers msg pretty printer
func (self *peersMsgData) String() string { func (data *peersMsgData) String() string {
var from string var from string
if self.from == nil { if data.from == nil {
from = "ourselves" from = "ourselves"
} else { } else {
from = self.from.Addr().String() from = data.from.Addr().String()
} }
var target []byte var target []byte
if len(self.Key) > 3 { if len(data.Key) > 3 {
target = self.Key[:4] target = data.Key[:4]
} }
return fmt.Sprintf("from: %v, Key: %x; ID: %v, Peers: %v", from, target, self.Id, self.Peers) return fmt.Sprintf("from: %v, Key: %x; ID: %v, Peers: %v", from, target, data.Id, data.Peers)
} }
func (self *peersMsgData) setTimeout(t *time.Time) { func (data *peersMsgData) setTimeout(t *time.Time) {
self.timeout = t data.timeout = t
if t != nil { if t != nil {
self.Timeout = uint64(t.UnixNano()) data.Timeout = uint64(t.UnixNano())
} else { } else {
self.Timeout = 0 data.Timeout = 0
} }
} }
@ -248,8 +248,8 @@ type syncRequestMsgData struct {
SyncState *syncState `rlp:"nil"` SyncState *syncState `rlp:"nil"`
} }
func (self *syncRequestMsgData) String() string { func (data *syncRequestMsgData) String() string {
return fmt.Sprintf("%v", self.SyncState) return fmt.Sprintf("%v", data.SyncState)
} }
/* /*
@ -265,8 +265,8 @@ type deliveryRequestMsgData struct {
Deliver []*syncRequest Deliver []*syncRequest
} }
func (self *deliveryRequestMsgData) String() string { func (data *deliveryRequestMsgData) String() string {
return fmt.Sprintf("sync request for new chunks\ndelivery request for %v chunks", len(self.Deliver)) return fmt.Sprintf("sync request for new chunks\ndelivery request for %v chunks", len(data.Deliver))
} }
/* /*
@ -287,8 +287,8 @@ type unsyncedKeysMsgData struct {
State *syncState State *syncState
} }
func (self *unsyncedKeysMsgData) String() string { func (data *unsyncedKeysMsgData) String() string {
return fmt.Sprintf("sync: keys of %d new chunks (state %v) => synced: %v", len(self.Unsynced), self.State, self.State.Synced) return fmt.Sprintf("sync: keys of %d new chunks (state %v) => synced: %v", len(data.Unsynced), data.State, data.State.Synced)
} }
/* /*
@ -303,6 +303,6 @@ type paymentMsgData struct {
Promise *chequebook.Cheque // payment with cheque Promise *chequebook.Cheque // payment with cheque
} }
func (self *paymentMsgData) String() string { func (data *paymentMsgData) String() string {
return fmt.Sprintf("payment for %d units: %v", self.Units, self.Promise) return fmt.Sprintf("payment for %d units: %v", data.Units, data.Promise)
} }

View file

@ -145,7 +145,7 @@ the main protocol loop that
*/ */
func run(requestDb *storage.LDBDatabase, depo StorageHandler, backend chequebook.Backend, hive *Hive, dbaccess *DbAccess, sp *bzzswap.SwapParams, sy *SyncParams, networkId uint64, p *p2p.Peer, rw p2p.MsgReadWriter) (err error) { func run(requestDb *storage.LDBDatabase, depo StorageHandler, backend chequebook.Backend, hive *Hive, dbaccess *DbAccess, sp *bzzswap.SwapParams, sy *SyncParams, networkId uint64, p *p2p.Peer, rw p2p.MsgReadWriter) (err error) {
self := &bzz{ b := &bzz{
storage: depo, storage: depo,
backend: backend, backend: backend,
hive: hive, hive: hive,
@ -161,30 +161,30 @@ func run(requestDb *storage.LDBDatabase, depo StorageHandler, backend chequebook
} }
// handle handshake // handle handshake
err = self.handleStatus() err = b.handleStatus()
if err != nil { if err != nil {
return err return err
} }
defer func() { defer func() {
// if the handler loop exits, the peer is disconnecting // if the handler loop exits, the peer is disconnecting
// deregister the peer in the hive // deregister the peer in the hive
self.hive.removePeer(&peer{bzz: self}) b.hive.removePeer(&peer{bzz: b})
if self.syncer != nil { if b.syncer != nil {
self.syncer.stop() // quits request db and delivery loops, save requests b.syncer.stop() // quits request db and delivery loops, save requests
} }
if self.swap != nil { if b.swap != nil {
self.swap.Stop() // quits chequebox autocash etc b.swap.Stop() // quits chequebox autocash etc
} }
}() }()
// the main forever loop that handles incoming requests // the main forever loop that handles incoming requests
for { for {
if self.hive.blockRead { if b.hive.blockRead {
log.Warn(fmt.Sprintf("Cannot read network")) log.Warn(fmt.Sprintf("Cannot read network"))
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
continue continue
} }
err = self.handle() err = b.handle()
if err != nil { if err != nil {
return return
} }
@ -193,13 +193,13 @@ func run(requestDb *storage.LDBDatabase, depo StorageHandler, backend chequebook
// TODO: may need to implement protocol drop only? don't want to kick off the peer // TODO: may need to implement protocol drop only? don't want to kick off the peer
// if they are useful for other protocols // if they are useful for other protocols
func (self *bzz) Drop() { func (b *bzz) Drop() {
self.peer.Disconnect(p2p.DiscSubprotocolError) b.peer.Disconnect(p2p.DiscSubprotocolError)
} }
// one cycle of the main forever loop that handles and dispatches incoming messages // one cycle of the main forever loop that handles and dispatches incoming messages
func (self *bzz) handle() error { func (b *bzz) handle() error {
msg, err := self.rw.ReadMsg() msg, err := b.rw.ReadMsg()
log.Debug(fmt.Sprintf("<- %v", msg)) log.Debug(fmt.Sprintf("<- %v", msg))
if err != nil { if err != nil {
return err return err
@ -229,10 +229,10 @@ func (self *bzz) handle() error {
return fmt.Errorf("<- %v: Data too short (%v)", msg, n) return fmt.Errorf("<- %v: Data too short (%v)", msg, n)
} }
// last Active time is set only when receiving chunks // last Active time is set only when receiving chunks
self.lastActive = time.Now() b.lastActive = time.Now()
log.Trace(fmt.Sprintf("incoming store request: %s", req.String())) log.Trace(fmt.Sprintf("incoming store request: %s", req.String()))
// swap accounting is done within forwarding // swap accounting is done within forwarding
self.storage.HandleStoreRequestMsg(&req, &peer{bzz: self}) b.storage.HandleStoreRequestMsg(&req, &peer{bzz: b})
case retrieveRequestMsg: case retrieveRequestMsg:
// retrieve Requests are dispatched to netStore // retrieve Requests are dispatched to netStore
@ -241,18 +241,18 @@ func (self *bzz) handle() error {
if err := msg.Decode(&req); err != nil { if err := msg.Decode(&req); err != nil {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
req.from = &peer{bzz: self} req.from = &peer{bzz: b}
// if request is lookup and not to be delivered // if request is lookup and not to be delivered
if req.isLookup() { if req.isLookup() {
log.Trace(fmt.Sprintf("self lookup for %v: responding with peers only...", req.from)) log.Trace(fmt.Sprintf("b lookup for %v: responding with peers only...", req.from))
} else if req.Key == nil { } else if req.Key == nil {
return fmt.Errorf("protocol handler: req.Key == nil || req.Timeout == nil") return fmt.Errorf("protocol handler: req.Key == nil || req.Timeout == nil")
} else { } else {
// swap accounting is done within netStore // swap accounting is done within netStore
self.storage.HandleRetrieveRequestMsg(&req, &peer{bzz: self}) b.storage.HandleRetrieveRequestMsg(&req, &peer{bzz: b})
} }
// direct response with peers, TODO: sort this out // direct response with peers, TODO: sort this out
self.hive.peers(&req) b.hive.peers(&req)
case peersMsg: case peersMsg:
// response to lookups and immediate response to retrieve requests // response to lookups and immediate response to retrieve requests
@ -262,9 +262,9 @@ func (self *bzz) handle() error {
if err := msg.Decode(&req); err != nil { if err := msg.Decode(&req); err != nil {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
req.from = &peer{bzz: self} req.from = &peer{bzz: b}
log.Trace(fmt.Sprintf("<- peer addresses: %v", req)) log.Trace(fmt.Sprintf("<- peer addresses: %v", req))
self.hive.HandlePeersMsg(&req, &peer{bzz: self}) b.hive.HandlePeersMsg(&req, &peer{bzz: b})
case syncRequestMsg: case syncRequestMsg:
syncRequestMsgCounter.Inc(1) syncRequestMsgCounter.Inc(1)
@ -273,8 +273,8 @@ func (self *bzz) handle() error {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
log.Debug(fmt.Sprintf("<- sync request: %v", req)) log.Debug(fmt.Sprintf("<- sync request: %v", req))
self.lastActive = time.Now() b.lastActive = time.Now()
self.sync(req.SyncState) b.sync(req.SyncState)
case unsyncedKeysMsg: case unsyncedKeysMsg:
// coming from parent node offering // coming from parent node offering
@ -284,8 +284,8 @@ func (self *bzz) handle() error {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
log.Debug(fmt.Sprintf("<- unsynced keys : %s", req.String())) log.Debug(fmt.Sprintf("<- unsynced keys : %s", req.String()))
err := self.storage.HandleUnsyncedKeysMsg(&req, &peer{bzz: self}) err := b.storage.HandleUnsyncedKeysMsg(&req, &peer{bzz: b})
self.lastActive = time.Now() b.lastActive = time.Now()
if err != nil { if err != nil {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
@ -299,8 +299,8 @@ func (self *bzz) handle() error {
return fmt.Errorf("<-msg %v: %v", msg, err) return fmt.Errorf("<-msg %v: %v", msg, err)
} }
log.Debug(fmt.Sprintf("<- delivery request: %s", req.String())) log.Debug(fmt.Sprintf("<- delivery request: %s", req.String()))
err := self.storage.HandleDeliveryRequestMsg(&req, &peer{bzz: self}) err := b.storage.HandleDeliveryRequestMsg(&req, &peer{bzz: b})
self.lastActive = time.Now() b.lastActive = time.Now()
if err != nil { if err != nil {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
@ -308,13 +308,13 @@ func (self *bzz) handle() error {
case paymentMsg: case paymentMsg:
// swap protocol message for payment, Units paid for, Cheque paid with // swap protocol message for payment, Units paid for, Cheque paid with
paymentMsgCounter.Inc(1) paymentMsgCounter.Inc(1)
if self.swapEnabled { if b.swapEnabled {
var req paymentMsgData var req paymentMsgData
if err := msg.Decode(&req); err != nil { if err := msg.Decode(&req); err != nil {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
log.Debug(fmt.Sprintf("<- payment: %s", req.String())) log.Debug(fmt.Sprintf("<- payment: %s", req.String()))
self.swap.Receive(int(req.Units), req.Promise) b.swap.Receive(int(req.Units), req.Promise)
} }
default: default:
@ -325,27 +325,27 @@ func (self *bzz) handle() error {
return nil return nil
} }
func (self *bzz) handleStatus() (err error) { func (b *bzz) handleStatus() (err error) {
handshake := &statusMsgData{ handshake := &statusMsgData{
Version: uint64(Version), Version: uint64(Version),
ID: "honey", ID: "honey",
Addr: self.selfAddr(), Addr: b.bAddr(),
NetworkId: self.NetworkId, NetworkId: b.NetworkId,
Swap: &bzzswap.SwapProfile{ Swap: &bzzswap.SwapProfile{
Profile: self.swapParams.Profile, Profile: b.swapParams.Profile,
PayProfile: self.swapParams.PayProfile, PayProfile: b.swapParams.PayProfile,
}, },
} }
err = p2p.Send(self.rw, statusMsg, handshake) err = p2p.Send(b.rw, statusMsg, handshake)
if err != nil { if err != nil {
return err return err
} }
// read and handle remote status // read and handle remote status
var msg p2p.Msg var msg p2p.Msg
msg, err = self.rw.ReadMsg() msg, err = b.rw.ReadMsg()
if err != nil { if err != nil {
return err return err
} }
@ -365,52 +365,52 @@ func (self *bzz) handleStatus() (err error) {
return fmt.Errorf("<- %v: %v", msg, err) return fmt.Errorf("<- %v: %v", msg, err)
} }
if status.NetworkId != self.NetworkId { if status.NetworkId != b.NetworkId {
return fmt.Errorf("network id mismatch: %d (!= %d)", status.NetworkId, self.NetworkId) return fmt.Errorf("network id mismatch: %d (!= %d)", status.NetworkId, b.NetworkId)
} }
if Version != status.Version { if Version != status.Version {
return fmt.Errorf("protocol version mismatch: %d (!= %d)", status.Version, Version) return fmt.Errorf("protocol version mismatch: %d (!= %d)", status.Version, Version)
} }
self.remoteAddr = self.peerAddr(status.Addr) b.remoteAddr = b.peerAddr(status.Addr)
log.Trace(fmt.Sprintf("self: advertised IP: %v, peer advertised: %v, local address: %v\npeer: advertised IP: %v, remote address: %v\n", self.selfAddr(), self.remoteAddr, self.peer.LocalAddr(), status.Addr.IP, self.peer.RemoteAddr())) log.Trace(fmt.Sprintf("b: advertised IP: %v, peer advertised: %v, local address: %v\npeer: advertised IP: %v, remote address: %v\n", b.bAddr(), b.remoteAddr, b.peer.LocalAddr(), status.Addr.IP, b.peer.RemoteAddr()))
if self.swapEnabled { if b.swapEnabled {
// set remote profile for accounting // set remote profile for accounting
self.swap, err = bzzswap.NewSwap(self.swapParams, status.Swap, self.backend, self) b.swap, err = bzzswap.NewSwap(b.swapParams, status.Swap, b.backend, b)
if err != nil { if err != nil {
return err return err
} }
} }
log.Info(fmt.Sprintf("Peer %08x is capable (%d/%d)", self.remoteAddr.Addr[:4], status.Version, status.NetworkId)) log.Info(fmt.Sprintf("Peer %08x is capable (%d/%d)", b.remoteAddr.Addr[:4], status.Version, status.NetworkId))
err = self.hive.addPeer(&peer{bzz: self}) err = b.hive.addPeer(&peer{bzz: b})
if err != nil { if err != nil {
return err return err
} }
// hive sets syncstate so sync should start after node added // hive sets syncstate so sync should start after node added
log.Info(fmt.Sprintf("syncronisation request sent with %v", self.syncState)) log.Info(fmt.Sprintf("syncronisation request sent with %v", b.syncState))
self.syncRequest() b.syncRequest()
return nil return nil
} }
func (self *bzz) sync(state *syncState) error { func (b *bzz) sync(state *syncState) error {
// syncer setup // syncer setup
if self.syncer != nil { if b.syncer != nil {
return errors.New("sync request can only be sent once") return errors.New("sync request can only be sent once")
} }
cnt := self.dbAccess.counter() cnt := b.dbAccess.counter()
remoteaddr := self.remoteAddr.Addr remoteaddr := b.remoteAddr.Addr
start, stop := self.hive.kad.KeyRange(remoteaddr) start, stop := b.hive.kad.KeyRange(remoteaddr)
// an explicitly received nil syncstate disables syncronisation // an explicitly received nil syncstate disables syncronisation
if state == nil { if state == nil {
self.syncEnabled = false b.syncEnabled = false
log.Warn(fmt.Sprintf("syncronisation disabled for peer %v", self)) log.Warn(fmt.Sprintf("syncronisation disabled for peer %v", b))
state = &syncState{DbSyncState: &storage.DbSyncState{}, Synced: true} state = &syncState{DbSyncState: &storage.DbSyncState{}, Synced: true}
} else { } else {
state.synced = make(chan bool) state.synced = make(chan bool)
@ -419,45 +419,45 @@ func (self *bzz) sync(state *syncState) error {
state.Start = storage.Key(start[:]) state.Start = storage.Key(start[:])
state.Stop = storage.Key(stop[:]) state.Stop = storage.Key(stop[:])
} }
log.Debug(fmt.Sprintf("syncronisation requested by peer %v at state %v", self, state)) log.Debug(fmt.Sprintf("syncronisation requested by peer %v at state %v", b, state))
} }
var err error var err error
self.syncer, err = newSyncer( b.syncer, err = newSyncer(
self.requestDb, b.requestDb,
storage.Key(remoteaddr[:]), storage.Key(remoteaddr[:]),
self.dbAccess, b.dbAccess,
self.unsyncedKeys, self.store, b.unsyncedKeys, b.store,
self.syncParams, state, func() bool { return self.syncEnabled }, b.syncParams, state, func() bool { return b.syncEnabled },
) )
if err != nil { if err != nil {
return nil return nil
} }
log.Trace(fmt.Sprintf("syncer set for peer %v", self)) log.Trace(fmt.Sprintf("syncer set for peer %v", b))
return nil return nil
} }
func (self *bzz) String() string { func (b *bzz) String() string {
return self.remoteAddr.String() return b.remoteAddr.String()
} }
// repair reported address if IP missing // repair reported address if IP missing
func (self *bzz) peerAddr(base *peerAddr) *peerAddr { func (b *bzz) peerAddr(base *peerAddr) *peerAddr {
if base.IP.IsUnspecified() { if base.IP.IsUnspecified() {
host, _, _ := net.SplitHostPort(self.peer.RemoteAddr().String()) host, _, _ := net.SplitHostPort(b.peer.RemoteAddr().String())
base.IP = net.ParseIP(host) base.IP = net.ParseIP(host)
} }
return base return base
} }
// returns self advertised node connection info (listening address w enodes) // returns b advertised node connection info (listening address w enodes)
// IP will get repaired on the other end if missing // IP will get repaired on the other end if missing
// or resolved via ID by discovery at dialout // or resolved via ID by discovery at dialout
func (self *bzz) selfAddr() *peerAddr { func (b *bzz) bAddr() *peerAddr {
id := self.hive.id id := b.hive.id
host, port, _ := net.SplitHostPort(self.hive.listenAddr()) host, port, _ := net.SplitHostPort(b.hive.listenAddr())
intport, _ := strconv.Atoi(port) intport, _ := strconv.Atoi(port)
addr := &peerAddr{ addr := &peerAddr{
Addr: self.hive.addr, Addr: b.hive.addr,
ID: id[:], ID: id[:],
IP: net.ParseIP(host), IP: net.ParseIP(host),
Port: uint16(intport), Port: uint16(intport),
@ -467,68 +467,68 @@ func (self *bzz) selfAddr() *peerAddr {
// outgoing messages // outgoing messages
// send retrieveRequestMsg // send retrieveRequestMsg
func (self *bzz) retrieve(req *retrieveRequestMsgData) error { func (b *bzz) retrieve(req *retrieveRequestMsgData) error {
return self.send(retrieveRequestMsg, req) return b.send(retrieveRequestMsg, req)
} }
// send storeRequestMsg // send storeRequestMsg
func (self *bzz) store(req *storeRequestMsgData) error { func (b *bzz) store(req *storeRequestMsgData) error {
return self.send(storeRequestMsg, req) return b.send(storeRequestMsg, req)
} }
func (self *bzz) syncRequest() error { func (b *bzz) syncRequest() error {
req := &syncRequestMsgData{} req := &syncRequestMsgData{}
if self.hive.syncEnabled { if b.hive.syncEnabled {
log.Debug(fmt.Sprintf("syncronisation request to peer %v at state %v", self, self.syncState)) log.Debug(fmt.Sprintf("syncronisation request to peer %v at state %v", b, b.syncState))
req.SyncState = self.syncState req.SyncState = b.syncState
} }
if self.syncState == nil { if b.syncState == nil {
log.Warn(fmt.Sprintf("syncronisation disabled for peer %v at state %v", self, self.syncState)) log.Warn(fmt.Sprintf("syncronisation disabled for peer %v at state %v", b, b.syncState))
} }
return self.send(syncRequestMsg, req) return b.send(syncRequestMsg, req)
} }
// queue storeRequestMsg in request db // queue storeRequestMsg in request db
func (self *bzz) deliveryRequest(reqs []*syncRequest) error { func (b *bzz) deliveryRequest(reqs []*syncRequest) error {
req := &deliveryRequestMsgData{ req := &deliveryRequestMsgData{
Deliver: reqs, Deliver: reqs,
} }
return self.send(deliveryRequestMsg, req) return b.send(deliveryRequestMsg, req)
} }
// batch of syncRequests to send off // batch of syncRequests to send off
func (self *bzz) unsyncedKeys(reqs []*syncRequest, state *syncState) error { func (b *bzz) unsyncedKeys(reqs []*syncRequest, state *syncState) error {
req := &unsyncedKeysMsgData{ req := &unsyncedKeysMsgData{
Unsynced: reqs, Unsynced: reqs,
State: state, State: state,
} }
return self.send(unsyncedKeysMsg, req) return b.send(unsyncedKeysMsg, req)
} }
// send paymentMsg // send paymentMsg
func (self *bzz) Pay(units int, promise swap.Promise) { func (b *bzz) Pay(units int, promise swap.Promise) {
req := &paymentMsgData{uint(units), promise.(*chequebook.Cheque)} req := &paymentMsgData{uint(units), promise.(*chequebook.Cheque)}
self.payment(req) b.payment(req)
} }
// send paymentMsg // send paymentMsg
func (self *bzz) payment(req *paymentMsgData) error { func (b *bzz) payment(req *paymentMsgData) error {
return self.send(paymentMsg, req) return b.send(paymentMsg, req)
} }
// sends peersMsg // sends peersMsg
func (self *bzz) peers(req *peersMsgData) error { func (b *bzz) peers(req *peersMsgData) error {
return self.send(peersMsg, req) return b.send(peersMsg, req)
} }
func (self *bzz) send(msg uint64, data interface{}) error { func (b *bzz) send(msg uint64, data interface{}) error {
if self.hive.blockWrite { if b.hive.blockWrite {
return fmt.Errorf("network write blocked") return fmt.Errorf("network write blocked")
} }
log.Trace(fmt.Sprintf("-> %v: %v (%T) to %v", msg, data, data, self)) log.Trace(fmt.Sprintf("-> %v: %v (%T) to %v", msg, data, data, b))
err := p2p.Send(self.rw, msg, data) err := p2p.Send(b.rw, msg, data)
if err != nil { if err != nil {
self.Drop() b.Drop()
} }
return err return err
} }

View file

@ -108,26 +108,26 @@ It is automatically started when syncdb is initialised.
It saves the buffer to db upon receiving quit signal. syncDb#stop() It saves the buffer to db upon receiving quit signal. syncDb#stop()
*/ */
func (self *syncDb) bufferRead(deliver func(interface{}, chan bool) bool) { func (db *syncDb) bufferRead(deliver func(interface{}, chan bool) bool) {
var buffer, db chan interface{} // channels representing the two read modes var buffer, dbChan chan interface{} // channels representing the two read modes
var more bool var more bool
var req interface{} var req interface{}
var entry *syncDbEntry var entry *syncDbEntry
var inBatch, inDb int var inBatch, inDb int
batch := new(leveldb.Batch) batch := new(leveldb.Batch)
var dbSize chan int var dbSize chan int
quit := self.quit quit := db.quit
counterValue := make([]byte, 8) counterValue := make([]byte, 8)
// counter is used for keeping the items in order, persisted to db // counter is used for keeping the items in order, persisted to db
// start counter where db was at, 0 if not found // start counter where db was at, 0 if not found
data, err := self.db.Get(self.counterKey) data, err := db.db.Get(db.counterKey)
var counter uint64 var counter uint64
if err == nil { if err == nil {
counter = binary.BigEndian.Uint64(data) counter = binary.BigEndian.Uint64(data)
log.Trace(fmt.Sprintf("syncDb[%v/%v] - counter read from db at %v", self.key.Log(), self.priority, counter)) log.Trace(fmt.Sprintf("syncDb[%v/%v] - counter read from db at %v", db.key.Log(), db.priority, counter))
} else { } else {
log.Trace(fmt.Sprintf("syncDb[%v/%v] - counter starts at %v", self.key.Log(), self.priority, counter)) log.Trace(fmt.Sprintf("syncDb[%v/%v] - counter starts at %v", db.key.Log(), db.priority, counter))
} }
LOOP: LOOP:
@ -139,58 +139,58 @@ LOOP:
// deliver request : this is blocking on network write so // deliver request : this is blocking on network write so
// it is passed the quit channel as argument, so that it returns // it is passed the quit channel as argument, so that it returns
// if syncdb is stopped. In this case we need to save the item to the db // if syncdb is stopped. In this case we need to save the item to the db
more = deliver(req, self.quit) more = deliver(req, db.quit)
if !more { if !more {
log.Debug(fmt.Sprintf("syncDb[%v/%v] quit: switching to db. session tally (db/total): %v/%v", self.key.Log(), self.priority, self.dbTotal, self.total)) log.Debug(fmt.Sprintf("syncDb[%v/%v] quit: switching to db. session tally (db/total): %v/%v", db.key.Log(), db.priority, db.dbTotal, db.total))
// received quit signal, save request currently waiting delivery // received quit signal, save request currently waiting delivery
// by switching to db mode and closing the buffer // by switching to db mode and closing the buffer
buffer = nil buffer = nil
db = self.buffer dbChan = db.buffer
close(db) close(dbChan)
quit = nil // needs to block the quit case in select quit = nil // needs to block the quit case in select
break // break from select, this item will be written to the db break // break from select, this item will be written to the db
} }
self.total++ db.total++
log.Trace(fmt.Sprintf("syncDb[%v/%v] deliver (db/total): %v/%v", self.key.Log(), self.priority, self.dbTotal, self.total)) log.Trace(fmt.Sprintf("syncDb[%v/%v] deliver (db/total): %v/%v", db.key.Log(), db.priority, db.dbTotal, db.total))
// by the time deliver returns, there were new writes to the buffer // by the time deliver returns, there were new writes to the buffer
// if buffer contention is detected, switch to db mode which drains // if buffer contention is detected, switch to db mode which drains
// the buffer so no process will block on pushing store requests // the buffer so no process will block on pushing store requests
if len(buffer) == cap(buffer) { if len(buffer) == cap(buffer) {
log.Debug(fmt.Sprintf("syncDb[%v/%v] buffer full %v: switching to db. session tally (db/total): %v/%v", self.key.Log(), self.priority, cap(buffer), self.dbTotal, self.total)) log.Debug(fmt.Sprintf("syncDb[%v/%v] buffer full %v: switching to db. session tally (db/total): %v/%v", db.key.Log(), db.priority, cap(buffer), db.dbTotal, db.total))
buffer = nil buffer = nil
db = self.buffer dbChan = db.buffer
} }
continue LOOP continue LOOP
// incoming entry to put into db // incoming entry to put into db
case req, more = <-db: case req, more = <-dbChan:
if !more { if !more {
// only if quit is called, saved all the buffer // only if quit is called, saved all the buffer
binary.BigEndian.PutUint64(counterValue, counter) binary.BigEndian.PutUint64(counterValue, counter)
batch.Put(self.counterKey, counterValue) // persist counter in batch batch.Put(db.counterKey, counterValue) // persist counter in batch
self.writeSyncBatch(batch) // save batch db.writeSyncBatch(batch) // save batch
log.Trace(fmt.Sprintf("syncDb[%v/%v] quitting: save current batch to db", self.key.Log(), self.priority)) log.Trace(fmt.Sprintf("syncDb[%v/%v] quitting: save current batch to db", db.key.Log(), db.priority))
break LOOP break LOOP
} }
self.dbTotal++ db.dbTotal++
self.total++ db.total++
// otherwise break after select // otherwise break after select
case dbSize = <-self.batch: case dbSize = <-db.batch:
// explicit request for batch // explicit request for batch
if inBatch == 0 && quit != nil { if inBatch == 0 && quit != nil {
// there was no writes since the last batch so db depleted // there was no writes since the last batch so db depleted
// switch to buffer mode // switch to buffer mode
log.Debug(fmt.Sprintf("syncDb[%v/%v] empty db: switching to buffer", self.key.Log(), self.priority)) log.Debug(fmt.Sprintf("syncDb[%v/%v] empty db: switching to buffer", db.key.Log(), db.priority))
db = nil dbChan = nil
buffer = self.buffer buffer = db.buffer
dbSize <- 0 // indicates to 'caller' that batch has been written dbSize <- 0 // indicates to 'caller' that batch has been written
inDb = 0 inDb = 0
continue LOOP continue LOOP
} }
binary.BigEndian.PutUint64(counterValue, counter) binary.BigEndian.PutUint64(counterValue, counter)
batch.Put(self.counterKey, counterValue) batch.Put(db.counterKey, counterValue)
log.Debug(fmt.Sprintf("syncDb[%v/%v] write batch %v/%v - %x - %x", self.key.Log(), self.priority, inBatch, counter, self.counterKey, counterValue)) log.Debug(fmt.Sprintf("syncDb[%v/%v] write batch %v/%v - %x - %x", db.key.Log(), db.priority, inBatch, counter, db.counterKey, counterValue))
batch = self.writeSyncBatch(batch) batch = db.writeSyncBatch(batch)
dbSize <- inBatch // indicates to 'caller' that batch has been written dbSize <- inBatch // indicates to 'caller' that batch has been written
inBatch = 0 inBatch = 0
continue LOOP continue LOOP
@ -198,45 +198,45 @@ LOOP:
// closing syncDb#quit channel is used to signal to all goroutines to quit // closing syncDb#quit channel is used to signal to all goroutines to quit
case <-quit: case <-quit:
// need to save backlog, so switch to db mode // need to save backlog, so switch to db mode
db = self.buffer dbChan = db.buffer
buffer = nil buffer = nil
quit = nil quit = nil
log.Trace(fmt.Sprintf("syncDb[%v/%v] quitting: save buffer to db", self.key.Log(), self.priority)) log.Trace(fmt.Sprintf("syncDb[%v/%v] quitting: save buffer to db", db.key.Log(), db.priority))
close(db) close(dbChan)
continue LOOP continue LOOP
} }
// only get here if we put req into db // only get here if we put req into db
entry, err = self.newSyncDbEntry(req, counter) entry, err = db.newSyncDbEntry(req, counter)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("syncDb[%v/%v] saving request %v (#%v/%v) failed: %v", self.key.Log(), self.priority, req, inBatch, inDb, err)) log.Warn(fmt.Sprintf("syncDb[%v/%v] saving request %v (#%v/%v) failed: %v", db.key.Log(), db.priority, req, inBatch, inDb, err))
continue LOOP continue LOOP
} }
batch.Put(entry.key, entry.val) batch.Put(entry.key, entry.val)
log.Trace(fmt.Sprintf("syncDb[%v/%v] to batch %v '%v' (#%v/%v/%v)", self.key.Log(), self.priority, req, entry, inBatch, inDb, counter)) log.Trace(fmt.Sprintf("syncDb[%v/%v] to batch %v '%v' (#%v/%v/%v)", db.key.Log(), db.priority, req, entry, inBatch, inDb, counter))
// if just switched to db mode and not quitting, then launch dbRead // if just switched to db mode and not quitting, then launch dbRead
// in a parallel go routine to send deliveries from db // in a parallel go routine to send deliveries from db
if inDb == 0 && quit != nil { if inDb == 0 && quit != nil {
log.Trace(fmt.Sprintf("syncDb[%v/%v] start dbRead", self.key.Log(), self.priority)) log.Trace(fmt.Sprintf("syncDb[%v/%v] start dbRead", db.key.Log(), db.priority))
go self.dbRead(true, counter, deliver) go db.dbRead(true, counter, deliver)
} }
inDb++ inDb++
inBatch++ inBatch++
counter++ counter++
// need to save the batch if it gets too large (== dbBatchSize) // need to save the batch if it gets too large (== dbBatchSize)
if inBatch%int(self.dbBatchSize) == 0 { if inBatch%int(db.dbBatchSize) == 0 {
batch = self.writeSyncBatch(batch) batch = db.writeSyncBatch(batch)
} }
} }
log.Info(fmt.Sprintf("syncDb[%v:%v]: saved %v keys (saved counter at %v)", self.key.Log(), self.priority, inBatch, counter)) log.Info(fmt.Sprintf("syncDb[%v:%v]: saved %v keys (saved counter at %v)", db.key.Log(), db.priority, inBatch, counter))
close(self.done) close(db.done)
} }
// writes the batch to the db and returns a new batch object // writes the batch to the db and returns a new batch object
func (self *syncDb) writeSyncBatch(batch *leveldb.Batch) *leveldb.Batch { func (db *syncDb) writeSyncBatch(batch *leveldb.Batch) *leveldb.Batch {
err := self.db.Write(batch) err := db.db.Write(batch)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("syncDb[%v/%v] saving batch to db failed: %v", self.key.Log(), self.priority, err)) log.Warn(fmt.Sprintf("syncDb[%v/%v] saving batch to db failed: %v", db.key.Log(), db.priority, err))
return batch return batch
} }
return new(leveldb.Batch) return new(leveldb.Batch)
@ -247,8 +247,8 @@ type syncDbEntry struct {
key, val []byte key, val []byte
} }
func (self syncDbEntry) String() string { func (entry syncDbEntry) String() string {
return fmt.Sprintf("key: %x, value: %x", self.key, self.val) return fmt.Sprintf("key: %x, value: %x", entry.key, entry.val)
} }
/* /*
@ -272,9 +272,9 @@ dbRead needs a boolean to indicate if on first round all the historical
record is synced. Second argument to indicate current db counter record is synced. Second argument to indicate current db counter
The third is the function to apply The third is the function to apply
*/ */
func (self *syncDb) dbRead(useBatches bool, counter uint64, fun func(interface{}, chan bool) bool) { func (db *syncDb) dbRead(useBatches bool, counter uint64, fun func(interface{}, chan bool) bool) {
key := make([]byte, 42) key := make([]byte, 42)
copy(key, self.start) copy(key, db.start)
binary.BigEndian.PutUint64(key[34:], counter) binary.BigEndian.PutUint64(key[34:], counter)
var batches, n, cnt, total int var batches, n, cnt, total int
var more bool var more bool
@ -290,8 +290,8 @@ func (self *syncDb) dbRead(useBatches bool, counter uint64, fun func(interface{}
// so that loop is not blocking while delivering // so that loop is not blocking while delivering
// only relevant if cnt is large // only relevant if cnt is large
select { select {
case self.batch <- batchSizes: case db.batch <- batchSizes:
case <-self.quit: case <-db.quit:
return return
} }
// wait for the write to finish and get the item count in the next batch // wait for the write to finish and get the item count in the next batch
@ -302,31 +302,31 @@ func (self *syncDb) dbRead(useBatches bool, counter uint64, fun func(interface{}
return return
} }
} }
it = self.db.NewIterator() it = db.db.NewIterator()
it.Seek(key) it.Seek(key)
if !it.Valid() { if !it.Valid() {
copy(key, self.start) copy(key, db.start)
useBatches = true useBatches = true
continue continue
} }
del = new(leveldb.Batch) del = new(leveldb.Batch)
log.Trace(fmt.Sprintf("syncDb[%v/%v]: new iterator: %x (batch %v, count %v)", self.key.Log(), self.priority, key, batches, cnt)) log.Trace(fmt.Sprintf("syncDb[%v/%v]: new iterator: %x (batch %v, count %v)", db.key.Log(), db.priority, key, batches, cnt))
for n = 0; !useBatches || n < cnt; it.Next() { for n = 0; !useBatches || n < cnt; it.Next() {
copy(key, it.Key()) copy(key, it.Key())
if len(key) == 0 || key[0] != 0 { if len(key) == 0 || key[0] != 0 {
copy(key, self.start) copy(key, db.start)
useBatches = true useBatches = true
break break
} }
val := make([]byte, 40) val := make([]byte, 40)
copy(val, it.Value()) copy(val, it.Value())
entry = &syncDbEntry{key, val} entry = &syncDbEntry{key, val}
// log.Trace(fmt.Sprintf("syncDb[%v/%v] - %v, batches: %v, total: %v, session total from db: %v/%v", self.key.Log(), self.priority, self.key.Log(), batches, total, self.dbTotal, self.total)) // log.Trace(fmt.Sprintf("syncDb[%v/%v] - %v, batches: %v, total: %v, session total from db: %v/%v", db.key.Log(), db.priority, db.key.Log(), batches, total, db.dbTotal, db.total))
more = fun(entry, self.quit) more = fun(entry, db.quit)
if !more { if !more {
// quit received when waiting to deliver entry, the entry will not be deleted // quit received when waiting to deliver entry, the entry will not be deleted
log.Trace(fmt.Sprintf("syncDb[%v/%v] batch %v quit after %v/%v items", self.key.Log(), self.priority, batches, n, cnt)) log.Trace(fmt.Sprintf("syncDb[%v/%v] batch %v quit after %v/%v items", db.key.Log(), db.priority, batches, n, cnt))
break break
} }
// since subsequent batches of the same db session are indexed incrementally // since subsequent batches of the same db session are indexed incrementally
@ -336,22 +336,22 @@ func (self *syncDb) dbRead(useBatches bool, counter uint64, fun func(interface{}
n++ n++
total++ total++
} }
log.Debug(fmt.Sprintf("syncDb[%v/%v] - db session closed, batches: %v, total: %v, session total from db: %v/%v", self.key.Log(), self.priority, batches, total, self.dbTotal, self.total)) log.Debug(fmt.Sprintf("syncDb[%v/%v] - db session closed, batches: %v, total: %v, session total from db: %v/%v", db.key.Log(), db.priority, batches, total, db.dbTotal, db.total))
self.db.Write(del) // this could be async called only when db is idle db.db.Write(del) // this could be async called only when db is idle
it.Release() it.Release()
} }
} }
// //
func (self *syncDb) stop() { func (db *syncDb) stop() {
close(self.quit) close(db.quit)
<-self.done <-db.done
} }
// calculate a dbkey for the request, for the db to work // calculate a dbkey for the request, for the db to work
// see syncdb for db key structure // see syncdb for db key structure
// polimorphic: accepted types, see syncer#addRequest // polimorphic: accepted types, see syncer#addRequest
func (self *syncDb) newSyncDbEntry(req interface{}, counter uint64) (entry *syncDbEntry, err error) { func (db *syncDb) newSyncDbEntry(req interface{}, counter uint64) (entry *syncDbEntry, err error) {
var key storage.Key var key storage.Key
var chunk *storage.Chunk var chunk *storage.Chunk
var id uint64 var id uint64
@ -377,7 +377,7 @@ func (self *syncDb) newSyncDbEntry(req interface{}, counter uint64) (entry *sync
dbval := make([]byte, 40) dbval := make([]byte, 40)
// encode key // encode key
copy(dbkey[:], self.start[:34]) // db peer copy(dbkey[:], db.start[:34]) // db peer
binary.BigEndian.PutUint64(dbkey[34:], counter) binary.BigEndian.PutUint64(dbkey[34:], counter)
// encode value // encode value
copy(dbval, key[:]) copy(dbval, key[:])

View file

@ -53,43 +53,43 @@ func newTestSyncDb(priority, bufferSize, batchSize int, dbdir string, t *testing
} }
dbdir = tmp dbdir = tmp
} }
db, err := storage.NewLDBDatabase(filepath.Join(dbdir, "requestdb")) database, err := storage.NewLDBDatabase(filepath.Join(dbdir, "requestdb"))
if err != nil { if err != nil {
t.Fatalf("unable to create db: %v", err) t.Fatalf("unable to create db: %v", err)
} }
self := &testSyncDb{ db := &testSyncDb{
fromDb: make(chan bool), fromDb: make(chan bool),
dbdir: dbdir, dbdir: dbdir,
t: t, t: t,
} }
h := crypto.Keccak256Hash([]byte{0}) h := crypto.Keccak256Hash([]byte{0})
key := storage.Key(h[:]) key := storage.Key(h[:])
self.syncDb = newSyncDb(db, key, uint(priority), uint(bufferSize), uint(batchSize), self.deliver) db.syncDb = newSyncDb(database, key, uint(priority), uint(bufferSize), uint(batchSize), db.deliver)
// kick off db iterator right away, if no items on db this will allow // kick off db iterator right away, if no items on db this will allow
// reading from the buffer // reading from the buffer
return self return db
} }
func (self *testSyncDb) close() { func (db *testSyncDb) close() {
self.db.Close() db.db.Close()
os.RemoveAll(self.dbdir) os.RemoveAll(db.dbdir)
} }
func (self *testSyncDb) push(n int) { func (db *testSyncDb) push(n int) {
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
self.buffer <- storage.Key(crypto.Keccak256([]byte{byte(self.c)})) db.buffer <- storage.Key(crypto.Keccak256([]byte{byte(db.c)}))
self.sent = append(self.sent, self.c) db.sent = append(db.sent, db.c)
self.c++ db.c++
} }
log.Debug(fmt.Sprintf("pushed %v requests", n)) log.Debug(fmt.Sprintf("pushed %v requests", n))
} }
func (self *testSyncDb) draindb() { func (db *testSyncDb) draindb() {
it := self.db.NewIterator() it := db.db.NewIterator()
defer it.Release() defer it.Release()
for { for {
it.Seek(self.start) it.Seek(db.start)
if !it.Valid() { if !it.Valid() {
return return
} }
@ -98,44 +98,44 @@ func (self *testSyncDb) draindb() {
return return
} }
it.Release() it.Release()
it = self.db.NewIterator() it = db.db.NewIterator()
} }
} }
func (self *testSyncDb) deliver(req interface{}, quit chan bool) bool { func (db *testSyncDb) deliver(req interface{}, quit chan bool) bool {
_, db := req.(*syncDbEntry) _, entry := req.(*syncDbEntry)
key, _, _, _, err := parseRequest(req) key, _, _, _, err := parseRequest(req)
if err != nil { if err != nil {
self.t.Fatalf("unexpected error of key %v: %v", key, err) db.t.Fatalf("unexpected error of key %v: %v", key, err)
} }
self.delivered = append(self.delivered, key) db.delivered = append(db.delivered, key)
select { select {
case self.fromDb <- db: case db.fromDb <- entry:
return true return true
case <-quit: case <-quit:
return false return false
} }
} }
func (self *testSyncDb) expect(n int, db bool) { func (db *testSyncDb) expect(n int, b bool) {
var ok bool var ok bool
// for n items // for n items
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
ok = <-self.fromDb ok = <-db.fromDb
if self.at+1 > len(self.delivered) { if db.at+1 > len(db.delivered) {
self.t.Fatalf("expected %v, got %v", self.at+1, len(self.delivered)) db.t.Fatalf("expected %v, got %v", db.at+1, len(db.delivered))
} }
if len(self.sent) > self.at && !bytes.Equal(crypto.Keccak256([]byte{byte(self.sent[self.at])}), self.delivered[self.at]) { if len(db.sent) > db.at && !bytes.Equal(crypto.Keccak256([]byte{byte(db.sent[db.at])}), db.delivered[db.at]) {
self.t.Fatalf("expected delivery %v/%v/%v to be hash of %v, from db: %v = %v", i, n, self.at, self.sent[self.at], ok, db) db.t.Fatalf("expected delivery %v/%v/%v to be hash of %v, from db: %v = %v", i, n, db.at, db.sent[db.at], ok, db)
log.Debug(fmt.Sprintf("%v/%v/%v to be hash of %v, from db: %v = %v", i, n, self.at, self.sent[self.at], ok, db)) log.Debug(fmt.Sprintf("%v/%v/%v to be hash of %v, from db: %v = %v", i, n, db.at, db.sent[db.at], ok, db))
} }
if !ok && db { if !ok && b {
self.t.Fatalf("expected delivery %v/%v/%v from db", i, n, self.at) db.t.Fatalf("expected delivery %v/%v/%v from db", i, n, db.at)
} }
if ok && !db { if ok && !b {
self.t.Fatalf("expected delivery %v/%v/%v from cache", i, n, self.at) db.t.Fatalf("expected delivery %v/%v/%v from cache", i, n, db.at)
} }
self.at++ db.at++
} }
} }

View file

@ -77,13 +77,13 @@ func NewDbAccess(loc *storage.LocalStore) *DbAccess {
} }
// to obtain the chunks from key or request db entry only // to obtain the chunks from key or request db entry only
func (self *DbAccess) get(key storage.Key) (*storage.Chunk, error) { func (access *DbAccess) get(key storage.Key) (*storage.Chunk, error) {
return self.loc.Get(key) return access.loc.Get(key)
} }
// current storage counter of chunk db // current storage counter of chunk db
func (self *DbAccess) counter() uint64 { func (access *DbAccess) counter() uint64 {
return self.db.Counter() return access.db.Counter()
} }
// implemented by dbStoreSyncIterator // implemented by dbStoreSyncIterator
@ -92,28 +92,28 @@ type keyIterator interface {
} }
// generator function for iteration by address range and storage counter // generator function for iteration by address range and storage counter
func (self *DbAccess) iterator(s *syncState) keyIterator { func (access *DbAccess) iterator(s *syncState) keyIterator {
it, err := self.db.NewSyncIterator(*(s.DbSyncState)) it, err := access.db.NewSyncIterator(*(s.DbSyncState))
if err != nil { if err != nil {
return nil return nil
} }
return keyIterator(it) return keyIterator(it)
} }
func (self syncState) String() string { func (state syncState) String() string {
if self.Synced { if state.Synced {
return fmt.Sprintf( return fmt.Sprintf(
"session started at: %v, last seen at: %v, latest key: %v", "session started at: %v, last seen at: %v, latest key: %v",
self.SessionAt, self.LastSeenAt, state.SessionAt, state.LastSeenAt,
self.Latest.Log(), state.Latest.Log(),
) )
} else { } else {
return fmt.Sprintf( return fmt.Sprintf(
"address: %v-%v, index: %v-%v, session started at: %v, last seen at: %v, latest key: %v", "address: %v-%v, index: %v-%v, session started at: %v, last seen at: %v, latest key: %v",
self.Start.Log(), self.Stop.Log(), state.Start.Log(), state.Stop.Log(),
self.First, self.Last, state.First, state.Last,
self.SessionAt, self.LastSeenAt, state.SessionAt, state.LastSeenAt,
self.Latest.Log(), state.Latest.Log(),
) )
} }
} }
@ -145,8 +145,8 @@ func NewDefaultSyncParams() *SyncParams {
//this can only finally be set after all config options (file, cmd line, env vars) //this can only finally be set after all config options (file, cmd line, env vars)
//have been evaluated //have been evaluated
func (self *SyncParams) Init(path string) { func (params *SyncParams) Init(path string) {
self.RequestDbPath = filepath.Join(path, "requests") params.RequestDbPath = filepath.Join(path, "requests")
} }
// syncer is the agent that manages content distribution/storage replication/chunk storeRequest forwarding // syncer is the agent that manages content distribution/storage replication/chunk storeRequest forwarding
@ -191,7 +191,7 @@ func newSyncer(
keyBufferSize := params.KeyBufferSize keyBufferSize := params.KeyBufferSize
dbBatchSize := params.RequestDbBatchSize dbBatchSize := params.RequestDbBatchSize
self := &syncer{ syncer := &syncer{
syncF: syncF, syncF: syncF,
key: remotekey, key: remotekey,
dbAccess: dbAccess, dbAccess: dbAccess,
@ -207,22 +207,22 @@ func newSyncer(
// initialising // initialising
for i := 0; i < priorities; i++ { for i := 0; i < priorities; i++ {
self.keys[i] = make(chan interface{}, keyBufferSize) syncer.keys[i] = make(chan interface{}, keyBufferSize)
self.deliveries[i] = make(chan *storeRequestMsgData) syncer.deliveries[i] = make(chan *storeRequestMsgData)
// initialise a syncdb instance for each priority queue // initialise a syncdb instance for each priority queue
self.queues[i] = newSyncDb(db, remotekey, uint(i), syncBufferSize, dbBatchSize, self.deliver(uint(i))) syncer.queues[i] = newSyncDb(db, remotekey, uint(i), syncBufferSize, dbBatchSize, syncer.deliver(uint(i)))
} }
log.Info(fmt.Sprintf("syncer started: %v", state)) log.Info(fmt.Sprintf("syncer started: %v", state))
// launch chunk delivery service // launch chunk delivery service
go self.syncDeliveries() go syncer.syncDeliveries()
// launch sync task manager // launch sync task manager
if self.syncF() { if syncer.syncF() {
go self.sync() go syncer.sync()
} }
// process unsynced keys to broadcast // process unsynced keys to broadcast
go self.syncUnsyncedKeys() go syncer.syncUnsyncedKeys()
return self, nil return syncer, nil
} }
// metadata serialisation // metadata serialisation
@ -266,21 +266,21 @@ func decodeSync(meta *json.RawMessage) (*syncState, error) {
sync is called from the syncer constructor and is not supposed to be used externally sync is called from the syncer constructor and is not supposed to be used externally
*/ */
func (self *syncer) sync() { func (s *syncer) sync() {
state := self.state state := s.state
// sync finished // sync finished
defer close(self.syncStates) defer close(s.syncStates)
// 0. first replay stale requests from request db // 0. first replay stale requests from request db
if state.SessionAt == 0 { if state.SessionAt == 0 {
log.Debug(fmt.Sprintf("syncer[%v]: nothing to sync", self.key.Log())) log.Debug(fmt.Sprintf("syncer[%v]: nothing to sync", s.key.Log()))
return return
} }
log.Debug(fmt.Sprintf("syncer[%v]: start replaying stale requests from request db", self.key.Log())) log.Debug(fmt.Sprintf("syncer[%v]: start replaying stale requests from request db", s.key.Log()))
for p := priorities - 1; p >= 0; p-- { for p := priorities - 1; p >= 0; p-- {
self.queues[p].dbRead(false, 0, self.replay()) s.queues[p].dbRead(false, 0, s.replay())
} }
log.Debug(fmt.Sprintf("syncer[%v]: done replaying stale requests from request db", self.key.Log())) log.Debug(fmt.Sprintf("syncer[%v]: done replaying stale requests from request db", s.key.Log()))
// unless peer is synced sync unfinished history beginning on // unless peer is synced sync unfinished history beginning on
if !state.Synced { if !state.Synced {
@ -289,9 +289,9 @@ func (self *syncer) sync() {
if !storage.IsZeroKey(state.Latest) { if !storage.IsZeroKey(state.Latest) {
// 1. there is unfinished earlier sync // 1. there is unfinished earlier sync
state.Start = state.Latest state.Start = state.Latest
log.Debug(fmt.Sprintf("syncer[%v]: start syncronising backlog (unfinished sync: %v)", self.key.Log(), state)) log.Debug(fmt.Sprintf("syncer[%v]: start syncronising backlog (unfinished sync: %v)", s.key.Log(), state))
// blocks while the entire history upto state is synced // blocks while the entire history upto state is synced
self.syncState(state) s.syncState(state)
if state.Last < state.SessionAt { if state.Last < state.SessionAt {
state.First = state.Last + 1 state.First = state.Last + 1
} }
@ -301,8 +301,8 @@ func (self *syncer) sync() {
// 2. sync up to last disconnect1 // 2. sync up to last disconnect1
if state.First < state.LastSeenAt { if state.First < state.LastSeenAt {
state.Last = state.LastSeenAt state.Last = state.LastSeenAt
log.Debug(fmt.Sprintf("syncer[%v]: start syncronising history upto last disconnect at %v: %v", self.key.Log(), state.LastSeenAt, state)) log.Debug(fmt.Sprintf("syncer[%v]: start syncronising history upto last disconnect at %v: %v", s.key.Log(), state.LastSeenAt, state))
self.syncState(state) s.syncState(state)
state.First = state.LastSeenAt state.First = state.LastSeenAt
} }
state.Latest = storage.ZeroKey state.Latest = storage.ZeroKey
@ -316,28 +316,28 @@ func (self *syncer) sync() {
// if there have been new chunks since last session // if there have been new chunks since last session
if state.LastSeenAt < state.SessionAt { if state.LastSeenAt < state.SessionAt {
state.Last = state.SessionAt state.Last = state.SessionAt
log.Debug(fmt.Sprintf("syncer[%v]: start syncronising history since last disconnect at %v up until session start at %v: %v", self.key.Log(), state.LastSeenAt, state.SessionAt, state)) log.Debug(fmt.Sprintf("syncer[%v]: start syncronising history since last disconnect at %v up until session start at %v: %v", s.key.Log(), state.LastSeenAt, state.SessionAt, state))
// blocks until state syncing is finished // blocks until state syncing is finished
self.syncState(state) s.syncState(state)
} }
log.Info(fmt.Sprintf("syncer[%v]: syncing all history complete", self.key.Log())) log.Info(fmt.Sprintf("syncer[%v]: syncing all history complete", s.key.Log()))
} }
// wait till syncronised block uptil state is synced // wait till syncronised block uptil state is synced
func (self *syncer) syncState(state *syncState) { func (s *syncer) syncState(state *syncState) {
self.syncStates <- state s.syncStates <- state
select { select {
case <-state.synced: case <-state.synced:
case <-self.quit: case <-s.quit:
} }
} }
// stop quits both request processor and saves the request cache to disk // stop quits both request processor and saves the request cache to disk
func (self *syncer) stop() { func (s *syncer) stop() {
close(self.quit) close(s.quit)
log.Trace(fmt.Sprintf("syncer[%v]: stop and save sync request db backlog", self.key.Log())) log.Trace(fmt.Sprintf("syncer[%v]: stop and save sync request db backlog", s.key.Log()))
for _, db := range self.queues { for _, db := range s.queues {
db.stop() db.stop()
} }
} }
@ -348,11 +348,11 @@ type syncRequest struct {
Priority uint Priority uint
} }
func (self *syncRequest) String() string { func (req *syncRequest) String() string {
return fmt.Sprintf("<Key: %v, Priority: %v>", self.Key.Log(), self.Priority) return fmt.Sprintf("<Key: %v, Priority: %v>", req.Key.Log(), req.Priority)
} }
func (self *syncer) newSyncRequest(req interface{}, p int) (*syncRequest, error) { func (s *syncer) newSyncRequest(req interface{}, p int) (*syncRequest, error) {
key, _, _, _, err := parseRequest(req) key, _, _, _, err := parseRequest(req)
// TODO: if req has chunk, it should be put in a cache // TODO: if req has chunk, it should be put in a cache
// create // create
@ -366,11 +366,11 @@ func (self *syncer) newSyncRequest(req interface{}, p int) (*syncRequest, error)
// * read is on demand, blocking unless history channel is read // * read is on demand, blocking unless history channel is read
// * accepts sync requests (syncStates) to create new db iterator // * accepts sync requests (syncStates) to create new db iterator
// * closes the channel one iteration finishes // * closes the channel one iteration finishes
func (self *syncer) syncHistory(state *syncState) chan interface{} { func (s *syncer) syncHistory(state *syncState) chan interface{} {
var n uint var n uint
history := make(chan interface{}) history := make(chan interface{})
log.Debug(fmt.Sprintf("syncer[%v]: syncing history between %v - %v for chunk addresses %v - %v", self.key.Log(), state.First, state.Last, state.Start, state.Stop)) log.Debug(fmt.Sprintf("syncer[%v]: syncing history between %v - %v for chunk addresses %v - %v", s.key.Log(), state.First, state.Last, state.Start, state.Stop))
it := self.dbAccess.iterator(state) it := s.dbAccess.iterator(state)
if it != nil { if it != nil {
go func() { go func() {
// signal end of the iteration ended // signal end of the iteration ended
@ -385,22 +385,22 @@ func (self *syncer) syncHistory(state *syncState) chan interface{} {
// blocking until history channel is read from // blocking until history channel is read from
case history <- key: case history <- key:
n++ n++
log.Trace(fmt.Sprintf("syncer[%v]: history: %v (%v keys)", self.key.Log(), key.Log(), n)) log.Trace(fmt.Sprintf("syncer[%v]: history: %v (%v keys)", s.key.Log(), key.Log(), n))
state.Latest = key state.Latest = key
case <-self.quit: case <-s.quit:
return return
} }
} }
log.Debug(fmt.Sprintf("syncer[%v]: finished syncing history between %v - %v for chunk addresses %v - %v (at %v) (chunks = %v)", self.key.Log(), state.First, state.Last, state.Start, state.Stop, state.Latest, n)) log.Debug(fmt.Sprintf("syncer[%v]: finished syncing history between %v - %v for chunk addresses %v - %v (at %v) (chunks = %v)", s.key.Log(), state.First, state.Last, state.Start, state.Stop, state.Latest, n))
}() }()
} }
return history return history
} }
// triggers key syncronisation // triggers key syncronisation
func (self *syncer) sendUnsyncedKeys() { func (s *syncer) sendUnsyncedKeys() {
select { select {
case self.deliveryRequest <- true: case s.deliveryRequest <- true:
default: default:
} }
} }
@ -411,7 +411,7 @@ func (self *syncer) sendUnsyncedKeys() {
// historical data is used so historical items are lower priority within // historical data is used so historical items are lower priority within
// their priority group. // their priority group.
// * Order of historical data is unspecified // * Order of historical data is unspecified
func (self *syncer) syncUnsyncedKeys() { func (s *syncer) syncUnsyncedKeys() {
// send out new // send out new
var unsynced []*syncRequest var unsynced []*syncRequest
var more, justSynced bool var more, justSynced bool
@ -419,12 +419,12 @@ func (self *syncer) syncUnsyncedKeys() {
var history chan interface{} var history chan interface{}
priority := High priority := High
keys := self.keys[priority] keys := s.keys[priority]
var newUnsyncedKeys, deliveryRequest chan bool var newUnsyncedKeys, deliveryRequest chan bool
keyCounts := make([]int, priorities) keyCounts := make([]int, priorities)
histPrior := self.SyncPriorities[HistoryReq] histPrior := s.SyncPriorities[HistoryReq]
syncStates := self.syncStates syncStates := s.syncStates
state := self.state state := s.state
LOOP: LOOP:
for { for {
@ -440,15 +440,15 @@ LOOP:
PRIORITIES: PRIORITIES:
for priority = High; priority >= 0; priority-- { for priority = High; priority >= 0; priority-- {
// the first priority channel that is non-empty will be assigned to keys // the first priority channel that is non-empty will be assigned to keys
if len(self.keys[priority]) > 0 { if len(s.keys[priority]) > 0 {
log.Trace(fmt.Sprintf("syncer[%v]: reading request with priority %v", self.key.Log(), priority)) log.Trace(fmt.Sprintf("syncer[%v]: reading request with priority %v", s.key.Log(), priority))
keys = self.keys[priority] keys = s.keys[priority]
break PRIORITIES break PRIORITIES
} }
log.Trace(fmt.Sprintf("syncer[%v/%v]: queue: [%v, %v, %v]", self.key.Log(), priority, len(self.keys[High]), len(self.keys[Medium]), len(self.keys[Low]))) log.Trace(fmt.Sprintf("syncer[%v/%v]: queue: [%v, %v, %v]", s.key.Log(), priority, len(s.keys[High]), len(s.keys[Medium]), len(s.keys[Low])))
// if the input queue is empty on this level, resort to history if there is any // if the input queue is empty on this level, resort to history if there is any
if uint(priority) == histPrior && history != nil { if uint(priority) == histPrior && history != nil {
log.Trace(fmt.Sprintf("syncer[%v]: reading history for %v", self.key.Log(), self.key)) log.Trace(fmt.Sprintf("syncer[%v]: reading history for %v", s.key.Log(), s.key))
keys = history keys = history
break PRIORITIES break PRIORITIES
} }
@ -458,8 +458,8 @@ LOOP:
// if peer ready to receive but nothing to send // if peer ready to receive but nothing to send
if keys == nil && deliveryRequest == nil { if keys == nil && deliveryRequest == nil {
// if no items left and switch to waiting mode // if no items left and switch to waiting mode
log.Trace(fmt.Sprintf("syncer[%v]: buffers consumed. Waiting", self.key.Log())) log.Trace(fmt.Sprintf("syncer[%v]: buffers consumed. Waiting", s.key.Log()))
newUnsyncedKeys = self.newUnsyncedKeys newUnsyncedKeys = s.newUnsyncedKeys
} }
// send msg iff // send msg iff
@ -470,48 +470,48 @@ LOOP:
if deliveryRequest == nil && if deliveryRequest == nil &&
(justSynced || (justSynced ||
len(unsynced) > 0 && keys == nil || len(unsynced) > 0 && keys == nil ||
len(unsynced) == int(self.SyncBatchSize)) { len(unsynced) == int(s.SyncBatchSize)) {
justSynced = false justSynced = false
// listen to requests // listen to requests
deliveryRequest = self.deliveryRequest deliveryRequest = s.deliveryRequest
newUnsyncedKeys = nil // not care about data until next req comes in newUnsyncedKeys = nil // not care about data until next req comes in
// set sync to current counter // set sync to current counter
// (all nonhistorical outgoing traffic sheduled and persisted // (all nonhistorical outgoing traffic sheduled and persisted
state.LastSeenAt = self.dbAccess.counter() state.LastSeenAt = s.dbAccess.counter()
state.Latest = storage.ZeroKey state.Latest = storage.ZeroKey
log.Trace(fmt.Sprintf("syncer[%v]: sending %v", self.key.Log(), unsynced)) log.Trace(fmt.Sprintf("syncer[%v]: sending %v", s.key.Log(), unsynced))
// send the unsynced keys // send the unsynced keys
stateCopy := *state stateCopy := *state
err := self.unsyncedKeys(unsynced, &stateCopy) err := s.unsyncedKeys(unsynced, &stateCopy)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("syncer[%v]: unable to send unsynced keys: %v", self.key.Log(), err)) log.Warn(fmt.Sprintf("syncer[%v]: unable to send unsynced keys: %v", s.key.Log(), err))
} }
self.state = state s.state = state
log.Debug(fmt.Sprintf("syncer[%v]: --> %v keys sent: (total: %v (%v), history: %v), sent sync state: %v", self.key.Log(), len(unsynced), keyCounts, keyCount, historyCnt, stateCopy)) log.Debug(fmt.Sprintf("syncer[%v]: --> %v keys sent: (total: %v (%v), history: %v), sent sync state: %v", s.key.Log(), len(unsynced), keyCounts, keyCount, historyCnt, stateCopy))
unsynced = nil unsynced = nil
keys = nil keys = nil
} }
// process item and add it to the batch // process item and add it to the batch
select { select {
case <-self.quit: case <-s.quit:
break LOOP break LOOP
case req, more = <-keys: case req, more = <-keys:
if keys == history && !more { if keys == history && !more {
log.Trace(fmt.Sprintf("syncer[%v]: syncing history segment complete", self.key.Log())) log.Trace(fmt.Sprintf("syncer[%v]: syncing history segment complete", s.key.Log()))
// history channel is closed, waiting for new state (called from sync()) // history channel is closed, waiting for new state (called from sync())
syncStates = self.syncStates syncStates = s.syncStates
state.Synced = true // this signals that the current segment is complete state.Synced = true // this signals that the current segment is complete
select { select {
case state.synced <- false: case state.synced <- false:
case <-self.quit: case <-s.quit:
break LOOP break LOOP
} }
justSynced = true justSynced = true
history = nil history = nil
} }
case <-deliveryRequest: case <-deliveryRequest:
log.Trace(fmt.Sprintf("syncer[%v]: peer ready to receive", self.key.Log())) log.Trace(fmt.Sprintf("syncer[%v]: peer ready to receive", s.key.Log()))
// this 1 cap channel can wake up the loop // this 1 cap channel can wake up the loop
// signaling that peer is ready to receive unsynced Keys // signaling that peer is ready to receive unsynced Keys
@ -519,23 +519,23 @@ LOOP:
deliveryRequest = nil deliveryRequest = nil
case <-newUnsyncedKeys: case <-newUnsyncedKeys:
log.Trace(fmt.Sprintf("syncer[%v]: new unsynced keys available", self.key.Log())) log.Trace(fmt.Sprintf("syncer[%v]: new unsynced keys available", s.key.Log()))
// this 1 cap channel can wake up the loop // this 1 cap channel can wake up the loop
// signals that data is available to send if peer is ready to receive // signals that data is available to send if peer is ready to receive
newUnsyncedKeys = nil newUnsyncedKeys = nil
keys = self.keys[High] keys = s.keys[High]
case state, more = <-syncStates: case state, more = <-syncStates:
// this resets the state // this resets the state
if !more { if !more {
state = self.state state = s.state
log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) syncing complete upto %v)", self.key.Log(), priority, state)) log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) syncing complete upto %v)", s.key.Log(), priority, state))
state.Synced = true state.Synced = true
syncStates = nil syncStates = nil
} else { } else {
log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) syncing history upto %v priority %v)", self.key.Log(), priority, state, histPrior)) log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) syncing history upto %v priority %v)", s.key.Log(), priority, state, histPrior))
state.Synced = false state.Synced = false
history = self.syncHistory(state) history = s.syncHistory(state)
// only one history at a time, only allow another one once the // only one history at a time, only allow another one once the
// history channel is closed // history channel is closed
syncStates = nil syncStates = nil
@ -545,19 +545,19 @@ LOOP:
continue LOOP continue LOOP
} }
log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) added to unsynced keys: %v", self.key.Log(), priority, req)) log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) added to unsynced keys: %v", s.key.Log(), priority, req))
keyCounts[priority]++ keyCounts[priority]++
keyCount++ keyCount++
if keys == history { if keys == history {
log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) history item %v (synced = %v)", self.key.Log(), priority, req, state.Synced)) log.Trace(fmt.Sprintf("syncer[%v]: (priority %v) history item %v (synced = %v)", s.key.Log(), priority, req, state.Synced))
historyCnt++ historyCnt++
} }
if sreq, err := self.newSyncRequest(req, priority); err == nil { if sreq, err := s.newSyncRequest(req, priority); err == nil {
// extract key from req // extract key from req
log.Trace(fmt.Sprintf("syncer[%v]: (priority %v): request %v (synced = %v)", self.key.Log(), priority, req, state.Synced)) log.Trace(fmt.Sprintf("syncer[%v]: (priority %v): request %v (synced = %v)", s.key.Log(), priority, req, state.Synced))
unsynced = append(unsynced, sreq) unsynced = append(unsynced, sreq)
} else { } else {
log.Warn(fmt.Sprintf("syncer[%v]: (priority %v): error creating request for %v: %v)", self.key.Log(), priority, req, err)) log.Warn(fmt.Sprintf("syncer[%v]: (priority %v): error creating request for %v: %v)", s.key.Log(), priority, req, err))
} }
} }
@ -566,7 +566,7 @@ LOOP:
// delivery loop // delivery loop
// takes into account priority, send store Requests with chunk (delivery) // takes into account priority, send store Requests with chunk (delivery)
// idle blocking if no new deliveries in any of the queues // idle blocking if no new deliveries in any of the queues
func (self *syncer) syncDeliveries() { func (s *syncer) syncDeliveries() {
var req *storeRequestMsgData var req *storeRequestMsgData
p := High p := High
var deliveries chan *storeRequestMsgData var deliveries chan *storeRequestMsgData
@ -577,7 +577,7 @@ func (self *syncer) syncDeliveries() {
var total, success uint var total, success uint
for { for {
deliveries = self.deliveries[p] deliveries = s.deliveries[p]
select { select {
case req = <-deliveries: case req = <-deliveries:
n[p]++ n[p]++
@ -586,13 +586,13 @@ func (self *syncer) syncDeliveries() {
if p == Low { if p == Low {
// blocking, depletion on all channels, no preference for priority // blocking, depletion on all channels, no preference for priority
select { select {
case req = <-self.deliveries[High]: case req = <-s.deliveries[High]:
n[High]++ n[High]++
case req = <-self.deliveries[Medium]: case req = <-s.deliveries[Medium]:
n[Medium]++ n[Medium]++
case req = <-self.deliveries[Low]: case req = <-s.deliveries[Low]:
n[Low]++ n[Low]++
case <-self.quit: case <-s.quit:
return return
} }
p = High p = High
@ -602,20 +602,20 @@ func (self *syncer) syncDeliveries() {
} }
} }
total++ total++
msg, err = self.newStoreRequestMsgData(req) msg, err = s.newStoreRequestMsgData(req)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("syncer[%v]: failed to create store request for %v: %v", self.key.Log(), req, err)) log.Warn(fmt.Sprintf("syncer[%v]: failed to create store request for %v: %v", s.key.Log(), req, err))
} else { } else {
err = self.store(msg) err = s.store(msg)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("syncer[%v]: failed to deliver %v: %v", self.key.Log(), req, err)) log.Warn(fmt.Sprintf("syncer[%v]: failed to deliver %v: %v", s.key.Log(), req, err))
} else { } else {
success++ success++
log.Trace(fmt.Sprintf("syncer[%v]: %v successfully delivered", self.key.Log(), req)) log.Trace(fmt.Sprintf("syncer[%v]: %v successfully delivered", s.key.Log(), req))
} }
} }
if total%self.SyncBatchSize == 0 { if total%s.SyncBatchSize == 0 {
log.Debug(fmt.Sprintf("syncer[%v]: deliver Total: %v, Success: %v, High: %v/%v, Medium: %v/%v, Low %v/%v", self.key.Log(), total, success, c[High], n[High], c[Medium], n[Medium], c[Low], n[Low])) log.Debug(fmt.Sprintf("syncer[%v]: deliver Total: %v, Success: %v, High: %v/%v, Medium: %v/%v, Low %v/%v", s.key.Log(), total, success, c[High], n[High], c[Medium], n[Medium], c[Low], n[Low]))
} }
} }
} }
@ -635,28 +635,28 @@ func (self *syncer) syncDeliveries() {
If sync mode is off then, requests are directly sent to deliveries If sync mode is off then, requests are directly sent to deliveries
*/ */
func (self *syncer) addRequest(req interface{}, ty int) { func (s *syncer) addRequest(req interface{}, ty int) {
// retrieve priority for request type name int8 // retrieve priority for request type name int8
priority := self.SyncPriorities[ty] priority := s.SyncPriorities[ty]
// sync mode for this type ON // sync mode for this type ON
if self.syncF() || ty == DeliverReq { if s.syncF() || ty == DeliverReq {
if self.SyncModes[ty] { if s.SyncModes[ty] {
self.addKey(req, priority, self.quit) s.addKey(req, priority, s.quit)
} else { } else {
self.addDelivery(req, priority, self.quit) s.addDelivery(req, priority, s.quit)
} }
} }
} }
// addKey queues sync request for sync confirmation with given priority // addKey queues sync request for sync confirmation with given priority
// ie the key will go out in an unsyncedKeys message // ie the key will go out in an unsyncedKeys message
func (self *syncer) addKey(req interface{}, priority uint, quit chan bool) bool { func (s *syncer) addKey(req interface{}, priority uint, quit chan bool) bool {
select { select {
case self.keys[priority] <- req: case s.keys[priority] <- req:
// this wakes up the unsynced keys loop if idle // this wakes up the unsynced keys loop if idle
select { select {
case self.newUnsyncedKeys <- true: case s.newUnsyncedKeys <- true:
default: default:
} }
return true return true
@ -668,9 +668,9 @@ func (self *syncer) addKey(req interface{}, priority uint, quit chan bool) bool
// addDelivery queues delivery request for with given priority // addDelivery queues delivery request for with given priority
// ie the chunk will be delivered ASAP mod priority queueing handled by syncdb // ie the chunk will be delivered ASAP mod priority queueing handled by syncdb
// requests are persisted across sessions for correct sync // requests are persisted across sessions for correct sync
func (self *syncer) addDelivery(req interface{}, priority uint, quit chan bool) bool { func (s *syncer) addDelivery(req interface{}, priority uint, quit chan bool) bool {
select { select {
case self.queues[priority].buffer <- req: case s.queues[priority].buffer <- req:
return true return true
case <-quit: case <-quit:
return false return false
@ -679,14 +679,14 @@ func (self *syncer) addDelivery(req interface{}, priority uint, quit chan bool)
// doDelivery delivers the chunk for the request with given priority // doDelivery delivers the chunk for the request with given priority
// without queuing // without queuing
func (self *syncer) doDelivery(req interface{}, priority uint, quit chan bool) bool { func (s *syncer) doDelivery(req interface{}, priority uint, quit chan bool) bool {
msgdata, err := self.newStoreRequestMsgData(req) msgdata, err := s.newStoreRequestMsgData(req)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("unable to deliver request %v: %v", msgdata, err)) log.Warn(fmt.Sprintf("unable to deliver request %v: %v", msgdata, err))
return false return false
} }
select { select {
case self.deliveries[priority] <- msgdata: case s.deliveries[priority] <- msgdata:
return true return true
case <-quit: case <-quit:
return false return false
@ -695,9 +695,9 @@ func (self *syncer) doDelivery(req interface{}, priority uint, quit chan bool) b
// returns the delivery function for given priority // returns the delivery function for given priority
// passed on to syncDb // passed on to syncDb
func (self *syncer) deliver(priority uint) func(req interface{}, quit chan bool) bool { func (s *syncer) deliver(priority uint) func(req interface{}, quit chan bool) bool {
return func(req interface{}, quit chan bool) bool { return func(req interface{}, quit chan bool) bool {
return self.doDelivery(req, priority, quit) return s.doDelivery(req, priority, quit)
} }
} }
@ -705,17 +705,17 @@ func (self *syncer) deliver(priority uint) func(req interface{}, quit chan bool)
// depending on sync mode settings for BacklogReq, // depending on sync mode settings for BacklogReq,
// re play of request db backlog sends items via confirmation // re play of request db backlog sends items via confirmation
// or directly delivers // or directly delivers
func (self *syncer) replay() func(req interface{}, quit chan bool) bool { func (s *syncer) replay() func(req interface{}, quit chan bool) bool {
sync := self.SyncModes[BacklogReq] sync := s.SyncModes[BacklogReq]
priority := self.SyncPriorities[BacklogReq] priority := s.SyncPriorities[BacklogReq]
// sync mode for this type ON // sync mode for this type ON
if sync { if sync {
return func(req interface{}, quit chan bool) bool { return func(req interface{}, quit chan bool) bool {
return self.addKey(req, priority, quit) return s.addKey(req, priority, quit)
} }
} else { } else {
return func(req interface{}, quit chan bool) bool { return func(req interface{}, quit chan bool) bool {
return self.doDelivery(req, priority, quit) return s.doDelivery(req, priority, quit)
} }
} }
@ -723,7 +723,7 @@ func (self *syncer) replay() func(req interface{}, quit chan bool) bool {
// given a request, extends it to a full storeRequestMsgData // given a request, extends it to a full storeRequestMsgData
// polimorphic: see addRequest for the types accepted // polimorphic: see addRequest for the types accepted
func (self *syncer) newStoreRequestMsgData(req interface{}) (*storeRequestMsgData, error) { func (s *syncer) newStoreRequestMsgData(req interface{}) (*storeRequestMsgData, error) {
key, id, chunk, sreq, err := parseRequest(req) key, id, chunk, sreq, err := parseRequest(req)
if err != nil { if err != nil {
@ -733,7 +733,7 @@ func (self *syncer) newStoreRequestMsgData(req interface{}) (*storeRequestMsgDat
if sreq == nil { if sreq == nil {
if chunk == nil { if chunk == nil {
var err error var err error
chunk, err = self.dbAccess.get(key) chunk, err = s.dbAccess.get(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -104,10 +104,10 @@ func NewDefaultSwapParams() *SwapParams {
//this can only finally be set after all config options (file, cmd line, env vars) //this can only finally be set after all config options (file, cmd line, env vars)
//have been evaluated //have been evaluated
func (self *SwapParams) Init(contract common.Address, prvkey *ecdsa.PrivateKey) { func (params *SwapParams) Init(contract common.Address, prvkey *ecdsa.PrivateKey) {
pubkey := &prvkey.PublicKey pubkey := &prvkey.PublicKey
self.PayProfile = &PayProfile{ params.PayProfile = &PayProfile{
PublicKey: common.ToHex(crypto.FromECDSAPub(pubkey)), PublicKey: common.ToHex(crypto.FromECDSAPub(pubkey)),
Contract: contract, Contract: contract,
Beneficiary: crypto.PubkeyToAddress(*pubkey), Beneficiary: crypto.PubkeyToAddress(*pubkey),
@ -126,7 +126,7 @@ func (self *SwapParams) Init(contract common.Address, prvkey *ecdsa.PrivateKey)
// n < 0 called when receiving chunks = receiving delivery responses // n < 0 called when receiving chunks = receiving delivery responses
// OR receiving cheques. // OR receiving cheques.
func NewSwap(local *SwapParams, remote *SwapProfile, backend chequebook.Backend, proto swap.Protocol) (self *swap.Swap, err error) { func NewSwap(local *SwapParams, remote *SwapProfile, backend chequebook.Backend, proto swap.Protocol) (s *swap.Swap, err error) {
var ( var (
ctx = context.TODO() ctx = context.TODO()
ok bool ok bool
@ -162,19 +162,19 @@ func NewSwap(local *SwapParams, remote *SwapProfile, backend chequebook.Backend,
Buys: out != nil, Buys: out != nil,
Sells: in != nil, Sells: in != nil,
} }
self, err = swap.New(local.Params, pm, proto) s, err = swap.New(local.Params, pm, proto)
if err != nil { if err != nil {
return return
} }
// remote profile given (first) in handshake // remote profile given (first) in handshake
self.SetRemote(remote.Profile) s.SetRemote(remote.Profile)
var buy, sell string var buy, sell string
if self.Buys { if s.Buys {
buy = "purchase from peer enabled at " + remote.SellAt.String() + " wei/chunk" buy = "purchase from peer enabled at " + remote.SellAt.String() + " wei/chunk"
} else { } else {
buy = "purchase from peer disabled" buy = "purchase from peer disabled"
} }
if self.Sells { if s.Sells {
sell = "selling to peer enabled at " + local.SellAt.String() + " wei/chunk" sell = "selling to peer enabled at " + local.SellAt.String() + " wei/chunk"
} else { } else {
sell = "selling to peer disabled" sell = "selling to peer disabled"
@ -184,44 +184,44 @@ func NewSwap(local *SwapParams, remote *SwapProfile, backend chequebook.Backend,
return return
} }
func (self *SwapParams) Chequebook() *chequebook.Chequebook { func (params *SwapParams) Chequebook() *chequebook.Chequebook {
defer self.lock.Unlock() defer params.lock.Unlock()
self.lock.Lock() params.lock.Lock()
return self.chbook return params.chbook
} }
func (self *SwapParams) PrivateKey() *ecdsa.PrivateKey { func (params *SwapParams) PrivateKey() *ecdsa.PrivateKey {
return self.privateKey return params.privateKey
} }
// func (self *SwapParams) PublicKey() *ecdsa.PublicKey { // func (params *SwapParams) PublicKey() *ecdsa.PublicKey {
// return self.publicKey // return params.publicKey
// } // }
func (self *SwapParams) SetKey(prvkey *ecdsa.PrivateKey) { func (params *SwapParams) SetKey(prvkey *ecdsa.PrivateKey) {
self.privateKey = prvkey params.privateKey = prvkey
self.publicKey = &prvkey.PublicKey params.publicKey = &prvkey.PublicKey
} }
// setChequebook(path, backend) wraps the // setChequebook(path, backend) wraps the
// chequebook initialiser and sets up autoDeposit to cover spending. // chequebook initialiser and sets up autoDeposit to cover spending.
func (self *SwapParams) SetChequebook(ctx context.Context, backend chequebook.Backend, path string) error { func (params *SwapParams) SetChequebook(ctx context.Context, backend chequebook.Backend, path string) error {
self.lock.Lock() params.lock.Lock()
contract := self.Contract contract := params.Contract
self.lock.Unlock() params.lock.Unlock()
valid, err := chequebook.ValidateCode(ctx, backend, contract) valid, err := chequebook.ValidateCode(ctx, backend, contract)
if err != nil { if err != nil {
return err return err
} else if valid { } else if valid {
return self.newChequebookFromContract(path, backend) return params.newChequebookFromContract(path, backend)
} }
return self.deployChequebook(ctx, backend, path) return params.deployChequebook(ctx, backend, path)
} }
func (self *SwapParams) deployChequebook(ctx context.Context, backend chequebook.Backend, path string) error { func (params *SwapParams) deployChequebook(ctx context.Context, backend chequebook.Backend, path string) error {
opts := bind.NewKeyedTransactor(self.privateKey) opts := bind.NewKeyedTransactor(params.privateKey)
opts.Value = self.AutoDepositBuffer opts.Value = params.AutoDepositBuffer
opts.Context = ctx opts.Context = ctx
log.Info(fmt.Sprintf("Deploying new chequebook (owner: %v)", opts.From.Hex())) log.Info(fmt.Sprintf("Deploying new chequebook (owner: %v)", opts.From.Hex()))
@ -233,10 +233,10 @@ func (self *SwapParams) deployChequebook(ctx context.Context, backend chequebook
log.Info(fmt.Sprintf("new chequebook deployed at %v (owner: %v)", contract.Hex(), opts.From.Hex())) log.Info(fmt.Sprintf("new chequebook deployed at %v (owner: %v)", contract.Hex(), opts.From.Hex()))
// need to save config at this point // need to save config at this point
self.lock.Lock() params.lock.Lock()
self.Contract = contract params.Contract = contract
err = self.newChequebookFromContract(path, backend) err = params.newChequebookFromContract(path, backend)
self.lock.Unlock() params.lock.Unlock()
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("error initialising cheque book (owner: %v): %v", opts.From.Hex(), err)) log.Warn(fmt.Sprintf("error initialising cheque book (owner: %v): %v", opts.From.Hex(), err))
} }
@ -265,26 +265,26 @@ func deployChequebookLoop(opts *bind.TransactOpts, backend chequebook.Backend) (
// initialise the chequebook from a persisted json file or create a new one // initialise the chequebook from a persisted json file or create a new one
// caller holds the lock // caller holds the lock
func (self *SwapParams) newChequebookFromContract(path string, backend chequebook.Backend) error { func (params *SwapParams) newChequebookFromContract(path string, backend chequebook.Backend) error {
hexkey := common.Bytes2Hex(self.Contract.Bytes()) hexkey := common.Bytes2Hex(params.Contract.Bytes())
err := os.MkdirAll(filepath.Join(path, "chequebooks"), os.ModePerm) err := os.MkdirAll(filepath.Join(path, "chequebooks"), os.ModePerm)
if err != nil { if err != nil {
return fmt.Errorf("unable to create directory for chequebooks: %v", err) return fmt.Errorf("unable to create directory for chequebooks: %v", err)
} }
chbookpath := filepath.Join(path, "chequebooks", hexkey+".json") chbookpath := filepath.Join(path, "chequebooks", hexkey+".json")
self.chbook, err = chequebook.LoadChequebook(chbookpath, self.privateKey, backend, true) params.chbook, err = chequebook.LoadChequebook(chbookpath, params.privateKey, backend, true)
if err != nil { if err != nil {
self.chbook, err = chequebook.NewChequebook(chbookpath, self.Contract, self.privateKey, backend) params.chbook, err = chequebook.NewChequebook(chbookpath, params.Contract, params.privateKey, backend)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("unable to initialise chequebook (owner: %v): %v", self.owner.Hex(), err)) log.Warn(fmt.Sprintf("unable to initialise chequebook (owner: %v): %v", params.owner.Hex(), err))
return fmt.Errorf("unable to initialise chequebook (owner: %v): %v", self.owner.Hex(), err) return fmt.Errorf("unable to initialise chequebook (owner: %v): %v", params.owner.Hex(), err)
} }
} }
self.chbook.AutoDeposit(self.AutoDepositInterval, self.AutoDepositThreshold, self.AutoDepositBuffer) params.chbook.AutoDeposit(params.AutoDepositInterval, params.AutoDepositThreshold, params.AutoDepositBuffer)
log.Info(fmt.Sprintf("auto deposit ON for %v -> %v: interval = %v, threshold = %v, buffer = %v)", crypto.PubkeyToAddress(*(self.publicKey)).Hex()[:8], self.Contract.Hex()[:8], self.AutoDepositInterval, self.AutoDepositThreshold, self.AutoDepositBuffer)) log.Info(fmt.Sprintf("auto deposit ON for %v -> %v: interval = %v, threshold = %v, buffer = %v)", crypto.PubkeyToAddress(*(params.publicKey)).Hex()[:8], params.Contract.Hex()[:8], params.AutoDepositInterval, params.AutoDepositThreshold, params.AutoDepositBuffer))
return nil return nil
} }

View file

@ -100,153 +100,153 @@ type Payment struct {
} }
// swap constructor // swap constructor
func New(local *Params, pm Payment, proto Protocol) (self *Swap, err error) { func New(local *Params, pm Payment, proto Protocol) (s *Swap, err error) {
self = &Swap{ s = &Swap{
local: local, local: local,
Payment: pm, Payment: pm,
proto: proto, proto: proto,
} }
self.SetParams(local) s.SetParams(local)
return return
} }
// entry point for setting remote swap profile (e.g from handshake or other message) // entry point for setting remote swap profile (e.g from handshake or other message)
func (self *Swap) SetRemote(remote *Profile) { func (s *Swap) SetRemote(remote *Profile) {
defer self.lock.Unlock() defer s.lock.Unlock()
self.lock.Lock() s.lock.Lock()
self.remote = remote s.remote = remote
if self.Sells && (remote.BuyAt.Sign() <= 0 || self.local.SellAt.Sign() <= 0 || remote.BuyAt.Cmp(self.local.SellAt) < 0) { if s.Sells && (remote.BuyAt.Sign() <= 0 || s.local.SellAt.Sign() <= 0 || remote.BuyAt.Cmp(s.local.SellAt) < 0) {
self.Out.Stop() s.Out.Stop()
self.Sells = false s.Sells = false
} }
if self.Buys && (remote.SellAt.Sign() <= 0 || self.local.BuyAt.Sign() <= 0 || self.local.BuyAt.Cmp(self.remote.SellAt) < 0) { if s.Buys && (remote.SellAt.Sign() <= 0 || s.local.BuyAt.Sign() <= 0 || s.local.BuyAt.Cmp(s.remote.SellAt) < 0) {
self.In.Stop() s.In.Stop()
self.Buys = false s.Buys = false
} }
log.Debug(fmt.Sprintf("<%v> remote profile set: pay at: %v, drop at: %v, buy at: %v, sell at: %v", self.proto, remote.PayAt, remote.DropAt, remote.BuyAt, remote.SellAt)) log.Debug(fmt.Sprintf("<%v> remote profile set: pay at: %v, drop at: %v, buy at: %v, sell at: %v", s.proto, remote.PayAt, remote.DropAt, remote.BuyAt, remote.SellAt))
} }
// to set strategy dynamically // to set strategy dynamically
func (self *Swap) SetParams(local *Params) { func (s *Swap) SetParams(local *Params) {
defer self.lock.Unlock() defer s.lock.Unlock()
self.lock.Lock() s.lock.Lock()
self.local = local s.local = local
self.setParams(local) s.setParams(local)
} }
// caller holds the lock // caller holds the lock
func (self *Swap) setParams(local *Params) { func (s *Swap) setParams(local *Params) {
if self.Sells { if s.Sells {
self.In.AutoCash(local.AutoCashInterval, local.AutoCashThreshold) s.In.AutoCash(local.AutoCashInterval, local.AutoCashThreshold)
log.Info(fmt.Sprintf("<%v> set autocash to every %v, max uncashed limit: %v", self.proto, local.AutoCashInterval, local.AutoCashThreshold)) log.Info(fmt.Sprintf("<%v> set autocash to every %v, max uncashed limit: %v", s.proto, local.AutoCashInterval, local.AutoCashThreshold))
} else { } else {
log.Info(fmt.Sprintf("<%v> autocash off (not selling)", self.proto)) log.Info(fmt.Sprintf("<%v> autocash off (not selling)", s.proto))
} }
if self.Buys { if s.Buys {
self.Out.AutoDeposit(local.AutoDepositInterval, local.AutoDepositThreshold, local.AutoDepositBuffer) s.Out.AutoDeposit(local.AutoDepositInterval, local.AutoDepositThreshold, local.AutoDepositBuffer)
log.Info(fmt.Sprintf("<%v> set autodeposit to every %v, pay at: %v, buffer: %v", self.proto, local.AutoDepositInterval, local.AutoDepositThreshold, local.AutoDepositBuffer)) log.Info(fmt.Sprintf("<%v> set autodeposit to every %v, pay at: %v, buffer: %v", s.proto, local.AutoDepositInterval, local.AutoDepositThreshold, local.AutoDepositBuffer))
} else { } else {
log.Info(fmt.Sprintf("<%v> autodeposit off (not buying)", self.proto)) log.Info(fmt.Sprintf("<%v> autodeposit off (not buying)", s.proto))
} }
} }
// Add(n) // Add(n)
// n > 0 called when promised/provided n units of service // n > 0 called when promised/provided n units of service
// n < 0 called when used/requested n units of service // n < 0 called when used/requested n units of service
func (self *Swap) Add(n int) error { func (s *Swap) Add(n int) error {
defer self.lock.Unlock() defer s.lock.Unlock()
self.lock.Lock() s.lock.Lock()
self.balance += n s.balance += n
if !self.Sells && self.balance > 0 { if !s.Sells && s.balance > 0 {
log.Trace(fmt.Sprintf("<%v> remote peer cannot have debt (balance: %v)", self.proto, self.balance)) log.Trace(fmt.Sprintf("<%v> remote peer cannot have debt (balance: %v)", s.proto, s.balance))
self.proto.Drop() s.proto.Drop()
return fmt.Errorf("[SWAP] <%v> remote peer cannot have debt (balance: %v)", self.proto, self.balance) return fmt.Errorf("[SWAP] <%v> remote peer cannot have debt (balance: %v)", s.proto, s.balance)
} }
if !self.Buys && self.balance < 0 { if !s.Buys && s.balance < 0 {
log.Trace(fmt.Sprintf("<%v> we cannot have debt (balance: %v)", self.proto, self.balance)) log.Trace(fmt.Sprintf("<%v> we cannot have debt (balance: %v)", s.proto, s.balance))
return fmt.Errorf("[SWAP] <%v> we cannot have debt (balance: %v)", self.proto, self.balance) return fmt.Errorf("[SWAP] <%v> we cannot have debt (balance: %v)", s.proto, s.balance)
} }
if self.balance >= int(self.local.DropAt) { if s.balance >= int(s.local.DropAt) {
log.Trace(fmt.Sprintf("<%v> remote peer has too much debt (balance: %v, disconnect threshold: %v)", self.proto, self.balance, self.local.DropAt)) log.Trace(fmt.Sprintf("<%v> remote peer has too much debt (balance: %v, disconnect threshold: %v)", s.proto, s.balance, s.local.DropAt))
self.proto.Drop() s.proto.Drop()
return fmt.Errorf("[SWAP] <%v> remote peer has too much debt (balance: %v, disconnect threshold: %v)", self.proto, self.balance, self.local.DropAt) return fmt.Errorf("[SWAP] <%v> remote peer has too much debt (balance: %v, disconnect threshold: %v)", s.proto, s.balance, s.local.DropAt)
} else if self.balance <= -int(self.remote.PayAt) { } else if s.balance <= -int(s.remote.PayAt) {
self.send() s.send()
} }
return nil return nil
} }
func (self *Swap) Balance() int { func (s *Swap) Balance() int {
defer self.lock.Unlock() defer s.lock.Unlock()
self.lock.Lock() s.lock.Lock()
return self.balance return s.balance
} }
// send(units) is called when payment is due // send(units) is called when payment is due
// In case of insolvency no promise is issued and sent, safe against fraud // In case of insolvency no promise is issued and sent, safe against fraud
// No return value: no error = payment is opportunistic = hang in till dropped // No return value: no error = payment is opportunistic = hang in till dropped
func (self *Swap) send() { func (s *Swap) send() {
if self.local.BuyAt != nil && self.balance < 0 { if s.local.BuyAt != nil && s.balance < 0 {
amount := big.NewInt(int64(-self.balance)) amount := big.NewInt(int64(-s.balance))
amount.Mul(amount, self.remote.SellAt) amount.Mul(amount, s.remote.SellAt)
promise, err := self.Out.Issue(amount) promise, err := s.Out.Issue(amount)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("<%v> cannot issue cheque (amount: %v, channel: %v): %v", self.proto, amount, self.Out, err)) log.Warn(fmt.Sprintf("<%v> cannot issue cheque (amount: %v, channel: %v): %v", s.proto, amount, s.Out, err))
} else { } else {
log.Warn(fmt.Sprintf("<%v> cheque issued (amount: %v, channel: %v)", self.proto, amount, self.Out)) log.Warn(fmt.Sprintf("<%v> cheque issued (amount: %v, channel: %v)", s.proto, amount, s.Out))
self.proto.Pay(-self.balance, promise) s.proto.Pay(-s.balance, promise)
self.balance = 0 s.balance = 0
} }
} }
} }
// receive(units, promise) is called by the protocol when a payment msg is received // receive(units, promise) is called by the protocol when a payment msg is received
// returns error if promise is invalid. // returns error if promise is invalid.
func (self *Swap) Receive(units int, promise Promise) error { func (s *Swap) Receive(units int, promise Promise) error {
if units <= 0 { if units <= 0 {
return fmt.Errorf("invalid units: %v <= 0", units) return fmt.Errorf("invalid units: %v <= 0", units)
} }
price := new(big.Int).SetInt64(int64(units)) price := new(big.Int).SetInt64(int64(units))
price.Mul(price, self.local.SellAt) price.Mul(price, s.local.SellAt)
amount, err := self.In.Receive(promise) amount, err := s.In.Receive(promise)
if err != nil { if err != nil {
err = fmt.Errorf("invalid promise: %v", err) err = fmt.Errorf("invalid promise: %v", err)
} else if price.Cmp(amount) != 0 { } else if price.Cmp(amount) != 0 {
// verify amount = units * unit sale price // verify amount = units * unit sale price
return fmt.Errorf("invalid amount: %v = %v * %v (units sent in msg * agreed sale unit price) != %v (signed in cheque)", price, units, self.local.SellAt, amount) return fmt.Errorf("invalid amount: %v = %v * %v (units sent in msg * agreed sale unit price) != %v (signed in cheque)", price, units, s.local.SellAt, amount)
} }
if err != nil { if err != nil {
log.Trace(fmt.Sprintf("<%v> invalid promise (amount: %v, channel: %v): %v", self.proto, amount, self.In, err)) log.Trace(fmt.Sprintf("<%v> invalid promise (amount: %v, channel: %v): %v", s.proto, amount, s.In, err))
return err return err
} }
// credit remote peer with units // credit remote peer with units
self.Add(-units) s.Add(-units)
log.Trace(fmt.Sprintf("<%v> received promise (amount: %v, channel: %v): %v", self.proto, amount, self.In, promise)) log.Trace(fmt.Sprintf("<%v> received promise (amount: %v, channel: %v): %v", s.proto, amount, s.In, promise))
return nil return nil
} }
// stop() causes autocash loop to terminate. // stop() causes autocash loop to terminate.
// Called after protocol handle loop terminates. // Called after protocol handle loop terminates.
func (self *Swap) Stop() { func (s *Swap) Stop() {
defer self.lock.Unlock() defer s.lock.Unlock()
self.lock.Lock() s.lock.Lock()
if self.Buys { if s.Buys {
self.Out.Stop() s.Out.Stop()
} }
if self.Sells { if s.Sells {
self.In.Stop() s.In.Stop()
} }
} }

View file

@ -34,20 +34,20 @@ type testPromise struct {
amount *big.Int amount *big.Int
} }
func (self *testInPayment) Receive(promise Promise) (*big.Int, error) { func (t *testInPayment) Receive(promise Promise) (*big.Int, error) {
p := promise.(*testPromise) p := promise.(*testPromise)
self.received = append(self.received, p) t.received = append(t.received, p)
return p.amount, nil return p.amount, nil
} }
func (self *testInPayment) AutoCash(interval time.Duration, limit *big.Int) { func (t *testInPayment) AutoCash(interval time.Duration, limit *big.Int) {
self.autocashInterval = interval t.autocashInterval = interval
self.autocashLimit = limit t.autocashLimit = limit
} }
func (self *testInPayment) Cash() (string, error) { return "", nil } func (t *testInPayment) Cash() (string, error) { return "", nil }
func (self *testInPayment) Stop() {} func (t *testInPayment) Stop() {}
type testOutPayment struct { type testOutPayment struct {
deposits []*big.Int deposits []*big.Int
@ -56,22 +56,22 @@ type testOutPayment struct {
autodepositBuffer *big.Int autodepositBuffer *big.Int
} }
func (self *testOutPayment) Issue(amount *big.Int) (promise Promise, err error) { func (t *testOutPayment) Issue(amount *big.Int) (promise Promise, err error) {
return &testPromise{amount}, nil return &testPromise{amount}, nil
} }
func (self *testOutPayment) Deposit(amount *big.Int) (string, error) { func (t *testOutPayment) Deposit(amount *big.Int) (string, error) {
self.deposits = append(self.deposits, amount) t.deposits = append(t.deposits, amount)
return "", nil return "", nil
} }
func (self *testOutPayment) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) { func (t *testOutPayment) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
self.autodepositInterval = interval t.autodepositInterval = interval
self.autodepositThreshold = threshold t.autodepositThreshold = threshold
self.autodepositBuffer = buffer t.autodepositBuffer = buffer
} }
func (self *testOutPayment) Stop() {} func (t *testOutPayment) Stop() {}
type testProtocol struct { type testProtocol struct {
drop bool drop bool
@ -79,18 +79,18 @@ type testProtocol struct {
promises []*testPromise promises []*testPromise
} }
func (self *testProtocol) Drop() { func (t *testProtocol) Drop() {
self.drop = true t.drop = true
} }
func (self *testProtocol) String() string { func (t *testProtocol) String() string {
return "" return ""
} }
func (self *testProtocol) Pay(amount int, promise Promise) { func (t *testProtocol) Pay(amount int, promise Promise) {
p := promise.(*testPromise) p := promise.(*testPromise)
self.promises = append(self.promises, p) t.promises = append(t.promises, p)
self.amounts = append(self.amounts, amount) t.amounts = append(t.amounts, amount)
} }
func TestSwap(t *testing.T) { func TestSwap(t *testing.T) {

View file

@ -74,30 +74,30 @@ type TreeChunker struct {
branches int64 branches int64
hashFunc SwarmHasher hashFunc SwarmHasher
// calculated // calculated
hashSize int64 // self.hashFunc.New().Size() hashSize int64 // hashFunc.New().Size()
chunkSize int64 // hashSize* branches chunkSize int64 // hashSize*branches
workerCount int64 // the number of worker routines used workerCount int64 // the number of worker routines used
workerLock sync.RWMutex // lock for the worker count workerLock sync.RWMutex // lock for the worker count
} }
func NewTreeChunker(params *ChunkerParams) (self *TreeChunker) { func NewTreeChunker(params *ChunkerParams) (chunker *TreeChunker) {
self = &TreeChunker{} chunker = &TreeChunker{}
self.hashFunc = MakeHashFunc(params.Hash) chunker.hashFunc = MakeHashFunc(params.Hash)
self.branches = params.Branches chunker.branches = params.Branches
self.hashSize = int64(self.hashFunc().Size()) chunker.hashSize = int64(chunker.hashFunc().Size())
self.chunkSize = self.hashSize * self.branches chunker.chunkSize = chunker.hashSize * chunker.branches
self.workerCount = 0 chunker.workerCount = 0
return return
} }
// func (self *TreeChunker) KeySize() int64 { // func (chunker *TreeChunker) KeySize() int64 {
// return self.hashSize // return chunker.hashSize
// } // }
// String() for pretty printing // String() for pretty printing
func (self *Chunk) String() string { func (c *Chunk) String() string {
return fmt.Sprintf("Key: %v TreeSize: %v Chunksize: %v", self.Key.Log(), self.Size, len(self.SData)) return fmt.Sprintf("Key: %v TreeSize: %v Chunksize: %v", c.Key.Log(), c.Size, len(c.SData))
} }
type hashJob struct { type hashJob struct {
@ -107,26 +107,26 @@ type hashJob struct {
parentWg *sync.WaitGroup parentWg *sync.WaitGroup
} }
func (self *TreeChunker) incrementWorkerCount() { func (chunker *TreeChunker) incrementWorkerCount() {
self.workerLock.Lock() chunker.workerLock.Lock()
defer self.workerLock.Unlock() defer chunker.workerLock.Unlock()
self.workerCount += 1 chunker.workerCount += 1
} }
func (self *TreeChunker) getWorkerCount() int64 { func (chunker *TreeChunker) getWorkerCount() int64 {
self.workerLock.RLock() chunker.workerLock.RLock()
defer self.workerLock.RUnlock() defer chunker.workerLock.RUnlock()
return self.workerCount return chunker.workerCount
} }
func (self *TreeChunker) decrementWorkerCount() { func (chunker *TreeChunker) decrementWorkerCount() {
self.workerLock.Lock() chunker.workerLock.Lock()
defer self.workerLock.Unlock() defer chunker.workerLock.Unlock()
self.workerCount -= 1 chunker.workerCount -= 1
} }
func (self *TreeChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, swg, wwg *sync.WaitGroup) (Key, error) { func (chunker *TreeChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, swg, wwg *sync.WaitGroup) (Key, error) {
if self.chunkSize <= 0 { if chunker.chunkSize <= 0 {
panic("chunker must be initialised") panic("chunker must be initialised")
} }
@ -140,23 +140,23 @@ func (self *TreeChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, s
wwg.Add(1) wwg.Add(1)
} }
self.incrementWorkerCount() chunker.incrementWorkerCount()
go self.hashWorker(jobC, chunkC, errC, quitC, swg, wwg) go chunker.hashWorker(jobC, chunkC, errC, quitC, swg, wwg)
depth := 0 depth := 0
treeSize := self.chunkSize treeSize := chunker.chunkSize
// takes lowest depth such that chunksize*HashCount^(depth+1) > size // takes lowest depth such that chunksize*HashCount^(depth+1) > size
// power series, will find the order of magnitude of the data size in base hashCount or numbers of levels of branching in the resulting tree. // power series, will find the order of magnitude of the data size in base hashCount or numbers of levels of branching in the resulting tree.
for ; treeSize < size; treeSize *= self.branches { for ; treeSize < size; treeSize *= chunker.branches {
depth++ depth++
} }
key := make([]byte, self.hashFunc().Size()) key := make([]byte, chunker.hashFunc().Size())
// this waitgroup member is released after the root hash is calculated // this waitgroup member is released after the root hash is calculated
wg.Add(1) wg.Add(1)
//launch actual recursive function passing the waitgroups //launch actual recursive function passing the waitgroups
go self.split(depth, treeSize/self.branches, key, data, size, jobC, chunkC, errC, quitC, wg, swg, wwg) go chunker.split(depth, treeSize/chunker.branches, key, data, size, jobC, chunkC, errC, quitC, wg, swg, wwg)
// closes internal error channel if all subprocesses in the workgroup finished // closes internal error channel if all subprocesses in the workgroup finished
go func() { go func() {
@ -182,12 +182,12 @@ func (self *TreeChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, s
return key, nil return key, nil
} }
func (self *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reader, size int64, jobC chan *hashJob, chunkC chan *Chunk, errC chan error, quitC chan bool, parentWg, swg, wwg *sync.WaitGroup) { func (chunker *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reader, size int64, jobC chan *hashJob, chunkC chan *Chunk, errC chan error, quitC chan bool, parentWg, swg, wwg *sync.WaitGroup) {
// //
for depth > 0 && size < treeSize { for depth > 0 && size < treeSize {
treeSize /= self.branches treeSize /= chunker.branches
depth-- depth--
} }
@ -214,7 +214,7 @@ func (self *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reade
// intermediate chunk containing child nodes hashes // intermediate chunk containing child nodes hashes
branchCnt := (size + treeSize - 1) / treeSize branchCnt := (size + treeSize - 1) / treeSize
var chunk = make([]byte, branchCnt*self.hashSize+8) var chunk = make([]byte, branchCnt*chunker.hashSize+8)
var pos, i int64 var pos, i int64
binary.LittleEndian.PutUint64(chunk[0:8], uint64(size)) binary.LittleEndian.PutUint64(chunk[0:8], uint64(size))
@ -229,10 +229,10 @@ func (self *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reade
secSize = treeSize secSize = treeSize
} }
// the hash of that data // the hash of that data
subTreeKey := chunk[8+i*self.hashSize : 8+(i+1)*self.hashSize] subTreeKey := chunk[8+i*chunker.hashSize : 8+(i+1)*chunker.hashSize]
childrenWg.Add(1) childrenWg.Add(1)
self.split(depth-1, treeSize/self.branches, subTreeKey, data, secSize, jobC, chunkC, errC, quitC, childrenWg, swg, wwg) chunker.split(depth-1, treeSize/chunker.branches, subTreeKey, data, secSize, jobC, chunkC, errC, quitC, childrenWg, swg, wwg)
i++ i++
pos += treeSize pos += treeSize
@ -242,13 +242,13 @@ func (self *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reade
// go func() { // go func() {
childrenWg.Wait() childrenWg.Wait()
worker := self.getWorkerCount() worker := chunker.getWorkerCount()
if int64(len(jobC)) > worker && worker < ChunkProcessors { if int64(len(jobC)) > worker && worker < ChunkProcessors {
if wwg != nil { if wwg != nil {
wwg.Add(1) wwg.Add(1)
} }
self.incrementWorkerCount() chunker.incrementWorkerCount()
go self.hashWorker(jobC, chunkC, errC, quitC, swg, wwg) go chunker.hashWorker(jobC, chunkC, errC, quitC, swg, wwg)
} }
select { select {
@ -257,10 +257,10 @@ func (self *TreeChunker) split(depth int, treeSize int64, key Key, data io.Reade
} }
} }
func (self *TreeChunker) hashWorker(jobC chan *hashJob, chunkC chan *Chunk, errC chan error, quitC chan bool, swg, wwg *sync.WaitGroup) { func (chunker *TreeChunker) hashWorker(jobC chan *hashJob, chunkC chan *Chunk, errC chan error, quitC chan bool, swg, wwg *sync.WaitGroup) {
defer self.decrementWorkerCount() defer chunker.decrementWorkerCount()
hasher := self.hashFunc() hasher := chunker.hashFunc()
if wwg != nil { if wwg != nil {
defer wwg.Done() defer wwg.Done()
} }
@ -272,7 +272,7 @@ func (self *TreeChunker) hashWorker(jobC chan *hashJob, chunkC chan *Chunk, errC
return return
} }
// now we got the hashes in the chunk, then hash the chunks // now we got the hashes in the chunk, then hash the chunks
self.hashChunk(hasher, job, chunkC, swg) chunker.hashChunk(hasher, job, chunkC, swg)
case <-quitC: case <-quitC:
return return
} }
@ -282,7 +282,7 @@ func (self *TreeChunker) hashWorker(jobC chan *hashJob, chunkC chan *Chunk, errC
// The treeChunkers own Hash hashes together // The treeChunkers own Hash hashes together
// - the size (of the subtree encoded in the Chunk) // - the size (of the subtree encoded in the Chunk)
// - the Chunk, ie. the contents read from the input reader // - the Chunk, ie. the contents read from the input reader
func (self *TreeChunker) hashChunk(hasher SwarmHash, job *hashJob, chunkC chan *Chunk, swg *sync.WaitGroup) { func (chunker *TreeChunker) hashChunk(hasher SwarmHash, job *hashJob, chunkC chan *Chunk, swg *sync.WaitGroup) {
hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length
hasher.Write(job.chunk[8:]) // minus 8 []byte length hasher.Write(job.chunk[8:]) // minus 8 []byte length
h := hasher.Sum(nil) h := hasher.Sum(nil)
@ -316,7 +316,7 @@ func (self *TreeChunker) hashChunk(hasher SwarmHash, job *hashJob, chunkC chan *
} }
} }
func (self *TreeChunker) Append(key Key, data io.Reader, chunkC chan *Chunk, swg, wwg *sync.WaitGroup) (Key, error) { func (chunker *TreeChunker) Append(key Key, data io.Reader, chunkC chan *Chunk, swg, wwg *sync.WaitGroup) (Key, error) {
return nil, errAppendOppNotSuported return nil, errAppendOppNotSuported
} }
@ -332,44 +332,44 @@ type LazyChunkReader struct {
} }
// implements the Joiner interface // implements the Joiner interface
func (self *TreeChunker) Join(key Key, chunkC chan *Chunk) LazySectionReader { func (chunker *TreeChunker) Join(key Key, chunkC chan *Chunk) LazySectionReader {
return &LazyChunkReader{ return &LazyChunkReader{
key: key, key: key,
chunkC: chunkC, chunkC: chunkC,
chunkSize: self.chunkSize, chunkSize: chunker.chunkSize,
branches: self.branches, branches: chunker.branches,
hashSize: self.hashSize, hashSize: chunker.hashSize,
} }
} }
// Size is meant to be called on the LazySectionReader // Size is meant to be called on the LazySectionReader
func (self *LazyChunkReader) Size(quitC chan bool) (n int64, err error) { func (reader *LazyChunkReader) Size(quitC chan bool) (n int64, err error) {
if self.chunk != nil { if reader.chunk != nil {
return self.chunk.Size, nil return reader.chunk.Size, nil
} }
chunk := retrieve(self.key, self.chunkC, quitC) chunk := retrieve(reader.key, reader.chunkC, quitC)
if chunk == nil { if chunk == nil {
select { select {
case <-quitC: case <-quitC:
return 0, errors.New("aborted") return 0, errors.New("aborted")
default: default:
return 0, fmt.Errorf("root chunk not found for %v", self.key.Hex()) return 0, fmt.Errorf("root chunk not found for %v", reader.key.Hex())
} }
} }
self.chunk = chunk reader.chunk = chunk
return chunk.Size, nil return chunk.Size, nil
} }
// read at can be called numerous times // read at can be called numerous times
// concurrent reads are allowed // concurrent reads are allowed
// Size() needs to be called synchronously on the LazyChunkReader first // Size() needs to be called synchronously on the LazyChunkReader first
func (self *LazyChunkReader) ReadAt(b []byte, off int64) (read int, err error) { func (reader *LazyChunkReader) ReadAt(b []byte, off int64) (read int, err error) {
// this is correct, a swarm doc cannot be zero length, so no EOF is expected // this is correct, a swarm doc cannot be zero length, so no EOF is expected
if len(b) == 0 { if len(b) == 0 {
return 0, nil return 0, nil
} }
quitC := make(chan bool) quitC := make(chan bool)
size, err := self.Size(quitC) size, err := reader.Size(quitC)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -380,13 +380,13 @@ func (self *LazyChunkReader) ReadAt(b []byte, off int64) (read int, err error) {
var treeSize int64 var treeSize int64
var depth int var depth int
// calculate depth and max treeSize // calculate depth and max treeSize
treeSize = self.chunkSize treeSize = reader.chunkSize
for ; treeSize < size; treeSize *= self.branches { for ; treeSize < size; treeSize *= reader.branches {
depth++ depth++
} }
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(1) wg.Add(1)
go self.join(b, off, off+int64(len(b)), depth, treeSize/self.branches, self.chunk, &wg, errC, quitC) go reader.join(b, off, off+int64(len(b)), depth, treeSize/reader.branches, reader.chunk, &wg, errC, quitC)
go func() { go func() {
wg.Wait() wg.Wait()
close(errC) close(errC)
@ -404,7 +404,7 @@ func (self *LazyChunkReader) ReadAt(b []byte, off int64) (read int, err error) {
return len(b), nil return len(b), nil
} }
func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, treeSize int64, chunk *Chunk, parentWg *sync.WaitGroup, errC chan error, quitC chan bool) { func (reader *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, treeSize int64, chunk *Chunk, parentWg *sync.WaitGroup, errC chan error, quitC chan bool) {
defer parentWg.Done() defer parentWg.Done()
// return NewDPA(&LocalStore{}) // return NewDPA(&LocalStore{})
@ -412,7 +412,7 @@ func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, tr
// find appropriate block level // find appropriate block level
for chunk.Size < treeSize && depth > 0 { for chunk.Size < treeSize && depth > 0 {
treeSize /= self.branches treeSize /= reader.branches
depth-- depth--
} }
@ -449,8 +449,8 @@ func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, tr
} }
wg.Add(1) wg.Add(1)
go func(j int64) { go func(j int64) {
childKey := chunk.SData[8+j*self.hashSize : 8+(j+1)*self.hashSize] childKey := chunk.SData[8+j*reader.hashSize : 8+(j+1)*reader.hashSize]
chunk := retrieve(childKey, self.chunkC, quitC) chunk := retrieve(childKey, reader.chunkC, quitC)
if chunk == nil { if chunk == nil {
select { select {
case errC <- fmt.Errorf("chunk %v-%v not found", off, off+treeSize): case errC <- fmt.Errorf("chunk %v-%v not found", off, off+treeSize):
@ -461,7 +461,7 @@ func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, tr
if soff < off { if soff < off {
soff = off soff = off
} }
self.join(b[soff-off:seoff-off], soff-roff, seoff-roff, depth-1, treeSize/self.branches, chunk, wg, errC, quitC) reader.join(b[soff-off:seoff-off], soff-roff, seoff-roff, depth-1, treeSize/reader.branches, chunk, wg, errC, quitC)
}(i) }(i)
} //for } //for
} }
@ -496,10 +496,10 @@ func retrieve(key Key, chunkC chan *Chunk, quitC chan bool) *Chunk {
} }
// Read keeps a cursor so cannot be called simulateously, see ReadAt // Read keeps a cursor so cannot be called simulateously, see ReadAt
func (self *LazyChunkReader) Read(b []byte) (read int, err error) { func (reader *LazyChunkReader) Read(b []byte) (read int, err error) {
read, err = self.ReadAt(b, self.off) read, err = reader.ReadAt(b, reader.off)
self.off += int64(read) reader.off += int64(read)
return return
} }

View file

@ -45,12 +45,12 @@ type chunkerTester struct {
t test t test
} }
func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) { func (tester *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) {
// reset // reset
self.chunks = make(map[string]*Chunk) tester.chunks = make(map[string]*Chunk)
if self.inputs == nil { if tester.inputs == nil {
self.inputs = make(map[uint64][]byte) tester.inputs = make(map[uint64][]byte)
} }
quitC := make(chan bool) quitC := make(chan bool)
@ -64,8 +64,8 @@ func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, c
case <-quitC: case <-quitC:
return nil return nil
case chunk := <-chunkC: case chunk := <-chunkC:
// self.chunks = append(self.chunks, chunk) // tester.chunks = append(tester.chunks, chunk)
self.chunks[chunk.Key.String()] = chunk tester.chunks[chunk.Key.String()] = chunk
if chunk.wg != nil { if chunk.wg != nil {
chunk.wg.Done() chunk.wg.Done()
} }
@ -89,7 +89,7 @@ func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, c
return key, err return key, err
} }
func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) { func (tester *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) {
quitC := make(chan bool) quitC := make(chan bool)
timeout := time.After(60 * time.Second) timeout := time.After(60 * time.Second)
if chunkC != nil { if chunkC != nil {
@ -102,10 +102,10 @@ func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader,
return nil return nil
case chunk := <-chunkC: case chunk := <-chunkC:
if chunk != nil { if chunk != nil {
stored, success := self.chunks[chunk.Key.String()] stored, success := tester.chunks[chunk.Key.String()]
if !success { if !success {
// Requesting data // Requesting data
self.chunks[chunk.Key.String()] = chunk tester.chunks[chunk.Key.String()] = chunk
if chunk.wg != nil { if chunk.wg != nil {
chunk.wg.Done() chunk.wg.Done()
} }
@ -135,7 +135,7 @@ func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader,
return key, err return key, err
} }
func (self *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Chunk, quitC chan bool) LazySectionReader { func (tester *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Chunk, quitC chan bool) LazySectionReader {
// reset but not the chunks // reset but not the chunks
reader := chunker.Join(key, chunkC) reader := chunker.Join(key, chunkC)
@ -153,7 +153,7 @@ func (self *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Ch
return nil return nil
} }
// this just mocks the behaviour of a chunk store retrieval // this just mocks the behaviour of a chunk store retrieval
stored, success := self.chunks[chunk.Key.String()] stored, success := tester.chunks[chunk.Key.String()]
if !success { if !success {
return errors.New("Not found") return errors.New("Not found")
} }

View file

@ -46,12 +46,12 @@ func testDataReader(l int) (r io.Reader) {
return io.LimitReader(rand.Reader, int64(l)) return io.LimitReader(rand.Reader, int64(l))
} }
func (self *brokenLimitedReader) Read(buf []byte) (int, error) { func (reader *brokenLimitedReader) Read(buf []byte) (int, error) {
if self.off+len(buf) > self.errAt { if reader.off+len(buf) > reader.errAt {
return 0, fmt.Errorf("Broken reader") return 0, fmt.Errorf("Broken reader")
} }
self.off += len(buf) reader.off += len(buf)
return self.lr.Read(buf) return reader.lr.Read(buf)
} }
func testDataReaderAndSlice(l int) (r io.Reader, slice []byte) { func testDataReaderAndSlice(l int) (r io.Reader, slice []byte) {

View file

@ -45,27 +45,27 @@ func NewLDBDatabase(file string) (*LDBDatabase, error) {
return database, nil return database, nil
} }
func (self *LDBDatabase) Put(key []byte, value []byte) { func (database *LDBDatabase) Put(key []byte, value []byte) {
err := self.db.Put(key, value, nil) err := database.db.Put(key, value, nil)
if err != nil { if err != nil {
fmt.Println("Error put", err) fmt.Println("Error put", err)
} }
} }
func (self *LDBDatabase) Get(key []byte) ([]byte, error) { func (database *LDBDatabase) Get(key []byte) ([]byte, error) {
dat, err := self.db.Get(key, nil) dat, err := database.db.Get(key, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return dat, nil return dat, nil
} }
func (self *LDBDatabase) Delete(key []byte) error { func (database *LDBDatabase) Delete(key []byte) error {
return self.db.Delete(key, nil) return database.db.Delete(key, nil)
} }
func (self *LDBDatabase) LastKnownTD() []byte { func (database *LDBDatabase) LastKnownTD() []byte {
data, _ := self.Get([]byte("LTD")) data, _ := database.Get([]byte("LTD"))
if len(data) == 0 { if len(data) == 0 {
data = []byte{0x0} data = []byte{0x0}
@ -74,15 +74,15 @@ func (self *LDBDatabase) LastKnownTD() []byte {
return data return data
} }
func (self *LDBDatabase) NewIterator() iterator.Iterator { func (database *LDBDatabase) NewIterator() iterator.Iterator {
return self.db.NewIterator(nil, nil) return database.db.NewIterator(nil, nil)
} }
func (self *LDBDatabase) Write(batch *leveldb.Batch) error { func (database *LDBDatabase) Write(batch *leveldb.Batch) error {
return self.db.Write(batch, nil) return database.db.Write(batch, nil)
} }
func (self *LDBDatabase) Close() { func (database *LDBDatabase) Close() {
// Close the leveldb database // Close the leveldb database
self.db.Close() database.db.Close()
} }

View file

@ -559,12 +559,12 @@ type dbSyncIterator struct {
} }
// initialises a sync iterator from a syncToken (passed in with the handshake) // initialises a sync iterator from a syncToken (passed in with the handshake)
func (self *DbStore) NewSyncIterator(state DbSyncState) (si *dbSyncIterator, err error) { func (store *DbStore) NewSyncIterator(state DbSyncState) (si *dbSyncIterator, err error) {
if state.First > state.Last { if state.First > state.Last {
return nil, fmt.Errorf("no entries found") return nil, fmt.Errorf("no entries found")
} }
si = &dbSyncIterator{ si = &dbSyncIterator{
it: self.db.NewIterator(), it: store.db.NewIterator(),
DbSyncState: state, DbSyncState: state,
} }
si.it.Seek(getIndexKey(state.Start)) si.it.Seek(getIndexKey(state.Start))
@ -573,28 +573,28 @@ func (self *DbStore) NewSyncIterator(state DbSyncState) (si *dbSyncIterator, err
// walk the area from Start to Stop and returns items within time interval // walk the area from Start to Stop and returns items within time interval
// First to Last // First to Last
func (self *dbSyncIterator) Next() (key Key) { func (iterator *dbSyncIterator) Next() (key Key) {
for self.it.Valid() { for iterator.it.Valid() {
dbkey := self.it.Key() dbkey := iterator.it.Key()
if dbkey[0] != 0 { if dbkey[0] != 0 {
break break
} }
key = Key(make([]byte, len(dbkey)-1)) key = Key(make([]byte, len(dbkey)-1))
copy(key[:], dbkey[1:]) copy(key[:], dbkey[1:])
if bytes.Compare(key[:], self.Start) <= 0 { if bytes.Compare(key[:], iterator.Start) <= 0 {
self.it.Next() iterator.it.Next()
continue continue
} }
if bytes.Compare(key[:], self.Stop) > 0 { if bytes.Compare(key[:], iterator.Stop) > 0 {
break break
} }
var index dpaDBIndex var index dpaDBIndex
decodeIndex(self.it.Value(), &index) decodeIndex(iterator.it.Value(), &index)
self.it.Next() iterator.it.Next()
if (index.Idx >= self.First) && (index.Idx < self.Last) { if (index.Idx >= iterator.First) && (index.Idx < iterator.Last) {
return return
} }
} }
self.it.Release() iterator.it.Release()
return nil return nil
} }

View file

@ -90,53 +90,53 @@ func NewDPA(store ChunkStore, params *ChunkerParams) *DPA {
// FS-aware API and httpaccess // FS-aware API and httpaccess
// Chunk retrieval blocks on netStore requests with a timeout so reader will // Chunk retrieval blocks on netStore requests with a timeout so reader will
// report error if retrieval of chunks within requested range time out. // report error if retrieval of chunks within requested range time out.
func (self *DPA) Retrieve(key Key) LazySectionReader { func (dpa *DPA) Retrieve(key Key) LazySectionReader {
return self.Chunker.Join(key, self.retrieveC) return dpa.Chunker.Join(key, dpa.retrieveC)
} }
// Public API. Main entry point for document storage directly. Used by the // Public API. Main entry point for document storage directly. Used by the
// FS-aware API and httpaccess // FS-aware API and httpaccess
func (self *DPA) Store(data io.Reader, size int64, swg *sync.WaitGroup, wwg *sync.WaitGroup) (key Key, err error) { func (dpa *DPA) Store(data io.Reader, size int64, swg *sync.WaitGroup, wwg *sync.WaitGroup) (key Key, err error) {
return self.Chunker.Split(data, size, self.storeC, swg, wwg) return dpa.Chunker.Split(data, size, dpa.storeC, swg, wwg)
} }
func (self *DPA) Start() { func (dpa *DPA) Start() {
self.lock.Lock() dpa.lock.Lock()
defer self.lock.Unlock() defer dpa.lock.Unlock()
if self.running { if dpa.running {
return return
} }
self.running = true dpa.running = true
self.retrieveC = make(chan *Chunk, retrieveChanCapacity) dpa.retrieveC = make(chan *Chunk, retrieveChanCapacity)
self.storeC = make(chan *Chunk, storeChanCapacity) dpa.storeC = make(chan *Chunk, storeChanCapacity)
self.quitC = make(chan bool) dpa.quitC = make(chan bool)
self.storeLoop() dpa.storeLoop()
self.retrieveLoop() dpa.retrieveLoop()
} }
func (self *DPA) Stop() { func (dpa *DPA) Stop() {
self.lock.Lock() dpa.lock.Lock()
defer self.lock.Unlock() defer dpa.lock.Unlock()
if !self.running { if !dpa.running {
return return
} }
self.running = false dpa.running = false
close(self.quitC) close(dpa.quitC)
} }
// retrieveLoop dispatches the parallel chunk retrieval requests received on the // retrieveLoop dispatches the parallel chunk retrieval requests received on the
// retrieve channel to its ChunkStore (NetStore or LocalStore) // retrieve channel to its ChunkStore (NetStore or LocalStore)
func (self *DPA) retrieveLoop() { func (dpa *DPA) retrieveLoop() {
for i := 0; i < maxRetrieveProcesses; i++ { for i := 0; i < maxRetrieveProcesses; i++ {
go self.retrieveWorker() go dpa.retrieveWorker()
} }
log.Trace(fmt.Sprintf("dpa: retrieve loop spawning %v workers", maxRetrieveProcesses)) log.Trace(fmt.Sprintf("dpa: retrieve loop spawning %v workers", maxRetrieveProcesses))
} }
func (self *DPA) retrieveWorker() { func (dpa *DPA) retrieveWorker() {
for chunk := range self.retrieveC { for chunk := range dpa.retrieveC {
log.Trace(fmt.Sprintf("dpa: retrieve loop : chunk %v", chunk.Key.Log())) log.Trace(fmt.Sprintf("dpa: retrieve loop : chunk %v", chunk.Key.Log()))
storedChunk, err := self.Get(chunk.Key) storedChunk, err := dpa.Get(chunk.Key)
if err == notFound { if err == notFound {
log.Trace(fmt.Sprintf("chunk %v not found", chunk.Key.Log())) log.Trace(fmt.Sprintf("chunk %v not found", chunk.Key.Log()))
} else if err != nil { } else if err != nil {
@ -148,7 +148,7 @@ func (self *DPA) retrieveWorker() {
close(chunk.C) close(chunk.C)
select { select {
case <-self.quitC: case <-dpa.quitC:
return return
default: default:
} }
@ -157,24 +157,24 @@ func (self *DPA) retrieveWorker() {
// storeLoop dispatches the parallel chunk store request processors // storeLoop dispatches the parallel chunk store request processors
// received on the store channel to its ChunkStore (NetStore or LocalStore) // received on the store channel to its ChunkStore (NetStore or LocalStore)
func (self *DPA) storeLoop() { func (dpa *DPA) storeLoop() {
for i := 0; i < maxStoreProcesses; i++ { for i := 0; i < maxStoreProcesses; i++ {
go self.storeWorker() go dpa.storeWorker()
} }
log.Trace(fmt.Sprintf("dpa: store spawning %v workers", maxStoreProcesses)) log.Trace(fmt.Sprintf("dpa: store spawning %v workers", maxStoreProcesses))
} }
func (self *DPA) storeWorker() { func (dpa *DPA) storeWorker() {
for chunk := range self.storeC { for chunk := range dpa.storeC {
self.Put(chunk) dpa.Put(chunk)
if chunk.wg != nil { if chunk.wg != nil {
log.Trace(fmt.Sprintf("dpa: store processor %v", chunk.Key.Log())) log.Trace(fmt.Sprintf("dpa: store processor %v", chunk.Key.Log()))
chunk.wg.Done() chunk.wg.Done()
} }
select { select {
case <-self.quitC: case <-dpa.quitC:
return return
default: default:
} }
@ -198,14 +198,14 @@ func NewDpaChunkStore(localStore, netStore ChunkStore) *dpaChunkStore {
// Get is the entrypoint for local retrieve requests // Get is the entrypoint for local retrieve requests
// waits for response or times out // waits for response or times out
func (self *dpaChunkStore) Get(key Key) (chunk *Chunk, err error) { func (store *dpaChunkStore) Get(key Key) (chunk *Chunk, err error) {
chunk, err = self.netStore.Get(key) chunk, err = store.netStore.Get(key)
// timeout := time.Now().Add(searchTimeout) // timeout := time.Now().Add(searchTimeout)
if chunk.SData != nil { if chunk.SData != nil {
log.Trace(fmt.Sprintf("DPA.Get: %v found locally, %d bytes", key.Log(), len(chunk.SData))) log.Trace(fmt.Sprintf("DPA.Get: %v found locally, %d bytes", key.Log(), len(chunk.SData)))
return return
} }
// TODO: use self.timer time.Timer and reset with defer disableTimer // TODO: use store.timer time.Timer and reset with defer disableTimer
timer := time.After(searchTimeout) timer := time.After(searchTimeout)
select { select {
case <-timer: case <-timer:
@ -218,8 +218,8 @@ func (self *dpaChunkStore) Get(key Key) (chunk *Chunk, err error) {
} }
// Put is the entrypoint for local store requests coming from storeLoop // Put is the entrypoint for local store requests coming from storeLoop
func (self *dpaChunkStore) Put(entry *Chunk) { func (store *dpaChunkStore) Put(entry *Chunk) {
chunk, err := self.localStore.Get(entry.Key) chunk, err := store.localStore.Get(entry.Key)
if err != nil { if err != nil {
log.Trace(fmt.Sprintf("DPA.Put: %v new chunk. call netStore.Put", entry.Key.Log())) log.Trace(fmt.Sprintf("DPA.Put: %v new chunk. call netStore.Put", entry.Key.Log()))
chunk = entry chunk = entry
@ -232,10 +232,10 @@ func (self *dpaChunkStore) Put(entry *Chunk) {
return return
} }
// from this point on the storage logic is the same with network storage requests // from this point on the storage logic is the same with network storage requests
log.Trace(fmt.Sprintf("DPA.Put %v: %v", self.n, chunk.Key.Log())) log.Trace(fmt.Sprintf("DPA.Put %v: %v", store.n, chunk.Key.Log()))
self.n++ store.n++
self.netStore.Put(chunk) store.netStore.Put(chunk)
} }
// Close chunk store // Close chunk store
func (self *dpaChunkStore) Close() {} func (store *dpaChunkStore) Close() {}

View file

@ -46,25 +46,25 @@ func NewLocalStore(hash SwarmHasher, params *StoreParams) (*LocalStore, error) {
}, nil }, nil
} }
func (self *LocalStore) CacheCounter() uint64 { func (store *LocalStore) CacheCounter() uint64 {
return uint64(self.memStore.(*MemStore).Counter()) return uint64(store.memStore.(*MemStore).Counter())
} }
func (self *LocalStore) DbCounter() uint64 { func (store *LocalStore) DbCounter() uint64 {
return self.DbStore.(*DbStore).Counter() return store.DbStore.(*DbStore).Counter()
} }
// LocalStore is itself a chunk store // LocalStore is itstore a chunk store
// unsafe, in that the data is not integrity checked // unsafe, in that the data is not integrity checked
func (self *LocalStore) Put(chunk *Chunk) { func (store *LocalStore) Put(chunk *Chunk) {
chunk.dbStored = make(chan bool) chunk.dbStored = make(chan bool)
self.memStore.Put(chunk) store.memStore.Put(chunk)
if chunk.wg != nil { if chunk.wg != nil {
chunk.wg.Add(1) chunk.wg.Add(1)
} }
go func() { go func() {
dbStorePutCounter.Inc(1) dbStorePutCounter.Inc(1)
self.DbStore.Put(chunk) store.DbStore.Put(chunk)
if chunk.wg != nil { if chunk.wg != nil {
chunk.wg.Done() chunk.wg.Done()
} }
@ -75,19 +75,19 @@ func (self *LocalStore) Put(chunk *Chunk) {
// This method is blocking until the chunk is retrieved // This method is blocking until the chunk is retrieved
// so additional timeout may be needed to wrap this call if // so additional timeout may be needed to wrap this call if
// ChunkStores are remote and can have long latency // ChunkStores are remote and can have long latency
func (self *LocalStore) Get(key Key) (chunk *Chunk, err error) { func (store *LocalStore) Get(key Key) (chunk *Chunk, err error) {
chunk, err = self.memStore.Get(key) chunk, err = store.memStore.Get(key)
if err == nil { if err == nil {
return return
} }
chunk, err = self.DbStore.Get(key) chunk, err = store.DbStore.Get(key)
if err != nil { if err != nil {
return return
} }
chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8])) chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
self.memStore.Put(chunk) store.memStore.Put(chunk)
return return
} }
// Close local store // Close local store
func (self *LocalStore) Close() {} func (store *LocalStore) Close() {}

View file

@ -58,7 +58,7 @@ type StoreParams struct {
} }
//create params with default values //create params with default values
func NewDefaultStoreParams() (self *StoreParams) { func NewDefaultStoreParams() *StoreParams {
return &StoreParams{ return &StoreParams{
DbCapacity: defaultDbCapacity, DbCapacity: defaultDbCapacity,
CacheCapacity: defaultCacheCapacity, CacheCapacity: defaultCacheCapacity,
@ -68,8 +68,8 @@ func NewDefaultStoreParams() (self *StoreParams) {
//this can only finally be set after all config options (file, cmd line, env vars) //this can only finally be set after all config options (file, cmd line, env vars)
//have been evaluated //have been evaluated
func (self *StoreParams) Init(path string) { func (params *StoreParams) Init(path string) {
self.ChunkDbPath = filepath.Join(path, "chunks") params.ChunkDbPath = filepath.Join(path, "chunks")
} }
// netstore contructor, takes path argument that is used to initialise dbStore, // netstore contructor, takes path argument that is used to initialise dbStore,
@ -92,8 +92,8 @@ var (
// ~ unsafe put in localdb no check if exists no extra copy no hash validation // ~ unsafe put in localdb no check if exists no extra copy no hash validation
// the chunk is forced to propagate (Cloud.Store) even if locally found! // the chunk is forced to propagate (Cloud.Store) even if locally found!
// caller needs to make sure if that is wanted // caller needs to make sure if that is wanted
func (self *NetStore) Put(entry *Chunk) { func (store *NetStore) Put(entry *Chunk) {
self.localStore.Put(entry) store.localStore.Put(entry)
// handle deliveries // handle deliveries
if entry.Req != nil { if entry.Req != nil {
@ -102,19 +102,19 @@ func (self *NetStore) Put(entry *Chunk) {
// that the chunk is has been retrieved // that the chunk is has been retrieved
close(entry.Req.C) close(entry.Req.C)
// deliver the chunk to requesters upstream // deliver the chunk to requesters upstream
go self.cloud.Deliver(entry) go store.cloud.Deliver(entry)
} else { } else {
log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log())) log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log()))
// handle propagating store requests // handle propagating store requests
// go self.cloud.Store(entry) // go store.cloud.Store(entry)
go self.cloud.Store(entry) go store.cloud.Store(entry)
} }
} }
// retrieve logic common for local and network chunk retrieval requests // retrieve logic common for local and network chunk retrieval requests
func (self *NetStore) Get(key Key) (*Chunk, error) { func (store *NetStore) Get(key Key) (*Chunk, error) {
var err error var err error
chunk, err := self.localStore.Get(key) chunk, err := store.localStore.Get(key)
if err == nil { if err == nil {
if chunk.Req == nil { if chunk.Req == nil {
log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key)) log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key))
@ -127,10 +127,10 @@ func (self *NetStore) Get(key Key) (*Chunk, error) {
// no data and no request status // no data and no request status
log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key)) log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key))
chunk = NewChunk(key, newRequestStatus(key)) chunk = NewChunk(key, newRequestStatus(key))
self.localStore.memStore.Put(chunk) store.localStore.memStore.Put(chunk)
go self.cloud.Retrieve(chunk) go store.cloud.Retrieve(chunk)
return chunk, nil return chunk, nil
} }
// Close netstore // Close netstore
func (self *NetStore) Close() {} func (store *NetStore) Close() {}

View file

@ -126,54 +126,54 @@ type PyramidChunker struct {
workerLock sync.RWMutex workerLock sync.RWMutex
} }
func NewPyramidChunker(params *ChunkerParams) (self *PyramidChunker) { func NewPyramidChunker(params *ChunkerParams) *PyramidChunker {
self = &PyramidChunker{} chunker := &PyramidChunker{}
self.hashFunc = MakeHashFunc(params.Hash) chunker.hashFunc = MakeHashFunc(params.Hash)
self.branches = params.Branches chunker.branches = params.Branches
self.hashSize = int64(self.hashFunc().Size()) chunker.hashSize = int64(chunker.hashFunc().Size())
self.chunkSize = self.hashSize * self.branches chunker.chunkSize = chunker.hashSize * chunker.branches
self.workerCount = 0 chunker.workerCount = 0
return return chunker
} }
func (self *PyramidChunker) Join(key Key, chunkC chan *Chunk) LazySectionReader { func (chunker *PyramidChunker) Join(key Key, chunkC chan *Chunk) LazySectionReader {
return &LazyChunkReader{ return &LazyChunkReader{
key: key, key: key,
chunkC: chunkC, chunkC: chunkC,
chunkSize: self.chunkSize, chunkSize: chunker.chunkSize,
branches: self.branches, branches: chunker.branches,
hashSize: self.hashSize, hashSize: chunker.hashSize,
} }
} }
func (self *PyramidChunker) incrementWorkerCount() { func (chunker *PyramidChunker) incrementWorkerCount() {
self.workerLock.Lock() chunker.workerLock.Lock()
defer self.workerLock.Unlock() defer chunker.workerLock.Unlock()
self.workerCount += 1 chunker.workerCount += 1
} }
func (self *PyramidChunker) getWorkerCount() int64 { func (chunker *PyramidChunker) getWorkerCount() int64 {
self.workerLock.Lock() chunker.workerLock.Lock()
defer self.workerLock.Unlock() defer chunker.workerLock.Unlock()
return self.workerCount return chunker.workerCount
} }
func (self *PyramidChunker) decrementWorkerCount() { func (chunker *PyramidChunker) decrementWorkerCount() {
self.workerLock.Lock() chunker.workerLock.Lock()
defer self.workerLock.Unlock() defer chunker.workerLock.Unlock()
self.workerCount -= 1 chunker.workerCount -= 1
} }
func (self *PyramidChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, storageWG, processorWG *sync.WaitGroup) (Key, error) { func (chunker *PyramidChunker) Split(data io.Reader, size int64, chunkC chan *Chunk, storageWG, processorWG *sync.WaitGroup) (Key, error) {
jobC := make(chan *chunkJob, 2*ChunkProcessors) jobC := make(chan *chunkJob, 2*ChunkProcessors)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
errC := make(chan error) errC := make(chan error)
quitC := make(chan bool) quitC := make(chan bool)
rootKey := make([]byte, self.hashSize) rootKey := make([]byte, chunker.hashSize)
chunkLevel := make([][]*TreeEntry, self.branches) chunkLevel := make([][]*TreeEntry, chunker.branches)
wg.Add(1) wg.Add(1)
go self.prepareChunks(false, chunkLevel, data, rootKey, quitC, wg, jobC, processorWG, chunkC, errC, storageWG) go chunker.prepareChunks(false, chunkLevel, data, rootKey, quitC, wg, jobC, processorWG, chunkC, errC, storageWG)
// closes internal error channel if all subprocesses in the workgroup finished // closes internal error channel if all subprocesses in the workgroup finished
go func() { go func() {
@ -204,20 +204,20 @@ func (self *PyramidChunker) Split(data io.Reader, size int64, chunkC chan *Chunk
} }
func (self *PyramidChunker) Append(key Key, data io.Reader, chunkC chan *Chunk, storageWG, processorWG *sync.WaitGroup) (Key, error) { func (chunker *PyramidChunker) Append(key Key, data io.Reader, chunkC chan *Chunk, storageWG, processorWG *sync.WaitGroup) (Key, error) {
quitC := make(chan bool) quitC := make(chan bool)
rootKey := make([]byte, self.hashSize) rootKey := make([]byte, chunker.hashSize)
chunkLevel := make([][]*TreeEntry, self.branches) chunkLevel := make([][]*TreeEntry, chunker.branches)
// Load the right most unfinished tree chunks in every level // Load the right most unfinished tree chunks in every level
self.loadTree(chunkLevel, key, chunkC, quitC) chunker.loadTree(chunkLevel, key, chunkC, quitC)
jobC := make(chan *chunkJob, 2*ChunkProcessors) jobC := make(chan *chunkJob, 2*ChunkProcessors)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
errC := make(chan error) errC := make(chan error)
wg.Add(1) wg.Add(1)
go self.prepareChunks(true, chunkLevel, data, rootKey, quitC, wg, jobC, processorWG, chunkC, errC, storageWG) go chunker.prepareChunks(true, chunkLevel, data, rootKey, quitC, wg, jobC, processorWG, chunkC, errC, storageWG)
// closes internal error channel if all subprocesses in the workgroup finished // closes internal error channel if all subprocesses in the workgroup finished
go func() { go func() {
@ -245,10 +245,10 @@ func (self *PyramidChunker) Append(key Key, data io.Reader, chunkC chan *Chunk,
} }
func (self *PyramidChunker) processor(id int64, jobC chan *chunkJob, chunkC chan *Chunk, errC chan error, quitC chan bool, swg, wwg *sync.WaitGroup) { func (chunker *PyramidChunker) processor(id int64, jobC chan *chunkJob, chunkC chan *Chunk, errC chan error, quitC chan bool, swg, wwg *sync.WaitGroup) {
defer self.decrementWorkerCount() defer chunker.decrementWorkerCount()
hasher := self.hashFunc() hasher := chunker.hashFunc()
if wwg != nil { if wwg != nil {
defer wwg.Done() defer wwg.Done()
} }
@ -259,14 +259,14 @@ func (self *PyramidChunker) processor(id int64, jobC chan *chunkJob, chunkC chan
if !ok { if !ok {
return return
} }
self.processChunk(id, hasher, job, chunkC, swg) chunker.processChunk(id, hasher, job, chunkC, swg)
case <-quitC: case <-quitC:
return return
} }
} }
} }
func (self *PyramidChunker) processChunk(id int64, hasher SwarmHash, job *chunkJob, chunkC chan *Chunk, swg *sync.WaitGroup) { func (chunker *PyramidChunker) processChunk(id int64, hasher SwarmHash, job *chunkJob, chunkC chan *Chunk, swg *sync.WaitGroup) {
hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length
hasher.Write(job.chunk[8:]) // minus 8 []byte length hasher.Write(job.chunk[8:]) // minus 8 []byte length
h := hasher.Sum(nil) h := hasher.Sum(nil)
@ -294,7 +294,7 @@ func (self *PyramidChunker) processChunk(id int64, hasher SwarmHash, job *chunkJ
} }
} }
func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC chan *Chunk, quitC chan bool) error { func (chunker *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC chan *Chunk, quitC chan bool) error {
// Get the root chunk to get the total size // Get the root chunk to get the total size
chunk := retrieve(key, chunkC, quitC) chunk := retrieve(key, chunkC, quitC)
if chunk == nil { if chunk == nil {
@ -302,13 +302,13 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
} }
//if data size is less than a chunk... add a parent with update as pending //if data size is less than a chunk... add a parent with update as pending
if chunk.Size <= self.chunkSize { if chunk.Size <= chunker.chunkSize {
newEntry := &TreeEntry{ newEntry := &TreeEntry{
level: 0, level: 0,
branchCount: 1, branchCount: 1,
subtreeSize: uint64(chunk.Size), subtreeSize: uint64(chunk.Size),
chunk: make([]byte, self.chunkSize+8), chunk: make([]byte, chunker.chunkSize+8),
key: make([]byte, self.hashSize), key: make([]byte, chunker.hashSize),
index: 0, index: 0,
updatePending: true, updatePending: true,
} }
@ -319,13 +319,13 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
var treeSize int64 var treeSize int64
var depth int var depth int
treeSize = self.chunkSize treeSize = chunker.chunkSize
for ; treeSize < chunk.Size; treeSize *= self.branches { for ; treeSize < chunk.Size; treeSize *= chunker.branches {
depth++ depth++
} }
// Add the root chunk entry // Add the root chunk entry
branchCount := int64(len(chunk.SData)-8) / self.hashSize branchCount := int64(len(chunk.SData)-8) / chunker.hashSize
newEntry := &TreeEntry{ newEntry := &TreeEntry{
level: depth - 1, level: depth - 1,
branchCount: branchCount, branchCount: branchCount,
@ -343,14 +343,14 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
//TODO(jmozah): instead of loading finished branches and then trim in the end, //TODO(jmozah): instead of loading finished branches and then trim in the end,
//avoid loading them in the first place //avoid loading them in the first place
for _, ent := range chunkLevel[lvl] { for _, ent := range chunkLevel[lvl] {
branchCount = int64(len(ent.chunk)-8) / self.hashSize branchCount = int64(len(ent.chunk)-8) / chunker.hashSize
for i := int64(0); i < branchCount; i++ { for i := int64(0); i < branchCount; i++ {
key := ent.chunk[8+(i*self.hashSize) : 8+((i+1)*self.hashSize)] key := ent.chunk[8+(i*chunker.hashSize) : 8+((i+1)*chunker.hashSize)]
newChunk := retrieve(key, chunkC, quitC) newChunk := retrieve(key, chunkC, quitC)
if newChunk == nil { if newChunk == nil {
return errLoadingTreeChunk return errLoadingTreeChunk
} }
bewBranchCount := int64(len(newChunk.SData)-8) / self.hashSize bewBranchCount := int64(len(newChunk.SData)-8) / chunker.hashSize
newEntry := &TreeEntry{ newEntry := &TreeEntry{
level: lvl - 1, level: lvl - 1,
branchCount: bewBranchCount, branchCount: bewBranchCount,
@ -365,7 +365,7 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
} }
// We need to get only the right most unfinished branch.. so trim all finished branches // We need to get only the right most unfinished branch.. so trim all finished branches
if int64(len(chunkLevel[lvl-1])) >= self.branches { if int64(len(chunkLevel[lvl-1])) >= chunker.branches {
chunkLevel[lvl-1] = nil chunkLevel[lvl-1] = nil
} }
} }
@ -374,7 +374,7 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
return nil return nil
} }
func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEntry, data io.Reader, rootKey []byte, quitC chan bool, wg *sync.WaitGroup, jobC chan *chunkJob, processorWG *sync.WaitGroup, chunkC chan *Chunk, errC chan error, storageWG *sync.WaitGroup) { func (chunker *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEntry, data io.Reader, rootKey []byte, quitC chan bool, wg *sync.WaitGroup, jobC chan *chunkJob, processorWG *sync.WaitGroup, chunkC chan *Chunk, errC chan error, storageWG *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
chunkWG := &sync.WaitGroup{} chunkWG := &sync.WaitGroup{}
@ -385,10 +385,10 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
processorWG.Add(1) processorWG.Add(1)
} }
self.incrementWorkerCount() chunker.incrementWorkerCount()
go self.processor(self.workerCount, jobC, chunkC, errC, quitC, storageWG, processorWG) go chunker.processor(chunker.workerCount, jobC, chunkC, errC, quitC, storageWG, processorWG)
parent := NewTreeEntry(self) parent := NewTreeEntry(chunker)
var unFinishedChunk *Chunk var unFinishedChunk *Chunk
if isAppend && len(chunkLevel[0]) != 0 { if isAppend && len(chunkLevel[0]) != 0 {
@ -396,7 +396,7 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
lastIndex := len(chunkLevel[0]) - 1 lastIndex := len(chunkLevel[0]) - 1
ent := chunkLevel[0][lastIndex] ent := chunkLevel[0][lastIndex]
if ent.branchCount < self.branches { if ent.branchCount < chunker.branches {
parent = &TreeEntry{ parent = &TreeEntry{
level: 0, level: 0,
branchCount: ent.branchCount, branchCount: ent.branchCount,
@ -408,10 +408,10 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
} }
lastBranch := parent.branchCount - 1 lastBranch := parent.branchCount - 1
lastKey := parent.chunk[8+lastBranch*self.hashSize : 8+(lastBranch+1)*self.hashSize] lastKey := parent.chunk[8+lastBranch*chunker.hashSize : 8+(lastBranch+1)*chunker.hashSize]
unFinishedChunk = retrieve(lastKey, chunkC, quitC) unFinishedChunk = retrieve(lastKey, chunkC, quitC)
if unFinishedChunk.Size < self.chunkSize { if unFinishedChunk.Size < chunker.chunkSize {
parent.subtreeSize = parent.subtreeSize - uint64(unFinishedChunk.Size) parent.subtreeSize = parent.subtreeSize - uint64(unFinishedChunk.Size)
parent.branchCount = parent.branchCount - 1 parent.branchCount = parent.branchCount - 1
@ -425,7 +425,7 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
var n int var n int
var err error var err error
chunkData := make([]byte, self.chunkSize+8) chunkData := make([]byte, chunker.chunkSize+8)
if unFinishedChunk != nil { if unFinishedChunk != nil {
copy(chunkData, unFinishedChunk.SData) copy(chunkData, unFinishedChunk.SData)
n, err = data.Read(chunkData[8+unFinishedChunk.Size:]) n, err = data.Read(chunkData[8+unFinishedChunk.Size:])
@ -441,7 +441,7 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
if parent.branchCount == 1 { if parent.branchCount == 1 {
// Data is exactly one chunk.. pick the last chunk key as root // Data is exactly one chunk.. pick the last chunk key as root
chunkWG.Wait() chunkWG.Wait()
lastChunksKey := parent.chunk[8 : 8+self.hashSize] lastChunksKey := parent.chunk[8 : 8+chunker.hashSize]
copy(rootKey, lastChunksKey) copy(rootKey, lastChunksKey)
break break
} }
@ -453,18 +453,18 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
// Data ended in chunk boundary.. just signal to start bulding tree // Data ended in chunk boundary.. just signal to start bulding tree
if n == 0 { if n == 0 {
self.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, true, rootKey) chunker.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, true, rootKey)
break break
} else { } else {
pkey := self.enqueueDataChunk(chunkData, uint64(n), parent, chunkWG, jobC, quitC) pkey := chunker.enqueueDataChunk(chunkData, uint64(n), parent, chunkWG, jobC, quitC)
// update tree related parent data structures // update tree related parent data structures
parent.subtreeSize += uint64(n) parent.subtreeSize += uint64(n)
parent.branchCount++ parent.branchCount++
// Data got exhausted... signal to send any parent tree related chunks // Data got exhausted... signal to send any parent tree related chunks
if int64(n) < self.chunkSize { if int64(n) < chunker.chunkSize {
// only one data chunk .. so dont add any parent chunk // only one data chunk .. so dont add any parent chunk
if parent.branchCount <= 1 { if parent.branchCount <= 1 {
@ -473,39 +473,39 @@ func (self *PyramidChunker) prepareChunks(isAppend bool, chunkLevel [][]*TreeEnt
break break
} }
self.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, true, rootKey) chunker.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, true, rootKey)
break break
} }
if parent.branchCount == self.branches { if parent.branchCount == chunker.branches {
self.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, false, rootKey) chunker.buildTree(isAppend, chunkLevel, parent, chunkWG, jobC, quitC, false, rootKey)
parent = NewTreeEntry(self) parent = NewTreeEntry(chunker)
} }
} }
workers := self.getWorkerCount() workers := chunker.getWorkerCount()
if int64(len(jobC)) > workers && workers < ChunkProcessors { if int64(len(jobC)) > workers && workers < ChunkProcessors {
if processorWG != nil { if processorWG != nil {
processorWG.Add(1) processorWG.Add(1)
} }
self.incrementWorkerCount() chunker.incrementWorkerCount()
go self.processor(self.workerCount, jobC, chunkC, errC, quitC, storageWG, processorWG) go chunker.processor(chunker.workerCount, jobC, chunkC, errC, quitC, storageWG, processorWG)
} }
} }
} }
func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry, ent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool, last bool, rootKey []byte) { func (chunker *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry, ent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool, last bool, rootKey []byte) {
chunkWG.Wait() chunkWG.Wait()
self.enqueueTreeChunk(chunkLevel, ent, chunkWG, jobC, quitC, last) chunker.enqueueTreeChunk(chunkLevel, ent, chunkWG, jobC, quitC, last)
compress := false compress := false
endLvl := self.branches endLvl := chunker.branches
for lvl := int64(0); lvl < self.branches; lvl++ { for lvl := int64(0); lvl < chunker.branches; lvl++ {
lvlCount := int64(len(chunkLevel[lvl])) lvlCount := int64(len(chunkLevel[lvl]))
if lvlCount >= self.branches { if lvlCount >= chunker.branches {
endLvl = lvl + 1 endLvl = lvl + 1
compress = true compress = true
break break
@ -527,9 +527,9 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
return return
} }
for startCount := int64(0); startCount < lvlCount; startCount += self.branches { for startCount := int64(0); startCount < lvlCount; startCount += chunker.branches {
endCount := startCount + self.branches endCount := startCount + chunker.branches
if endCount > lvlCount { if endCount > lvlCount {
endCount = lvlCount endCount = lvlCount
} }
@ -545,18 +545,18 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
level: int(lvl + 1), level: int(lvl + 1),
branchCount: 0, branchCount: 0,
subtreeSize: 0, subtreeSize: 0,
chunk: make([]byte, self.chunkSize+8), chunk: make([]byte, chunker.chunkSize+8),
key: make([]byte, self.hashSize), key: make([]byte, chunker.hashSize),
index: int(nextLvlCount), index: int(nextLvlCount),
updatePending: true, updatePending: true,
} }
for index := int64(0); index < lvlCount; index++ { for index := int64(0); index < lvlCount; index++ {
updateEntry.branchCount++ updateEntry.branchCount++
updateEntry.subtreeSize += chunkLevel[lvl][index].subtreeSize updateEntry.subtreeSize += chunkLevel[lvl][index].subtreeSize
copy(updateEntry.chunk[8+(index*self.hashSize):8+((index+1)*self.hashSize)], chunkLevel[lvl][index].key[:self.hashSize]) copy(updateEntry.chunk[8+(index*chunker.hashSize):8+((index+1)*chunker.hashSize)], chunkLevel[lvl][index].key[:chunker.hashSize])
} }
self.enqueueTreeChunk(chunkLevel, updateEntry, chunkWG, jobC, quitC, last) chunker.enqueueTreeChunk(chunkLevel, updateEntry, chunkWG, jobC, quitC, last)
} else { } else {
@ -565,8 +565,8 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
level: int(lvl + 1), level: int(lvl + 1),
branchCount: noOfBranches, branchCount: noOfBranches,
subtreeSize: 0, subtreeSize: 0,
chunk: make([]byte, (noOfBranches*self.hashSize)+8), chunk: make([]byte, (noOfBranches*chunker.hashSize)+8),
key: make([]byte, self.hashSize), key: make([]byte, chunker.hashSize),
index: int(nextLvlCount), index: int(nextLvlCount),
updatePending: false, updatePending: false,
} }
@ -575,11 +575,11 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
for i := startCount; i < endCount; i++ { for i := startCount; i < endCount; i++ {
entry := chunkLevel[lvl][i] entry := chunkLevel[lvl][i]
newEntry.subtreeSize += entry.subtreeSize newEntry.subtreeSize += entry.subtreeSize
copy(newEntry.chunk[8+(index*self.hashSize):8+((index+1)*self.hashSize)], entry.key[:self.hashSize]) copy(newEntry.chunk[8+(index*chunker.hashSize):8+((index+1)*chunker.hashSize)], entry.key[:chunker.hashSize])
index++ index++
} }
self.enqueueTreeChunk(chunkLevel, newEntry, chunkWG, jobC, quitC, last) chunker.enqueueTreeChunk(chunkLevel, newEntry, chunkWG, jobC, quitC, last)
} }
@ -595,7 +595,7 @@ func (self *PyramidChunker) buildTree(isAppend bool, chunkLevel [][]*TreeEntry,
} }
func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool, last bool) { func (chunker *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool, last bool) {
if ent != nil { if ent != nil {
// wait for data chunks to get over before processing the tree chunk // wait for data chunks to get over before processing the tree chunk
@ -604,10 +604,10 @@ func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *Tre
} }
binary.LittleEndian.PutUint64(ent.chunk[:8], ent.subtreeSize) binary.LittleEndian.PutUint64(ent.chunk[:8], ent.subtreeSize)
ent.key = make([]byte, self.hashSize) ent.key = make([]byte, chunker.hashSize)
chunkWG.Add(1) chunkWG.Add(1)
select { select {
case jobC <- &chunkJob{ent.key, ent.chunk[:ent.branchCount*self.hashSize+8], int64(ent.subtreeSize), chunkWG, TreeChunk, 0}: case jobC <- &chunkJob{ent.key, ent.chunk[:ent.branchCount*chunker.hashSize+8], int64(ent.subtreeSize), chunkWG, TreeChunk, 0}:
case <-quitC: case <-quitC:
} }
@ -622,9 +622,9 @@ func (self *PyramidChunker) enqueueTreeChunk(chunkLevel [][]*TreeEntry, ent *Tre
} }
} }
func (self *PyramidChunker) enqueueDataChunk(chunkData []byte, size uint64, parent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool) Key { func (chunker *PyramidChunker) enqueueDataChunk(chunkData []byte, size uint64, parent *TreeEntry, chunkWG *sync.WaitGroup, jobC chan *chunkJob, quitC chan bool) Key {
binary.LittleEndian.PutUint64(chunkData[:8], size) binary.LittleEndian.PutUint64(chunkData[:8], size)
pkey := parent.chunk[8+parent.branchCount*self.hashSize : 8+(parent.branchCount+1)*self.hashSize] pkey := parent.chunk[8+parent.branchCount*chunker.hashSize : 8+(parent.branchCount+1)*chunker.hashSize]
chunkWG.Add(1) chunkWG.Add(1)
select { select {

View file

@ -34,7 +34,7 @@ type HashWithLength struct {
hash.Hash hash.Hash
} }
func (self *HashWithLength) ResetWithLength(length []byte) { func (h *HashWithLength) ResetWithLength(length []byte) {
self.Reset() h.Reset()
self.Write(length) h.Write(length)
} }

View file

@ -243,6 +243,6 @@ type LazyTestSectionReader struct {
*io.SectionReader *io.SectionReader
} }
func (self *LazyTestSectionReader) Size(chan bool) (int64, error) { func (reader *LazyTestSectionReader) Size(chan bool) (int64, error) {
return self.SectionReader.Size(), nil return reader.SectionReader.Size(), nil
} }

View file

@ -82,17 +82,17 @@ type SwarmAPI struct {
PrvKey *ecdsa.PrivateKey PrvKey *ecdsa.PrivateKey
} }
func (self *Swarm) API() *SwarmAPI { func (s *Swarm) API() *SwarmAPI {
return &SwarmAPI{ return &SwarmAPI{
Api: self.api, Api: s.api,
Backend: self.backend, Backend: s.backend,
PrvKey: self.privateKey, PrvKey: s.privateKey,
} }
} }
// creates a new swarm service instance // creates a new swarm service instance
// implements node.Service // implements node.Service
func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.Config) (self *Swarm, err error) { func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.Config) (s *Swarm, err error) {
if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) { if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
return nil, fmt.Errorf("empty public key") return nil, fmt.Errorf("empty public key")
} }
@ -100,7 +100,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
return nil, fmt.Errorf("empty bzz key") return nil, fmt.Errorf("empty bzz key")
} }
self = &Swarm{ s = &Swarm{
config: config, config: config,
swapEnabled: config.SwapEnabled, swapEnabled: config.SwapEnabled,
backend: backend, backend: backend,
@ -110,7 +110,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
log.Debug(fmt.Sprintf("Setting up Swarm service components")) log.Debug(fmt.Sprintf("Setting up Swarm service components"))
hash := storage.MakeHashFunc(config.ChunkerParams.Hash) hash := storage.MakeHashFunc(config.ChunkerParams.Hash)
self.lstore, err = storage.NewLocalStore(hash, config.StoreParams) s.lstore, err = storage.NewLocalStore(hash, config.StoreParams)
if err != nil { if err != nil {
return return
} }
@ -118,35 +118,35 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
// setup local store // setup local store
log.Debug(fmt.Sprintf("Set up local storage")) log.Debug(fmt.Sprintf("Set up local storage"))
self.dbAccess = network.NewDbAccess(self.lstore) s.dbAccess = network.NewDbAccess(s.lstore)
log.Debug(fmt.Sprintf("Set up local db access (iterator/counter)")) log.Debug(fmt.Sprintf("Set up local db access (iterator/counter)"))
// set up the kademlia hive // set up the kademlia hive
self.hive = network.NewHive( s.hive = network.NewHive(
common.HexToHash(self.config.BzzKey), // key to hive (kademlia base address) common.HexToHash(s.config.BzzKey), // key to hive (kademlia base address)
config.HiveParams, // configuration parameters config.HiveParams, // configuration parameters
config.SwapEnabled, // SWAP enabled config.SwapEnabled, // SWAP enabled
config.SyncEnabled, // syncronisation enabled config.SyncEnabled, // syncronisation enabled
) )
log.Debug(fmt.Sprintf("Set up swarm network with Kademlia hive")) log.Debug(fmt.Sprintf("Set up swarm network with Kademlia hive"))
// setup cloud storage backend // setup cloud storage backend
self.cloud = network.NewForwarder(self.hive) s.cloud = network.NewForwarder(s.hive)
log.Debug(fmt.Sprintf("-> set swarm forwarder as cloud storage backend")) log.Debug(fmt.Sprintf("-> set swarm forwarder as cloud storage backend"))
// setup cloud storage internal access layer // setup cloud storage internal access layer
self.storage = storage.NewNetStore(hash, self.lstore, self.cloud, config.StoreParams) s.storage = storage.NewNetStore(hash, s.lstore, s.cloud, config.StoreParams)
log.Debug(fmt.Sprintf("-> swarm net store shared access layer to Swarm Chunk Store")) log.Debug(fmt.Sprintf("-> swarm net store shared access layer to Swarm Chunk Store"))
// set up Depo (storage handler = cloud storage access layer for incoming remote requests) // set up Depo (storage handler = cloud storage access layer for incoming remote requests)
self.depo = network.NewDepo(hash, self.lstore, self.storage) s.depo = network.NewDepo(hash, s.lstore, s.storage)
log.Debug(fmt.Sprintf("-> REmote Access to CHunks")) log.Debug(fmt.Sprintf("-> REmote Access to CHunks"))
// set up DPA, the cloud storage local access layer // set up DPA, the cloud storage local access layer
dpaChunkStore := storage.NewDpaChunkStore(self.lstore, self.storage) dpaChunkStore := storage.NewDpaChunkStore(s.lstore, s.storage)
log.Debug(fmt.Sprintf("-> Local Access to Swarm")) log.Debug(fmt.Sprintf("-> Local Access to Swarm"))
// Swarm Hash Merklised Chunking for Arbitrary-length Document/File storage // Swarm Hash Merklised Chunking for Arbitrary-length Document/File storage
self.dpa = storage.NewDPA(dpaChunkStore, self.config.ChunkerParams) s.dpa = storage.NewDPA(dpaChunkStore, s.config.ChunkerParams)
log.Debug(fmt.Sprintf("-> Content Store API")) log.Debug(fmt.Sprintf("-> Content Store API"))
if len(config.EnsAPIs) > 0 { if len(config.EnsAPIs) > 0 {
@ -159,17 +159,17 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
} }
opts = append(opts, api.MultiResolverOptionWithResolver(r, tld)) opts = append(opts, api.MultiResolverOptionWithResolver(r, tld))
} }
self.dns = api.NewMultiResolver(opts...) s.dns = api.NewMultiResolver(opts...)
} }
self.api = api.NewApi(self.dpa, self.dns) s.api = api.NewApi(s.dpa, s.dns)
// Manifests for Smart Hosting // Manifests for Smart Hosting
log.Debug(fmt.Sprintf("-> Web3 virtual server API")) log.Debug(fmt.Sprintf("-> Web3 virtual server API"))
self.sfs = fuse.NewSwarmFS(self.api) s.sfs = fuse.NewSwarmFS(s.api)
log.Debug("-> Initializing Fuse file system") log.Debug("-> Initializing Fuse file system")
return self, nil return s, nil
} }
// parseEnsAPIAddress parses string according to format // parseEnsAPIAddress parses string according to format
@ -272,7 +272,7 @@ Start is called when the stack is started
* TODO: start subservices like sword, swear, swarmdns * TODO: start subservices like sword, swear, swarmdns
*/ */
// implements the node.Service interface // implements the node.Service interface
func (self *Swarm) Start(srv *p2p.Server) error { func (s *Swarm) Start(srv *p2p.Server) error {
startTime = time.Now() startTime = time.Now()
connectPeer := func(url string) error { connectPeer := func(url string) error {
node, err := discover.ParseNode(url) node, err := discover.ParseNode(url)
@ -283,85 +283,85 @@ func (self *Swarm) Start(srv *p2p.Server) error {
return nil return nil
} }
// set chequebook // set chequebook
if self.swapEnabled { if s.swapEnabled {
ctx := context.Background() // The initial setup has no deadline. ctx := context.Background() // The initial setup has no deadline.
err := self.SetChequebook(ctx) err := s.SetChequebook(ctx)
if err != nil { if err != nil {
return fmt.Errorf("Unable to set chequebook for SWAP: %v", err) return fmt.Errorf("Unable to set chequebook for SWAP: %v", err)
} }
log.Debug(fmt.Sprintf("-> cheque book for SWAP: %v", self.config.Swap.Chequebook())) log.Debug(fmt.Sprintf("-> cheque book for SWAP: %v", s.config.Swap.Chequebook()))
} else { } else {
log.Debug(fmt.Sprintf("SWAP disabled: no cheque book set")) log.Debug(fmt.Sprintf("SWAP disabled: no cheque book set"))
} }
log.Warn(fmt.Sprintf("Starting Swarm service")) log.Warn(fmt.Sprintf("Starting Swarm service"))
self.hive.Start( s.hive.Start(
discover.PubkeyID(&srv.PrivateKey.PublicKey), discover.PubkeyID(&srv.PrivateKey.PublicKey),
func() string { return srv.ListenAddr }, func() string { return srv.ListenAddr },
connectPeer, connectPeer,
) )
log.Info(fmt.Sprintf("Swarm network started on bzz address: %v", self.hive.Addr())) log.Info(fmt.Sprintf("Swarm network started on bzz address: %v", s.hive.Addr()))
self.dpa.Start() s.dpa.Start()
log.Debug(fmt.Sprintf("Swarm DPA started")) log.Debug(fmt.Sprintf("Swarm DPA started"))
// start swarm http proxy server // start swarm http proxy server
if self.config.Port != "" { if s.config.Port != "" {
addr := net.JoinHostPort(self.config.ListenAddr, self.config.Port) addr := net.JoinHostPort(s.config.ListenAddr, s.config.Port)
go httpapi.StartHttpServer(self.api, &httpapi.ServerConfig{ go httpapi.StartHttpServer(s.api, &httpapi.ServerConfig{
Addr: addr, Addr: addr,
CorsString: self.corsString, CorsString: s.corsString,
}) })
log.Info(fmt.Sprintf("Swarm http proxy started on %v", addr)) log.Info(fmt.Sprintf("Swarm http proxy started on %v", addr))
if self.corsString != "" { if s.corsString != "" {
log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", self.corsString)) log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", s.corsString))
} }
} }
self.periodicallyUpdateGauges() s.periodicallyUpdateGauges()
startCounter.Inc(1) startCounter.Inc(1)
return nil return nil
} }
func (self *Swarm) periodicallyUpdateGauges() { func (s *Swarm) periodicallyUpdateGauges() {
ticker := time.NewTicker(updateGaugesPeriod) ticker := time.NewTicker(updateGaugesPeriod)
go func() { go func() {
for range ticker.C { for range ticker.C {
self.updateGauges() s.updateGauges()
} }
}() }()
} }
func (self *Swarm) updateGauges() { func (s *Swarm) updateGauges() {
dbSizeGauge.Update(int64(self.lstore.DbCounter())) dbSizeGauge.Update(int64(s.lstore.DbCounter()))
cacheSizeGauge.Update(int64(self.lstore.CacheCounter())) cacheSizeGauge.Update(int64(s.lstore.CacheCounter()))
uptimeGauge.Update(time.Since(startTime).Nanoseconds()) uptimeGauge.Update(time.Since(startTime).Nanoseconds())
} }
// implements the node.Service interface // implements the node.Service interface
// stops all component services. // stops all component services.
func (self *Swarm) Stop() error { func (s *Swarm) Stop() error {
self.dpa.Stop() s.dpa.Stop()
err := self.hive.Stop() err := s.hive.Stop()
if ch := self.config.Swap.Chequebook(); ch != nil { if ch := s.config.Swap.Chequebook(); ch != nil {
ch.Stop() ch.Stop()
ch.Save() ch.Save()
} }
if self.lstore != nil { if s.lstore != nil {
self.lstore.DbStore.Close() s.lstore.DbStore.Close()
} }
self.sfs.Stop() s.sfs.Stop()
stopCounter.Inc(1) stopCounter.Inc(1)
return err return err
} }
// implements the node.Service interface // implements the node.Service interface
func (self *Swarm) Protocols() []p2p.Protocol { func (s *Swarm) Protocols() []p2p.Protocol {
proto, err := network.Bzz(self.depo, self.backend, self.hive, self.dbAccess, self.config.Swap, self.config.SyncParams, self.config.NetworkId) proto, err := network.Bzz(s.depo, s.backend, s.hive, s.dbAccess, s.config.Swap, s.config.SyncParams, s.config.NetworkId)
if err != nil { if err != nil {
return nil return nil
} }
@ -370,32 +370,32 @@ func (self *Swarm) Protocols() []p2p.Protocol {
// implements node.Service // implements node.Service
// Apis returns the RPC Api descriptors the Swarm implementation offers // Apis returns the RPC Api descriptors the Swarm implementation offers
func (self *Swarm) APIs() []rpc.API { func (s *Swarm) APIs() []rpc.API {
return []rpc.API{ return []rpc.API{
// public APIs // public APIs
{ {
Namespace: "bzz", Namespace: "bzz",
Version: "0.1", Version: "0.1",
Service: &Info{self.config, chequebook.ContractParams}, Service: &Info{s.config, chequebook.ContractParams},
Public: true, Public: true,
}, },
// admin APIs // admin APIs
{ {
Namespace: "bzz", Namespace: "bzz",
Version: "0.1", Version: "0.1",
Service: api.NewControl(self.api, self.hive), Service: api.NewControl(s.api, s.hive),
Public: false, Public: false,
}, },
{ {
Namespace: "chequebook", Namespace: "chequebook",
Version: chequebook.Version, Version: chequebook.Version,
Service: chequebook.NewApi(self.config.Swap.Chequebook), Service: chequebook.NewApi(s.config.Swap.Chequebook),
Public: false, Public: false,
}, },
{ {
Namespace: "swarmfs", Namespace: "swarmfs",
Version: fuse.Swarmfs_Version, Version: fuse.Swarmfs_Version,
Service: self.sfs, Service: s.sfs,
Public: false, Public: false,
}, },
// storage APIs // storage APIs
@ -403,36 +403,36 @@ func (self *Swarm) APIs() []rpc.API {
{ {
Namespace: "bzz", Namespace: "bzz",
Version: "0.1", Version: "0.1",
Service: api.NewStorage(self.api), Service: api.NewStorage(s.api),
Public: true, Public: true,
}, },
{ {
Namespace: "bzz", Namespace: "bzz",
Version: "0.1", Version: "0.1",
Service: api.NewFileSystem(self.api), Service: api.NewFileSystem(s.api),
Public: false, Public: false,
}, },
// {Namespace, Version, api.NewAdmin(self), false}, // {Namespace, Version, api.NewAdmin(s), false},
} }
} }
func (self *Swarm) Api() *api.Api { func (s *Swarm) Api() *api.Api {
return self.api return s.api
} }
// SetChequebook ensures that the local checquebook is set up on chain. // SetChequebook ensures that the local checquebook is set up on chain.
func (self *Swarm) SetChequebook(ctx context.Context) error { func (s *Swarm) SetChequebook(ctx context.Context) error {
err := self.config.Swap.SetChequebook(ctx, self.backend, self.config.Path) err := s.config.Swap.SetChequebook(ctx, s.backend, s.config.Path)
if err != nil { if err != nil {
return err return err
} }
log.Info(fmt.Sprintf("new chequebook set (%v): saving config file, resetting all connections in the hive", self.config.Swap.Contract.Hex())) log.Info(fmt.Sprintf("new chequebook set (%v): saving config file, resetting all connections in the hive", s.config.Swap.Contract.Hex()))
self.hive.DropAll() s.hive.DropAll()
return nil return nil
} }
// Local swarm without netStore // Local swarm without netStore
func NewLocalSwarm(datadir, port string) (self *Swarm, err error) { func NewLocalSwarm(datadir, port string) (s *Swarm, err error) {
prvKey, err := crypto.GenerateKey() prvKey, err := crypto.GenerateKey()
if err != nil { if err != nil {
@ -449,7 +449,7 @@ func NewLocalSwarm(datadir, port string) (self *Swarm, err error) {
return return
} }
self = &Swarm{ s = &Swarm{
api: api.NewApi(dpa, nil), api: api.NewApi(dpa, nil),
config: config, config: config,
} }
@ -463,6 +463,6 @@ type Info struct {
*chequebook.Params *chequebook.Params
} }
func (self *Info) Info() *Info { func (s *Info) Info() *Info {
return self return s
} }