Ejemplo n.º 1
0
  private void _storeFunctions(String what, boolean isPrintOutput) {

    _prepareKey();
    if (myKey == null) return;

    // +++TODO
    // errorMessage = _checkStore()

    // put & Co. return a Version, get returns a ValueVersion,
    // delete returns a boolean.
    try {
      if (what.equals("delete")) {
        boolean isSuccess = store.delete(myKey);
        if (isPrintOutput) System.out.println(isSuccess);
      } else if (what.equals("multiDelete")) {
        int isSuccess = store.multiDelete(myKey, null, null);
        if (isPrintOutput) System.out.println(isSuccess);
      } else if (what.equals("get")) {
        // store.get returns Null or the valueVersion.
        ValueVersion valueVersion = store.get(myKey);
        if (valueVersion != null) {
          // toString () from getValue ().getValue () does not work.
          String myValueString = new String(valueVersion.getValue().getValue());
          if (isPrintOutput) System.out.println(myValueString);
        } else {
          // If this is a test, assuming a proper key was put,
          // it did not pass it.
          if (isPrintOutput) {
            System.out.println("Key " + keysString + " could not be found.");
          }
          return;
        }
      } else if (what.equals("put")) {
        // put, putIfAbsent, putIfPresent.
        myValue = Value.createValue(valueString.getBytes());

        // Reflection is giving me too many troubles. So forget it.
        store.put(myKey, myValue);
      } else if (what.equals("putIfAbsent")) {
        myValue = Value.createValue(valueString.getBytes());
        store.putIfAbsent(myKey, myValue);
      } else if (what.equals("putIfPresent")) {
        myValue = Value.createValue(valueString.getBytes());
        store.putIfPresent(myKey, myValue);
      }
      positiveMessage = what + ": passed";
    } catch (Exception ex) {
      errorMessage = "ERROR in " + what + ": " + ex.toString();
      _printErrorMessage("False");
      return;
    }
    return;
  }
  /*------------------------------------------------------------ */
  @Override
  protected Object refresh(NoSqlSession session, Object version) {
    __log.debug("KVStoreSessionManager:refresh session {}", session.getId());

    // check if our in memory version is the same as what is on the disk
    if (version != null) {
      ValueVersion vval_version =
          this._kvstorehandler.get(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()),
                  Arrays.asList(__CONTEXT, _contextId, __VERSION)));

      if (vval_version != null && vval_version.getValue().getValue() != null) {

        Long saved_version = new Long(-1L);
        try {
          saved_version =
              new Long(
                  Base62Converter.toBase10(
                      new String(vval_version.getValue().getValue(), "UTF-8")));
        } catch (UnsupportedEncodingException e) {
        }

        if (saved_version.equals(version)) {
          __log.debug("KVStoreSessionManager:refresh not needed, session {}", session.getId());
          return version;
        }
        version = saved_version;
      }
    }

    // If we are here, we have to load the object
    ValueVersion vver_valid =
        _kvstorehandler.get(
            Key.createKey(
                Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__VALID)));

    // If it doesn't exist, invalidate
    if (vver_valid == null
        || vver_valid.getValue() == null
        || vver_valid.getValue().getValue() == null) {
      __log.debug(
          "KVStoreSessionManager:refresh:marking session {} invalid, no object",
          session.getClusterId());
      session.invalidate();
      return null;
    }
    try {

      // If it has been flagged invalid, invalidate
      String valid_str = new String(vver_valid.getValue().getValue(), "UTF-8");
      Boolean valid = valid_str == "1" ? true : false;
      if (!valid) {
        __log.debug(
            "KVstoreSessionManager:refresh:marking session {} invalid, valid flag {}",
            session.getClusterId(),
            valid);
        session.invalidate();
        return null;
      }

      // We need to update the attributes. We will model this as a passivate,
      // followed by bindings and then activation.
      session.willPassivate();
      SortedMap<Key, ValueVersion> context_keyvalues =
          _kvstorehandler.multiGet(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()),
                  Arrays.asList(__CONTEXT, _contextId)),
              null,
              Depth.CHILDREN_ONLY);

      // if disk version now has no attributes, get rid of them
      if (context_keyvalues == null || context_keyvalues.size() == 0) {
        session.clearAttributes();
      } else {
        // iterate over the names of the attributes on the disk version, updating the value
        ArrayList<String> stored_attrs = new ArrayList<String>();
        for (Entry<Key, ValueVersion> attr_entry : context_keyvalues.entrySet()) {
          List<String> attr_minorpath = attr_entry.getKey().getMinorPath();
          String attribute_name = attr_minorpath.get(attr_minorpath.size() - 1);
          String attr = decodeName(attribute_name);
          Object value = null;
          if (attr_entry.getValue() != null
              && attr_entry.getValue().getValue() != null
              && attr_entry.getValue().getValue().getValue() != null)
            value = decodeValue(attr_entry.getValue().getValue().getValue());

          // session does not already contain this attribute, so bind it
          if (value != null) {
            stored_attrs.add(attr);
            if (session.getAttribute(attr) == null) {
              session.doPutOrRemove(attr, value);
              session.bindValue(attr, value);
            } else // session already contains this attribute, update its value
            session.doPutOrRemove(attr, value);
          }
        }
        // cleanup, remove values from session, that don't exist in data anymore:
        for (String sess_attr_entry : session.getNames()) {
          if (!stored_attrs.contains(sess_attr_entry)) {
            session.doPutOrRemove(sess_attr_entry, null);
            session.unbindValue(sess_attr_entry, session.getAttribute(sess_attr_entry));
          }
        }
      }

      /*
       * We are refreshing so we should update the last accessed time.
       */
      // update purge index too, if we here we assume valid is set to 1, so we do not need to check
      // for old value
      ValueVersion old_accessed =
          _kvstorehandler.get(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__ACCESSED)));
      if (old_accessed != null
          && old_accessed.getValue() != null
          && old_accessed.getValue().getValue() != null) {
        _kvstorehandler.delete(
            Key.createKey(
                Arrays.asList(
                    __purgeindexprefix,
                    "1",
                    new String(old_accessed.getValue().getValue(), "UTF-8")),
                Arrays.asList(session.getClusterId())));
      }
      String new_accessed = Base62Converter.longToLexiSortableBase62(System.currentTimeMillis());
      _kvstorehandler.put(
          Key.createKey(
              Arrays.asList(__purgeindexprefix, "1", new_accessed),
              Arrays.asList(session.getClusterId())),
          Value.EMPTY_VALUE);

      _kvstorehandler.put(
          Key.createKey(
              Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__ACCESSED)),
          Value.createValue(new_accessed.getBytes("UTF-8")));
      session.didActivate();

      return version;
    } catch (Exception e) {
      LOG.warn(e);
    }

    return null;
  }
  /** @see org.eclipse.jetty.nosql.NoSqlSessionManager#expire(java.lang.String) */
  @Override
  protected void expire(String idInCluster) {
    __log.debug("KVStoreSessionManager:expire session {} ", idInCluster);

    // Expire the session for this context
    super.expire(idInCluster);

    // If the outer session document has not already been marked invalid, do so.
    ValueVersion vver_valid =
        _kvstorehandler.get(
            Key.createKey(Arrays.asList(__storeprefix, idInCluster), Arrays.asList(__VALID)));

    try {
      if (vver_valid != null
          && vver_valid.getValue() != null
          && vver_valid.getValue().getValue() != null
          && "0".equals(new String(vver_valid.getValue().getValue(), "UTF-8"))) {
        if (this.kvstore_opfactory == null)
          this.kvstore_opfactory = this._kvstorehandler.getOperationFactory();
        kvstore_object_ops.clear();
        kvstore_object_ops.add(
            this.kvstore_opfactory.createPut(
                Key.createKey(Arrays.asList(__storeprefix, idInCluster), Arrays.asList(__VALID)),
                Value.createValue("0".getBytes("UTF-8"))));
        kvstore_object_ops.add(
            this.kvstore_opfactory.createPut(
                Key.createKey(
                    Arrays.asList(__storeprefix, idInCluster), Arrays.asList(__INVALIDATED)),
                Value.createValue(
                    Base62Converter.fromBase10(System.currentTimeMillis()).getBytes("UTF-8"))));

        // update indexes
        // delete old entries, if present
        ValueVersion old_valid =
            _kvstorehandler.get(
                Key.createKey(Arrays.asList(__storeprefix, idInCluster), Arrays.asList(__VALID)));
        __log.debug("old_valid=" + (old_valid != null ? "notnull" : "null"));
        ValueVersion old_accessed =
            _kvstorehandler.get(
                Key.createKey(
                    Arrays.asList(__storeprefix, idInCluster), Arrays.asList(__ACCESSED)));
        __log.debug("old_accessed=" + (old_accessed != null ? "notnull" : "null"));
        if (old_valid != null
            && old_valid.getValue() != null
            && old_valid.getValue().getValue() != null
            && old_accessed != null
            && old_accessed.getValue() != null
            && old_accessed.getValue().getValue() != null) {
          __log.debug("deleting old purgeindex entry");
          _kvstorehandler.delete(
              Key.createKey(
                  Arrays.asList(
                      __purgeindexprefix,
                      new String(old_valid.getValue().getValue(), "UTF-8"),
                      new String(old_accessed.getValue().getValue(), "UTF-8")),
                  Arrays.asList(idInCluster)));
        } else __log.debug("some keys for purge index missing, nothing to delete");

        _kvstorehandler.put(
            Key.createKey(
                Arrays.asList(
                    __purgeindexprefix,
                    "0",
                    new String(old_accessed.getValue().getValue(), "UTF-8")),
                Arrays.asList(idInCluster)),
            Value.EMPTY_VALUE);

        if (kvstore_object_ops.size() > 0) {
          _kvstorehandler.execute(kvstore_object_ops);
          kvstore_object_ops.clear();
        }
      }
    } catch (UnsupportedEncodingException | OperationExecutionException | FaultException e) {
      __log.debug(
          "KVStoreSessionManager: expire :: error :: session {} context {} ",
          idInCluster,
          _contextId);
    }
  }
  /* ------------------------------------------------------------ */
  @Override
  protected synchronized Object save(
      NoSqlSession session, Object version, boolean activateAfterSave) {
    try {
      __log.debug("KVStoreSessionManager:save session {}", session.getClusterId());
      session.willPassivate();
      this.kvstore_object_ops.clear();
      if (this.kvstore_opfactory == null)
        this.kvstore_opfactory = this._kvstorehandler.getOperationFactory();
      /*
              // Form query for upsert
              BasicDBObject key = new BasicDBObject(__ID,session.getClusterId());

              // Form updates
              BasicDBObject update = new BasicDBObject();

              BasicDBObject sets = new BasicDBObject();
              BasicDBObject unsets = new BasicDBObject();
      */
      boolean upsert = false;
      boolean need_to_purge_attributes = false;
      // handle valid or invalid
      String new_valid = null;
      String new_expiry = null;
      String new_accessed = Base62Converter.longToLexiSortableBase62(session.getAccessed());
      if (session.isValid()) {
        new_valid = "1";
        long expiry =
            (session.getMaxInactiveInterval() > 0
                ? (session.getAccessed() + (1000L * getMaxInactiveInterval()))
                : 0);
        new_expiry = Base62Converter.longToLexiSortableBase62(expiry);
        __log.debug(
            "KVStoreSessionManager: calculated expiry {} for session {}", expiry, session.getId());
        // handle new or existing
        if (version == null) {
          __log.debug("New session");
          upsert = true;
          version = new Long(1);
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__CREATED)),
                  Value.createValue(
                      Base62Converter.fromBase10(session.getCreationTime()).getBytes("UTF-8"))));
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__VALID)),
                  Value.createValue(new_valid.getBytes("UTF-8"))));
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__CONTEXT, _contextId, __VERSION)),
                  Value.createValue(
                      Base62Converter.fromBase10(((Long) version).longValue()).getBytes("UTF-8"))));
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__MAX_IDLE)),
                  Value.createValue(
                      Base62Converter.fromBase10(getMaxInactiveInterval()).getBytes("UTF-8"))));
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__EXPIRY)),
                  Value.createValue(new_expiry.getBytes("UTF-8"))));
        } else {
          version = new Long(((Number) version).longValue() + 1);
          kvstore_object_ops.add(
              this.kvstore_opfactory.createPut(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__CONTEXT, _contextId, __VERSION)),
                  Value.createValue(
                      Base62Converter.fromBase10(((Long) version).longValue()).getBytes("UTF-8"))));

          // if max idle time and/or expiry is smaller for this context, then choose that for the
          // whole session doc
          ValueVersion vval_max_idle =
              this._kvstorehandler.get(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__MAX_IDLE)));
          ValueVersion vval_expiry =
              this._kvstorehandler.get(
                  Key.createKey(
                      Arrays.asList(__storeprefix, session.getClusterId()),
                      Arrays.asList(__EXPIRY)));
          if (vval_max_idle != null && vval_max_idle.getValue().getValue() != null) {
            long currentMaxIdle =
                Base62Converter.toBase10(new String(vval_max_idle.getValue().getValue(), "UTF-8"));
            if (getMaxInactiveInterval() > 0 && getMaxInactiveInterval() < currentMaxIdle)
              kvstore_object_ops.add(
                  this.kvstore_opfactory.createPut(
                      Key.createKey(
                          Arrays.asList(__storeprefix, session.getClusterId()),
                          Arrays.asList(__MAX_IDLE)),
                      Value.createValue(
                          Base62Converter.fromBase10(getMaxInactiveInterval()).getBytes("UTF-8"))));
          }

          if (vval_expiry != null && vval_expiry.getValue().getValue() != null) {
            long currentExpiry =
                Base62Converter.toBase10(new String(vval_expiry.getValue().getValue(), "UTF-8"));
            if (expiry > 0 && expiry != currentExpiry) {
              new_expiry = Base62Converter.longToLexiSortableBase62(expiry);
              kvstore_object_ops.add(
                  this.kvstore_opfactory.createPut(
                      Key.createKey(
                          Arrays.asList(__storeprefix, session.getClusterId()),
                          Arrays.asList(__EXPIRY)),
                      Value.createValue(new_expiry.getBytes("UTF-8"))));
            }
          }
        }
        kvstore_object_ops.add(
            this.kvstore_opfactory.createPut(
                Key.createKey(
                    Arrays.asList(__storeprefix, session.getClusterId()),
                    Arrays.asList(__ACCESSED)),
                Value.createValue(new_accessed.getBytes("UTF-8"))));

        __log.debug(
            "session.isDirty=" + session.isDirty() + ";getSavePeriod=" + this.getSavePeriod());

        Set<String> names = session.takeDirty();
        if (isSaveAllAttributes() || upsert) {
          names.addAll(session.getNames()); // note dirty may include removed names
        }

        for (String name : names) {
          Object value = session.getAttribute(name);
          if (value == null)
            kvstore_object_ops.add(
                this.kvstore_opfactory.createDelete(
                    Key.createKey(
                        Arrays.asList(__storeprefix, session.getClusterId()),
                        Arrays.asList(__CONTEXT, _contextId, name))));
          else
            kvstore_object_ops.add(
                this.kvstore_opfactory.createPut(
                    Key.createKey(
                        Arrays.asList(__storeprefix, session.getClusterId()),
                        Arrays.asList(__CONTEXT, _contextId, name)),
                    Value.createValue(encodeValue(value))));
        }
      } else {
        need_to_purge_attributes = true;
        new_valid = "0";
        kvstore_object_ops.add(
            this.kvstore_opfactory.createPut(
                Key.createKey(
                    Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__VALID)),
                Value.createValue(new_valid.getBytes("UTF-8"))));
        kvstore_object_ops.add(
            this.kvstore_opfactory.createPut(
                Key.createKey(
                    Arrays.asList(__storeprefix, session.getClusterId()),
                    Arrays.asList(__INVALIDATED)),
                Value.createValue(
                    Base62Converter.fromBase10(System.currentTimeMillis()).getBytes("UTF-8"))));
        // unsets.put(getContextKey(),1);
      }

      // update indexes
      // delete old entries, if present
      ValueVersion old_valid =
          _kvstorehandler.get(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__VALID)));
      ValueVersion old_accessed =
          _kvstorehandler.get(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__ACCESSED)));
      ValueVersion old_expiry =
          _kvstorehandler.get(
              Key.createKey(
                  Arrays.asList(__storeprefix, session.getClusterId()), Arrays.asList(__EXPIRY)));

      if (old_valid != null
          && old_valid.getValue() != null
          && old_valid.getValue().getValue() != null
          && old_accessed != null
          && old_accessed.getValue() != null
          && old_accessed.getValue().getValue() != null) {
        __log.debug(
            "delete purgeindex entry for old_valid="
                + new String(old_valid.getValue().getValue(), "UTF-8")
                + ";old_accessed="
                + new String(old_accessed.getValue().getValue(), "UTF-8"));
        _kvstorehandler.delete(
            Key.createKey(
                Arrays.asList(
                    __purgeindexprefix,
                    new String(old_valid.getValue().getValue(), "UTF-8"),
                    new String(old_accessed.getValue().getValue(), "UTF-8")),
                Arrays.asList(session.getClusterId())));
      } else
        __log.debug(
            "nothing to delete from purge index, either accessed or valid keys are missing");
      __log.debug(
          "new_valid=" + new_valid + ";new_accessed=" + new_accessed + ";new_expiry=" + new_expiry);

      _kvstorehandler.put(
          Key.createKey(
              Arrays.asList(__purgeindexprefix, new_valid, new_accessed),
              Arrays.asList(session.getClusterId())),
          Value.EMPTY_VALUE);
      if (new_expiry != null) {
        if (old_expiry != null
            && old_expiry.getValue() != null
            && old_expiry.getValue().getValue() != null) {
          _kvstorehandler.delete(
              Key.createKey(
                  Arrays.asList(
                      __expirydailyindexprefix,
                      new String(old_expiry.getValue().getValue(), "UTF-8")),
                  Arrays.asList(session.getClusterId())));
        } else __log.debug("nothing to delete from expiry index, old expiry entry key is missing");

        _kvstorehandler.put(
            Key.createKey(
                Arrays.asList(__expirydailyindexprefix, new_expiry),
                Arrays.asList(session.getClusterId())),
            Value.EMPTY_VALUE);
      }
      // Done with indexes, do the upsert
      if (!kvstore_object_ops.isEmpty()) {
        _kvstorehandler.execute(kvstore_object_ops);
        kvstore_object_ops.clear();
      }
      if (need_to_purge_attributes) {
        /*
        __log.debug("before need to purge attrubutes");
           Iterator<Key> it = _kvstorehandler.multiGetKeysIterator(Direction.FORWARD, 10,
           		Key.createKey(Arrays.asList(
        				__storeprefix,
        				session.getClusterId())),
           		null,//new KeyRange("minorpart1",true,"minorpart1",true),
           		Depth.PARENT_AND_DESCENDANTS);
           while (it.hasNext()) {
           	Key key = it.next();
           	__log.debug("key="+key.toString());
           }
           */
        _kvstorehandler.multiDelete(
            Key.createKey(Arrays.asList(__storeprefix, session.getClusterId())),
            new KeyRange(__CONTEXT, true, __CONTEXT, true),
            Depth.PARENT_AND_DESCENDANTS);
        /*
        __log.debug("after need to purge attrubutes");
           Iterator<Key> it = _kvstorehandler.multiGetKeysIterator(Direction.FORWARD, 10,
           		Key.createKey(Arrays.asList(
        				__storeprefix,
        				session.getClusterId())),
           		null,//new KeyRange("minorpart1",true,"minorpart1",true),
           		Depth.PARENT_AND_DESCENDANTS);
           while (it.hasNext()) {
           	Key key = it.next();
           	__log.debug("key="+key.toString());
           }
           */

      }

      if (__log.isDebugEnabled()) __log.debug("KVStoreSessionManager:save:db.sessions.updated");
      if (activateAfterSave) session.didActivate();
      return version;
    } catch (Exception e) {
      LOG.warn(e);
    }
    return null;
  }