-
Notifications
You must be signed in to change notification settings - Fork 81
Use Opaque for locking instead of byte[], improve reuse of base64 keys #154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 16 commits
28fcfe4
e0176ff
bcb3e17
7334be2
d3a5bce
e1bcf35
f22dba3
72b87c9
52f8de7
a957861
da8f898
957551f
e74c087
b52ab01
7a64663
ff66e69
d53f432
d1bc72d
8f4c511
3ad63db
09e8063
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,49 +19,99 @@ | |
| */ | ||
| package org.dcache.nfs.util; | ||
|
|
||
| import java.io.Serializable; | ||
| import java.nio.ByteBuffer; | ||
| import java.util.Arrays; | ||
|
|
||
| import com.google.common.io.BaseEncoding; | ||
| import java.util.Base64; | ||
|
|
||
| /** | ||
| * A helper class for opaque data manipulations. Enabled opaque date to be used as a key in {@link java.util.Collection} | ||
| * Describes something that can be used as a key in {@link java.util.Map} and that can be converted to a {@code byte[]} | ||
| * and a Base64 string representation. | ||
| */ | ||
| public class Opaque implements Serializable { | ||
|
|
||
| private static final long serialVersionUID = 1532238396149112674L; | ||
| public interface Opaque { | ||
| /** | ||
| * Returns an {@link Opaque} instance based on a copy of the given bytes. | ||
| * | ||
| * @param bytes The bytes. | ||
| * @return The {@link Opaque} instance. | ||
| */ | ||
| public static Opaque forBytes(byte[] bytes) { | ||
| return new OpaqueImpl(bytes.clone()); | ||
| } | ||
|
|
||
| private final byte[] _opaque; | ||
| /** | ||
| * Returns an {@link Opaque} instance based on a copy of the {@code length} bytes from the given {@link ByteBuffer}. | ||
| * | ||
| * @param buf The buffer. | ||
| * @param length The number of bytes. | ||
| * @return The {@link Opaque} instance. | ||
| */ | ||
| public static Opaque forBytes(ByteBuffer buf, int length) { | ||
| byte[] bytes = new byte[length]; | ||
| buf.get(bytes); | ||
|
|
||
| public Opaque(byte[] opaque) { | ||
| _opaque = opaque; | ||
| return new OpaqueImpl(bytes); | ||
| } | ||
|
|
||
| public byte[] getOpaque() { | ||
| return _opaque; | ||
| } | ||
| byte[] toBytes(); | ||
|
|
||
| String toBase64(); | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Arrays.hashCode(_opaque); | ||
| } | ||
| int hashCode(); | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (o == this) { | ||
| return true; | ||
| boolean equals(Object o); | ||
|
|
||
| final class OpaqueImpl implements Opaque { | ||
| private final byte[] _opaque; | ||
| private String base64 = null; | ||
|
|
||
| private OpaqueImpl(byte[] opaque) { | ||
| _opaque = opaque; | ||
| } | ||
|
|
||
| @Override | ||
| public byte[] toBytes() { | ||
| return _opaque.clone(); | ||
| } | ||
| if (!(o instanceof Opaque)) { | ||
| return false; | ||
|
|
||
| @Override | ||
| public String toBase64() { | ||
| if (base64 == null) { | ||
| base64 = Base64.getEncoder().withoutPadding().encodeToString(_opaque); | ||
| } | ||
| return base64; | ||
| } | ||
|
|
||
| return Arrays.equals(_opaque, ((Opaque) o)._opaque); | ||
| } | ||
| @Override | ||
| public int hashCode() { | ||
| return Arrays.hashCode(_opaque); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| sb.append('[').append(BaseEncoding.base16().lowerCase().encode(_opaque)).append(']'); | ||
| return sb.toString(); | ||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (o == this) { | ||
| return true; | ||
| } | ||
| if (!(o instanceof Opaque)) { | ||
| return false; | ||
| } | ||
|
|
||
| if (o instanceof OpaqueImpl) { | ||
| return Arrays.equals(_opaque, ((OpaqueImpl) o)._opaque); | ||
| } else { | ||
| return Arrays.equals(_opaque, ((Opaque) o).toBytes()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This breaks the if
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow. This is the Other implementations of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Apart from the points above: My goal is to have an environment where an Since this may or may not be the default scenario for nfs4j, to keep the current Inode/file-id separation, we need a standard implementation ( |
||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns a (potentially non-stable) debug string. | ||
| * | ||
| * @see #toBase64() | ||
| */ | ||
| @Override | ||
| public String toString() { | ||
| return super.toString() + "[" + toBase64() + "]"; | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ByteBuffer has the
remainingmethod. Should do the job. No need to pass a length.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but we may not want to read the entire remainder