示例#1
0
//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
}
示例#2
0
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
}