// Write apply the given batch to the DB. The batch records will be applied // sequentially. Write might be used concurrently, when used concurrently and // batch is small enough, write will try to merge the batches. Set NoWriteMerge // option to true to disable write merge. // // It is safe to modify the contents of the arguments after Write returns but // not before. Write will not modify content of the batch. func (db *DB) Write(batch *Batch, wo *opt.WriteOptions) error { if err := db.ok(); err != nil || batch == nil || batch.Len() == 0 { return err } // If the batch size is larger than write buffer, it may justified to write // using transaction instead. Using transaction the batch will be written // into tables directly, skipping the journaling. if batch.internalLen > db.s.o.GetWriteBuffer() && !db.s.o.GetDisableLargeBatchTransaction() { tr, err := db.OpenTransaction() if err != nil { return err } if err := tr.Write(batch, wo); err != nil { tr.Discard() return err } return tr.Commit() } merge := !wo.GetNoWriteMerge() && !db.s.o.GetNoWriteMerge() sync := wo.GetSync() && !db.s.o.GetNoSync() // Acquire write lock. if merge { select { case db.writeMergeC <- writeMerge{sync: sync, batch: batch}: if <-db.writeMergedC { // Write is merged. return <-db.writeAckC } // Write is not merged, the write lock is handed to us. Continue. case db.writeLockC <- struct{}{}: // Write lock acquired. case err := <-db.compPerErrC: // Compaction error. return err case <-db.closeC: // Closed return ErrClosed } } else { select { case db.writeLockC <- struct{}{}: // Write lock acquired. case err := <-db.compPerErrC: // Compaction error. return err case <-db.closeC: // Closed return ErrClosed } } return db.writeLocked(batch, nil, merge, sync) }
func (db *DB) putRec(kt keyType, key, value []byte, wo *opt.WriteOptions) error { if err := db.ok(); err != nil { return err } merge := !wo.GetNoWriteMerge() && !db.s.o.GetNoWriteMerge() sync := wo.GetSync() && !db.s.o.GetNoSync() // Acquire write lock. if merge { select { case db.writeMergeC <- writeMerge{sync: sync, keyType: kt, key: key, value: value}: if <-db.writeMergedC { // Write is merged. return <-db.writeAckC } // Write is not merged, the write lock is handed to us. Continue. case db.writeLockC <- struct{}{}: // Write lock acquired. case err := <-db.compPerErrC: // Compaction error. return err case <-db.closeC: // Closed return ErrClosed } } else { select { case db.writeLockC <- struct{}{}: // Write lock acquired. case err := <-db.compPerErrC: // Compaction error. return err case <-db.closeC: // Closed return ErrClosed } } batch := db.batchPool.Get().(*Batch) batch.Reset() batch.appendRec(kt, key, value) return db.writeLocked(batch, batch, merge, sync) }