Exemplo n.º 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);
      }
    }
  }
Exemplo n.º 2
0
  private final boolean truncateLog(final LogInstance log, boolean force)
      throws ObjectStoreException {
    boolean delete = false;

    synchronized (_lock) {
      File fd = new File(genPathName(log.getName(), log.getTypeName(), StateStatus.OS_COMMITTED));

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

        ArrayList<InputObjectState> objectStates = scanLog(log.getName(), log.getTypeName());

        /*
         * At this stage we should now have a list of unique
         * entries. Write them back to the log. Do this
         * atomically! If the list is empty then delete the
         * file!
         */

        if ((objectStates != null) && (objectStates.size() > 0)) {
          /*
           * If we are terminating then we can truncate the log to the
           * real size needed to contain the existing entries since we
           * will not use it again within another VM except for
           * recovery purposes.
           */

          String fname = genPathName(log.getName(), log.getTypeName(), StateStatus.OS_UNCOMMITTED);
          File fd2 = openAndLock(fname, FileLock.F_WRLCK, true);
          RandomAccessFile oFile = new RandomAccessFile(fd2, FILE_MODE);
          int size = 0;

          oFile.setLength(_maxFileSize);

          for (int i = 0; i < objectStates.size(); i++) {
            byte[] uidString = objectStates.get(i).stateUid().stringForm().getBytes();
            int buffSize =
                _redzone.length + uidString.length + objectStates.get(i).buffer().length + 8;
            java.nio.ByteBuffer buff = java.nio.ByteBuffer.allocate(buffSize);

            size += buffSize;

            try {
              buff.put(_redzone);
              buff.putInt(uidString.length);
              buff.put(uidString);
              buff.putInt(objectStates.get(i).buffer().length);
              buff.put(objectStates.get(i).buffer(), 0, objectStates.get(i).buffer().length);
            } catch (final Exception ex) {
              ex.printStackTrace();

              // TODO log

              fd2.delete();

              unlockAndClose(fd2, oFile);

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

          try {
            if (force) {
              oFile.setLength(size);

              log.freeze();
            }

            fd2.renameTo(fd);
          } catch (final Exception ex) {
            ex.printStackTrace();

            // TODO log

            throw new ObjectStoreException(ex.toString(), ex);
          } finally {
            unlockAndClose(fd2, oFile);
          }
        } else {
          /*
           * Delete the log if there are no states in it. We could
           * keep the file around and reuse it, but the advantage of
           * this is small compared to having to cope with reusing old
           * log instances.
           */

          fd.delete();

          /*
           * Remember to remove the information from the memory cache.
           */

          delete = true;
        }
      } catch (final ObjectStoreException ex) {
        ex.printStackTrace();

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

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

    return delete;
  }