| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | package ethdb | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2014-08-23 11:00:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 17:06:15 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/compression/rle" | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb" | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb/iterator" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type LDBDatabase struct { | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	fn string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mu sync.Mutex | 
					
						
							|  |  |  | 	db *leveldb.DB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	queue map[string][]byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	quit chan struct{} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-06 02:46:56 +01:00
										 |  |  | func NewLDBDatabase(file string) (*LDBDatabase, error) { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Open the db | 
					
						
							| 
									
										
										
										
											2015-03-06 02:46:56 +01:00
										 |  |  | 	db, err := leveldb.OpenFile(file, nil) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	database := &LDBDatabase{ | 
					
						
							|  |  |  | 		fn:   file, | 
					
						
							|  |  |  | 		db:   db, | 
					
						
							|  |  |  | 		quit: make(chan struct{}), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	database.makeQueue() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	return database, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | func (self *LDBDatabase) makeQueue() { | 
					
						
							|  |  |  | 	self.queue = make(map[string][]byte) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Put(key []byte, value []byte) { | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self.queue[string(key)] = value | 
					
						
							|  |  |  | 	/* | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | 		value = rle.Compress(value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 		err := self.db.Put(key, value, nil) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			fmt.Println("Error put", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Get(key []byte) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check queue first | 
					
						
							|  |  |  | 	if dat, ok := self.queue[string(key)]; ok { | 
					
						
							|  |  |  | 		return dat, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | 	dat, err := self.db.Get(key, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	return rle.Decompress(dat) | 
					
						
							| 
									
										
										
										
											2014-02-24 12:12:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Delete(key []byte) error { | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// make sure it's not in the queue | 
					
						
							|  |  |  | 	delete(self.queue, string(key)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | 	return self.db.Delete(key, nil) | 
					
						
							| 
									
										
										
										
											2014-02-25 11:21:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) LastKnownTD() []byte { | 
					
						
							|  |  |  | 	data, _ := self.Get([]byte("LTD")) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(data) == 0 { | 
					
						
							|  |  |  | 		data = []byte{0x0} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) NewIterator() iterator.Iterator { | 
					
						
							|  |  |  | 	return self.db.NewIterator(nil, nil) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | func (self *LDBDatabase) Flush() error { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	batch := new(leveldb.Batch) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for key, value := range self.queue { | 
					
						
							|  |  |  | 		batch.Put([]byte(key), rle.Compress(value)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	self.makeQueue() // reset the queue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-22 12:46:41 +02:00
										 |  |  | 	glog.V(logger.Detail).Infoln("Flush database: ", self.fn) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-23 15:18:48 +01:00
										 |  |  | 	return self.db.Write(batch, nil) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Close() { | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	if err := self.Flush(); err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Error).Infof("error: flush '%s': %v\n", self.fn, err) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	self.db.Close() | 
					
						
							| 
									
										
										
										
											2015-04-22 12:46:41 +02:00
										 |  |  | 	glog.V(logger.Error).Infoln("flushed and closed db:", self.fn) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } |