From 84ca88762f2d84e641db984384bb9854e5492aaf Mon Sep 17 00:00:00 2001 From: f1v3-dev Date: Wed, 15 Jul 2026 14:53:32 +0900 Subject: [PATCH] INTERNAL: Move create clause and overflow action validation out of `CollectionCreate` - Move create clause serialization to CreateAttributes - Move overflow action validation to CollectionType --- .../collection/CollectionBulkInsert.java | 24 ++++------- .../collection/CollectionCreate.java | 41 ++----------------- .../collection/CollectionInsert.java | 4 +- .../collection/CollectionPipedInsert.java | 33 +++++++-------- .../memcached/collection/CollectionType.java | 7 +++- .../collection/CreateAttributes.java | 31 ++++++++++++++ 6 files changed, 63 insertions(+), 77 deletions(-) diff --git a/src/main/java/net/spy/memcached/collection/CollectionBulkInsert.java b/src/main/java/net/spy/memcached/collection/CollectionBulkInsert.java index f46a19d45..dfcbe3b3f 100644 --- a/src/main/java/net/spy/memcached/collection/CollectionBulkInsert.java +++ b/src/main/java/net/spy/memcached/collection/CollectionBulkInsert.java @@ -71,9 +71,7 @@ public BTreeBulkInsert(MemcachedNode node, List keyList, String bkey, CreateAttributes attributes) { super(node, keyList, cachedData, attributes); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction( - CollectionType.btree, attributes.getOverflowAction() - ); + CollectionType.btree.checkOverflowAction(attributes.getOverflowAction()); } this.bkey = bkey; this.eflag = eflag; @@ -98,7 +96,7 @@ public ByteBuffer getAsciiCommand() { int kSize = this.keyList.size(); byte[] value = cachedData.getData(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cachedData.getFlags()) : ""; + attributes.toCreateClause(cachedData.getFlags()) : ""; for (int i = this.nextOpIndex; i < kSize; i++) { String key = keyList.get(i); setArguments(bb, COMMAND, key, bkey, (eflag != null) ? eflag : "", value.length, @@ -129,9 +127,7 @@ public MapBulkInsert(MemcachedNode node, List keyList, String mkey, CachedData cachedData, CreateAttributes attributes) { super(node, keyList, cachedData, attributes); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction( - CollectionType.map, attributes.getOverflowAction() - ); + CollectionType.map.checkOverflowAction(attributes.getOverflowAction()); } this.mkey = mkey; } @@ -154,7 +150,7 @@ public ByteBuffer getAsciiCommand() { int kSize = this.keyList.size(); byte[] value = cachedData.getData(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cachedData.getFlags()) : ""; + attributes.toCreateClause(cachedData.getFlags()) : ""; for (int i = this.nextOpIndex; i < kSize; i++) { String key = keyList.get(i); setArguments(bb, COMMAND, key, mkey, value.length, @@ -184,9 +180,7 @@ public SetBulkInsert(MemcachedNode node, List keyList, CachedData cachedData, CreateAttributes attributes) { super(node, keyList, cachedData, attributes); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction( - CollectionType.set, attributes.getOverflowAction() - ); + CollectionType.set.checkOverflowAction(attributes.getOverflowAction()); } } @@ -207,7 +201,7 @@ public ByteBuffer getAsciiCommand() { int kSize = this.keyList.size(); byte[] value = cachedData.getData(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cachedData.getFlags()) : ""; + attributes.toCreateClause(cachedData.getFlags()) : ""; for (int i = this.nextOpIndex; i < kSize; i++) { String key = keyList.get(i); setArguments(bb, COMMAND, key, value.length, @@ -237,9 +231,7 @@ public ListBulkInsert(MemcachedNode node, List keyList, int index, CachedData cachedData, CreateAttributes attributes) { super(node, keyList, cachedData, attributes); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction( - CollectionType.list, attributes.getOverflowAction() - ); + CollectionType.list.checkOverflowAction(attributes.getOverflowAction()); } this.index = index; } @@ -262,7 +254,7 @@ public ByteBuffer getAsciiCommand() { int kSize = keyList.size(); byte[] value = cachedData.getData(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cachedData.getFlags()) : ""; + attributes.toCreateClause(cachedData.getFlags()) : ""; for (int i = this.nextOpIndex; i < kSize; i++) { String key = this.keyList.get(i); setArguments(bb, COMMAND, key, index, value.length, diff --git a/src/main/java/net/spy/memcached/collection/CollectionCreate.java b/src/main/java/net/spy/memcached/collection/CollectionCreate.java index e0258fb60..1aee4fb0d 100644 --- a/src/main/java/net/spy/memcached/collection/CollectionCreate.java +++ b/src/main/java/net/spy/memcached/collection/CollectionCreate.java @@ -25,7 +25,7 @@ public abstract class CollectionCreate { protected CollectionCreate(CollectionType type, int flags, CreateAttributes attributes, boolean noreply) { - checkOverflowAction(type, attributes.getOverflowAction()); + type.checkOverflowAction(attributes.getOverflowAction()); this.flags = flags; this.attributes = attributes; this.noreply = noreply; @@ -37,51 +37,16 @@ public String stringify() { } StringBuilder b = new StringBuilder(); - b.append(flags); - b.append(' ').append(attributes.getExpireTime()); - b.append(' ').append(attributes.getMaxCount()); - - if (null != attributes.getOverflowAction()) { - b.append(' ').append(attributes.getOverflowAction()); - } - - if (!attributes.getReadable()) { - b.append(' ').append("unreadable"); - } - + b.append(' ').append(attributes.stringify()); if (noreply) { - b.append((b.length() <= 0) ? "" : " ").append("noreply"); + b.append(' ').append("noreply"); } str = b.toString(); return str; } - public static String makeCreateClause(CreateAttributes attributes, int flags) { - if (attributes == null) { - return null; - } - StringBuilder b = new StringBuilder(); - b.append("create ").append(flags) - .append(" ").append(attributes.getExpireTime()) - .append(" ").append(attributes.getMaxCount()); - if (attributes.getOverflowAction() != null) { - b.append(" ").append(attributes.getOverflowAction()); - } - if (!attributes.getReadable()) { - b.append(" ").append("unreadable"); - } - return b.toString(); - } - - public static void checkOverflowAction(CollectionType type, CollectionOverflowAction action) { - if (action != null && !type.isAvailableOverflowAction(action)) { - throw new IllegalArgumentException( - action + " is unavailable overflow action in " + type + "."); - } - } - public String toString() { return (str != null) ? str : stringify(); } diff --git a/src/main/java/net/spy/memcached/collection/CollectionInsert.java b/src/main/java/net/spy/memcached/collection/CollectionInsert.java index c8ce177ef..4400b8d15 100644 --- a/src/main/java/net/spy/memcached/collection/CollectionInsert.java +++ b/src/main/java/net/spy/memcached/collection/CollectionInsert.java @@ -33,7 +33,7 @@ protected CollectionInsert() { protected CollectionInsert(CollectionType type, T value, byte[] elementFlag, RequestMode requestMode, CreateAttributes attributes) { if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(type, attributes.getOverflowAction()); + type.checkOverflowAction(attributes.getOverflowAction()); } if (elementFlag != null) { if (elementFlag.length < 1 || elementFlag.length > ElementFlagFilter.MAX_EFLAG_LENGTH) { @@ -56,7 +56,7 @@ public String stringify() { StringBuilder b = new StringBuilder(); if (attributes != null) { - b.append(CollectionCreate.makeCreateClause(attributes, flags)); + b.append(attributes.toCreateClause(flags)); } // an optional request mode like noreply, pipe and getrim diff --git a/src/main/java/net/spy/memcached/collection/CollectionPipedInsert.java b/src/main/java/net/spy/memcached/collection/CollectionPipedInsert.java index 9db941042..699576547 100644 --- a/src/main/java/net/spy/memcached/collection/CollectionPipedInsert.java +++ b/src/main/java/net/spy/memcached/collection/CollectionPipedInsert.java @@ -55,8 +55,7 @@ public ListPipedInsert(String key, int index, Collection list, CreateAttributes attributes, Transcoder tc) { super(key, attributes, tc, list.size()); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(CollectionType.list, - attributes.getOverflowAction()); + CollectionType.list.checkOverflowAction(attributes.getOverflowAction()); } this.index = index; this.list = list; @@ -88,7 +87,7 @@ public ByteBuffer getAsciiCommand() { // create ascii operation string int eSize = encodedList.size(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cd.getFlags()) : ""; + attributes.toCreateClause(cd.getFlags()) : ""; for (i = 0; i < eSize; i++) { byte[] each = encodedList.get(i); int eIndex = index; @@ -96,7 +95,7 @@ public ByteBuffer getAsciiCommand() { eIndex += (i + nextOpIndex); } setArguments(bb, COMMAND, key, eIndex, each.length, - createClause, (i < eSize - 1) ? PIPE : ""); + createClause, (i < eSize - 1) ? PIPE : ""); bb.put(each); bb.put(CRLF); } @@ -120,8 +119,7 @@ public SetPipedInsert(String key, Collection set, CreateAttributes attributes, Transcoder tc) { super(key, attributes, tc, set.size()); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(CollectionType.set, - attributes.getOverflowAction()); + CollectionType.set.checkOverflowAction(attributes.getOverflowAction()); } this.set = set; } @@ -152,7 +150,7 @@ public ByteBuffer getAsciiCommand() { // create ascii operation string int eSize = encodedList.size(); String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cd.getFlags()) : ""; + attributes.toCreateClause(cd.getFlags()) : ""; for (i = 0; i < eSize; i++) { byte[] each = encodedList.get(i); setArguments(bb, COMMAND, key, each.length, @@ -180,8 +178,7 @@ public BTreePipedInsert(String key, Map map, CreateAttributes attributes, Transcoder tc) { super(key, attributes, tc, map.size()); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(CollectionType.btree, - attributes.getOverflowAction()); + CollectionType.btree.checkOverflowAction(attributes.getOverflowAction()); } this.map = map; } @@ -215,7 +212,7 @@ public ByteBuffer getAsciiCommand() { // create ascii operation string String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cd.getFlags()) : ""; + attributes.toCreateClause(cd.getFlags()) : ""; for (i = 0; i < eSize; i++) { Long bkey = bkeyList.get(i); byte[] value = encodedList.get(i); @@ -244,8 +241,7 @@ public ByteArraysBTreePipedInsert(String key, List> elements, CreateAttributes attributes, Transcoder tc) { super(key, attributes, tc, elements.size()); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(CollectionType.btree, - attributes.getOverflowAction()); + CollectionType.btree.checkOverflowAction(attributes.getOverflowAction()); } this.elements = elements; } @@ -279,13 +275,13 @@ public ByteBuffer getAsciiCommand() { // create ascii operation string String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cd.getFlags()) : ""; + attributes.toCreateClause(cd.getFlags()) : ""; for (i = 0; i < eSize; i++) { Element element = elements.get(i + nextOpIndex); byte[] value = encodedList.get(i); setArguments(bb, COMMAND, key, - element.getStringBkey(), element.getStringEFlag(), value.length, - createClause, (i < eSize - 1) ? PIPE : ""); + element.getStringBkey(), element.getStringEFlag(), value.length, + createClause, (i < eSize - 1) ? PIPE : ""); bb.put(value); bb.put(CRLF); } @@ -309,8 +305,7 @@ public MapPipedInsert(String key, Map map, CreateAttributes attributes, Transcoder tc) { super(key, attributes, tc, map.size()); if (attributes != null) { /* item creation option */ - CollectionCreate.checkOverflowAction(CollectionType.map, - attributes.getOverflowAction()); + CollectionType.map.checkOverflowAction(attributes.getOverflowAction()); } this.map = map; } @@ -344,12 +339,12 @@ public ByteBuffer getAsciiCommand() { // create ascii operation string String createClause = attributes != null ? - CollectionCreate.makeCreateClause(attributes, cd.getFlags()) : ""; + attributes.toCreateClause(cd.getFlags()) : ""; for (i = 0; i < eSize; i++) { String mkey = mkeyList.get(i); byte[] value = encodedList.get(i); setArguments(bb, COMMAND, key, mkey, value.length, - createClause, (i < eSize - 1) ? PIPE : ""); + createClause, (i < eSize - 1) ? PIPE : ""); bb.put(value); bb.put(CRLF); } diff --git a/src/main/java/net/spy/memcached/collection/CollectionType.java b/src/main/java/net/spy/memcached/collection/CollectionType.java index 821fee92b..63c8d7bc8 100644 --- a/src/main/java/net/spy/memcached/collection/CollectionType.java +++ b/src/main/java/net/spy/memcached/collection/CollectionType.java @@ -72,7 +72,10 @@ public static CollectionType find(String value) { return null; } - public boolean isAvailableOverflowAction(CollectionOverflowAction overflowAction) { - return availableOverflowAction.contains(overflowAction); + public void checkOverflowAction(CollectionOverflowAction overflowAction) { + if (overflowAction != null && !availableOverflowAction.contains(overflowAction)) { + throw new IllegalArgumentException( + overflowAction + " is unavailable overflow action in " + this + "."); + } } } diff --git a/src/main/java/net/spy/memcached/collection/CreateAttributes.java b/src/main/java/net/spy/memcached/collection/CreateAttributes.java index e8fff6248..536e7a1da 100644 --- a/src/main/java/net/spy/memcached/collection/CreateAttributes.java +++ b/src/main/java/net/spy/memcached/collection/CreateAttributes.java @@ -41,6 +41,7 @@ public final class CreateAttributes { private final long maxCount; private final CollectionOverflowAction overflowAction; private final boolean readable; + private String clause; private CreateAttributes(Builder builder) { this.expireTime = builder.expireTime; @@ -72,6 +73,36 @@ public static CreateAttributes of(CollectionAttributes attr) { .build(); } + /** + * Serializes the create-command attribute clause into a string. + * + * @return {@code [overflow action] [unreadable]} (no flags / create / noreply) + */ + public String stringify() { + if (clause == null) { + StringBuilder sb = new StringBuilder(); + sb.append(expireTime).append(' ').append(maxCount); + if (overflowAction != null) { + sb.append(' ').append(overflowAction); + } + if (!readable) { + sb.append(' ').append("unreadable"); + } + clause = sb.toString(); + } + return clause; + } + + /** + * Builds the {@code create} clause embedded in an insert-with-create command. + * + * @param flags the item flags + * @return {@code create } followed by {@link #stringify()} + */ + public String toCreateClause(int flags) { + return "create " + flags + " " + stringify(); + } + public long getExpireTime() { return this.expireTime; }