4 Replies Latest reply on Mar 8, 2011 4:52 PM by oflo

    HotRod server not supporting Berkeley DB as a cache store

    oflo

      Configuring HotRot caches to use BdbjeCacheStore as a cache store does not work:

      - try to put a value (string) for a key (string)

      - CacheLoaderInterceptor.loadIfNeeded() is invoked

      - BdbjeCacheStore.load(Object key) throws as the key is an ByteArrayKey and not serializable

       

      Any quick way to support this configuration? Thanks

        • 1. HotRod server not supporting Berkeley DB as a cache store
          oflo

          I wrote this test code (it relies on modification I have done to HotRod server - Main.scala class - to support passing the name of a class that implements EmbeddedCacheManager to be used by the server instead of DefaultCacheManager, I might submit that as a patch if of interest). It basically injects an interceptor before CacheLoaderInterceptor and that replaces ByteArrayKey with _ByteArrayKey that implements Serializable.

           

          The (limited) testing I have done seems to show that this works. Now my real question, is there a specific reason that eludes me right now for NOT having ByteArrayKey serializable? What could this approach break?

           

          Thanks

           

          @Marshallable(externalizer = ByteArrayKey.Externalizer.class, id = Ids.BYTE_ARRAY_KEY)

              static class _ByteArrayKey implements Serializable {

                  private static final long serialVersionUID = 4354582048886475960L;

                 

                  private final byte[] data;

                 

                  public _ByteArrayKey(ByteArrayKey key) {

                      data = key.getData();

                  }

                 

                  public _ByteArrayKey(byte[] data) {

                      this.data = data;

                  }

                 

                  public byte[] getData() {

                        return data;

                     }

           

                     @Override

                     public boolean equals(Object obj) {

                        if (this == obj)

                            return true;

                        if (obj == null || getClass() != obj.getClass())

                            return false;

                        _ByteArrayKey key = (_ByteArrayKey) obj;

                        return Arrays.equals(key.data, this.data);

                     }

           

                     @Override

                     public int hashCode() {

                        return 41 + Arrays.hashCode(data);

                     }

           

                     @Override

                     public String toString() {

                        return new StringBuilder().append("_ByteArrayKey").append("{")

                           .append("data=").append(Util.printArray(data, true))

                           .append("}").toString();

                     }

           

                     public static class Externalizer implements org.infinispan.marshall.Externalizer {

                        public void writeObject(ObjectOutput output, Object object) throws IOException {

                           _ByteArrayKey key = (_ByteArrayKey) object;

                           output.writeInt(key.data.length);

                           output.write(key.data);

                        }

           

                        public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {

                           byte[] data = new byte[input.readInt()];

                           input.readFully(data);

                           return new _ByteArrayKey(data);

                        }

                     }

              }

             

              private static void wrappKey(AbstractDataCommand command) {

                  Object key = command.getKey();

                  if(!(key instanceof ByteArrayKey)) {

                      return;

                  }

                  command.setKey(new _ByteArrayKey((ByteArrayKey)key));

              }

             

              private static <K, V> void injectInterceptors(Cache<K, V> cache) {

                  CommandInterceptor interceptor = new CacheLoaderInterceptor() {

                      @Override

                      public Object visitGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand command) throws Throwable {

                          wrappKey(command);

                          return invokeNextInterceptor(ctx, command);

                      }

                      @Override

                      public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {

                          wrappKey(command);

                          return invokeNextInterceptor(ctx, command);

                      }

                      @Override

                      public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {

                          wrappKey(command);

                          return invokeNextInterceptor(ctx, command);

                      }

                      @Override

                      public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {

                          wrappKey(command);

                          return invokeNextInterceptor(ctx, command);

                      }

                  };

                  cache.getAdvancedCache().addInterceptorBefore(interceptor, CacheLoaderInterceptor.class);

              }

          • 2. Re: HotRod server not supporting Berkeley DB as a cache store
            oflo

            To add to the previous post, I am aware of the fact that interceptors can be injected using the declarative method. I am using a programatic approach as we have other reasons to use our own cache manager, like having special control over some aspects of Berkely DB cache store, etc. I have also temporarily disabled the check for a pre-defined named cache in HotRodDecoder.scala:getCache() so we could create caches on demand.

             

            I understand that creating caches on demand is not yet supported (https://issues.jboss.org/browse/ISPN-658) but I have high hopes that it will make into 5.0.0

             

            Please note that my investigation is on 4.2.1.CR1

             

            I created https://issues.jboss.org/browse/ISPN-955 asking for the ability to pass to the HotRod server the name of a user defined cache manager class. That jira has the scala source code implementing the enhancement if anyone is interested...

            • 3. HotRod server not supporting Berkeley DB as a cache store
              galder.zamarreno

              Hmmmm, the fact that ByteArrayKey is not serializable is a problem for situations like this. Your workaround is rather wacky but works

               

              Would you mind opening a JIRA for the original issue and assign it to me? Username: galder.zamarreno

               

              It needs some thinking to stop users needing to do this wacky workarounds. Btw, when you fill the JIRA, make sure you note the workaround.

              • 4. HotRod server not supporting Berkeley DB as a cache store
                oflo