Package org.waveprotocol.box.server.persistence.file

Source Code of org.waveprotocol.box.server.persistence.file.FileDeltaStore

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.box.server.persistence.file;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
import com.google.inject.name.Named;

import org.waveprotocol.box.common.ExceptionalIterator;
import org.waveprotocol.box.server.CoreSettings;
import org.waveprotocol.box.server.persistence.PersistenceException;
import org.waveprotocol.box.server.waveserver.DeltaStore;
import org.waveprotocol.wave.model.id.WaveId;
import org.waveprotocol.wave.model.id.WaveletId;
import org.waveprotocol.wave.model.id.WaveletName;
import org.waveprotocol.wave.model.version.HashedVersion;
import org.waveprotocol.wave.util.logging.Log;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.waveprotocol.box.stat.Timed;

/**
* A flat file based implementation of DeltaStore.
*
* The delta store lives at some base directory. The directory structure looks like this:
* base/encoded-wave-id/encoded-wavelet-id.delta
* base/encoded-wave-id/encoded-wavelet-id.index
*
* See design doc:
* https://sites.google.com/a/waveprotocol.org/wave-protocol/protocol/design-proposals/wave-store-design-for-wave-in-a-box
*

* @author josephg@gmail.com (Joseph Gentle)
*/
public class FileDeltaStore implements DeltaStore {
  private static final Log LOG = Log.get(FileDeltaStore.class);
  /**
   * The directory in which the wavelets are stored
   */
  final private String basePath;

  @Inject
  public FileDeltaStore(@Named(CoreSettings.DELTA_STORE_DIRECTORY) String basePath) {
    Preconditions.checkNotNull(basePath, "Requested path is null");
    this.basePath = basePath;
  }

  @Timed
  @Override
  public FileDeltaCollection open(WaveletName waveletName) throws PersistenceException {
    try {
      return FileDeltaCollection.open(waveletName, basePath);
    } catch (IOException e) {
      throw new PersistenceException("Failed to open deltas for wavelet " + waveletName, e);
    }
  }

  @Override
  public void delete(WaveletName waveletName) throws PersistenceException {
    FileDeltaCollection.delete(waveletName, basePath);
  }

  @Timed
  @Override
  public ImmutableSet<WaveletId> lookup(WaveId waveId) throws PersistenceException {
    String waveDirectory = FileUtils.waveIdToPathSegment(waveId);
    File waveDir = new File(basePath, waveDirectory);
    if (!waveDir.exists()) {
      return ImmutableSet.of();
    }

    File[] deltaFiles = waveDir.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        return name.endsWith(FileDeltaCollection.DELTAS_FILE_SUFFIX);
      }
    });

    ImmutableSet.Builder<WaveletId> results = ImmutableSet.builder();
    for(File deltaFile : deltaFiles) {
      String name = deltaFile.getName();
      String encodedWaveletId =
          name.substring(0, name.lastIndexOf(FileDeltaCollection.DELTAS_FILE_SUFFIX));
      WaveletId waveletId = FileUtils.waveletIdFromPathSegment(encodedWaveletId);
        FileDeltaCollection deltas = open(WaveletName.of(waveId, waveletId));
        HashedVersion endVersion = deltas.getEndVersion();
        if (endVersion != null && endVersion.getVersion() > 0) {
          results.add(waveletId);
        }
      try {
        deltas.close();
      } catch (IOException e) {
        LOG.info("Failed to close deltas file " + name, e);
      }
    }

    return results.build();
  }

  @Timed
  @Override
  public ExceptionalIterator<WaveId, PersistenceException> getWaveIdIterator() {
    File baseDir = new File(basePath);
    if (!baseDir.exists()) {
      return ExceptionalIterator.Empty.create();
    }

    File[] waveDirs = baseDir.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        try {
          FileUtils.waveIdFromPathSegment(name);
          return true;
        } catch (IllegalArgumentException e) {
          return false;
        }
      }
    });

    final ImmutableSet.Builder<WaveId> results = ImmutableSet.builder();
    for(File waveDir : waveDirs) {
      results.add(FileUtils.waveIdFromPathSegment(waveDir.getName()));
    }

    return new ExceptionalIterator<WaveId, PersistenceException>() {
      private final Iterator<WaveId> iterator = results.build().iterator();
      private boolean nextFetched = false;
      private WaveId nextWaveId = null;

      private void fetchNext() throws PersistenceException {
        while(!nextFetched) {
          if (iterator.hasNext()) {
            nextWaveId = iterator.next();
            if (!lookup(nextWaveId).isEmpty()) {
              nextFetched = true;
            }
          } else {
            nextFetched = true;
            nextWaveId = null;
          }
        }
      }

      @Override
      public boolean hasNext() throws PersistenceException {
        fetchNext();
        return nextWaveId != null;
      }

      @Override
      public WaveId next() throws PersistenceException {
        fetchNext();
        if (nextWaveId == null) {
          throw new NoSuchElementException();
        } else {
          nextFetched = false;
          return nextWaveId;
        }
      }

    };
  }
}
TOP

Related Classes of org.waveprotocol.box.server.persistence.file.FileDeltaStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.