db.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. package bolt
  2. import (
  3. "errors"
  4. "fmt"
  5. "hash/fnv"
  6. "log"
  7. "os"
  8. "runtime"
  9. "runtime/debug"
  10. "strings"
  11. "sync"
  12. "time"
  13. "unsafe"
  14. )
  15. // The largest step that can be taken when remapping the mmap.
  16. const maxMmapStep = 1 << 30 // 1GB
  17. // The data file format version.
  18. const version = 2
  19. // Represents a marker value to indicate that a file is a Bolt DB.
  20. const magic uint32 = 0xED0CDAED
  21. // IgnoreNoSync specifies whether the NoSync field of a DB is ignored when
  22. // syncing changes to a file. This is required as some operating systems,
  23. // such as OpenBSD, do not have a unified buffer cache (UBC) and writes
  24. // must be synchronized using the msync(2) syscall.
  25. const IgnoreNoSync = runtime.GOOS == "openbsd"
  26. // Default values if not set in a DB instance.
  27. const (
  28. DefaultMaxBatchSize int = 1000
  29. DefaultMaxBatchDelay = 10 * time.Millisecond
  30. DefaultAllocSize = 16 * 1024 * 1024
  31. )
  32. // DB represents a collection of buckets persisted to a file on disk.
  33. // All data access is performed through transactions which can be obtained through the DB.
  34. // All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
  35. type DB struct {
  36. // When enabled, the database will perform a Check() after every commit.
  37. // A panic is issued if the database is in an inconsistent state. This
  38. // flag has a large performance impact so it should only be used for
  39. // debugging purposes.
  40. StrictMode bool
  41. // Setting the NoSync flag will cause the database to skip fsync()
  42. // calls after each commit. This can be useful when bulk loading data
  43. // into a database and you can restart the bulk load in the event of
  44. // a system failure or database corruption. Do not set this flag for
  45. // normal use.
  46. //
  47. // If the package global IgnoreNoSync constant is true, this value is
  48. // ignored. See the comment on that constant for more details.
  49. //
  50. // THIS IS UNSAFE. PLEASE USE WITH CAUTION.
  51. NoSync bool
  52. // When true, skips the truncate call when growing the database.
  53. // Setting this to true is only safe on non-ext3/ext4 systems.
  54. // Skipping truncation avoids preallocation of hard drive space and
  55. // bypasses a truncate() and fsync() syscall on remapping.
  56. //
  57. // https://github.com/boltdb/bolt/issues/284
  58. NoGrowSync bool
  59. // If you want to read the entire database fast, you can set MmapFlag to
  60. // syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead.
  61. MmapFlags int
  62. // MaxBatchSize is the maximum size of a batch. Default value is
  63. // copied from DefaultMaxBatchSize in Open.
  64. //
  65. // If <=0, disables batching.
  66. //
  67. // Do not change concurrently with calls to Batch.
  68. MaxBatchSize int
  69. // MaxBatchDelay is the maximum delay before a batch starts.
  70. // Default value is copied from DefaultMaxBatchDelay in Open.
  71. //
  72. // If <=0, effectively disables batching.
  73. //
  74. // Do not change concurrently with calls to Batch.
  75. MaxBatchDelay time.Duration
  76. // AllocSize is the amount of space allocated when the database
  77. // needs to create new pages. This is done to amortize the cost
  78. // of truncate() and fsync() when growing the data file.
  79. AllocSize int
  80. path string
  81. file *os.File
  82. lockfile *os.File // windows only
  83. dataref []byte // mmap'ed readonly, write throws SEGV
  84. data *[maxMapSize]byte
  85. datasz int
  86. filesz int // current on disk file size
  87. meta0 *meta
  88. meta1 *meta
  89. pageSize int
  90. opened bool
  91. rwtx *Tx
  92. txs []*Tx
  93. freelist *freelist
  94. stats Stats
  95. batchMu sync.Mutex
  96. batch *batch
  97. rwlock sync.Mutex // Allows only one writer at a time.
  98. metalock sync.Mutex // Protects meta page access.
  99. mmaplock sync.RWMutex // Protects mmap access during remapping.
  100. statlock sync.RWMutex // Protects stats access.
  101. ops struct {
  102. writeAt func(b []byte, off int64) (n int, err error)
  103. }
  104. // Read only mode.
  105. // When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately.
  106. readOnly bool
  107. }
  108. // Path returns the path to currently open database file.
  109. func (db *DB) Path() string {
  110. return db.path
  111. }
  112. // GoString returns the Go string representation of the database.
  113. func (db *DB) GoString() string {
  114. return fmt.Sprintf("bolt.DB{path:%q}", db.path)
  115. }
  116. // String returns the string representation of the database.
  117. func (db *DB) String() string {
  118. return fmt.Sprintf("DB<%q>", db.path)
  119. }
  120. // Open creates and opens a database at the given path.
  121. // If the file does not exist then it will be created automatically.
  122. // Passing in nil options will cause Bolt to open the database with the default options.
  123. func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
  124. var db = &DB{opened: true}
  125. // Set default options if no options are provided.
  126. if options == nil {
  127. options = DefaultOptions
  128. }
  129. db.NoGrowSync = options.NoGrowSync
  130. db.MmapFlags = options.MmapFlags
  131. // Set default values for later DB operations.
  132. db.MaxBatchSize = DefaultMaxBatchSize
  133. db.MaxBatchDelay = DefaultMaxBatchDelay
  134. db.AllocSize = DefaultAllocSize
  135. flag := os.O_RDWR
  136. if options.ReadOnly {
  137. flag = os.O_RDONLY
  138. db.readOnly = true
  139. }
  140. // Open data file and separate sync handler for metadata writes.
  141. db.path = path
  142. var err error
  143. if db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode); err != nil {
  144. _ = db.close()
  145. return nil, err
  146. }
  147. // Lock file so that other processes using Bolt in read-write mode cannot
  148. // use the database at the same time. This would cause corruption since
  149. // the two processes would write meta pages and free pages separately.
  150. // The database file is locked exclusively (only one process can grab the lock)
  151. // if !options.ReadOnly.
  152. // The database file is locked using the shared lock (more than one process may
  153. // hold a lock at the same time) otherwise (options.ReadOnly is set).
  154. if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil {
  155. _ = db.close()
  156. return nil, err
  157. }
  158. // Default values for test hooks
  159. db.ops.writeAt = db.file.WriteAt
  160. // Initialize the database if it doesn't exist.
  161. if info, err := db.file.Stat(); err != nil {
  162. return nil, err
  163. } else if info.Size() == 0 {
  164. // Initialize new files with meta pages.
  165. if err := db.init(); err != nil {
  166. return nil, err
  167. }
  168. } else {
  169. // Read the first meta page to determine the page size.
  170. var buf [0x1000]byte
  171. if _, err := db.file.ReadAt(buf[:], 0); err == nil {
  172. m := db.pageInBuffer(buf[:], 0).meta()
  173. if err := m.validate(); err != nil {
  174. return nil, err
  175. }
  176. db.pageSize = int(m.pageSize)
  177. }
  178. }
  179. // Memory map the data file.
  180. if err := db.mmap(options.InitialMmapSize); err != nil {
  181. _ = db.close()
  182. return nil, err
  183. }
  184. // Read in the freelist.
  185. db.freelist = newFreelist()
  186. db.freelist.read(db.page(db.meta().freelist))
  187. // Mark the database as opened and return.
  188. return db, nil
  189. }
  190. // mmap opens the underlying memory-mapped file and initializes the meta references.
  191. // minsz is the minimum size that the new mmap can be.
  192. func (db *DB) mmap(minsz int) error {
  193. db.mmaplock.Lock()
  194. defer db.mmaplock.Unlock()
  195. info, err := db.file.Stat()
  196. if err != nil {
  197. return fmt.Errorf("mmap stat error: %s", err)
  198. } else if int(info.Size()) < db.pageSize*2 {
  199. return fmt.Errorf("file size too small")
  200. }
  201. // Ensure the size is at least the minimum size.
  202. var size = int(info.Size())
  203. if size < minsz {
  204. size = minsz
  205. }
  206. size, err = db.mmapSize(size)
  207. if err != nil {
  208. return err
  209. }
  210. // Dereference all mmap references before unmapping.
  211. if db.rwtx != nil {
  212. db.rwtx.root.dereference()
  213. }
  214. // Unmap existing data before continuing.
  215. if err := db.munmap(); err != nil {
  216. return err
  217. }
  218. // Memory-map the data file as a byte slice.
  219. if err := mmap(db, size); err != nil {
  220. return err
  221. }
  222. // Save references to the meta pages.
  223. db.meta0 = db.page(0).meta()
  224. db.meta1 = db.page(1).meta()
  225. // Validate the meta pages.
  226. if err := db.meta0.validate(); err != nil {
  227. return err
  228. }
  229. if err := db.meta1.validate(); err != nil {
  230. return err
  231. }
  232. return nil
  233. }
  234. // munmap unmaps the data file from memory.
  235. func (db *DB) munmap() error {
  236. if err := munmap(db); err != nil {
  237. return fmt.Errorf("unmap error: " + err.Error())
  238. }
  239. return nil
  240. }
  241. // mmapSize determines the appropriate size for the mmap given the current size
  242. // of the database. The minimum size is 32KB and doubles until it reaches 1GB.
  243. // Returns an error if the new mmap size is greater than the max allowed.
  244. func (db *DB) mmapSize(size int) (int, error) {
  245. // Double the size from 32KB until 1GB.
  246. for i := uint(15); i <= 30; i++ {
  247. if size <= 1<<i {
  248. return 1 << i, nil
  249. }
  250. }
  251. // Verify the requested size is not above the maximum allowed.
  252. if size > maxMapSize {
  253. return 0, fmt.Errorf("mmap too large")
  254. }
  255. // If larger than 1GB then grow by 1GB at a time.
  256. sz := int64(size)
  257. if remainder := sz % int64(maxMmapStep); remainder > 0 {
  258. sz += int64(maxMmapStep) - remainder
  259. }
  260. // Ensure that the mmap size is a multiple of the page size.
  261. // This should always be true since we're incrementing in MBs.
  262. pageSize := int64(db.pageSize)
  263. if (sz % pageSize) != 0 {
  264. sz = ((sz / pageSize) + 1) * pageSize
  265. }
  266. // If we've exceeded the max size then only grow up to the max size.
  267. if sz > maxMapSize {
  268. sz = maxMapSize
  269. }
  270. return int(sz), nil
  271. }
  272. // init creates a new database file and initializes its meta pages.
  273. func (db *DB) init() error {
  274. // Set the page size to the OS page size.
  275. db.pageSize = os.Getpagesize()
  276. // Create two meta pages on a buffer.
  277. buf := make([]byte, db.pageSize*4)
  278. for i := 0; i < 2; i++ {
  279. p := db.pageInBuffer(buf[:], pgid(i))
  280. p.id = pgid(i)
  281. p.flags = metaPageFlag
  282. // Initialize the meta page.
  283. m := p.meta()
  284. m.magic = magic
  285. m.version = version
  286. m.pageSize = uint32(db.pageSize)
  287. m.freelist = 2
  288. m.root = bucket{root: 3}
  289. m.pgid = 4
  290. m.txid = txid(i)
  291. }
  292. // Write an empty freelist at page 3.
  293. p := db.pageInBuffer(buf[:], pgid(2))
  294. p.id = pgid(2)
  295. p.flags = freelistPageFlag
  296. p.count = 0
  297. // Write an empty leaf page at page 4.
  298. p = db.pageInBuffer(buf[:], pgid(3))
  299. p.id = pgid(3)
  300. p.flags = leafPageFlag
  301. p.count = 0
  302. // Write the buffer to our data file.
  303. if _, err := db.ops.writeAt(buf, 0); err != nil {
  304. return err
  305. }
  306. if err := fdatasync(db); err != nil {
  307. return err
  308. }
  309. return nil
  310. }
  311. // Close releases all database resources.
  312. // All transactions must be closed before closing the database.
  313. func (db *DB) Close() error {
  314. db.rwlock.Lock()
  315. defer db.rwlock.Unlock()
  316. db.metalock.Lock()
  317. defer db.metalock.Unlock()
  318. db.mmaplock.RLock()
  319. defer db.mmaplock.RUnlock()
  320. return db.close()
  321. }
  322. func (db *DB) close() error {
  323. if !db.opened {
  324. return nil
  325. }
  326. db.opened = false
  327. db.freelist = nil
  328. db.path = ""
  329. // Clear ops.
  330. db.ops.writeAt = nil
  331. // Close the mmap.
  332. if err := db.munmap(); err != nil {
  333. return err
  334. }
  335. // Close file handles.
  336. if db.file != nil {
  337. // No need to unlock read-only file.
  338. if !db.readOnly {
  339. // Unlock the file.
  340. if err := funlock(db); err != nil {
  341. log.Printf("bolt.Close(): funlock error: %s", err)
  342. }
  343. }
  344. // Close the file descriptor.
  345. if err := db.file.Close(); err != nil {
  346. return fmt.Errorf("db file close: %s", err)
  347. }
  348. db.file = nil
  349. }
  350. return nil
  351. }
  352. // Begin starts a new transaction.
  353. // Multiple read-only transactions can be used concurrently but only one
  354. // write transaction can be used at a time. Starting multiple write transactions
  355. // will cause the calls to block and be serialized until the current write
  356. // transaction finishes.
  357. //
  358. // Transactions should not be dependent on one another. Opening a read
  359. // transaction and a write transaction in the same goroutine can cause the
  360. // writer to deadlock because the database periodically needs to re-mmap itself
  361. // as it grows and it cannot do that while a read transaction is open.
  362. //
  363. // If a long running read transaction (for example, a snapshot transaction) is
  364. // needed, you might want to set DB.InitialMmapSize to a large enough value
  365. // to avoid potential blocking of write transaction.
  366. //
  367. // IMPORTANT: You must close read-only transactions after you are finished or
  368. // else the database will not reclaim old pages.
  369. func (db *DB) Begin(writable bool) (*Tx, error) {
  370. if writable {
  371. return db.beginRWTx()
  372. }
  373. return db.beginTx()
  374. }
  375. func (db *DB) beginTx() (*Tx, error) {
  376. // Lock the meta pages while we initialize the transaction. We obtain
  377. // the meta lock before the mmap lock because that's the order that the
  378. // write transaction will obtain them.
  379. db.metalock.Lock()
  380. // Obtain a read-only lock on the mmap. When the mmap is remapped it will
  381. // obtain a write lock so all transactions must finish before it can be
  382. // remapped.
  383. db.mmaplock.RLock()
  384. // Exit if the database is not open yet.
  385. if !db.opened {
  386. db.mmaplock.RUnlock()
  387. db.metalock.Unlock()
  388. return nil, ErrDatabaseNotOpen
  389. }
  390. // Create a transaction associated with the database.
  391. t := &Tx{}
  392. t.init(db)
  393. // Keep track of transaction until it closes.
  394. db.txs = append(db.txs, t)
  395. n := len(db.txs)
  396. // Unlock the meta pages.
  397. db.metalock.Unlock()
  398. // Update the transaction stats.
  399. db.statlock.Lock()
  400. db.stats.TxN++
  401. db.stats.OpenTxN = n
  402. db.statlock.Unlock()
  403. return t, nil
  404. }
  405. func (db *DB) beginRWTx() (*Tx, error) {
  406. // If the database was opened with Options.ReadOnly, return an error.
  407. if db.readOnly {
  408. return nil, ErrDatabaseReadOnly
  409. }
  410. // Obtain writer lock. This is released by the transaction when it closes.
  411. // This enforces only one writer transaction at a time.
  412. db.rwlock.Lock()
  413. // Once we have the writer lock then we can lock the meta pages so that
  414. // we can set up the transaction.
  415. db.metalock.Lock()
  416. defer db.metalock.Unlock()
  417. // Exit if the database is not open yet.
  418. if !db.opened {
  419. db.rwlock.Unlock()
  420. return nil, ErrDatabaseNotOpen
  421. }
  422. // Create a transaction associated with the database.
  423. t := &Tx{writable: true}
  424. t.init(db)
  425. db.rwtx = t
  426. // Free any pages associated with closed read-only transactions.
  427. var minid txid = 0xFFFFFFFFFFFFFFFF
  428. for _, t := range db.txs {
  429. if t.meta.txid < minid {
  430. minid = t.meta.txid
  431. }
  432. }
  433. if minid > 0 {
  434. db.freelist.release(minid - 1)
  435. }
  436. return t, nil
  437. }
  438. // removeTx removes a transaction from the database.
  439. func (db *DB) removeTx(tx *Tx) {
  440. // Release the read lock on the mmap.
  441. db.mmaplock.RUnlock()
  442. // Use the meta lock to restrict access to the DB object.
  443. db.metalock.Lock()
  444. // Remove the transaction.
  445. for i, t := range db.txs {
  446. if t == tx {
  447. db.txs = append(db.txs[:i], db.txs[i+1:]...)
  448. break
  449. }
  450. }
  451. n := len(db.txs)
  452. // Unlock the meta pages.
  453. db.metalock.Unlock()
  454. // Merge statistics.
  455. db.statlock.Lock()
  456. db.stats.OpenTxN = n
  457. db.stats.TxStats.add(&tx.stats)
  458. db.statlock.Unlock()
  459. }
  460. // Update executes a function within the context of a read-write managed transaction.
  461. // If no error is returned from the function then the transaction is committed.
  462. // If an error is returned then the entire transaction is rolled back.
  463. // Any error that is returned from the function or returned from the commit is
  464. // returned from the Update() method.
  465. //
  466. // Attempting to manually commit or rollback within the function will cause a panic.
  467. func (db *DB) Update(fn func(*Tx) error) error {
  468. t, err := db.Begin(true)
  469. if err != nil {
  470. return err
  471. }
  472. // Make sure the transaction rolls back in the event of a panic.
  473. defer func() {
  474. if t.db != nil {
  475. t.rollback()
  476. }
  477. }()
  478. // Mark as a managed tx so that the inner function cannot manually commit.
  479. t.managed = true
  480. // If an error is returned from the function then rollback and return error.
  481. err = fn(t)
  482. t.managed = false
  483. if err != nil {
  484. _ = t.Rollback()
  485. return err
  486. }
  487. return t.Commit()
  488. }
  489. // View executes a function within the context of a managed read-only transaction.
  490. // Any error that is returned from the function is returned from the View() method.
  491. //
  492. // Attempting to manually rollback within the function will cause a panic.
  493. func (db *DB) View(fn func(*Tx) error) error {
  494. t, err := db.Begin(false)
  495. if err != nil {
  496. return err
  497. }
  498. // Make sure the transaction rolls back in the event of a panic.
  499. defer func() {
  500. if t.db != nil {
  501. t.rollback()
  502. }
  503. }()
  504. // Mark as a managed tx so that the inner function cannot manually rollback.
  505. t.managed = true
  506. // If an error is returned from the function then pass it through.
  507. err = fn(t)
  508. t.managed = false
  509. if err != nil {
  510. _ = t.Rollback()
  511. return err
  512. }
  513. if err := t.Rollback(); err != nil {
  514. return err
  515. }
  516. return nil
  517. }
  518. // Batch calls fn as part of a batch. It behaves similar to Update,
  519. // except:
  520. //
  521. // 1. concurrent Batch calls can be combined into a single Bolt
  522. // transaction.
  523. //
  524. // 2. the function passed to Batch may be called multiple times,
  525. // regardless of whether it returns error or not.
  526. //
  527. // This means that Batch function side effects must be idempotent and
  528. // take permanent effect only after a successful return is seen in
  529. // caller.
  530. //
  531. // The maximum batch size and delay can be adjusted with DB.MaxBatchSize
  532. // and DB.MaxBatchDelay, respectively.
  533. //
  534. // Batch is only useful when there are multiple goroutines calling it.
  535. func (db *DB) Batch(fn func(*Tx) error) error {
  536. errCh := make(chan error, 1)
  537. db.batchMu.Lock()
  538. if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) {
  539. // There is no existing batch, or the existing batch is full; start a new one.
  540. db.batch = &batch{
  541. db: db,
  542. }
  543. db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger)
  544. }
  545. db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh})
  546. if len(db.batch.calls) >= db.MaxBatchSize {
  547. // wake up batch, it's ready to run
  548. go db.batch.trigger()
  549. }
  550. db.batchMu.Unlock()
  551. err := <-errCh
  552. if err == trySolo {
  553. err = db.Update(fn)
  554. }
  555. return err
  556. }
  557. type call struct {
  558. fn func(*Tx) error
  559. err chan<- error
  560. }
  561. type batch struct {
  562. db *DB
  563. timer *time.Timer
  564. start sync.Once
  565. calls []call
  566. }
  567. // trigger runs the batch if it hasn't already been run.
  568. func (b *batch) trigger() {
  569. b.start.Do(b.run)
  570. }
  571. // run performs the transactions in the batch and communicates results
  572. // back to DB.Batch.
  573. func (b *batch) run() {
  574. b.db.batchMu.Lock()
  575. b.timer.Stop()
  576. // Make sure no new work is added to this batch, but don't break
  577. // other batches.
  578. if b.db.batch == b {
  579. b.db.batch = nil
  580. }
  581. b.db.batchMu.Unlock()
  582. retry:
  583. for len(b.calls) > 0 {
  584. var failIdx = -1
  585. err := b.db.Update(func(tx *Tx) error {
  586. for i, c := range b.calls {
  587. if err := safelyCall(c.fn, tx); err != nil {
  588. failIdx = i
  589. return err
  590. }
  591. }
  592. return nil
  593. })
  594. if failIdx >= 0 {
  595. // take the failing transaction out of the batch. it's
  596. // safe to shorten b.calls here because db.batch no longer
  597. // points to us, and we hold the mutex anyway.
  598. c := b.calls[failIdx]
  599. b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1]
  600. // tell the submitter re-run it solo, continue with the rest of the batch
  601. c.err <- trySolo
  602. continue retry
  603. }
  604. // pass success, or bolt internal errors, to all callers
  605. for _, c := range b.calls {
  606. if c.err != nil {
  607. c.err <- err
  608. }
  609. }
  610. break retry
  611. }
  612. }
  613. // trySolo is a special sentinel error value used for signaling that a
  614. // transaction function should be re-run. It should never be seen by
  615. // callers.
  616. var trySolo = errors.New("batch function returned an error and should be re-run solo")
  617. type panicked struct {
  618. reason interface{}
  619. }
  620. func (p panicked) Error() string {
  621. if err, ok := p.reason.(error); ok {
  622. return err.Error()
  623. }
  624. return fmt.Sprintf("panic: %v", p.reason)
  625. }
  626. func safelyCall(fn func(*Tx) error, tx *Tx) (err error) {
  627. defer func() {
  628. if p := recover(); p != nil {
  629. err = panicked{p}
  630. }
  631. }()
  632. return fn(tx)
  633. }
  634. // Sync executes fdatasync() against the database file handle.
  635. //
  636. // This is not necessary under normal operation, however, if you use NoSync
  637. // then it allows you to force the database file to sync against the disk.
  638. func (db *DB) Sync() error { return fdatasync(db) }
  639. // Stats retrieves ongoing performance stats for the database.
  640. // This is only updated when a transaction closes.
  641. func (db *DB) Stats() Stats {
  642. db.statlock.RLock()
  643. defer db.statlock.RUnlock()
  644. return db.stats
  645. }
  646. // This is for internal access to the raw data bytes from the C cursor, use
  647. // carefully, or not at all.
  648. func (db *DB) Info() *Info {
  649. return &Info{uintptr(unsafe.Pointer(&db.data[0])), db.pageSize}
  650. }
  651. // page retrieves a page reference from the mmap based on the current page size.
  652. func (db *DB) page(id pgid) *page {
  653. pos := id * pgid(db.pageSize)
  654. return (*page)(unsafe.Pointer(&db.data[pos]))
  655. }
  656. // pageInBuffer retrieves a page reference from a given byte array based on the current page size.
  657. func (db *DB) pageInBuffer(b []byte, id pgid) *page {
  658. return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)]))
  659. }
  660. // meta retrieves the current meta page reference.
  661. func (db *DB) meta() *meta {
  662. if db.meta0.txid > db.meta1.txid {
  663. return db.meta0
  664. }
  665. return db.meta1
  666. }
  667. // allocate returns a contiguous block of memory starting at a given page.
  668. func (db *DB) allocate(count int) (*page, error) {
  669. // Allocate a temporary buffer for the page.
  670. buf := make([]byte, count*db.pageSize)
  671. p := (*page)(unsafe.Pointer(&buf[0]))
  672. p.overflow = uint32(count - 1)
  673. // Use pages from the freelist if they are available.
  674. if p.id = db.freelist.allocate(count); p.id != 0 {
  675. return p, nil
  676. }
  677. // Resize mmap() if we're at the end.
  678. p.id = db.rwtx.meta.pgid
  679. var minsz = int((p.id+pgid(count))+1) * db.pageSize
  680. if minsz >= db.datasz {
  681. if err := db.mmap(minsz); err != nil {
  682. return nil, fmt.Errorf("mmap allocate error: %s", err)
  683. }
  684. }
  685. // Move the page id high water mark.
  686. db.rwtx.meta.pgid += pgid(count)
  687. return p, nil
  688. }
  689. // grow grows the size of the database to the given sz.
  690. func (db *DB) grow(sz int) error {
  691. // Ignore if the new size is less than available file size.
  692. if sz <= db.filesz {
  693. return nil
  694. }
  695. // If the data is smaller than the alloc size then only allocate what's needed.
  696. // Once it goes over the allocation size then allocate in chunks.
  697. if db.datasz < db.AllocSize {
  698. sz = db.datasz
  699. } else {
  700. sz += db.AllocSize
  701. }
  702. // Truncate and fsync to ensure file size metadata is flushed.
  703. // https://github.com/boltdb/bolt/issues/284
  704. if !db.NoGrowSync && !db.readOnly {
  705. if runtime.GOOS != "windows" {
  706. if err := db.file.Truncate(int64(sz)); err != nil {
  707. return fmt.Errorf("file resize error: %s", err)
  708. }
  709. }
  710. if err := db.file.Sync(); err != nil {
  711. return fmt.Errorf("file sync error: %s", err)
  712. }
  713. }
  714. db.filesz = sz
  715. return nil
  716. }
  717. func (db *DB) IsReadOnly() bool {
  718. return db.readOnly
  719. }
  720. // Options represents the options that can be set when opening a database.
  721. type Options struct {
  722. // Timeout is the amount of time to wait to obtain a file lock.
  723. // When set to zero it will wait indefinitely. This option is only
  724. // available on Darwin and Linux.
  725. Timeout time.Duration
  726. // Sets the DB.NoGrowSync flag before memory mapping the file.
  727. NoGrowSync bool
  728. // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
  729. // grab a shared lock (UNIX).
  730. ReadOnly bool
  731. // Sets the DB.MmapFlags flag before memory mapping the file.
  732. MmapFlags int
  733. // InitialMmapSize is the initial mmap size of the database
  734. // in bytes. Read transactions won't block write transaction
  735. // if the InitialMmapSize is large enough to hold database mmap
  736. // size. (See DB.Begin for more information)
  737. //
  738. // If <=0, the initial map size is 0.
  739. // If initialMmapSize is smaller than the previous database size,
  740. // it takes no effect.
  741. InitialMmapSize int
  742. }
  743. // DefaultOptions represent the options used if nil options are passed into Open().
  744. // No timeout is used which will cause Bolt to wait indefinitely for a lock.
  745. var DefaultOptions = &Options{
  746. Timeout: 0,
  747. NoGrowSync: false,
  748. }
  749. // Stats represents statistics about the database.
  750. type Stats struct {
  751. // Freelist stats
  752. FreePageN int // total number of free pages on the freelist
  753. PendingPageN int // total number of pending pages on the freelist
  754. FreeAlloc int // total bytes allocated in free pages
  755. FreelistInuse int // total bytes used by the freelist
  756. // Transaction stats
  757. TxN int // total number of started read transactions
  758. OpenTxN int // number of currently open read transactions
  759. TxStats TxStats // global, ongoing stats.
  760. }
  761. // Sub calculates and returns the difference between two sets of database stats.
  762. // This is useful when obtaining stats at two different points and time and
  763. // you need the performance counters that occurred within that time span.
  764. func (s *Stats) Sub(other *Stats) Stats {
  765. if other == nil {
  766. return *s
  767. }
  768. var diff Stats
  769. diff.FreePageN = s.FreePageN
  770. diff.PendingPageN = s.PendingPageN
  771. diff.FreeAlloc = s.FreeAlloc
  772. diff.FreelistInuse = s.FreelistInuse
  773. diff.TxN = other.TxN - s.TxN
  774. diff.TxStats = s.TxStats.Sub(&other.TxStats)
  775. return diff
  776. }
  777. func (s *Stats) add(other *Stats) {
  778. s.TxStats.add(&other.TxStats)
  779. }
  780. type Info struct {
  781. Data uintptr
  782. PageSize int
  783. }
  784. type meta struct {
  785. magic uint32
  786. version uint32
  787. pageSize uint32
  788. flags uint32
  789. root bucket
  790. freelist pgid
  791. pgid pgid
  792. txid txid
  793. checksum uint64
  794. }
  795. // validate checks the marker bytes and version of the meta page to ensure it matches this binary.
  796. func (m *meta) validate() error {
  797. if m.checksum != 0 && m.checksum != m.sum64() {
  798. return ErrChecksum
  799. } else if m.magic != magic {
  800. return ErrInvalid
  801. } else if m.version != version {
  802. return ErrVersionMismatch
  803. }
  804. return nil
  805. }
  806. // copy copies one meta object to another.
  807. func (m *meta) copy(dest *meta) {
  808. *dest = *m
  809. }
  810. // write writes the meta onto a page.
  811. func (m *meta) write(p *page) {
  812. if m.root.root >= m.pgid {
  813. panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid))
  814. } else if m.freelist >= m.pgid {
  815. panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid))
  816. }
  817. // Page id is either going to be 0 or 1 which we can determine by the transaction ID.
  818. p.id = pgid(m.txid % 2)
  819. p.flags |= metaPageFlag
  820. // Calculate the checksum.
  821. m.checksum = m.sum64()
  822. m.copy(p.meta())
  823. }
  824. // generates the checksum for the meta.
  825. func (m *meta) sum64() uint64 {
  826. var h = fnv.New64a()
  827. _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
  828. return h.Sum64()
  829. }
  830. // _assert will panic with a given formatted message if the given condition is false.
  831. func _assert(condition bool, msg string, v ...interface{}) {
  832. if !condition {
  833. panic(fmt.Sprintf("assertion failed: "+msg, v...))
  834. }
  835. }
  836. func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
  837. func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
  838. func printstack() {
  839. stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n")
  840. fmt.Fprintln(os.Stderr, stack)
  841. }