/** Copy state from existing MetaDataRecord. */
  public CacheRepositoryEntryState(File controlFile, MetaDataRecord entry) throws IOException {
    _controlFile = controlFile;
    _state = entry.getState();

    for (StickyRecord record : entry.stickyRecords()) {
      _sticky.addRecord(record.owner(), record.expire(), true);
    }

    makeStatePersistent();
  }
  public boolean setSticky(String owner, long expire, boolean overwrite)
      throws IllegalStateException, IOException {
    if (_state == EntryState.REMOVED || _state == EntryState.DESTROYED) {
      throw new IllegalStateException("Entry in removed state");
    }

    // if sticky flag modified, make changes persistent
    if (_sticky.addRecord(owner, expire, overwrite)) {
      makeStatePersistent();
      return true;
    }
    return false;
  }
  private void loadState() throws IOException {
    try (BufferedReader in = new BufferedReader(new FileReader(_controlFile))) {
      _state = EntryState.BROKEN;

      String line;
      while ((line = in.readLine()) != null) {

        // ignore empty lines
        line = line.trim();
        if (line.length() == 0) {
          continue;
        }

        // a comment or version string
        if (line.startsWith("#")) {
          Matcher m = VERSION_PATTERN.matcher(line);

          // it's the version string
          if (m.matches()) {
            String[] versionLine = line.split("\\s");
            String[] versionNumber = versionLine[2].split("\\.");

            int major = Integer.parseInt(versionNumber[0]);
            int minor = Integer.parseInt(versionNumber[1]);

            if (major > FORMAT_VERSION_MAJOR || minor != FORMAT_VERSION_MINOR) {
              throw new IOException(
                  "control file format mismatch: supported <= "
                      + FORMAT_VERSION_MAJOR
                      + "."
                      + FORMAT_VERSION_MINOR
                      + " found: "
                      + versionLine[2]);
            }
          }

          continue;
        }

        if (line.equals("precious")) {
          _state = EntryState.PRECIOUS;
          continue;
        }

        if (line.equals("cached")) {
          _state = EntryState.CACHED;
          continue;
        }

        if (line.equals("from_client")) {
          _state = EntryState.FROM_CLIENT;
          continue;
        }

        if (line.equals("from_store")) {
          _state = EntryState.FROM_STORE;
          continue;
        }

        /*
         * backward compatibility
         */

        if (line.equals("receiving.store")) {
          _state = EntryState.FROM_STORE;
          continue;
        }

        if (line.equals("receiving.cient")) {
          _state = EntryState.FROM_CLIENT;
          continue;
        }

        // in case of some one fixed the spelling
        if (line.equals("receiving.client")) {
          _state = EntryState.FROM_CLIENT;
          continue;
        }

        // FORMAT: sticky:owner:exipire
        if (line.startsWith("sticky")) {

          String[] stickyOptions = line.split(":");

          String owner;
          long expire;

          switch (stickyOptions.length) {
            case 1:
              // old style
              owner = "system";
              expire = -1;
              break;
            case 2:
              // only owner defined
              owner = stickyOptions[1];
              expire = -1;
              break;
            case 3:
              owner = stickyOptions[1];
              try {
                expire = Long.parseLong(stickyOptions[2]);
              } catch (NumberFormatException nfe) {
                // bad number
                _state = EntryState.BROKEN;
                return;
              }

              break;
            default:
              _logBussiness.info(
                  "Unknow number of arguments in " + _controlFile.getPath() + " [" + line + "]");
              _state = EntryState.BROKEN;
              return;
          }

          _sticky.addRecord(owner, expire, true);
          continue;
        }

        // if none of knows states, then it's BAD state
        _logBussiness.error("Invalid state [" + line + "] for entry " + _controlFile);
        break;
      }
    }
  }