Пример #1
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);
  }
Пример #2
0
  /**
   * This is a recovery-only method and should not be called during normal execution. As such we
   * need to load in all of the logs we can find that aren't already loaded (or activated).
   */
  public boolean allObjUids(String tName, InputObjectState state, int match)
      throws ObjectStoreException {
    /*
     * match will always be OS_COMMITTED since that's all we ever write for
     * the logs.
     */

    // in case of asynchronous removals trigger the purger now.

    _purger.trigger();

    /*
     * Get a list of logs. Load them in to memory if we aren't already
     * working on them/it. But we can prune the entry once we're
     * finished or the memory footprint will grow. We should do this
     * for all frozen entries eventually too.
     */

    InputObjectState logs = new InputObjectState();
    OutputObjectState objUids = new OutputObjectState();

    /*
     * We never call this method except during recovery. As such we shouldn't
     * need to worry about optimizations such as checking whether or not the
     * log is in current working memory.
     */

    if (!super.allObjUids(tName, logs, match)) return false;
    else {
      /*
       * Now we have all of the log names let's attach to each one
       * and locate the committed instances (not deleted.)
       */

      Uid logName = new Uid(Uid.nullUid());

      try {
        do {
          logName = UidHelper.unpackFrom(logs);

          if (logName.notEquals(Uid.nullUid())) {
            /*
             * Could check to see if log is in current working memory.
             */

            /*
             * TODO
             *
             * First purge the log if we can, but we need to know that
             * we're not playing with an instance that is being manipulated
             * from another VM instance.
             */

            ArrayList<InputObjectState> txs = scanLog(logName, tName);

            if (txs.size() > 0) {
              for (int i = 0; i < txs.size(); i++) {
                UidHelper.packInto(txs.get(i).stateUid(), objUids);
              }
            }
          }
        } while (logName.notEquals(Uid.nullUid()));

        // remember null terminator

        UidHelper.packInto(Uid.nullUid(), objUids);

        state.setBuffer(objUids.buffer());
      } catch (final IOException ex) {
        ex.printStackTrace();

        return false;
      }

      return true;
    }
  }