Example #1
0
  /**
   * Allocates the requested space in the file.
   *
   * @param len requested space
   * @return allocated file position and length as FileEntry object
   */
  private FileEntry allocate(int len) {
    synchronized (freeList) {
      // lookup a free entry of sufficient size
      SortedSet<FileEntry> candidates = freeList.tailSet(new FileEntry(0, len));
      for (Iterator<FileEntry> it = candidates.iterator(); it.hasNext(); ) {
        FileEntry free = it.next();
        // ignore entries that are still in use by concurrent readers
        if (free.isLocked()) continue;

        // There's no race condition risk between locking the entry on
        // loading and checking whether it's locked (or store allocation),
        // because for the entry to be lockable, it needs to be in the
        // entries collection, in which case it's not in the free list.
        // The only way an entry can be found in the free list is if it's
        // been removed, and to remove it, lock on "entries" needs to be
        // acquired, which is also a pre-requisite for loading data.

        // found one, remove from freeList
        it.remove();
        return allocateExistingEntry(free, len);
      }

      // no appropriate free section available, append at end of file
      FileEntry fe = new FileEntry(filePos, len);
      filePos += len;
      if (trace)
        log.tracef(
            "New entry allocated at %d:%d, %d free entries, file size is %d",
            fe.offset, fe.size, freeList.size(), filePos);
      return fe;
    }
  }
Example #2
0
 /**
  * 创建Zipper对象
  *
  * @param out 输出流
  * @param filter 文件过滤,不过滤可以为null。
  * @param srcFilename 源文件名。可以有多个源文件,如果源文件是目录,那么所有子目录都将被包含。
  */
 protected Zipper(OutputStream out, List<FileEntry> fileEntrys, String encoding) {
   Assert.notEmpty(fileEntrys);
   long begin = System.currentTimeMillis();
   log.debug("开始制作压缩包");
   try {
     try {
       zipOut = new ZipOutputStream(out);
       if (!StringUtils.isBlank(encoding)) {
         log.debug("using encoding: {}", encoding);
         zipOut.setEncoding(encoding);
       } else {
         log.debug("using default encoding");
       }
       for (FileEntry fe : fileEntrys) {
         zip(fe.getFile(), fe.getFilter(), fe.getZipEntry(), fe.getPrefix());
       }
     } finally {
       zipOut.close();
     }
   } catch (IOException e) {
     throw new RuntimeException("制作压缩包时,出现IO异常!", e);
   }
   long end = System.currentTimeMillis();
   log.info("制作压缩包成功。耗时:{}ms。", end - begin);
 }
  @Override
  public View getView(final int position, final View convertView, final ViewGroup parent) {

    // We need to get the best view (re-used if possible) and then
    // retrieve its corresponding ViewHolder, which optimizes lookup efficiency
    final View view = getWorkingView(convertView);
    final ViewHolder viewHolder = getViewHolder(view);
    final FileEntry entry = getItem(position);

    // Setting the title view is straightforward
    viewHolder.titleView.setText(entry.getFilename());

    // Setting the subTitle view requires a tiny bit of formatting
    final String formattedSubTitle =
        String.format(
            "By %s on %s",
            entry.getAuthor(),
            DateFormat.getDateInstance(DateFormat.SHORT).format(entry.getPostDate()));

    viewHolder.subTitleView.setText(formattedSubTitle);

    // Setting image view is also simple
    viewHolder.imageView.setImageResource(entry.getIcon());

    return view;
  }
Example #4
0
  @Override
  public void clear() {
    resizeLock.writeLock().lock();
    try {
      synchronized (entries) {
        synchronized (freeList) {
          // wait until all readers are done reading file entries
          for (FileEntry fe : entries.values()) fe.waitUnlocked();
          for (FileEntry fe : freeList) fe.waitUnlocked();

          // clear in-memory state
          entries.clear();
          freeList.clear();

          // reset file
          if (trace) log.tracef("Truncating file, current size is %d", filePos);
          channel.truncate(0);
          channel.write(ByteBuffer.wrap(MAGIC), 0);
          filePos = MAGIC.length;
        }
      }
    } catch (Exception e) {
      throw new PersistenceException(e);
    } finally {
      resizeLock.writeLock().unlock();
    }
  }
Example #5
0
  /**
   * Coalesces adjacent free entries to create larger free entries (so that the probability of
   * finding a free entry during allocation increases)
   */
  private void mergeFreeEntries(List<FileEntry> entries) {
    long startTime = 0;
    if (trace) startTime = timeService.wallClockTime();
    FileEntry lastEntry = null;
    FileEntry newEntry = null;
    int mergeCounter = 0;
    for (Iterator<FileEntry> it = entries.iterator(); it.hasNext(); ) {
      FileEntry fe = it.next();
      if (fe.isLocked()) {
        continue;
      }

      // Merge any holes created (consecutive free entries) in the file
      if ((lastEntry != null) && (lastEntry.offset == (fe.offset + fe.size))) {
        if (newEntry == null) {
          newEntry = new FileEntry(fe.offset, fe.size + lastEntry.size);
          freeList.remove(lastEntry);
          mergeCounter++;
        } else {
          newEntry = new FileEntry(fe.offset, fe.size + newEntry.size);
        }
        freeList.remove(fe);
        mergeCounter++;
      } else {
        if (newEntry != null) {
          try {
            addNewFreeEntry(newEntry);
            if (trace)
              log.tracef(
                  "Merged %d entries at %d:%d, %d free entries",
                  mergeCounter, newEntry.offset, newEntry.size, freeList.size());
          } catch (IOException e) {
            throw new PersistenceException("Could not add new merged entry", e);
          }
          newEntry = null;
          mergeCounter = 0;
        }
      }
      lastEntry = fe;
    }

    if (newEntry != null) {
      try {
        addNewFreeEntry(newEntry);
        if (trace)
          log.tracef(
              "Merged %d entries at %d:%d, %d free entries",
              mergeCounter, newEntry.offset, newEntry.size, freeList.size());
      } catch (IOException e) {
        throw new PersistenceException("Could not add new merged entry", e);
      }
    }

    if (trace)
      log.tracef(
          "Total time taken for mergeFreeEntries: "
              + (timeService.wallClockTime() - startTime)
              + " (ms)");
  }
Example #6
0
 /**
  * Initialize the observer.
  *
  * @throws Exception if an error occurs
  */
 public void initialize() throws Exception {
   rootEntry.refresh(rootEntry.getFile());
   File[] files = listFiles(rootEntry.getFile());
   FileEntry[] children = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_ENTRIES;
   for (int i = 0; i < files.length; i++) {
     children[i] = createFileEntry(rootEntry, files[i]);
   }
   rootEntry.setChildren(children);
 }
Example #7
0
 /**
  * Fire directory/file delete events to the registered listeners.
  *
  * @param entry The file entry
  */
 private void doDelete(FileEntry entry) {
   for (FileAlterationListener listener : listeners) {
     if (entry.isDirectory()) {
       listener.onDirectoryDelete(entry.getFile());
     } else {
       listener.onFileDelete(entry.getFile());
     }
   }
 }
Example #8
0
 /**
  * Create a new file entry for the specified file.
  *
  * @param parent The parent file entry
  * @param file The file to create an entry for
  * @return A new file entry
  */
 private FileEntry createFileEntry(FileEntry parent, File file) {
   FileEntry entry = parent.newChildInstance(file);
   entry.refresh(file);
   File[] files = listFiles(file);
   FileEntry[] children = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_ENTRIES;
   for (int i = 0; i < files.length; i++) {
     children[i] = createFileEntry(entry, files[i]);
   }
   entry.setChildren(children);
   return entry;
 }
Example #9
0
 /**
  * Fire directory/file change events to the registered listeners.
  *
  * @param entry The previous file system entry
  * @param file The current file
  */
 private void doMatch(FileEntry entry, File file) {
   if (entry.refresh(file)) {
     for (FileAlterationListener listener : listeners) {
       if (entry.isDirectory()) {
         listener.onDirectoryChange(file);
       } else {
         listener.onFileChange(file);
       }
     }
   }
 }
Example #10
0
 /**
  * Fire directory/file created events to the registered listeners.
  *
  * @param entry The file entry
  */
 private void doCreate(FileEntry entry) {
   for (FileAlterationListener listener : listeners) {
     if (entry.isDirectory()) {
       listener.onDirectoryCreate(entry.getFile());
     } else {
       listener.onFileCreate(entry.getFile());
     }
   }
   FileEntry[] children = entry.getChildren();
   for (FileEntry aChildren : children) {
     doCreate(aChildren);
   }
 }
Example #11
0
 void assertFileEntryEquals(FileEntry actual, FileEntry expected) {
   assertEquals(
       actual.getType(), expected.getType(), "The first column, the entry type, is wrong");
   assertEquals(
       actual.getNewSHA(), expected.getNewSHA(), "The second column, the new SHA-256, is wrong");
   assertEquals(
       actual.getOldSHA(), expected.getOldSHA(), "The third column, the old SHA-256, is wrong");
   assertEquals(
       actual.getFile(), expected.getFile(), "The fourth column, the file name, is wrong");
 }
Example #12
0
  @Override
  public void purge(Executor threadPool, final PurgeListener task) {
    long now = timeService.wallClockTime();
    List<KeyValuePair<Object, FileEntry>> entriesToPurge =
        new ArrayList<KeyValuePair<Object, FileEntry>>();
    synchronized (entries) {
      for (Iterator<Map.Entry<K, FileEntry>> it = entries.entrySet().iterator(); it.hasNext(); ) {
        Map.Entry<K, FileEntry> next = it.next();
        FileEntry fe = next.getValue();
        if (fe.isExpired(now)) {
          it.remove();
          entriesToPurge.add(new KeyValuePair<Object, FileEntry>(next.getKey(), fe));
        }
      }
    }

    resizeLock.readLock().lock();
    try {
      for (Iterator<KeyValuePair<Object, FileEntry>> it = entriesToPurge.iterator();
          it.hasNext(); ) {
        KeyValuePair<Object, FileEntry> next = it.next();
        FileEntry fe = next.getValue();
        if (fe.isExpired(now)) {
          it.remove();
          try {
            free(fe);
          } catch (Exception e) {
            throw new PersistenceException(e);
          }
          if (task != null) task.entryPurged(next.getKey());
        }
      }

      // Disk space optimizations
      synchronized (freeList) {
        processFreeEntries();
      }
    } finally {
      resizeLock.readLock().unlock();
    }
  }
Example #13
0
 /**
  * Compare two file lists for files which have been created, modified or deleted.
  *
  * @param parent The parent entry
  * @param previous The original list of files
  * @param files The current list of files
  */
 private void checkAndNotify(FileEntry parent, FileEntry[] previous, File[] files) {
   int c = 0;
   FileEntry[] current = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_ENTRIES;
   for (FileEntry entry : previous) {
     while (c < files.length && comparator.compare(entry.getFile(), files[c]) > 0) {
       current[c] = createFileEntry(parent, files[c]);
       doCreate(current[c]);
       c++;
     }
     if (c < files.length && comparator.compare(entry.getFile(), files[c]) == 0) {
       doMatch(entry, files[c]);
       checkAndNotify(entry, entry.getChildren(), listFiles(files[c]));
       current[c] = entry;
       c++;
     } else {
       checkAndNotify(entry, entry.getChildren(), FileUtils.EMPTY_FILE_ARRAY);
       doDelete(entry);
     }
   }
   for (; c < files.length; c++) {
     current[c] = createFileEntry(parent, files[c]);
     doCreate(current[c]);
   }
   parent.setChildren(current);
 }
Example #14
0
  /** Check whether the file and its chlidren have been created, modified or deleted. */
  public void checkAndNotify() {

    /* fire onStart() */
    for (FileAlterationListener listener : listeners) {
      listener.onStart(this);
    }

    /* fire directory/file events */
    File rootFile = rootEntry.getFile();
    if (rootFile.exists()) {
      checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootFile));
    } else if (rootEntry.isExists()) {
      checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY);
    } else {
      // Didn't exist and still doesn't
    }

    /* fire onStop() */
    for (FileAlterationListener listener : listeners) {
      listener.onStop(this);
    }
  }
Example #15
0
  /** Removes free entries towards the end of the file and truncates the file. */
  private void truncateFile(List<FileEntry> entries) {
    long startTime = 0;
    if (trace) startTime = timeService.wallClockTime();

    int reclaimedSpace = 0;
    int removedEntries = 0;
    long truncateOffset = -1;
    for (Iterator<FileEntry> it = entries.iterator(); it.hasNext(); ) {
      FileEntry fe = it.next();
      // Till we have free entries at the end of the file,
      // we can remove them and contract the file to release disk
      // space.
      if (!fe.isLocked() && ((fe.offset + fe.size) == filePos)) {
        truncateOffset = fe.offset;
        filePos = fe.offset;
        freeList.remove(fe);
        it.remove();
        reclaimedSpace += fe.size;
        removedEntries++;
      } else {
        break;
      }
    }

    if (truncateOffset > 0) {
      try {
        channel.truncate(truncateOffset);
      } catch (IOException e) {
        throw new PersistenceException("Error while truncating file", e);
      }
    }

    if (trace) {
      log.tracef("Removed entries: " + removedEntries + ", Reclaimed Space: " + reclaimedSpace);
      log.tracef(
          "Time taken for truncateFile: " + (timeService.wallClockTime() - startTime) + " (ms)");
    }
  }
Example #16
0
  private MarshalledEntry<K, V> _load(Object key, boolean loadValue, boolean loadMetadata) {
    final FileEntry fe;
    resizeLock.readLock().lock();
    try {
      synchronized (entries) {
        // lookup FileEntry of the key
        fe = entries.get(key);
        if (fe == null) return null;

        // Entries are removed due to expiration from {@link SingleFileStore#purge}
        if (fe.isExpired(timeService.wallClockTime())) {
          return null;
        } else {
          // lock entry for reading before releasing entries monitor
          fe.lock();
        }
      }
    } finally {
      resizeLock.readLock().unlock();
    }

    org.infinispan.commons.io.ByteBuffer valueBb = null;
    org.infinispan.commons.io.ByteBuffer metadataBb = null;

    // If we only require the key, then no need to read disk
    if (!loadValue && !loadMetadata) {
      try {
        return ctx.getMarshalledEntryFactory().newMarshalledEntry(key, valueBb, metadataBb);
      } finally {
        fe.unlock();
      }
    }

    final byte[] data;
    try {
      // load serialized data from disk
      data = new byte[fe.keyLen + fe.dataLen + (loadMetadata ? fe.metadataLen : 0)];
      // The entry lock will prevent clear() from truncating the file at this point
      channel.read(ByteBuffer.wrap(data), fe.offset + KEY_POS);
    } catch (Exception e) {
      throw new PersistenceException(e);
    } finally {
      // No need to keep the lock for deserialization.
      // FileEntry is immutable, so its members can't be changed by another thread.
      fe.unlock();
    }

    if (trace) log.tracef("Read entry %s at %d:%d", key, fe.offset, fe.actualSize());
    ByteBufferFactory factory = ctx.getByteBufferFactory();
    org.infinispan.commons.io.ByteBuffer keyBb = factory.newByteBuffer(data, 0, fe.keyLen);
    if (loadValue) {
      valueBb = factory.newByteBuffer(data, fe.keyLen, fe.dataLen);
    }
    if (loadMetadata && fe.metadataLen > 0) {
      metadataBb = factory.newByteBuffer(data, fe.keyLen + fe.dataLen, fe.metadataLen);
    }
    return ctx.getMarshalledEntryFactory().newMarshalledEntry(keyBb, valueBb, metadataBb);
  }
Example #17
0
 /**
  * Construct an observer for the specified directory, file filter and file comparator.
  *
  * @param rootEntry the root directory to observe
  * @param fileFilter The file filter or null if none
  * @param caseSensitivity what case sensitivity to use comparing file names, null means system
  *     sensitive
  */
 protected FileAlterationObserver(
     FileEntry rootEntry, FileFilter fileFilter, IOCase caseSensitivity) {
   if (rootEntry == null) {
     throw new IllegalArgumentException("Root entry is missing");
   }
   if (rootEntry.getFile() == null) {
     throw new IllegalArgumentException("Root directory is missing");
   }
   this.rootEntry = rootEntry;
   this.fileFilter = fileFilter;
   if (caseSensitivity == null || caseSensitivity.equals(IOCase.SYSTEM)) {
     this.comparator = NameFileComparator.NAME_SYSTEM_COMPARATOR;
   } else if (caseSensitivity.equals(IOCase.INSENSITIVE)) {
     this.comparator = NameFileComparator.NAME_INSENSITIVE_COMPARATOR;
   } else {
     this.comparator = NameFileComparator.NAME_COMPARATOR;
   }
 }
Example #18
0
 /**
  * The base class implementation calls {@link #load(Object)} for this, we can do better because we
  * keep all keys in memory.
  */
 @Override
 public boolean contains(Object key) {
   FileEntry entry = entries.get(key);
   return entry != null && !entry.isExpired(timeService.wallClockTime());
 }
Example #19
0
 /**
  * Return the directory being observed.
  *
  * @return the directory being observed
  */
 public File getDirectory() {
   return rootEntry.getFile();
 }