| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | package ethdb | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb/errors" | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb/iterator" | 
					
						
							| 
									
										
										
										
											2015-05-10 01:55:39 +02:00
										 |  |  | 	"github.com/syndtr/goleveldb/leveldb/opt" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 11:28:33 +02:00
										 |  |  | var OpenFileLimit = 64 | 
					
						
							| 
									
										
										
										
											2015-05-10 01:55:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | type LDBDatabase struct { | 
					
						
							| 
									
										
										
										
											2015-05-27 18:03:16 +02:00
										 |  |  | 	// filename for reporting | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	fn string | 
					
						
							| 
									
										
										
										
											2015-05-27 18:03:16 +02:00
										 |  |  | 	// LevelDB instance | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	db *leveldb.DB | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | // NewLDBDatabase returns a LevelDB wrapped object. LDBDatabase does not persist data by | 
					
						
							|  |  |  | // it self but requires a background poller which syncs every X. `Flush` should be called | 
					
						
							|  |  |  | // when data needs to be stored and written to disk. | 
					
						
							| 
									
										
										
										
											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-05-12 11:28:33 +02:00
										 |  |  | 	db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit}) | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | 	// check for curruption and attempt to recover | 
					
						
							|  |  |  | 	if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { | 
					
						
							|  |  |  | 		db, err = leveldb.RecoverFile(file, nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// (re) check for errors and abort if opening of the db failed | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	database := &LDBDatabase{ | 
					
						
							| 
									
										
										
										
											2015-05-27 18:03:16 +02:00
										 |  |  | 		fn: file, | 
					
						
							|  |  |  | 		db: db, | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	return database, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | // Put puts the given key / value to the queue | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Put(key []byte, value []byte) { | 
					
						
							| 
									
										
										
										
											2015-05-27 18:03:16 +02:00
										 |  |  | 	self.db.Put(key, rle.Compress(value), nil) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | // Get returns the given key if it's present. | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Get(key []byte) ([]byte, error) { | 
					
						
							|  |  |  | 	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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | // Delete deletes the key from the queue and database | 
					
						
							| 
									
										
										
										
											2014-11-03 00:31:15 +01:00
										 |  |  | func (self *LDBDatabase) Delete(key []byte) error { | 
					
						
							|  |  |  | 	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) NewIterator() iterator.Iterator { | 
					
						
							|  |  |  | 	return self.db.NewIterator(nil, nil) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 11:43:05 +02:00
										 |  |  | // Flush flushes out the queue to leveldb | 
					
						
							| 
									
										
										
										
											2015-04-07 22:19:01 +02:00
										 |  |  | func (self *LDBDatabase) Flush() error { | 
					
						
							| 
									
										
										
										
											2015-05-27 18:03:16 +02:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-12-23 15:18:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } |