//WriteKey writes blob by Key. func (s *Session) WriteKey(key *Key, input io.Reader, offset, total_size uint64) <-chan Lookuper { responseCh := make(chan Lookuper, defaultVOLUME) onWriteContext := NextContext() onWriteFinishContext := NextContext() chunk_context := NextContext() onWriteResult := func(lookup *lookupResult) { responseCh <- lookup } onWriteFinish := func(err error) { if err != nil { responseCh <- &lookupResult{err: err} } close(responseCh) Pool.Delete(onWriteContext) Pool.Delete(onWriteFinishContext) Pool.Delete(chunk_context) } chunk, err := ioutil.ReadAll(input) if err != nil { responseCh <- &lookupResult{err: err} close(responseCh) return responseCh } if len(chunk) == 0 { responseCh <- &lookupResult{ err: &DnetError{ Code: -22, Flags: 0, Message: "Invalid zero-length write request", }, } close(responseCh) return responseCh } Pool.Store(onWriteContext, onWriteResult) Pool.Store(onWriteFinishContext, onWriteFinish) Pool.Store(chunk_context, chunk) C.session_write_data(s.session, C.context_t(onWriteContext), C.context_t(onWriteFinishContext), key.key, C.uint64_t(offset), (*C.char)(unsafe.Pointer(&chunk[0])), C.uint64_t(len(chunk))) return responseCh }
func (w *WriteSeeker) Flush(buf []byte, final bool) (err error) { if w.session == nil || w.key == nil { return fmt.Errorf("trying to write into empty interface") } if w.local_offset == 0 { return nil } wch := new_write_channel() len64 := uint64(len(buf)) if w.prepared { if (uint64(w.remote_offset)+len64 == w.total_size) || final { w.prepared = false C.session_write_commit(w.session.session, C.context_t(wch.on_result_context), C.context_t(wch.on_finish_context), w.key.key, C.uint64_t(w.remote_offset), C.uint64_t(w.total_size), (*C.char)(unsafe.Pointer(&buf[0])), C.uint64_t(len64)) } else { C.session_write_plain(w.session.session, C.context_t(wch.on_result_context), C.context_t(wch.on_finish_context), w.key.key, C.uint64_t(w.remote_offset), (*C.char)(unsafe.Pointer(&buf[0])), C.uint64_t(len64)) } } else { if uint64(w.remote_offset)+len64 == w.total_size || w.reserve_size == 0 { // the whole package fits this chunk, use common write C.session_write_data(w.session.session, C.context_t(wch.on_result_context), C.context_t(wch.on_finish_context), w.key.key, C.uint64_t(w.remote_offset), (*C.char)(unsafe.Pointer(&buf[0])), C.uint64_t(len64)) } else { w.prepared = true C.session_write_prepare(w.session.session, C.context_t(wch.on_result_context), C.context_t(wch.on_finish_context), w.key.key, C.uint64_t(w.remote_offset), C.uint64_t(w.reserve_size), (*C.char)(unsafe.Pointer(&buf[0])), C.uint64_t(len64)) } } w.remote_offset += int64(len64) have_good_write := false errors := make([]error, 0) for wr := range wch.response { err = wr.Error() if err != nil { errors = append(errors, err) continue } have_good_write = true } if have_good_write == false { return fmt.Errorf("write failed, remote_offset: %d, reserve_size: %d, total_size: %d, chunk_size: %d, errors: %v", w.remote_offset-int64(len64), w.reserve_size, w.total_size, len64, errors) } return nil }