Beispiel #1
0
  private final ArrayList<InputObjectState> scanLog(final Uid logName, final String typeName)
      throws ObjectStoreException {
    /*
     * Make sure no new entries can be created while we scan.
     */

    synchronized (_lock) {
      try {
        String fname = genPathName(logName, typeName, StateStatus.OS_COMMITTED);
        File fd = openAndLock(fname, FileLock.F_WRLCK, true);
        RandomAccessFile iFile = new RandomAccessFile(fd, FILE_MODE);
        // iFile.getChannel().lock();

        try {
          /*
           * Create a list of ObjectState entries.
           */

          ArrayList<InputObjectState> objectStates = new ArrayList<InputObjectState>();

          iFile.seek(0); // make sure we're at the start

          while (iFile.getFilePointer() < iFile.length()) {
            byte[] buff = new byte[_redzone.length];

            iFile.read(buff);

            if (!redzoneProtected(buff)) {
              // end

              break;

              /*
               * TODO add an end-of-log entry and check for that. Currently just assume
               * that no RZ means end, rather than corruption.
               */
            } else {
              int uidSize = iFile.readInt();
              byte[] uidString = new byte[uidSize];

              iFile.read(uidString);

              Uid txId = new Uid(new String(uidString));
              int imageSize = iFile.readInt();
              byte[] imageState = new byte[imageSize];

              iFile.read(imageState);

              try {
                InputObjectState state = new InputObjectState(txId, "", imageState);

                objectStates.add(state);
              } catch (final Exception ex) {
                ex.printStackTrace();

                throw new ObjectStoreException(ex.toString(), ex);
              }
            }
          }

          unlockAndClose(fd, iFile);
          iFile = null;

          /*
           * At this stage we now have a list of ObjectState entries.
           * Now we need to go through and prune the list. This is
           * complicated by the fact that there can be 1.. entries for
           * a specific transaction since we continually update the
           * log as we drive recovery. If an entry hasn't been deleted
           * then we will keep the latest one we find.
           */

          /*
           * First search for those entries that have been deleted.
           */

          ArrayList<InputObjectState> deletedLogs = new ArrayList<InputObjectState>();

          for (int i = 0; i < objectStates.size(); i++) {
            InputObjectState curr = objectStates.get(i);

            try {
              if (Arrays.equals(curr.unpackBytes(), _removedState)) {
                deletedLogs.add(curr);
              } else curr.reread(); // don't forget to reset the read pointer!
            } catch (final Exception ex) {
              // if not a delete record then the first entry won't
              // be an the defined byte array.
              curr.reread(); // don't forget to reset the read pointer!
            }
          }

          if (deletedLogs.size() > 0) {
            /*
             * make sure we remove them from the first list to save time.
             */

            objectStates.removeAll(deletedLogs);

            deleteEntries(objectStates, deletedLogs);

            /*
             * At this stage we should only have entries that refer
             * to in-flight transactions. Go through the list and
             * remove N-1 references for each transaction id.
             */

            pruneEntries(objectStates);

            /*
             * Now return the list of committed entries.
             */

            return objectStates;
          } else return objectStates;
        } finally {
          if (iFile != null) unlockAndClose(fd, iFile);
        }
      } catch (final ObjectStoreException ex) {
        ex.printStackTrace();

        throw ex;
      } catch (final Exception ex) {
        ex.printStackTrace();

        throw new ObjectStoreException(ex.toString(), ex);
      }
    }
  }
  public boolean restore_state(InputObjectState os, int t) {
    boolean res = false;

    try {
      _heuristic = os.unpackInt();
      _committed = os.unpackBoolean();

      _tranID = XidImple.unpack(os);

      _theXAResource = null;
      _recoveryObject = null;

      if (os.unpackInt() == RecoverableXAConnection.OBJECT_RECOVERY) {
        _productName = os.unpackString();
        _productVersion = os.unpackString();
        _jndiName = os.unpackString();

        boolean haveXAResource = os.unpackBoolean();

        if (haveXAResource) {
          try {
            // Read the classname of the serialized XAResource
            String className = os.unpackString();

            byte[] b = os.unpackBytes();

            ByteArrayInputStream s = new ByteArrayInputStream(b);
            ObjectInputStream o = new ObjectInputStream(s);

            // Give the list of deserializers a chance to deserialize the record
            boolean deserialized = false;
            Iterator<SerializableXAResourceDeserializer> iterator =
                getXAResourceDeserializers().iterator();
            while (iterator.hasNext()) {
              SerializableXAResourceDeserializer proxyXAResourceDeserializer = iterator.next();
              if (proxyXAResourceDeserializer.canDeserialze(className)) {
                _theXAResource = proxyXAResourceDeserializer.deserialze(o);
                deserialized = true;
                break;
              }
            }

            // Give it a go ourselves
            if (!deserialized) {
              _theXAResource = (XAResource) o.readObject();
            }
            o.close();

            if (jtaLogger.logger.isTraceEnabled()) {
              jtaLogger.logger.trace("XAResourceRecord.restore_state - XAResource de-serialized");
            }
          } catch (Exception ex) {
            // not serializable in the first place!

            jtaLogger.i18NLogger.warn_resources_arjunacore_restorestate(ex);

            return false;
          }
        } else {
          /*
           * Lookup new XAResource via XARecoveryModule if possible.
           */

          _theXAResource = getNewXAResource();

          if (_theXAResource == null) {
            jtaLogger.i18NLogger.warn_resources_arjunacore_norecoveryxa(toString());

            /*
             * Don't prevent tx from activating because there may be
             * other participants that can still recover. Plus, we will
             * try to get a new XAResource later for this instance.
             */

            res = true;
          }
        }
      } else {
        String creatorName = os.unpackString();

        _recoveryObject =
            ClassloadingUtility.loadAndInstantiateClass(
                RecoverableXAConnection.class, creatorName, null);
        if (_recoveryObject == null) {
          throw new ClassNotFoundException();
        }

        _recoveryObject.unpackFrom(os);
        _theXAResource = _recoveryObject.getResource();

        if (jtaLogger.logger.isTraceEnabled()) {
          jtaLogger.logger.trace(
              "XAResourceRecord.restore_state - XAResource got from " + creatorName);
        }
      }

      res = true;
    } catch (Exception e) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_restorestateerror(
          _theXAResource.toString(), XAHelper.xidToString(_tranID), e);

      res = false;
    }

    if (res) res = super.restore_state(os, t);

    return res;
  }