github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/swarm/storage/localstore/mode_put.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package localstore 18 19 import ( 20 "github.com/ethereum/go-ethereum/swarm/chunk" 21 "github.com/ethereum/go-ethereum/swarm/shed" 22 "github.com/syndtr/goleveldb/leveldb" 23 ) 24 25 // ModePut enumerates different Putter modes. 26 type ModePut int 27 28 // Putter modes. 29 const ( 30 // ModePutRequest: when a chunk is received as a result of retrieve request and delivery 31 ModePutRequest ModePut = iota 32 // ModePutSync: when a chunk is received via syncing 33 ModePutSync 34 // ModePutUpload: when a chunk is created by local upload 35 ModePutUpload 36 ) 37 38 // Putter provides Put method to store Chunks 39 // to database. 40 type Putter struct { 41 db *DB 42 mode ModePut 43 } 44 45 // NewPutter returns a new Putter on database 46 // with a specific Mode. 47 func (db *DB) NewPutter(mode ModePut) *Putter { 48 return &Putter{ 49 mode: mode, 50 db: db, 51 } 52 } 53 54 // Put stores the Chunk to database and depending 55 // on the Putter mode, it updates required indexes. 56 func (p *Putter) Put(ch chunk.Chunk) (err error) { 57 return p.db.put(p.mode, chunkToItem(ch)) 58 } 59 60 // put stores Item to database and updates other 61 // indexes. It acquires lockAddr to protect two calls 62 // of this function for the same address in parallel. 63 // Item fields Address and Data must not be 64 // with their nil values. 65 func (db *DB) put(mode ModePut, item shed.Item) (err error) { 66 // protect parallel updates 67 db.batchMu.Lock() 68 defer db.batchMu.Unlock() 69 70 batch := new(leveldb.Batch) 71 72 // variables that provide information for operations 73 // to be done after write batch function successfully executes 74 var gcSizeChange int64 // number to add or subtract from gcSize 75 var triggerPullFeed bool // signal pull feed subscriptions to iterate 76 var triggerPushFeed bool // signal push feed subscriptions to iterate 77 78 switch mode { 79 case ModePutRequest: 80 // put to indexes: retrieve, gc; it does not enter the syncpool 81 82 // check if the chunk already is in the database 83 // as gc index is updated 84 i, err := db.retrievalAccessIndex.Get(item) 85 switch err { 86 case nil: 87 item.AccessTimestamp = i.AccessTimestamp 88 case leveldb.ErrNotFound: 89 // no chunk accesses 90 default: 91 return err 92 } 93 i, err = db.retrievalDataIndex.Get(item) 94 switch err { 95 case nil: 96 item.StoreTimestamp = i.StoreTimestamp 97 case leveldb.ErrNotFound: 98 // no chunk accesses 99 default: 100 return err 101 } 102 if item.AccessTimestamp != 0 { 103 // delete current entry from the gc index 104 db.gcIndex.DeleteInBatch(batch, item) 105 gcSizeChange-- 106 } 107 if item.StoreTimestamp == 0 { 108 item.StoreTimestamp = now() 109 } 110 // update access timestamp 111 item.AccessTimestamp = now() 112 // update retrieve access index 113 db.retrievalAccessIndex.PutInBatch(batch, item) 114 // add new entry to gc index 115 db.gcIndex.PutInBatch(batch, item) 116 gcSizeChange++ 117 118 db.retrievalDataIndex.PutInBatch(batch, item) 119 120 case ModePutUpload: 121 // put to indexes: retrieve, push, pull 122 123 item.StoreTimestamp = now() 124 db.retrievalDataIndex.PutInBatch(batch, item) 125 db.pullIndex.PutInBatch(batch, item) 126 triggerPullFeed = true 127 db.pushIndex.PutInBatch(batch, item) 128 triggerPushFeed = true 129 130 case ModePutSync: 131 // put to indexes: retrieve, pull 132 133 item.StoreTimestamp = now() 134 db.retrievalDataIndex.PutInBatch(batch, item) 135 db.pullIndex.PutInBatch(batch, item) 136 triggerPullFeed = true 137 138 default: 139 return ErrInvalidMode 140 } 141 142 err = db.incGCSizeInBatch(batch, gcSizeChange) 143 if err != nil { 144 return err 145 } 146 147 err = db.shed.WriteBatch(batch) 148 if err != nil { 149 return err 150 } 151 if triggerPullFeed { 152 db.triggerPullSubscriptions(db.po(item.Address)) 153 } 154 if triggerPushFeed { 155 db.triggerPushSubscriptions() 156 } 157 return nil 158 }