// Write apply the specified batch to the database. func (d *DB) Write(b *Batch, wo *opt.WriteOptions) (err error) { err = d.wok() if err != nil || b == nil || b.len() == 0 { return } b.init(wo.HasFlag(opt.WFSync)) select { case d.wqueue <- b: return <-d.wack case d.wlock <- struct{}{}: } merged := 0 defer func() { <-d.wlock for i := 0; i < merged; i++ { d.wack <- err } }() mem, err := d.flush() if err != nil { return } // calculate maximum size of the batch m := 1 << 20 if x := b.size(); x <= 128<<10 { m = x + (128 << 10) } // merge with other batch drain: for b.size() <= m && !b.sync { select { case nb := <-d.wqueue: b.append(nb) merged++ default: break drain } } // set batch first seq number relative from last seq b.seq = d.seq + 1 // write log concurrently if it is large enough if b.size() >= (128 << 10) { d.lch <- b b.memReplay(mem) err = <-d.lack if err != nil { b.revertMemReplay(mem) return } } else { err = d.doWriteLog(b) if err != nil { return } b.memReplay(mem) } // set last seq number d.addSeq(uint64(b.len())) return }