func (client *Client) store(cmd string, item *Item) error { client.lock() defer client.unlock() key := client.addPrefix(item.Key) cKey := C.CString(key) defer C.free(unsafe.Pointer(cKey)) cKeyLen := C.size_t(len(key)) cFlags := C.flags_t(item.Flags) cExptime := C.exptime_t(item.Expiration) cNoreply := C.bool(client.noreply) cValue := C.CString(string(item.Value)) defer C.free(unsafe.Pointer(cValue)) cValueSize := C.size_t(len(item.Value)) var rst **C.message_result_t var n C.size_t var errCode C.int switch cmd { case "set": errCode = C.client_set( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "add": errCode = C.client_add( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "replace": errCode = C.client_replace( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "prepend": errCode = C.client_prepend( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "append": errCode = C.client_append( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "cas": cCasUnique := C.cas_unique_t(item.casid) errCode = C.client_cas( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, &cCasUnique, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) } defer C.client_destroy_message_result(client._imp) if errCode == 0 { if client.noreply { return nil } else if int(n) == 1 { switch (*rst).type_ { case C.MSG_STORED: return nil case C.MSG_NOT_STORED: return ErrNotStored case C.MSG_EXISTS: return ErrCASConflict case C.MSG_NOT_FOUND: return ErrCacheMiss } } } else if errCode == C.RET_INVALID_KEY_ERR { return ErrMalformedKey } return networkError(errorMessage[errCode]) }
// SetMulti will set multi values at once func (client *Client) SetMulti(items []*Item) (failedKeys []string, err error) { client.lock() defer client.unlock() nItems := len(items) cKeys := make([]*C.char, nItems) cKeyLens := make([]C.size_t, nItems) cValues := make([]*C.char, nItems) cValueSizes := make([]C.size_t, nItems) cFlagsList := make([]C.flags_t, nItems) for i, item := range items { rawKey := client.addPrefix(item.Key) cKey := C.CString(rawKey) defer C.free(unsafe.Pointer(cKey)) cKeys[i] = cKey cKeyLen := C.size_t(len(rawKey)) cKeyLens[i] = cKeyLen cVal := C.CString(string(item.Value)) defer C.free(unsafe.Pointer(cVal)) cValues[i] = cVal cValueSize := C.size_t(len(item.Value)) cValueSizes[i] = cValueSize cFlags := C.flags_t(item.Flags) cFlagsList[i] = cFlags } cExptime := C.exptime_t(items[0].Expiration) cNoreply := C.bool(client.noreply) cNItems := C.size_t(nItems) var results **C.message_result_t var n C.size_t errCode := C.client_set( client._imp, (**C.char)(&cKeys[0]), (*C.size_t)(&cKeyLens[0]), (*C.flags_t)(&cFlagsList[0]), cExptime, nil, cNoreply, (**C.char)(&cValues[0]), (*C.size_t)(&cValueSizes[0]), cNItems, &results, &n, ) defer C.client_destroy_message_result(client._imp) if errCode == 0 { return []string{}, nil } if errCode == C.RET_INVALID_KEY_ERR { err = ErrMalformedKey } else { err = networkError(errorMessage[errCode]) } sr := unsafe.Sizeof(*results) storedKeySet := make(map[string]struct{}) for i := 0; i <= int(n); i++ { if (*results).type_ == C.MSG_STORED { storedKey := C.GoStringN((*results).key, C.int((*results).key_len)) storedKeySet[storedKey] = struct{}{} } results = (**C.message_result_t)( unsafe.Pointer(uintptr(unsafe.Pointer(results)) + sr), ) } failedKeys = make([]string, len(items)-len(storedKeySet)) i := 0 for _, item := range items { if _, contains := storedKeySet[item.Key]; contains { continue } failedKeys[i] = client.removePrefix(item.Key) i++ } return failedKeys, err }
func (client *Client) store(cmd string, item *Item) error { client.lock() defer client.unlock() key := client.addPrefix(item.Key) cKey := C.CString(key) defer C.free(unsafe.Pointer(cKey)) cKeyLen := C.size_t(len(key)) cFlags := C.flags_t(item.Flags) cExptime := C.exptime_t(item.Expiration) cNoreply := C.bool(client.noreply) cValue := C.CString(string(item.Value)) defer C.free(unsafe.Pointer(cValue)) cValueSize := C.size_t(len(item.Value)) var rst **C.message_result_t var n C.size_t var errCode C.int switch cmd { case "set": errCode = C.client_set( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "add": errCode = C.client_add( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "replace": errCode = C.client_replace( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "prepend": errCode = C.client_prepend( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "append": errCode = C.client_append( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, nil, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) case "cas": cCasUnique := C.cas_unique_t(item.casid) errCode = C.client_cas( client._imp, &cKey, &cKeyLen, &cFlags, cExptime, &cCasUnique, cNoreply, &cValue, &cValueSize, 1, &rst, &n, ) } defer C.client_destroy_message_result(client._imp) if errCode == 0 { if client.noreply { return nil } else if int(n) == 1 && (*rst).type_ == C.MSG_STORED { return nil } } return errors.New(errorMessage[errCode]) }