Beispiel #1
0
  boolean truncateLogs(boolean force) throws ObjectStoreException {
    synchronized (_logNames) {
      Iterator<LogInstance> iter = _logNames.iterator();

      /*
       * Only do this for logs that are full to save time,
       * except if we are terminating.
       */

      while (iter.hasNext()) {
        boolean delete = false;
        LogInstance log = null;

        try {
          log = iter.next();

          if (log.isFrozen() || force) delete = truncateLog(log, force);
        } catch (final Exception ex) {
          // TODO log
        }

        if (delete) iter.remove();
      }
    }

    return true;
  }
Beispiel #2
0
  private final void removeFromLog(Uid txid) {
    if (_synchronousRemoval) {
      synchronized (_logNames) {
        Iterator<LogInstance> iter = _logNames.iterator();
        LogInstance entry = null;

        while (iter.hasNext()) {
          entry = (LogInstance) iter.next();

          if (entry.present(txid)) {
            // entry.removeTxId(txid);
            break;
          }
        }
      }
    }
  }
Beispiel #3
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;
  }
Beispiel #4
0
  /**
   * write_state saves the ObjectState in a file named by the type and Uid of the ObjectState. If
   * the second argument is SHADOW, then the file name is different so that a subsequent
   * commit_state invocation will rename the file.
   *
   * <p>We need to make sure that each entry is written to the next empty location in the log even
   * if there's already an entry for this tx.
   */
  protected boolean write_state(Uid objUid, String tName, OutputObjectState state, int ft)
      throws ObjectStoreException {
    if (tsLogger.logger.isTraceEnabled()) {
      tsLogger.logger.trace(
          "ShadowingStore.write_state("
              + objUid
              + ", "
              + tName
              + ", "
              + StateType.stateTypeString(ft)
              + ")");
    }

    String fname = null;
    File fd = null;

    if (tName != null) {
      int imageSize = (int) state.length();
      byte[] uidString = objUid.stringForm().getBytes();
      int buffSize =
          _redzone.length
              + uidString.length
              + imageSize
              + 8; // don't put in endOfLog since we keep overwriting that.
      RandomAccessFile ofile = null;
      java.nio.channels.FileLock lock = null;

      if (imageSize > 0) {
        TransactionData theLogEntry =
            getLogName(objUid, tName, buffSize); // always adds entry to log
        LogInstance theLog = theLogEntry.container;

        if (theLog == null) throw new ObjectStoreException();

        fname = genPathName(theLog.getName(), tName, ft);
        fd = openAndLock(fname, FileLock.F_WRLCK, true);

        if (fd == null) {
          tsLogger.i18NLogger.warn_objectstore_ShadowingStore_18(fname);

          return false;
        }

        boolean setLength = !fd.exists();

        try {
          ofile = new RandomAccessFile(fd, FILE_MODE);

          if (setLength) {
            ofile.setLength(_maxFileSize);
          } else {
            // may have to resize file if we keep updating this transaction info

            if (theLog.remaining() < buffSize) {
              long size = ofile.length() + buffSize - theLog.remaining();

              ofile.setLength(size);

              theLog.resize(size);
            }
          }

          java.nio.ByteBuffer buff = java.nio.ByteBuffer.allocate(buffSize);

          buff.put(_redzone);
          buff.putInt(uidString.length);
          buff.put(uidString);
          buff.putInt(imageSize);
          buff.put(state.buffer());

          synchronized (_lock) {
            ofile.seek(theLogEntry.offset);

            ofile.write(buff.array());
          }
        } catch (SyncFailedException e) {
          unlockAndClose(fd, ofile);

          throw new ObjectStoreException(
              "ShadowingStore::write_state() - write failed to sync for " + fname, e);
        } catch (FileNotFoundException e) {
          unlockAndClose(fd, ofile);

          e.printStackTrace();

          throw new ObjectStoreException(
              "ShadowingStore::write_state() - write failed to locate file " + fname + ": " + e, e);
        } catch (IOException e) {
          unlockAndClose(fd, ofile);

          e.printStackTrace();

          throw new ObjectStoreException(
              "ShadowingStore::write_state() - write failed for " + fname + ": " + e, e);
        } finally {
          try {
            if (lock != null) lock.release();
          } catch (IOException ex) {
            ex.printStackTrace();
          }
        }
      }

      if (!unlockAndClose(fd, ofile)) {
        tsLogger.i18NLogger.warn_objectstore_ShadowingStore_19(fname);
      }

      super.addToCache(fname);

      return true;
    } else
      throw new ObjectStoreException(
          "ShadowStore::write_state - "
              + tsLogger.i18NLogger.get_objectstore_notypenameuid()
              + objUid);
  }
Beispiel #5
0
  private final TransactionData getLogName(Uid txid, String tName, long size)
      throws ObjectStoreException {
    synchronized (_logNames) {
      Iterator<LogInstance> iter = _logNames.iterator();
      LogInstance entry = null;

      /*
       * First check to see if the TxId is in an existing log. Always
       * return the same log instance for the same txid so we can
       * keep all data in the same location. This may mean that we have
       * to extend the size of the log over time to accommodate situations
       * where the log is modified but not deleted for a while, e.g., during
       * recovery.
       */

      while (iter.hasNext()) {
        entry = (LogInstance) iter.next();

        if (entry.present(txid)) {
          if (size == -1) // we are reading only
          return entry.getTxId(txid);
          else return entry.addTxId(txid, size);
        }
      }

      /*
       * If we get here then this TxId isn't in one of the
       * logs we are maintaining currently. So go back through
       * the list of logs and find one that is small enough
       * for us to use. The first one with room will do.
       */

      iter = _logNames.iterator();

      while (iter.hasNext()) {
        entry = (LogInstance) iter.next();

        if (!entry.isFrozen()) {
          if (entry.remaining() > size) {
            return entry.addTxId(txid, size);
          } else {
            /*
             * TODO
             *
             * When can we remove the information about this
             * log from memory? If we do it too soon then it's possible
             * that delete entries will not go into the right log. If we
             * leave it too late then the memory footprint increases. Prune
             * the entry when we prune the log from disk?
             */

            entry.freeze();
          }
        }
      }

      // if we get here, then we need to create a new log

      entry = new LogInstance(tName, _maxFileSize);
      _logNames.add(entry);

      return entry.addTxId(txid, size);
    }
  }