private ByteBuffer processAsciiCommand(ByteBuffer buffer, Cache cache) { CharBuffer flb = getFirstLineBuffer(); getAsciiDecoder().reset(); getAsciiDecoder().decode(buffer, flb, false); flb.flip(); String firstLine = getFirstLine(); String[] firstLineElements = firstLine.split(" "); assert "decr".equals(firstLineElements[0]); String key = firstLineElements[1]; String decrByStr = stripNewline(firstLineElements[2]); Long decrBy = Long.parseLong(decrByStr); boolean noReply = firstLineElements.length > 3; Region<Object, ValueWrapper> r = getMemcachedRegion(cache); String reply = Reply.NOT_FOUND.toString(); ByteBuffer newVal = ByteBuffer.allocate(8); while (true) { ValueWrapper oldValWrapper = r.get(key); if (oldValWrapper == null) { break; } newVal.clear(); byte[] oldVal = oldValWrapper.getValue(); long oldLong = getLongFromByteArray(oldVal); long newLong = oldLong - decrBy; newVal.putLong(newLong); ValueWrapper newValWrapper = ValueWrapper.getWrappedValue(newVal.array(), 0 /*flags*/); if (r.replace(key, oldValWrapper, newValWrapper)) { reply = newLong + "\r\n"; break; } } return noReply ? null : asciiCharset.encode(reply); }
private ByteBuffer processBinaryProtocol(RequestReader request, Cache cache) { ByteBuffer buffer = request.getRequest(); int extrasLength = buffer.get(EXTRAS_LENGTH_INDEX); final KeyWrapper key = getKey(buffer, HEADER_LENGTH + extrasLength); long decrBy = buffer.getLong(HEADER_LENGTH); long initialVal = buffer.getLong(HEADER_LENGTH + LONG_LENGTH); int expiration = buffer.getInt(HEADER_LENGTH + LONG_LENGTH + LONG_LENGTH); final Region<Object, ValueWrapper> r = getMemcachedRegion(cache); ByteBuffer newVal = ByteBuffer.allocate(8); boolean notFound = false; ValueWrapper newValWrapper = null; try { while (true) { ValueWrapper oldValWrapper = r.get(key); if (oldValWrapper == null) { if (expiration == -1) { notFound = true; } else { newVal.putLong(0, initialVal); newValWrapper = ValueWrapper.getWrappedValue(newVal.array(), 0 /*flags*/); r.put(key, newValWrapper); } break; } byte[] oldVal = oldValWrapper.getValue(); long oldLong = getLongFromByteArray(oldVal); long newLong = oldLong - decrBy; if (newLong < 0) { newLong = 0; } newVal.putLong(0, newLong); newValWrapper = ValueWrapper.getWrappedValue(newVal.array(), 0 /*flags*/); if (r.replace(key, oldValWrapper, newValWrapper)) { break; } } } catch (Exception e) { return handleBinaryException(key, request, request.getResponse(), "decrement", e); } if (expiration > 0) { StorageCommand.getExpiryExecutor() .schedule( new Runnable() { @Override public void run() { r.destroy(key); } }, expiration, TimeUnit.SECONDS); } if (getLogger().fineEnabled()) { getLogger() .fine( "decr:key:" + key + " decrBy:" + decrBy + " initVal:" + initialVal + " exp:" + expiration + " notFound:" + notFound); } ByteBuffer response = null; if (notFound) { response = request.getResponse(); response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.KEY_NOT_FOUND.asShort()); } else { if (isQuiet()) { return null; } response = request.getResponse(HEADER_LENGTH + LONG_LENGTH); response.putInt(TOTAL_BODY_LENGTH_INDEX, LONG_LENGTH); response.putLong(HEADER_LENGTH, newVal.getLong(0)); response.putLong(POSITION_CAS, newValWrapper.getVersion()); } return response; }
@SuppressWarnings({"rawtypes", "unchecked"}) private void doRegionTest(final RegionShortcut rs, final String rName, boolean compressed) { boolean isPersistent = rs == RegionShortcut.LOCAL_PERSISTENT || rs == RegionShortcut.REPLICATE_PERSISTENT || rs == RegionShortcut.PARTITION_PERSISTENT; GemFireCacheImpl gfc = createCache(isPersistent); Region r = null; try { gfc.setCopyOnRead(true); final MemoryAllocator ma = gfc.getOffHeapStore(); assertNotNull(ma); assertEquals(0, ma.getUsedMemory()); Compressor compressor = null; if (compressed) { compressor = SnappyCompressor.getDefaultInstance(); } r = gfc.createRegionFactory(rs).setOffHeap(true).setCompressor(compressor).create(rName); assertEquals(true, r.isEmpty()); assertEquals(0, ma.getUsedMemory()); Object data = new Integer(123456789); r.put("key1", data); // System.out.println("After put of Integer value off heap used memory=" + // ma.getUsedMemory()); assertTrue(ma.getUsedMemory() == 0); assertEquals(data, r.get("key1")); r.invalidate("key1"); assertEquals(0, ma.getUsedMemory()); r.put("key1", data); assertTrue(ma.getUsedMemory() == 0); long usedBeforeUpdate = ma.getUsedMemory(); r.put("key1", data); assertEquals(usedBeforeUpdate, ma.getUsedMemory()); assertEquals(data, r.get("key1")); r.destroy("key1"); assertEquals(0, ma.getUsedMemory()); data = new Long(0x007FFFFFL); r.put("key1", data); if (!compressed) { assertTrue(ma.getUsedMemory() == 0); } assertEquals(data, r.get("key1")); data = new Long(0xFF8000000L); r.put("key1", data); if (!compressed) { assertTrue(ma.getUsedMemory() == 0); } assertEquals(data, r.get("key1")); // now lets set data to something that will be stored offheap data = new Long(Long.MAX_VALUE); r.put("key1", data); assertEquals(data, r.get("key1")); // System.out.println("After put of Integer value off heap used memory=" + // ma.getUsedMemory()); assertTrue(ma.getUsedMemory() > 0); data = new Long(Long.MIN_VALUE); r.put("key1", data); assertEquals(data, r.get("key1")); // System.out.println("After put of Integer value off heap used memory=" + // ma.getUsedMemory()); assertTrue(ma.getUsedMemory() > 0); r.invalidate("key1"); assertEquals(0, ma.getUsedMemory()); r.put("key1", data); assertTrue(ma.getUsedMemory() > 0); usedBeforeUpdate = ma.getUsedMemory(); r.put("key1", data); assertEquals(usedBeforeUpdate, ma.getUsedMemory()); assertEquals(data, r.get("key1")); r.destroy("key1"); assertEquals(0, ma.getUsedMemory()); // confirm that byte[] do use off heap { byte[] originalBytes = new byte[1024]; Object oldV = r.put("byteArray", originalBytes); long startUsedMemory = ma.getUsedMemory(); assertEquals(null, oldV); byte[] readBytes = (byte[]) r.get("byteArray"); if (originalBytes == readBytes) { fail("Expected different byte[] identity"); } if (!Arrays.equals(readBytes, originalBytes)) { fail("Expected byte array contents to be equal"); } assertEquals(startUsedMemory, ma.getUsedMemory()); oldV = r.put("byteArray", originalBytes); if (!compressed) { assertEquals(null, oldV); // we default to old value being null for offheap } assertEquals(startUsedMemory, ma.getUsedMemory()); readBytes = (byte[]) r.putIfAbsent("byteArray", originalBytes); if (originalBytes == readBytes) { fail("Expected different byte[] identity"); } if (!Arrays.equals(readBytes, originalBytes)) { fail("Expected byte array contents to be equal"); } assertEquals(startUsedMemory, ma.getUsedMemory()); if (!r.replace("byteArray", readBytes, originalBytes)) { fail("Expected replace to happen"); } assertEquals(startUsedMemory, ma.getUsedMemory()); byte[] otherBytes = new byte[1024]; otherBytes[1023] = 1; if (r.replace("byteArray", otherBytes, originalBytes)) { fail("Expected replace to not happen"); } if (r.replace("byteArray", "bogus string", originalBytes)) { fail("Expected replace to not happen"); } if (r.remove("byteArray", "bogus string")) { fail("Expected remove to not happen"); } assertEquals(startUsedMemory, ma.getUsedMemory()); if (!r.remove("byteArray", originalBytes)) { fail("Expected remove to happen"); } assertEquals(0, ma.getUsedMemory()); oldV = r.putIfAbsent("byteArray", "string value"); assertEquals(null, oldV); assertEquals("string value", r.get("byteArray")); if (r.replace("byteArray", "string valuE", originalBytes)) { fail("Expected replace to not happen"); } if (!r.replace("byteArray", "string value", originalBytes)) { fail("Expected replace to happen"); } oldV = r.destroy("byteArray"); // we default to old value being null for offheap if (!compressed) { assertEquals(null, oldV); } MyCacheListener listener = new MyCacheListener(); r.getAttributesMutator().addCacheListener(listener); try { Object valueToReplace = "string value1"; r.put("byteArray", valueToReplace); assertEquals(null, listener.ohOldValue); if (!compressed) { assertEquals("string value1", listener.ohNewValue.getDeserializedForReading()); valueToReplace = listener.ohNewValue; } if (!r.replace("byteArray", valueToReplace, "string value2")) { fail("expected replace to happen"); } if (!compressed) { assertEquals("string value2", listener.ohNewValue.getDeserializedForReading()); assertEquals("string value1", listener.ohOldValue.getDeserializedForReading()); } // make sure that a custom equals/hashCode are not used when comparing values. } finally { r.getAttributesMutator().removeCacheListener(listener); } } assertTrue(ma.getUsedMemory() > 0); { Object key = "MyValueWithPartialEquals"; MyValueWithPartialEquals v1 = new MyValueWithPartialEquals("s1"); MyValueWithPartialEquals v2 = new MyValueWithPartialEquals("s2"); MyValueWithPartialEquals v3 = new MyValueWithPartialEquals("s1"); r.put(key, v1); try { if (r.replace(key, v2, "should not happen")) { fail("v1 should not be equal to v2 on an offheap region"); } if (!r.replace(key, v3, "should happen")) { fail("v1 should be equal to v3 on an offheap region"); } r.put(key, v1); if (r.remove(key, v2)) { fail("v1 should not be equal to v2 on an offheap region"); } if (!r.remove(key, v3)) { fail("v1 should be equal to v3 on an offheap region"); } } finally { r.remove(key); } } { Object key = "MyPdxWithPartialEquals"; MyPdxWithPartialEquals v1 = new MyPdxWithPartialEquals("s", "1"); MyPdxWithPartialEquals v2 = new MyPdxWithPartialEquals("s", "2"); MyPdxWithPartialEquals v3 = new MyPdxWithPartialEquals("t", "1"); r.put(key, v1); try { if (r.replace(key, v3, "should not happen")) { fail("v1 should not be equal to v3 on an offheap region"); } if (!r.replace(key, v2, "should happen")) { fail("v1 should be equal to v2 on an offheap region"); } r.put(key, v1); if (r.remove(key, v3)) { fail("v1 should not be equal to v3 on an offheap region"); } if (!r.remove(key, v2)) { fail("v1 should be equal to v2 on an offheap region"); } } finally { r.remove(key); } } byte[] value = new byte[1024]; /*while (value != null) */ { r.put("byteArray", value); } r.remove("byteArray"); assertEquals(0, ma.getUsedMemory()); r.put("key1", data); assertTrue(ma.getUsedMemory() > 0); r.invalidateRegion(); assertEquals(0, ma.getUsedMemory()); r.put("key1", data); assertTrue(ma.getUsedMemory() > 0); try { r.clear(); assertEquals(0, ma.getUsedMemory()); } catch (UnsupportedOperationException ok) { } r.put("key1", data); assertTrue(ma.getUsedMemory() > 0); if (r.getAttributes().getDataPolicy().withPersistence()) { r.put("key2", Integer.valueOf(1234567890)); r.put("key3", new Long(0x007FFFFFL)); r.put("key4", new Long(0xFF8000000L)); assertEquals(4, r.size()); r.close(); assertEquals(0, ma.getUsedMemory()); // simple test of recovery r = gfc.createRegionFactory(rs).setOffHeap(true).create(rName); assertEquals(4, r.size()); assertEquals(data, r.get("key1")); assertEquals(Integer.valueOf(1234567890), r.get("key2")); assertEquals(new Long(0x007FFFFFL), r.get("key3")); assertEquals(new Long(0xFF8000000L), r.get("key4")); closeCache(gfc, true); assertEquals(0, ma.getUsedMemory()); gfc = createCache(); if (ma != gfc.getOffHeapStore()) { fail("identity of offHeapStore changed when cache was recreated"); } r = gfc.createRegionFactory(rs).setOffHeap(true).create(rName); assertTrue(ma.getUsedMemory() > 0); assertEquals(4, r.size()); assertEquals(data, r.get("key1")); assertEquals(Integer.valueOf(1234567890), r.get("key2")); assertEquals(new Long(0x007FFFFFL), r.get("key3")); assertEquals(new Long(0xFF8000000L), r.get("key4")); } r.destroyRegion(); assertEquals(0, ma.getUsedMemory()); } finally { if (r != null && !r.isDestroyed()) { r.destroyRegion(); } closeCache(gfc, false); } }