text:
package org.apache.hadoop.fs.azure;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeNotNull;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.security.UserGroupInformation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.apache.hadoop.fs.azure.AzureException;
import org.apache.hadoop.fs.azure.NativeAzureFileSystem.FolderRenamePending;

import com.microsoft.azure.storage.AccessCondition;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.blob.CloudBlob;

/*
 * Tests the Native Azure file system (WASB) against an actual blob store if
 * provided in the environment.
 * Subclasses implement createTestAccount() to hit local&mock storage with the same test code.
 *
 * For hand-testing: remove "abstract" keyword and copy in an implementation of createTestAccount
 * from one of the subclasses
 */
public abstract class NativeAzureFileSystemBaseTest {

  protected FileSystem fs;
  private AzureBlobStorageTestAccount testAccount;
  private final long modifiedTimeErrorMargin = 5 * 1000; // Give it +/-5 seconds

  protected abstract AzureBlobStorageTestAccount createTestAccount() throws Exception;

  public static final Log LOG = LogFactory.getLog(NativeAzureFileSystemBaseTest.class);

  @Before
  public void setUp() throws Exception {
    testAccount = createTestAccount();
    if (testAccount != null) {
      fs = testAccount.getFileSystem();
    }
    assumeNotNull(testAccount);
  }

  @After
  public void tearDown() throws Exception {
    if (testAccount != null) {
      testAccount.cleanup();
      testAccount = null;
      fs = null;
    }
  }

  @Test
  public void testCheckingNonExistentOneLetterFile() throws Exception {
    assertFalse(fs.exists(new Path("/a")));
  }

  @Test
  public void testStoreRetrieveFile() throws Exception {
    Path testFile = new Path("unit-test-file");
    writeString(testFile, "Testing");
    assertTrue(fs.exists(testFile));
    FileStatus status = fs.getFileStatus(testFile);
    assertNotNull(status);
    // By default, files should be have masked permissions
    // that grant RW to user, and R to group/other
    assertEquals(new FsPermission((short) 0644), status.getPermission());
    assertEquals("Testing", readString(testFile));
    fs.delete(testFile, true);
  }

  @Test
  public void testStoreDeleteFolder() throws Exception {
    Path testFolder = new Path("storeDeleteFolder");
    assertFalse(fs.exists(testFolder));
    assertTrue(fs.mkdirs(testFolder));
    assertTrue(fs.exists(testFolder));
    FileStatus status = fs.getFileStatus(testFolder);
    assertNotNull(status);
    assertTrue(status.isDirectory());
    // By default, directories should be have masked permissions
    // that grant RWX to user, and RX to group/other
    assertEquals(new FsPermission((short) 0755), status.getPermission());
    Path innerFile = new Path(testFolder, "innerFile");
    assertTrue(fs.createNewFile(innerFile));
    assertTrue(fs.exists(innerFile));
    assertTrue(fs.delete(testFolder, true));
    assertFalse(fs.exists(innerFile));
    assertFalse(fs.exists(testFolder));
  }

  @Test
  public void testFileOwnership() throws Exception {
    Path testFile = new Path("ownershipTestFile");
    writeString(testFile, "Testing");
    testOwnership(testFile);
  }

  @Test
  public void testFolderOwnership() throws Exception {
    Path testFolder = new Path("ownershipTestFolder");
    fs.mkdirs(testFolder);
    testOwnership(testFolder);
  }

  private void testOwnership(Path pathUnderTest) throws IOException {
    FileStatus ret = fs.getFileStatus(pathUnderTest);
    UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
    assertTrue(ret.getOwner().equals(currentUser.getShortUserName()));
    fs.delete(pathUnderTest, true);
  }

  private static FsPermission ignoreStickyBit(FsPermission original) {
    return new FsPermission(original.getUserAction(),
        original.getGroupAction(), original.getOtherAction());
  }

  // When FsPermission applies a UMask, it loses sticky bit information.
  // And since we always apply UMask, we should ignore whether the sticky
  // bit is equal or not.
  private static void assertEqualsIgnoreStickyBit(FsPermission expected,
      FsPermission actual) {
    assertEquals(ignoreStickyBit(expected), ignoreStickyBit(actual));
  }

  @Test
  public void testFilePermissions() throws Exception {
    Path testFile = new Path("permissionTestFile");
    FsPermission permission = FsPermission.createImmutable((short) 644);
    createEmptyFile(testFile, permission);
    FileStatus ret = fs.getFileStatus(testFile);
    assertEqualsIgnoreStickyBit(permission, ret.getPermission());
    fs.delete(testFile, true);
  }

  @Test
  public void testFolderPermissions() throws Exception {
    Path testFolder = new Path("permissionTestFolder");
    FsPermission permission = FsPermission.createImmutable((short) 644);
    fs.mkdirs(testFolder, permission);
    FileStatus ret = fs.getFileStatus(testFolder);
    assertEqualsIgnoreStickyBit(permission, ret.getPermission());
    fs.delete(testFolder, true);
  }

  void testDeepFileCreationBase(String testFilePath, String firstDirPath, String middleDirPath,
          short permissionShort, short umaskedPermissionShort) throws Exception  {
    Path testFile = new Path(testFilePath);
    Path firstDir = new Path(firstDirPath);
    Path middleDir = new Path(middleDirPath);
    FsPermission permission = FsPermission.createImmutable(permissionShort);
    FsPermission umaskedPermission = FsPermission.createImmutable(umaskedPermissionShort);

    createEmptyFile(testFile, permission);
    FsPermission rootPerm = fs.getFileStatus(firstDir.getParent()).getPermission();
    FsPermission inheritPerm = FsPermission.createImmutable((short)(rootPerm.toShort() | 0300));
    assertTrue(fs.exists(testFile));
    assertTrue(fs.exists(firstDir));
    assertTrue(fs.exists(middleDir));
    // verify that the indirectly created directory inherited its permissions from the root directory
    FileStatus directoryStatus = fs.getFileStatus(middleDir);
    assertTrue(directoryStatus.isDirectory());
    assertEqualsIgnoreStickyBit(inheritPerm, directoryStatus.getPermission());
    // verify that the file itself has the permissions as specified
    FileStatus fileStatus = fs.getFileStatus(testFile);
    assertFalse(fileStatus.isDirectory());
    assertEqualsIgnoreStickyBit(umaskedPermission, fileStatus.getPermission());
    assertTrue(fs.delete(firstDir, true));
    assertFalse(fs.exists(testFile));

    // An alternative test scenario would've been to delete the file first,
    // and then check for the existence of the upper folders still. But that
    // doesn't actually work as expected right now.
  }

  @Test
  public void testDeepFileCreation() throws Exception {
    // normal permissions in user home
    testDeepFileCreationBase("deep/file/creation/test", "deep", "deep/file/creation", (short)0644, (short)0644);
    // extra permissions in user home. umask will change the actual permissions.
    testDeepFileCreationBase("deep/file/creation/test", "deep", "deep/file/creation", (short)0777, (short)0755);
    // normal permissions in root
    testDeepFileCreationBase("/deep/file/creation/test", "/deep", "/deep/file/creation", (short)0644, (short)0644);
    // less permissions in root
    testDeepFileCreationBase("/deep/file/creation/test", "/deep", "/deep/file/creation", (short)0700, (short)0700);
    // one indirectly created directory in root
    testDeepFileCreationBase("/deep/file", "/deep", "/deep", (short)0644, (short)0644);
    // one indirectly created directory in user home
    testDeepFileCreationBase("deep/file", "deep", "deep", (short)0644, (short)0644);
  }

  private static enum RenameVariation {
    NormalFileName, SourceInAFolder, SourceWithSpace, SourceWithPlusAndPercent
  }

  @Test
  public void testRename() throws Exception {
    for (RenameVariation variation : RenameVariation.values()) {
      System.out.printf("Rename variation: %s\n", variation);
      Path originalFile;
      switch (variation) {
        case NormalFileName:
          originalFile = new Path("fileToRename");
          break;
        case SourceInAFolder:
          originalFile = new Path("file/to/rename");
          break;
        case SourceWithSpace:
          originalFile = new Path("file to rename");
          break;
        case SourceWithPlusAndPercent:
          originalFile = new Path("file+to%rename");
          break;
        default:
          throw new Exception("Unknown variation");
      }
      Path destinationFile = new Path("file/resting/destination");
      assertTrue(fs.createNewFile(originalFile));
      assertTrue(fs.exists(originalFile));
      assertFalse(fs.rename(originalFile, destinationFile)); // Parent directory
      // doesn't exist
      assertTrue(fs.mkdirs(destinationFile.getParent()));
      boolean result = fs.rename(originalFile, destinationFile);
      assertTrue(result);
      assertTrue(fs.exists(destinationFile));
      assertFalse(fs.exists(originalFile));
      fs.delete(destinationFile.getParent(), true);
    }
  }

  @Test
  public void testRenameImplicitFolder() throws Exception {
    Path testFile = new Path("deep/file/rename/test");
    FsPermission permission = FsPermission.createImmutable((short) 644);
    createEmptyFile(testFile, permission);
    boolean renameResult = fs.rename(new Path("deep/file"), new Path("deep/renamed"));
    assertTrue(renameResult);
    assertFalse(fs.exists(testFile));
    FileStatus newStatus = fs.getFileStatus(new Path("deep/renamed/rename/test"));
    assertNotNull(newStatus);
    assertEqualsIgnoreStickyBit(permission, newStatus.getPermission());
    assertTrue(fs.delete(new Path("deep"), true));
  }

  private static enum RenameFolderVariation {
    CreateFolderAndInnerFile, CreateJustInnerFile, CreateJustFolder
  }

  @Test
  public void testRenameFolder() throws Exception {
    for (RenameFolderVariation variation : RenameFolderVariation.values()) {
      Path originalFolder = new Path("folderToRename");
      if (variation != RenameFolderVariation.CreateJustInnerFile) {
        assertTrue(fs.mkdirs(originalFolder));
      }
      Path innerFile = new Path(originalFolder, "innerFile");
      Path innerFile2 = new Path(originalFolder, "innerFile2");
      if (variation != RenameFolderVariation.CreateJustFolder) {
        assertTrue(fs.createNewFile(innerFile));
        assertTrue(fs.createNewFile(innerFile2));
      }
      Path destination = new Path("renamedFolder");
      assertTrue(fs.rename(originalFolder, destination));
      assertTrue(fs.exists(destination));
      if (variation != RenameFolderVariation.CreateJustFolder) {
        assertTrue(fs.exists(new Path(destination, innerFile.getName())));
        assertTrue(fs.exists(new Path(destination, innerFile2.getName())));
      }
      assertFalse(fs.exists(originalFolder));
      assertFalse(fs.exists(innerFile));
      assertFalse(fs.exists(innerFile2));
      fs.delete(destination, true);
    }
  }

  @Test
  public void testCopyFromLocalFileSystem() throws Exception {
    Path localFilePath = new Path(System.getProperty("test.build.data",
        "azure_test"));
    FileSystem localFs = FileSystem.get(new Configuration());
    localFs.delete(localFilePath, true);
    try {
      writeString(localFs, localFilePath, "Testing");
      Path dstPath = new Path("copiedFromLocal");
      assertTrue(FileUtil.copy(localFs, localFilePath, fs, dstPath, false,
          fs.getConf()));
      assertTrue(fs.exists(dstPath));
      assertEquals("Testing", readString(fs, dstPath));
      fs.delete(dstPath, true);
    } finally {
      localFs.delete(localFilePath, true);
    }
  }

  @Test
  public void testListDirectory() throws Exception {
    Path rootFolder = new Path("testingList");
    assertTrue(fs.mkdirs(rootFolder));
    FileStatus[] listed = fs.listStatus(rootFolder);
    assertEquals(0, listed.length);
    Path innerFolder = new Path(rootFolder, "inner");
    assertTrue(fs.mkdirs(innerFolder));
    listed = fs.listStatus(rootFolder);
    assertEquals(1, listed.length);
    assertTrue(listed[0].isDirectory());
    Path innerFile = new Path(innerFolder, "innerFile");
    writeString(innerFile, "testing");
    listed = fs.listStatus(rootFolder);
    assertEquals(1, listed.length);
    assertTrue(listed[0].isDirectory());
    listed = fs.listStatus(innerFolder);
    assertEquals(1, listed.length);
    assertFalse(listed[0].isDirectory());
    assertTrue(fs.delete(rootFolder, true));
  }

  @Test
  public void testStatistics() throws Exception {
    FileSystem.clearStatistics();
    FileSystem.Statistics stats = FileSystem.getStatistics("wasb",
        NativeAzureFileSystem.class);
    assertEquals(0, stats.getBytesRead());
    assertEquals(0, stats.getBytesWritten());
    Path newFile = new Path("testStats");
    writeString(newFile, "12345678");
    assertEquals(8, stats.getBytesWritten());
    assertEquals(0, stats.getBytesRead());
    String readBack = readString(newFile);
    assertEquals("12345678", readBack);
    assertEquals(8, stats.getBytesRead());
    assertEquals(8, stats.getBytesWritten());
    assertTrue(fs.delete(newFile, true));
    assertEquals(8, stats.getBytesRead());
    assertEquals(8, stats.getBytesWritten());
  }

  @Test
  public void testUriEncoding() throws Exception {
    fs.create(new Path("p/t%5Fe")).close();
    FileStatus[] listing = fs.listStatus(new Path("p"));
    assertEquals(1, listing.length);
    assertEquals("t%5Fe", listing[0].getPath().getName());
    assertTrue(fs.rename(new Path("p"), new Path("q")));
    assertTrue(fs.delete(new Path("q"), true));
  }

  @Test
  public void testUriEncodingMoreComplexCharacters() throws Exception {
    // Create a file name with URI reserved characters, plus the percent
    String fileName = "!#$'()*;=[]%";
    String directoryName = "*;=[]%!#$'()";
    fs.create(new Path(directoryName, fileName)).close();
    FileStatus[] listing = fs.listStatus(new Path(directoryName));
    assertEquals(1, listing.length);
    assertEquals(fileName, listing[0].getPath().getName());
    FileStatus status = fs.getFileStatus(new Path(directoryName, fileName));
    assertEquals(fileName, status.getPath().getName());
    InputStream stream = fs.open(new Path(directoryName, fileName));
    assertNotNull(stream);
    stream.close();
    assertTrue(fs.delete(new Path(directoryName, fileName), true));
    assertTrue(fs.delete(new Path(directoryName), true));
  }

  @Test
  public void testChineseCharacters() throws Exception {
    // Create a file and a folder with Chinese (non-ASCI) characters
    String chinese = "" + '\u963f' + '\u4db5';
    String fileName = "filename" + chinese;
    String directoryName = chinese;
    fs.create(new Path(directoryName, fileName)).close();
    FileStatus[] listing = fs.listStatus(new Path(directoryName));
    assertEquals(1, listing.length);
    assertEquals(fileName, listing[0].getPath().getName());
    FileStatus status = fs.getFileStatus(new Path(directoryName, fileName));
    assertEquals(fileName, status.getPath().getName());
    InputStream stream = fs.open(new Path(directoryName, fileName));
    assertNotNull(stream);
    stream.close();
    assertTrue(fs.delete(new Path(directoryName, fileName), true));
    assertTrue(fs.delete(new Path(directoryName), true));
  }

  @Test
  public void testChineseCharactersFolderRename() throws Exception {
    // Create a file and a folder with Chinese (non-ASCI) characters
    String chinese = "" + '\u963f' + '\u4db5';
    String fileName = "filename" + chinese;
    String srcDirectoryName = chinese;
    String targetDirectoryName = "target" + chinese;
    fs.create(new Path(srcDirectoryName, fileName)).close();
    fs.rename(new Path(srcDirectoryName), new Path(targetDirectoryName));
    FileStatus[] listing = fs.listStatus(new Path(targetDirectoryName));
    assertEquals(1, listing.length);
    assertEquals(fileName, listing[0].getPath().getName());
    FileStatus status = fs.getFileStatus(new Path(targetDirectoryName, fileName));
    assertEquals(fileName, status.getPath().getName());
    assertTrue(fs.delete(new Path(targetDirectoryName, fileName), true));
    assertTrue(fs.delete(new Path(targetDirectoryName), true));
  }

  @Test
  public void testReadingDirectoryAsFile() throws Exception {
    Path dir = new Path("/x");
    assertTrue(fs.mkdirs(dir));
    try {
      fs.open(dir).close();
      assertTrue("Should've thrown", false);
    } catch (FileNotFoundException ex) {
      assertEquals("/x is a directory not a file.", ex.getMessage());
    }
  }

  @Test
  public void testCreatingFileOverDirectory() throws Exception {
    Path dir = new Path("/x");
    assertTrue(fs.mkdirs(dir));
    try {
      fs.create(dir).close();
      assertTrue("Should've thrown", false);
    } catch (IOException ex) {
      assertEquals("Cannot create file /x; already exists as a directory.",
          ex.getMessage());
    }
  }

  @Test
  public void testInputStreamReadWithZeroSizeBuffer() throws Exception {
    Path newFile = new Path("zeroSizeRead");
    OutputStream output = fs.create(newFile);
    output.write(10);
    output.close();

    InputStream input = fs.open(newFile);
    int result = input.read(new byte[2], 0, 0);
    assertEquals(0, result);
  }

  @Test
  public void testInputStreamReadWithBufferReturnsMinusOneOnEof() throws Exception {
    Path newFile = new Path("eofRead");
    OutputStream output = fs.create(newFile);
    output.write(10);
    output.close();

    // Read first byte back
    InputStream input = fs.open(newFile);
    byte[] buff = new byte[1];
    int result = input.read(buff, 0, 1);
    assertEquals(1, result);
    assertEquals(10, buff[0]);

    // Issue another read and make sure it returns -1
    buff[0] = 2;
    result = input.read(buff, 0, 1);
    assertEquals(-1, result);
    // Buffer is intact
    assertEquals(2, buff[0]);
  }

  @Test
  public void testInputStreamReadWithBufferReturnsMinusOneOnEofForLargeBuffer() throws Exception {
    Path newFile = new Path("eofRead2");
    OutputStream output = fs.create(newFile);
    byte[] outputBuff = new byte[97331];
    for(int i = 0; i < outputBuff.length; ++i) {
      outputBuff[i] = (byte)(Math.random() * 255);
    }
    output.write(outputBuff);
    output.close();

    // Read the content of the file
    InputStream input = fs.open(newFile);
    byte[] buff = new byte[131072];
    int result = input.read(buff, 0, buff.length);
    assertEquals(outputBuff.length, result);
    for(int i = 0; i < outputBuff.length; ++i) {
      assertEquals(outputBuff[i], buff[i]);
    }

    // Issue another read and make sure it returns -1
    buff = new byte[131072];
    result = input.read(buff, 0, buff.length);
    assertEquals(-1, result);
  }

  @Test
  public void testInputStreamReadIntReturnsMinusOneOnEof() throws Exception {
    Path newFile = new Path("eofRead3");
    OutputStream output = fs.create(newFile);
    output.write(10);
    output.close();

    // Read first byte back
    InputStream input = fs.open(newFile);
    int value = input.read();
    assertEquals(10, value);

    // Issue another read and make sure it returns -1
    value = input.read();
    assertEquals(-1, value);
  }

  @Test
  public void testSetPermissionOnFile() throws Exception {
    Path newFile = new Path("testPermission");
    OutputStream output = fs.create(newFile);
    output.write(13);
    output.close();
    FsPermission newPermission = new FsPermission((short) 0700);
    fs.setPermission(newFile, newPermission);
    FileStatus newStatus = fs.getFileStatus(newFile);
    assertNotNull(newStatus);
    assertEquals(newPermission, newStatus.getPermission());
    assertEquals("supergroup", newStatus.getGroup());
    assertEquals(UserGroupInformation.getCurrentUser().getShortUserName(),
        newStatus.getOwner());

    // Don't check the file length for page blobs. Only block blobs
    // provide the actual length of bytes written.
    if (!(this instanceof TestNativeAzureFSPageBlobLive)) {
      assertEquals(1, newStatus.getLen());
    }
  }

  @Test
  public void testSetPermissionOnFolder() throws Exception {
    Path newFolder = new Path("testPermission");
    assertTrue(fs.mkdirs(newFolder));
    FsPermission newPermission = new FsPermission((short) 0600);
    fs.setPermission(newFolder, newPermission);
    FileStatus newStatus = fs.getFileStatus(newFolder);
    assertNotNull(newStatus);
    assertEquals(newPermission, newStatus.getPermission());
    assertTrue(newStatus.isDirectory());
  }

  @Test
  public void testSetOwnerOnFile() throws Exception {
    Path newFile = new Path("testOwner");
    OutputStream output = fs.create(newFile);
    output.write(13);
    output.close();
    fs.setOwner(newFile, "newUser", null);
    FileStatus newStatus = fs.getFileStatus(newFile);
    assertNotNull(newStatus);
    assertEquals("newUser", newStatus.getOwner());
    assertEquals("supergroup", newStatus.getGroup());

    // File length is only reported to be the size of bytes written to the file for block blobs.
    // So only check it for block blobs, not page blobs.
    if (!(this instanceof TestNativeAzureFSPageBlobLive)) {
      assertEquals(1, newStatus.getLen());
    }
    fs.setOwner(newFile, null, "newGroup");
    newStatus = fs.getFileStatus(newFile);
    assertNotNull(newStatus);
    assertEquals("newUser", newStatus.getOwner());
    assertEquals("newGroup", newStatus.getGroup());
  }

  @Test
  public void testSetOwnerOnFolder() throws Exception {
    Path newFolder = new Path("testOwner");
    assertTrue(fs.mkdirs(newFolder));
    fs.setOwner(newFolder, "newUser", null);
    FileStatus newStatus = fs.getFileStatus(newFolder);
    assertNotNull(newStatus);
    assertEquals("newUser", newStatus.getOwner());
    assertTrue(newStatus.isDirectory());
  }

  @Test
  public void testModifiedTimeForFile() throws Exception {
    Path testFile = new Path("testFile");
    fs.create(testFile).close();
    testModifiedTime(testFile);
  }

  @Test
  public void testModifiedTimeForFolder() throws Exception {
    Path testFolder = new Path("testFolder");
    assertTrue(fs.mkdirs(testFolder));
    testModifiedTime(testFolder);
  }

  @Test
  public void testFolderLastModifiedTime() throws Exception {
    Path parentFolder = new Path("testFolder");
    Path innerFile = new Path(parentFolder, "innerfile");
    assertTrue(fs.mkdirs(parentFolder));

    // Create file
    long lastModifiedTime = fs.getFileStatus(parentFolder)
        .getModificationTime();
    // Wait at least the error margin
    Thread.sleep(modifiedTimeErrorMargin + 1);
    assertTrue(fs.createNewFile(innerFile));
    // The parent folder last modified time should have changed because we
    // create an inner file.
    assertFalse(testModifiedTime(parentFolder, lastModifiedTime));
    testModifiedTime(parentFolder);

    // Rename file
    lastModifiedTime = fs.getFileStatus(parentFolder).getModificationTime();
    Path destFolder = new Path("testDestFolder");
    assertTrue(fs.mkdirs(destFolder));
    long destLastModifiedTime = fs.getFileStatus(destFolder)
        .getModificationTime();
    Thread.sleep(modifiedTimeErrorMargin + 1);
    Path destFile = new Path(destFolder, "innerfile");
    assertTrue(fs.rename(innerFile, destFile));
    // Both source and destination folder last modified time should have changed
    // because of renaming.
    assertFalse(testModifiedTime(parentFolder, lastModifiedTime));
    assertFalse(testModifiedTime(destFolder, destLastModifiedTime));
    testModifiedTime(parentFolder);
    testModifiedTime(destFolder);

    // Delete file
    destLastModifiedTime = fs.getFileStatus(destFolder).getModificationTime();
    // Wait at least the error margin
    Thread.sleep(modifiedTimeErrorMargin + 1);
    fs.delete(destFile, false);
    // The parent folder last modified time should have changed because we
    // delete an inner file.
    assertFalse(testModifiedTime(destFolder, destLastModifiedTime));
    testModifiedTime(destFolder);
  }

  /**
   * Verify we can get file status of a directory with various forms of
   * the directory file name, including the nonstandard but legal form
   * ending in "/.". Check that we're getting status for a directory.
   */
  @Test
  public void testListSlash() throws Exception {
    Path testFolder = new Path("/testFolder");
    Path testFile = new Path(testFolder, "testFile");
    assertTrue(fs.mkdirs(testFolder));
    assertTrue(fs.createNewFile(testFile));
    FileStatus status;
    status = fs.getFileStatus(new Path("/testFolder"));
    assertTrue(status.isDirectory());
    status = fs.getFileStatus(new Path("/testFolder/"));
    assertTrue(status.isDirectory());
    status = fs.getFileStatus(new Path("/testFolder/."));
    assertTrue(status.isDirectory());
  }

  @Test
  public void testCannotCreatePageBlobByDefault() throws Exception {

    // Verify that the page blob directory list configuration setting
    // is not set in the default configuration.
    Configuration conf = new Configuration();
    String[] rawPageBlobDirs =
        conf.getStrings(AzureNativeFileSystemStore.KEY_PAGE_BLOB_DIRECTORIES);
    assertTrue(rawPageBlobDirs == null);
  }

  /*
   * Set up a situation where a folder rename is partway finished.
   * Then apply redo to finish the rename.
   *
   * The original source folder *would* have had contents
   * folderToRename  (0 byte dummy file for directory)
   * folderToRename/innerFile
   * folderToRename/innerFile2
   *
   * The actual source folder (after partial rename and failure)
   *
   * folderToRename
   * folderToRename/innerFile2
   *
   * The actual target folder (after partial rename and failure)
   *
   * renamedFolder
   * renamedFolder/innerFile
   */
  @Test
  public void testRedoRenameFolder() throws IOException {
    // create original folder
    String srcKey = "folderToRename";
    Path originalFolder = new Path(srcKey);
    assertTrue(fs.mkdirs(originalFolder));
    Path innerFile = new Path(originalFolder, "innerFile");
    assertTrue(fs.createNewFile(innerFile));
    Path innerFile2 = new Path(originalFolder, "innerFile2");
    assertTrue(fs.createNewFile(innerFile2));

    String dstKey = "renamedFolder";

    // propose (but don't do) the rename
    Path home = fs.getHomeDirectory();
    String relativeHomeDir = getRelativePath(home.toString());
    NativeAzureFileSystem.FolderRenamePending pending =
        new NativeAzureFileSystem.FolderRenamePending(
            relativeHomeDir + "/" + srcKey,
            relativeHomeDir + "/" + dstKey, null,
            (NativeAzureFileSystem) fs);

    // get the rename pending file contents
    String renameDescription = pending.makeRenamePendingFileContents();

    // Remove one file from source folder to simulate a partially done
    // rename operation.
    assertTrue(fs.delete(innerFile, false));

    // Create the destination folder with just one file in it, again
    // to simulate a partially done rename.
    Path destination = new Path(dstKey);
    Path innerDest = new Path(destination, "innerFile");
    assertTrue(fs.createNewFile(innerDest));

    // Create a rename-pending file and write rename information to it.
    final String renamePendingStr = "folderToRename-RenamePending.json";
    Path renamePendingFile = new Path(renamePendingStr);
    FSDataOutputStream out = fs.create(renamePendingFile, true);
    assertTrue(out != null);
    writeString(out, renameDescription);

    // Redo the rename operation based on the contents of the -RenamePending.json file.
    // Trigger the redo by checking for existence of the original folder. It must appear
    // to not exist.
    assertFalse(fs.exists(originalFolder));

    // Verify that the target is there, and the source is gone.
    assertTrue(fs.exists(destination));
    assertTrue(fs.exists(new Path(destination, innerFile.getName())));
    assertTrue(fs.exists(new Path(destination, innerFile2.getName())));
    assertFalse(fs.exists(originalFolder));
    assertFalse(fs.exists(innerFile));
    assertFalse(fs.exists(innerFile2));

    // Verify that there's no RenamePending file left.
    assertFalse(fs.exists(renamePendingFile));

    // Verify that we can list the target directory.
    FileStatus[] listed = fs.listStatus(destination);
    assertEquals(2, listed.length);

    // List the home directory and show the contents is a directory.
    Path root = fs.getHomeDirectory();
    listed = fs.listStatus(root);
    assertEquals(1, listed.length);
    assertTrue(listed[0].isDirectory());
  }

  /**
   * If there is a folder to be renamed inside a parent folder,
   * then when you list the parent folder, you should only see
   * the final result, after the rename.
   */
  @Test
  public void testRedoRenameFolderInFolderListing() throws IOException {

    // create original folder
    String parent = "parent";
    Path parentFolder = new Path(parent);
    assertTrue(fs.mkdirs(parentFolder));
    Path inner = new Path(parentFolder, "innerFolder");
    assertTrue(fs.mkdirs(inner));
    Path inner2 = new Path(parentFolder, "innerFolder2");
    assertTrue(fs.mkdirs(inner2));
    Path innerFile = new Path(inner2, "file");
    assertTrue(fs.createNewFile(innerFile));

    Path inner2renamed = new Path(parentFolder, "innerFolder2Renamed");

    // propose (but don't do) the rename of innerFolder2
    Path home = fs.getHomeDirectory();
    String relativeHomeDir = getRelativePath(home.toString());
    NativeAzureFileSystem.FolderRenamePending pending =
        new NativeAzureFileSystem.FolderRenamePending(
            relativeHomeDir + "/" + inner2,
            relativeHomeDir + "/" + inner2renamed, null,
            (NativeAzureFileSystem) fs);

    // Create a rename-pending file and write rename information to it.
    final String renamePendingStr = inner2 + FolderRenamePending.SUFFIX;
    Path renamePendingFile = new Path(renamePendingStr);
    FSDataOutputStream out = fs.create(renamePendingFile, true);
    assertTrue(out != null);
    writeString(out, pending.makeRenamePendingFileContents());

    // Redo the rename operation based on the contents of the
    // -RenamePending.json file. Trigger the redo by checking for existence of
    // the original folder. It must appear to not exist.
    FileStatus[] listed = fs.listStatus(parentFolder);
    assertEquals(2, listed.length);
    assertTrue(listed[0].isDirectory());
    assertTrue(listed[1].isDirectory());

    // The rename pending file is not a directory, so at this point we know the
    // redo has been done.
    assertFalse(fs.exists(inner2)); // verify original folder is gone
    assertTrue(fs.exists(inner2renamed)); // verify the target is there
    assertTrue(fs.exists(new Path(inner2renamed, "file")));
  }

  /**
   * There is a nested folder and file under the folder to be renamed
   * and the process crashes after the nested folder has been renamed but not the file.
   * then when you list the parent folder, pending renames should be redone
   * Apache jira HADOOP-12780
   */
  @Test
  public void testRedoRenameFolderRenameInProgress() throws IOException {

    // create original folder
    String parent = "parent";
    Path parentFolder = new Path(parent);
    assertTrue(fs.mkdirs(parentFolder));
    Path folderToBeRenamed = new Path(parentFolder, "folderToBeRenamed");
    assertTrue(fs.mkdirs(folderToBeRenamed));
    String innerFolderName = "innerFolder";
    Path inner = new Path(folderToBeRenamed, innerFolderName);
    assertTrue(fs.mkdirs(inner));
    String innerFileName = "file";
    Path innerFile = new Path(inner, innerFileName);
    assertTrue(fs.createNewFile(innerFile));

    Path renamedFolder = new Path(parentFolder, "renamedFolder");

    // propose (but don't do) the rename of innerFolder2
    Path home = fs.getHomeDirectory();
    String relativeHomeDir = getRelativePath(home.toString());
    NativeAzureFileSystem.FolderRenamePending pending =
        new NativeAzureFileSystem.FolderRenamePending(
            relativeHomeDir + "/" + folderToBeRenamed,
            relativeHomeDir + "/" + renamedFolder, null,
            (NativeAzureFileSystem) fs);

    // Create a rename-pending file and write rename information to it.
    final String renamePendingStr = folderToBeRenamed + FolderRenamePending.SUFFIX;
    Path renamePendingFile = new Path(renamePendingStr);
    FSDataOutputStream out = fs.create(renamePendingFile, true);
    assertTrue(out != null);
    writeString(out, pending.makeRenamePendingFileContents());

    // Rename inner folder to simulate the scenario where rename has started and
    // only one directory has been renamed but not the files under it
    ((NativeAzureFileSystem) fs).getStoreInterface().rename(
        relativeHomeDir + "/" +inner, relativeHomeDir + "/" +renamedFolder + "/" + innerFolderName , true, null);

    // Instead of using fs.exist use store.explicitFileExists because fs.exist will return true
    // even if directory has been renamed, but there are still file under that directory
    assertFalse(((NativeAzureFileSystem) fs).getStoreInterface().
        explicitFileExists(relativeHomeDir + "/" + inner)); // verify the explicit inner folder is gone
    assertTrue(((NativeAzureFileSystem) fs).getStoreInterface().
        explicitFileExists(relativeHomeDir + "/" + innerFile)); // verify inner file is present

    // Redo the rename operation based on the contents of the
    // -RenamePending.json file. Trigger the redo by checking for existence of
    // the original folder. It must appear to not exist.
    FileStatus[] listed = fs.listStatus(parentFolder);
    assertEquals(1, listed.length);
    assertTrue(listed[0].isDirectory());

    // The rename pending file is not a directory, so at this point we know the
    // redo has been done.
    assertFalse(fs.exists(inner)); // verify original folder is gone
    assertFalse(fs.exists(innerFile)); // verify original file is gone
    assertTrue(fs.exists(renamedFolder)); // verify the target is there
    assertTrue(fs.exists(new Path(renamedFolder, innerFolderName + "/" + innerFileName)));
  }

  /**
   * Test the situation when the rename metadata file is empty
   * i.e. it is created but not written yet. In that case in next rename
   * this empty file should be deleted. As zero byte metadata file means
   * rename has not started yet. This is to emulate the scenario where
   * the process crashes just after creating rename metadata file.
   *  We had a bug (HADOOP-12678) that in that case listing used to fail and
   * hbase master did not use to come up
   */
  @Test
  public void testRedoRenameFolderInFolderListingWithZeroByteRenameMetadata()
      throws IOException {
    // create original folder
    String parent = "parent";
    Path parentFolder = new Path(parent);
    assertTrue(fs.mkdirs(parentFolder));
    Path inner = new Path(parentFolder, "innerFolder");
    assertTrue(fs.mkdirs(inner));
    Path inner2 = new Path(parentFolder, "innerFolder2");
    assertTrue(fs.mkdirs(inner2));
    Path innerFile = new Path(inner2, "file");
    assertTrue(fs.createNewFile(innerFile));

    Path inner2renamed = new Path(parentFolder, "innerFolder2Renamed");

    // Create an empty rename-pending file
    final String renamePendingStr = inner2 + FolderRenamePending.SUFFIX;
    Path renamePendingFile = new Path(renamePendingStr);
    FSDataOutputStream out = fs.create(renamePendingFile, true);
    assertTrue(out != null);
    out.close();

    // Redo the rename operation based on the contents of the
    // -RenamePending.json file. Trigger the redo by listing
    // the parent folder. It should not throw and it should
    // delete empty rename pending file
    FileStatus[] listed = fs.listStatus(parentFolder);
    assertEquals(2, listed.length);
    assertTrue(listed[0].isDirectory());
    assertTrue(listed[1].isDirectory());
    assertFalse(fs.exists(renamePendingFile));

    // Verify that even if rename pending file is deleted,
    // deletion should handle that
    Path home = fs.getHomeDirectory();
    String relativeHomeDir = getRelativePath(home.toString());
    NativeAzureFileSystem.FolderRenamePending pending =
            new NativeAzureFileSystem.FolderRenamePending(
                relativeHomeDir + "/" + inner2,
                relativeHomeDir + "/" + inner2renamed, null,
                (NativeAzureFileSystem) fs);
    pending.deleteRenamePendingFile(fs, renamePendingFile);

    assertTrue(fs.exists(inner2)); // verify original folder is there
    assertFalse(fs.exists(inner2renamed)); // verify the target is not there
  }

  /**
   * Test the situation where a rename pending file exists but the rename
   * is really done. This could happen if the rename process died just
   * before deleting the rename pending file. It exercises a non-standard
   * code path in redo().
   */
  @Test
  public void testRenameRedoFolderAlreadyDone() throws IOException {
    // create only destination folder
    String orig = "originalFolder";
    String dest = "renamedFolder";
    Path destPath = new Path(dest);
    assertTrue(fs.mkdirs(destPath));

    // propose (but don't do) the rename of innerFolder2
    Path home = fs.getHomeDirectory();
    String relativeHomeDir = getRelativePath(home.toString());
    NativeAzureFileSystem.FolderRenamePending pending =
        new NativeAzureFileSystem.FolderRenamePending(
            relativeHomeDir + "/" + orig,
            relativeHomeDir + "/" + dest, null,
            (NativeAzureFileSystem) fs);

    // Create a rename-pending file and write rename information to it.
    final String renamePendingStr = orig + FolderRenamePending.SUFFIX;
    Path renamePendingFile = new Path(renamePendingStr);
    FSDataOutputStream out = fs.create(renamePendingFile, true);
    assertTrue(out != null);
    writeString(out, pending.makeRenamePendingFileContents());

    try {
      pending.redo();
    } catch (Exception e) {
      fail();
    }

    // Make sure rename pending file is gone.
    FileStatus[] listed = fs.listStatus(new Path("/"));
    assertEquals(1, listed.length);
    assertTrue(listed[0].isDirectory());
  }

  @Test
  public void testRedoFolderRenameAll() throws IllegalArgumentException, IOException {
    {
      FileFolder original = new FileFolder("folderToRename");
      original.add("innerFile").add("innerFile2");
      FileFolder partialSrc = original.copy();
      FileFolder partialDst = original.copy();
      partialDst.setName("renamedFolder");
      partialSrc.setPresent(0, false);
      partialDst.setPresent(1, false);

      testRenameRedoFolderSituation(original, partialSrc, partialDst);
    }
    {
      FileFolder original = new FileFolder("folderToRename");
      original.add("file1").add("file2").add("file3");
      FileFolder partialSrc = original.copy();
      FileFolder partialDst = original.copy();
      partialDst.setName("renamedFolder");

      // Set up this state before the redo:
      // folderToRename: file1       file3
      // renamedFolder:  file1 file2
      // This gives code coverage for all 3 expected cases for individual file
      // redo.
      partialSrc.setPresent(1, false);
      partialDst.setPresent(2, false);

      testRenameRedoFolderSituation(original, partialSrc, partialDst);
    }
    {
      // Simulate a situation with folder with a large number of files in it.
      // For the first half of the files, they will be in the destination
      // but not the source. For the second half, they will be in the source
      // but not the destination. There will be one file in the middle that is
      // in both source and destination. Then trigger redo and verify.
      // For testing larger folder sizes, manually change this, temporarily, and
      // edit the SIZE value.
      final int SIZE = 5;
      assertTrue(SIZE >= 3);
      // Try a lot of files in the folder.
      FileFolder original = new FileFolder("folderToRename");
      for (int i = 0; i < SIZE; i++) {
        original.add("file" + Integer.toString(i));
      }
      FileFolder partialSrc = original.copy();
      FileFolder partialDst = original.copy();
      partialDst.setName("renamedFolder");
      for (int i = 0; i < SIZE; i++) {
        partialSrc.setPresent(i, i >= SIZE / 2);
        partialDst.setPresent(i, i <= SIZE / 2);
      }

      testRenameRedoFolderSituation(original, partialSrc, partialDst);
    }
    {
      // Do a nested folder, like so:
      // folderToRename:
      //   nestedFolder: a, b, c
      //   p
      //   q
      //
      // Then delete file 'a' from the source and add it to destination.
      // Then trigger redo.

      FileFolder original = new FileFolder("folderToRename");
      FileFolder nested = new FileFolder("nestedFolder");
      nested.add("a").add("b").add("c");
      original.add(nested).add("p").add("q");

      FileFolder partialSrc = original.copy();
      FileFolder partialDst = original.copy();
      partialDst.setName("renamedFolder");

      // logically remove 'a' from source
      partialSrc.getMember(0).setPresent(0, false);

      // logically eliminate b, c from destination
      partialDst.getMember(0).setPresent(1, false);
      partialDst.getMember(0).setPresent(2, false);

      testRenameRedoFolderSituation(original, partialSrc, partialDst);
    }
  }

  private void testRenameRedoFolderSituation(
      FileFolder fullSrc,
      FileFolder partialSrc,
      FileFolder partialDst) throws IllegalArgumentException, IOException {

    // make file folder tree for source
    fullSrc.create();

    // set up rename pending file
    fullSrc.makeRenamePending(partialDst);

    // prune away some files (as marked) from source to simulate partial rename
    partialSrc.prune();

    // Create only the files indicated for the destination to indicate a partial rename.
    partialDst.create();

    // trigger redo
    assertFalse(fullSrc.exists());

    // verify correct results
    partialDst.verifyExists();
    fullSrc.verifyGone();

    // delete the new folder to leave no garbage behind
    fs.delete(new Path(partialDst.getName()), true);
  }

  // Mock up of a generalized folder (which can also be a leaf-level file)
  // for rename redo testing.
  private class FileFolder {
    private String name;

    // For rename testing, indicates whether an expected
    // file is present in the source or target folder.
    private boolean present;
    ArrayList<FileFolder> members; // Null if a leaf file, otherwise not null.

    // Make a new, empty folder (not a regular leaf file).
    public FileFolder(String name) {
      this.name = name;
      this.present = true;
      members = new ArrayList<FileFolder>();
    }

    public FileFolder getMember(int i) {
      return members.get(i);
    }

    // Verify a folder and all its contents are gone. This is only to
    // be called on the root of a FileFolder.
    public void verifyGone() throws IllegalArgumentException, IOException {
      assertFalse(fs.exists(new Path(name)));
      assertTrue(isFolder());
      verifyGone(new Path(name), members);
    }

    private void verifyGone(Path prefix, ArrayList<FileFolder> members2) throws IOException {
      for (FileFolder f : members2) {
        f.verifyGone(prefix);
      }
    }

    private void verifyGone(Path prefix) throws IOException {
      assertFalse(fs.exists(new Path(prefix, name)));
      if (isLeaf()) {
        return;
      }
      for (FileFolder f : members) {
        f.verifyGone(new Path(prefix, name));
      }
    }

    public void verifyExists() throws IllegalArgumentException, IOException {

      // verify the root is present
      assertTrue(fs.exists(new Path(name)));
      assertTrue(isFolder());

      // check the members
      verifyExists(new Path(name), members);
    }

    private void verifyExists(Path prefix, ArrayList<FileFolder> members2) throws IOException {
      for (FileFolder f : members2) {
        f.verifyExists(prefix);
      }
    }

    private void verifyExists(Path prefix) throws IOException {

      // verify this file/folder is present
      assertTrue(fs.exists(new Path(prefix, name)));

      // verify members are present
      if (isLeaf()) {
        return;
      }

      for (FileFolder f : members) {
        f.verifyExists(new Path(prefix, name));
      }
    }

    public boolean exists() throws IOException {
      return fs.exists(new Path(name));
    }

    // Make a rename pending file for the situation where we rename
    // this object (the source) to the specified destination.
    public void makeRenamePending(FileFolder dst) throws IOException {

      // Propose (but don't do) the rename.
      Path home = fs.getHomeDirectory();
      String relativeHomeDir = getRelativePath(home.toString());
      NativeAzureFileSystem.FolderRenamePending pending =
          new NativeAzureFileSystem.FolderRenamePending(
              relativeHomeDir + "/" + this.getName(),
              relativeHomeDir + "/" + dst.getName(), null,
              (NativeAzureFileSystem) fs);

      // Get the rename pending file contents.
      String renameDescription = pending.makeRenamePendingFileContents();

      // Create a rename-pending file and write rename information to it.
      final String renamePendingStr = this.getName() + "-RenamePending.json";
      Path renamePendingFile = new Path(renamePendingStr);
      FSDataOutputStream out = fs.create(renamePendingFile, true);
      assertTrue(out != null);
      writeString(out, renameDescription);
    }

    // set whether a child is present or not
    public void setPresent(int i, boolean b) {
      members.get(i).setPresent(b);
    }

    // Make an uninitialized folder
    private FileFolder() {
      this.present = true;
    }

    public void setPresent(boolean value) {
      present = value;
    }

    public FileFolder makeLeaf(String name) {
      FileFolder f = new FileFolder();
      f.setName(name);
      return f;
    }

    void setName(String name) {
      this.name = name;
    }

    public String getName() {
      return name;
    }

    public boolean isLeaf() {
      return members == null;
    }

    public boolean isFolder() {
      return members != null;
    }

    FileFolder add(FileFolder folder) {
      members.add(folder);
      return this;
    }

    // Add a leaf file (by convention, if you pass a string argument, you get a leaf).
    FileFolder add(String file) {
      FileFolder leaf = makeLeaf(file);
      members.add(leaf);
      return this;
    }

    public FileFolder copy() {
      if (isLeaf()) {
        return makeLeaf(name);
      } else {
        FileFolder f = new FileFolder(name);
        for (FileFolder member : members) {
          f.add(member.copy());
        }
        return f;
      }
    }

    // Create the folder structure. Return true on success, or else false.
    public void create() throws IllegalArgumentException, IOException {
      create(null);
    }

    private void create(Path prefix) throws IllegalArgumentException, IOException {
      if (isFolder()) {
        if (present) {
          assertTrue(fs.mkdirs(makePath(prefix, name)));
        }
        create(makePath(prefix, name), members);
      } else if (isLeaf()) {
        if (present) {
          assertTrue(fs.createNewFile(makePath(prefix, name)));
        }
      } else {
        assertTrue("The object must be a (leaf) file or a folder.", false);
      }
    }

    private void create(Path prefix, ArrayList<FileFolder> members2) throws IllegalArgumentException, IOException {
      for (FileFolder f : members2) {
        f.create(prefix);
      }
    }

    private Path makePath(Path prefix, String name) {
      if (prefix == null) {
        return new Path(name);
      } else {
        return new Path(prefix, name);
      }
    }

    // Remove the files marked as not present.
    public void prune() throws IOException {
      prune(null);
    }

    private void prune(Path prefix) throws IOException {
      Path path = null;
      if (prefix == null) {
        path = new Path(name);
      } else {
        path = new Path(prefix, name);
      }
      if (isLeaf() && !present) {
        assertTrue(fs.delete(path, false));
      } else if (isFolder() && !present) {
        assertTrue(fs.delete(path, true));
      } else if (isFolder()) {
        for (FileFolder f : members) {
          f.prune(path);
        }
      }
    }
  }

  private String getRelativePath(String path) {
    // example input: wasb://wasbtests-ehans-1404322046279@ehans9.blob.core.windows.net/user/ehans/folderToRename
    // example result: user/ehans/folderToRename

    // Find the third / position and return input substring after that.
    int slashCount = 0; // number of slashes so far
    int i;
    for (i = 0; i < path.length(); i++) {
      if (path.charAt(i) == '/') {
        slashCount++;
        if (slashCount == 3) {
          return path.substring(i + 1, path.length());
        }
      }
    }
    throw new RuntimeException("Incorrect path prefix -- expected wasb://.../...");
  }

  @Test
  public void testCloseFileSystemTwice() throws Exception {
    //make sure close() can be called multiple times without doing any harm
    fs.close();
    fs.close();
  }

  // Test the available() method for the input stream returned by fs.open().
  // This works for both page and block blobs.
  int FILE_SIZE = 4 * 1024 * 1024 + 1; // Make this 1 bigger than internal
                                       // buffer used in BlobInputStream
                                       // to exercise that case.
  int MAX_STRIDE = FILE_SIZE + 1;
  Path PATH = new Path("/available.dat");
  @Test
  public void testAvailable() throws IOException {

    // write FILE_SIZE bytes to page blob
    FSDataOutputStream out = fs.create(PATH);
    byte[] data = new byte[FILE_SIZE];
    Arrays.fill(data, (byte) 5);
    out.write(data, 0, FILE_SIZE);
    out.close();

    // Test available() for different read sizes
    verifyAvailable(1);
    verifyAvailable(100);
    verifyAvailable(5000);
    verifyAvailable(FILE_SIZE);
    verifyAvailable(MAX_STRIDE);

    fs.delete(PATH, false);
  }

  // Verify that available() for the input stream is always >= 1 unless we've
  // consumed all the input, and then it is 0. This is to match expectations by
  // HBase which were set based on behavior of DFSInputStream.available().
  private void verifyAvailable(int readStride) throws IOException {
    FSDataInputStream in = fs.open(PATH);
    try {
      byte[] inputBuffer = new byte[MAX_STRIDE];
      int position = 0;
      int bytesRead = 0;
      while(bytesRead != FILE_SIZE) {
        bytesRead += in.read(inputBuffer, position, readStride);
        int available = in.available();
        if (bytesRead < FILE_SIZE) {
          if (available < 1) {
            fail(String.format(
                  "expected available > 0 but got: "
                      + "position = %d, bytesRead = %d, in.available() = %d",
                  position, bytesRead, available));
          }
        }
      }
      int available = in.available();
      assertTrue(available == 0);
    } finally {
      in.close();
    }
  }

  @Test
  public void testGetFileSizeFromListing() throws IOException {
    Path path = new Path("file.dat");
    final int PAGE_SIZE = 512;
    final int FILE_SIZE = PAGE_SIZE + 1;

    // write FILE_SIZE bytes to page blob
    FSDataOutputStream out = fs.create(path);
    byte[] data = new byte[FILE_SIZE];
    Arrays.fill(data, (byte) 5);
    out.write(data, 0, FILE_SIZE);
    out.close();

    // list the file to get its properties
    FileStatus[] status = fs.listStatus(path);
    assertEquals(1, status.length);

    // The file length should report the number of bytes
    // written for either page or block blobs (subclasses
    // of this test class will exercise both).
    assertEquals(FILE_SIZE, status[0].getLen());
  }

  private boolean testModifiedTime(Path testPath, long time) throws Exception {
    FileStatus fileStatus = fs.getFileStatus(testPath);
    final long errorMargin = modifiedTimeErrorMargin;
    long lastModified = fileStatus.getModificationTime();
    return (lastModified > (time - errorMargin) && lastModified < (time + errorMargin));
  }

  @Test
  public void testCreateNonRecursive() throws Exception {
    Path testFolder = new Path("/testFolder");
    Path testFile = new Path(testFolder, "testFile");
    try {
      fs.createNonRecursive(testFile, true, 1024, (short)1, 1024, null);
      assertTrue("Should've thrown", false);
    } catch (FileNotFoundException e) {
    }
    fs.mkdirs(testFolder);
    fs.createNonRecursive(testFile, true, 1024, (short)1, 1024, null)
      .close();
    assertTrue(fs.exists(testFile));
  }

  public void testFileEndingInDot() throws Exception {
    Path testFolder = new Path("/testFolder.");
    Path testFile = new Path(testFolder, "testFile.");
    assertTrue(fs.mkdirs(testFolder));
    assertTrue(fs.createNewFile(testFile));
    assertTrue(fs.exists(testFile));
    FileStatus[] listed = fs.listStatus(testFolder);
    assertEquals(1, listed.length);
    assertEquals("testFile.", listed[0].getPath().getName());
  }
  private void testModifiedTime(Path testPath) throws Exception {
    Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    long currentUtcTime = utc.getTime().getTime();
    FileStatus fileStatus = fs.getFileStatus(testPath);
    final long errorMargin = 10 * 1000; // Give it +/-10 seconds
    assertTrue("Modification time " +
        new Date(fileStatus.getModificationTime()) + " is not close to now: " +
        utc.getTime(),
        fileStatus.getModificationTime() > (currentUtcTime - errorMargin) &&
        fileStatus.getModificationTime() < (currentUtcTime + errorMargin));
  }

  private void createEmptyFile(Path testFile, FsPermission permission)
      throws IOException {
    FSDataOutputStream outputStream = fs.create(testFile, permission, true,
        4096, (short) 1, 1024, null);
    outputStream.close();
  }

  private String readString(Path testFile) throws IOException {
    return readString(fs, testFile);
  }

  private String readString(FileSystem fs, Path testFile) throws IOException {
    FSDataInputStream inputStream = fs.open(testFile);
    String ret = readString(inputStream);
    inputStream.close();
    return ret;
  }

  private String readString(FSDataInputStream inputStream) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(
        inputStream));
    final int BUFFER_SIZE = 1024;
    char[] buffer = new char[BUFFER_SIZE];
    int count = reader.read(buffer, 0, BUFFER_SIZE);
    if (count > BUFFER_SIZE) {
      throw new IOException("Exceeded buffer size");
    }
    inputStream.close();
    return new String(buffer, 0, count);
  }

  private void writeString(Path path, String value) throws IOException {
    writeString(fs, path, value);
  }

  private void writeString(FileSystem fs, Path path, String value)
      throws IOException {
    FSDataOutputStream outputStream = fs.create(path, true);
    writeString(outputStream, value);
  }

  private void writeString(FSDataOutputStream outputStream, String value)
      throws IOException {
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
        outputStream));
    writer.write(value);
    writer.close();
  }

  @Test
  // Acquire and free a Lease object. Wait for more than the lease
  // timeout, to make sure the lease renews itself.
  public void testSelfRenewingLease() throws IllegalArgumentException, IOException,
    InterruptedException, StorageException {

    SelfRenewingLease lease;
    final String FILE_KEY = "file";
    fs.create(new Path(FILE_KEY));
    NativeAzureFileSystem nfs = (NativeAzureFileSystem) fs;
    String fullKey = nfs.pathToKey(nfs.makeAbsolute(new Path(FILE_KEY)));
    AzureNativeFileSystemStore store = nfs.getStore();
    lease = store.acquireLease(fullKey);
    assertTrue(lease.getLeaseID() != null);

    // The sleep time for the keep-alive thread is 40 seconds, so sleep just
    // a little beyond that, to make sure the keep-alive thread wakes up
    // and renews the lease.
    Thread.sleep(42000);
    lease.free();

    // Check that the lease is really freed.
    CloudBlob blob = lease.getCloudBlob();

    // Try to acquire it again, using direct Azure blob access.
    // If that succeeds, then the lease was already freed.
    String differentLeaseID = null;
    try {
      differentLeaseID = blob.acquireLease(15, null);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Caught exception trying to directly re-acquire lease from Azure");
    } finally {
      assertTrue(differentLeaseID != null);
      AccessCondition accessCondition = AccessCondition.generateEmptyCondition();
      accessCondition.setLeaseID(differentLeaseID);
      blob.releaseLease(accessCondition);
    }
  }

  @Test
  // Acquire a SelfRenewingLease object. Wait for more than the lease
  // timeout, to make sure the lease renews itself. Delete the file.
  // That will automatically free the lease.
  // (that should work without any failures).
  public void testSelfRenewingLeaseFileDelete()
      throws IllegalArgumentException, IOException,
        InterruptedException, StorageException {

    SelfRenewingLease lease;
    final String FILE_KEY = "file";
    final Path path = new Path(FILE_KEY);
    fs.create(path);
    NativeAzureFileSystem nfs = (NativeAzureFileSystem) fs;
    String fullKey = nfs.pathToKey(nfs.makeAbsolute(path));
    lease = nfs.getStore().acquireLease(fullKey);
    assertTrue(lease.getLeaseID() != null);

    // The sleep time for the keep-alive thread is 40 seconds, so sleep just
    // a little beyond that, to make sure the keep-alive thread wakes up
    // and renews the lease.
    Thread.sleep(42000);

    nfs.getStore().delete(fullKey, lease);

    // Check that the file is really gone and the lease is freed.
    assertTrue(!fs.exists(path));
    assertTrue(lease.isFreed());
  }

  // Variables to check assertions in next test.
  private long firstEndTime;
  private long secondStartTime;

  // Create two threads. One will get a lease on a file.
  // The second one will try to get the lease and thus block.
  // Then the first one will free the lease and the second
  // one will get it and proceed.
  @Test
  public void testLeaseAsDistributedLock() throws IllegalArgumentException,
      IOException {
    final String LEASE_LOCK_FILE_KEY = "file";
    fs.create(new Path(LEASE_LOCK_FILE_KEY));
    NativeAzureFileSystem nfs = (NativeAzureFileSystem) fs;
    String fullKey = nfs.pathToKey(nfs.makeAbsolute(new Path(LEASE_LOCK_FILE_KEY)));

    Thread first = new Thread(new LeaseLockAction("first-thread", fullKey));
    first.start();
    Thread second = new Thread(new LeaseLockAction("second-thread", fullKey));
    second.start();
    try {

      // Wait for the two  threads to finish.
      first.join();
      second.join();
      assertTrue(firstEndTime < secondStartTime);
    } catch (InterruptedException e) {
      fail("Unable to wait for threads to finish");
      Thread.currentThread().interrupt();
    }
  }

  private class LeaseLockAction implements Runnable {
    private String name;
    private String key;

    LeaseLockAction(String name, String key) {
      this.name = name;
      this.key = key;
    }

    @Override
    public void run() {
      LOG.info("starting thread " + name);
      SelfRenewingLease lease = null;
      NativeAzureFileSystem nfs = (NativeAzureFileSystem) fs;

      if (name.equals("first-thread")) {
        try {
          lease = nfs.getStore().acquireLease(key);
          LOG.info(name + " acquired lease " + lease.getLeaseID());
        } catch (AzureException e) {
          assertTrue("Unanticipated exception", false);
        }
        assertTrue(lease != null);
        try {

          // Sleep long enough for the lease to renew once.
          Thread.sleep(SelfRenewingLease.LEASE_RENEWAL_PERIOD + 2000);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
        }
        try {
          firstEndTime = System.currentTimeMillis();
          lease.free();
          LOG.info(name + " freed lease " + lease.getLeaseID());
        } catch (StorageException e) {
          fail("Unanticipated exception");
        }
      } else if (name.equals("second-thread")) {
        try {

          // sleep 2 sec to let first thread get ahead of this one
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
        }
        try {
          LOG.info(name + " before getting lease");
          lease = nfs.getStore().acquireLease(key);
          secondStartTime = System.currentTimeMillis();
          LOG.info(name + " acquired lease " + lease.getLeaseID());
        } catch (AzureException e) {
          assertTrue("Unanticipated exception", false);
        }
        assertTrue(lease != null);
        try {
          lease.free();
          LOG.info(name + " freed lease " + lease.getLeaseID());
        } catch (StorageException e) {
          assertTrue("Unanticipated exception", false);
        }
      } else {
        assertTrue("Unknown thread name", false);
      }

      LOG.info(name + " is exiting.");
    }

  }
}

redpajama_set_name: RedPajamaGithub


bunny coloring pages printable easter face expert free sheet.
rabbit coloring page bunny pages easter face for printable bu.
printable rabbit coloring pages rabbits bugs bunny p.
astonishing bunny coloring cute pages lola.
baby rabbit coloring pages bunny for kids bunnies waving ba.
rabbit coloring sheet baby bunny pages page color bunnies rab.
coloring pages rabbit page and bunny face colouring picture rab.
coloring pages bunny baby rabbit page ears printable tag f.
bunny coloring pages printable characters book lola free to print cute baby narwhal page t.
bunny rabbit coloring pages bunnies rabbits enchanting colorin.
coloring printable pages bunny lola.
rabbit coloring pages bunny face pictures to print bunnies sheets.
bunny coloring page pages bugs bunnies rabbit colouring color sheet.
carrot coloring pages bunny with image rabbit seed carrots w easter.
rabbit coloring pages photo bunny ears new page peter.
realistic bunny coloring pages sheets baby astonishing ideas page of bunnies rabbits col.
color in a bunny coloring page stead of buying some pets pages ears sharing carrot happy valentine.
jack rabbit coloring page be nimble pages bunny easter sheet bunnies colori.
drawn bunny coloring page pencil and in color pages easter eggs 8.
bunny coloring colouring pages best color lola page 3.
bunny coloring pages to print best rabbit bugs bunnies for view larger preschoolers pictures.
rabbits coloring pages bunny ear page rabbit of ears.
bunny and eggs coloring pages best face with big page sheets.
bunny rabbit coloring pages at free printable lola page bunnies.
coloring pages for adults best kids baby bunny page.
peter rabbit coloring pages color bunny bugs col.
coloring page of a rabbit pages bugs bunny free g printable.
bunny coloring sheets free bunnies pages easter face sheet related post colouring printable co.
bunny coloring pages for kids family guide to face related posts holiday.
bunny color pages coloring and eggs baby free rabbit colouring bunnies.
rabbit color pages coloring bunny colouring easter face kids col.
baby bunny coloring pages rabbit girl.
bunny print out coloring pages bunnies page printable rabbits book rabbit free silhouette kids.
bunny pictures to color also coloring page pages rabbits.
coloring pages bunny rabbit color page free printable easter eggs sheets kids online.
rabbit colouring page pencil and in color coloring pages bugs bunny 3.
egg coloring pages of eggs and bunnies page bunny dying with rice easter face pictures kit free p.
rabbit coloring page bunny free printable pages easter eggs for preschool rabbi.
printable coloring page bunny the graphics fairy pages easter eggs.


text:
Q: How to read QProcess output In the main thread of a Gui Application I am starting a QProcess of another GUI application that will log some messages over time in stdout using fputs(). The problem is that after some time the GUI application started with QProcess will freeze because it's output is not consumed by the parent. I know that this is the problem because if I am starting the QProcess with QIODevice::NotOpen or QIODevice::Unbuffered argument, it will not get stuck but the output will never be reached.
I've tried to connect the readyRead, readyReadStandardError, readyReadStandardOutput signals of the subprocess to a slot in the parent, but for some reasons the signals are never emitted. I am also flushing the stdout after each write.
My question is how to force QProcess to send some data in real time without closing it?
The connection of the signals, (T- is a wrapper for QProcess):
process->setWorkingDirectory(workingDir);
process->start(prog, argumentsList);
process->waitForStarted();
T* reciver = new V8QProcess(process);
QObject::connect(process, &QProcess::readyRead, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardError, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardOutput, reciver, &V8QProcess::OnMessageRecieved);

The code of the subprocess that will log in stdout:
QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);

The code of the OnMessageRecieved:
 if (!p) { // p is the QProcess
    return;
}
QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString());

This approach is working when running a shell script or other simple program.

A: I found out what the problem was on my case:
Because I was starting the QProcess in a std::Thread, the events(signals) that occur were skipped because std::Thread don't have a queue of events as QThread or QApplication does.
The solution that I use is:
 1. Use QThread instead of std::thread
 2. Call QCoreApplication::proccesEvents() from time to time.
The proper solution is to use QThread::exec() in order to create an event loop, but this approach would block the GUI Application, so in my case is no good.

redpajama_set_name: RedPajamaStackExchange


Accessories like mobile stand bracket for whiteboard, color pens, wall bracket for projector, speaker, microphone, voting system machine, original manufacturing products Interested in purchasing a product or learning more about our solutions? A local SinoEview team member is ready to help. Welcome to require now!
Accessories like mobile stand bracket for whiteboard, color pens, wall bracket for projector, speaker, microphone, voting system machine, original manufacturing products. Interested in purchasing a product or learning more about our solutions? A local SinoEview team member is ready to help. Welcome to require now!


text:
January 22, 2020 | Sticky Antibiotic Stays Put Inside the Body for Successful Treatment of Debilitating Gut Infections
Home Science News
Engineers Use Voltage to Control Magnetic Memory
TOPICS:ElectronicsMagnetismMaterials ScienceMIT
By David L. Chandler, Massachusetts Institute of Technology November 20, 2014
This diagram shows the principle behind using voltage to change material properties. In this sandwich of materials, applying a voltage results in movement of ions — electrically charged atoms — from the middle, functional layer of material into the target layer. This modifies some of the properties — magnetic, thermal, or optical — of the target material, and the changes remain after the voltage is removed.
New research details how a MIT-based team has made important strides in the concept of using an electrical signal to control a magnetic memory.
A new way of switching the magnetic properties of a material using just a small applied voltage, developed by researchers at MIT and collaborators elsewhere, could signal the beginning of a new family of materials with a variety of switchable properties, the researchers say.
The technique could ultimately be used to control properties other than magnetism, including reflectivity or thermal conductivity, they say. The first application of the new finding is likely to be a new kind of memory chip that requires no power to maintain data once it's written, drastically lowering its overall power needs. This could be especially useful for mobile devices, where battery life is often a major limitation.
The findings were published this week in the journal Nature Materials by MIT doctoral student Uwe Bauer, associate professor Geoffrey Beach, and six other co-authors.
Beach, the Class of '58 Associate Professor of Materials Science and Engineering, says the work is the culmination of Bauer's PhD thesis research on voltage-programmable materials. The work could lead to a new kind of nonvolatile, ultralow-power memory chips, Beach says.
The concept of using an electrical signal to control a magnetic memory element is the subject of much research by chip manufacturers, Beach says. But the MIT-based team has made important strides in making the technique practical, he says.
The structure of these devices is similar to that of a capacitor, Beach explains, with two thin layers of conductive material separated by an insulating layer. The insulating layer is so thin that under certain conditions, electrons can tunnel right through it.
But unlike in a capacitor, the conductive layers in these low-power chips are magnetized. In the new device, one conductive layer has fixed magnetization, but the other can be toggled between two magnetic orientations by applying a voltage to it. When the magnetic orientations are aligned, it is easier for electrons to tunnel from one layer to the other; when they have opposite orientations, the device is more insulating. These states can be used to represent "zero" and "one."
The work at MIT shows that it takes just a small voltage to flip the state of the device — which then retains its new state even after power is switched off. Conventional memory devices require a continuous source of power to maintain their state.
The MIT team was able to design a system in which voltage changes the magnetic properties 100 times more powerfully than other groups have been able to achieve; this strong change in magnetism makes possible the long-term stability of the new memory cells.
They achieved this by using an insulating layer made of an oxide material in which the applied voltage can rearrange the locations of the oxygen ions. They showed that the properties of the magnetic layer could be changed dramatically by moving the oxygen ions back and forth near the interface.
The team is now working to ramp up the speed at which these changes can be made to the memory elements. They have already reached rates of a megahertz (millions of times per second) in switching, but a fully competitive memory module will require further increase on the order of a hundredfold to a thousandfold, they say.
The team also found that the magnetic properties could be changed using a pulse of laser light that heats the oxide layer, helping the oxygen ions to move more easily. The laser beam used to alter the state of the material can scan across its surface, making changes as it goes.
The same techniques could be used to alter other properties of materials, Beach explains, such as reflectivity or thermal conductivity. Such properties can ordinarily be changed only through mechanical or chemical processing. "All these properties could come under electrical control, to be switched on and off, and even 'written' using a beam of light," Beach says. This ability to make such changes on the fly essentially produces "an Etch-a-Sketch for material properties," he says.The new findings "started as a fluke," Beach says: Bauer was experimenting with the layered material, expecting to see standard temporary capacitive effects from an applied voltage. "But he turned off the voltage and it stayed that way," with a reversed magnetic state, Beach says, leading to further investigation.
"I think this will have broad applications," Beach says, adding that it uses methods and materials that are already standard in microchip manufacturing.
In addition to Bauer and Beach, the team included Lide Yao and Sebastiaan van Dijken of Aalto University in Finland and, at MIT, graduate students Aik Jun Tan, Parnika Agrawal, and Satoru Emori and professor of ceramics and electronic materials Harry Tuller. The work was supported by the National Science Foundation and Samsung.
Publication: Uwe Bauer, et al., "Magneto-ionic control of interfacial magnetism," Nature Materials (2014); doi:10.1038/nmat4134
Image: Diagram courtesy of the researchers; edited by Jose-Luis Olivares/MIT
Voltage-Controlled Switchable Material Could Enable New Memory Chips
Researchers Discover an Efficient Way of Slowing the Rotation of Molecular Ions
Researchers Develop a Sampling Scheme That is Unconstrained by Bandwidth
Researchers Discover Electrical Switch for Magnetic Current
MIT Neuroscientists Challenge Standard Model of Memory Consolidation
"Silent Engrams" Build a Case for a New Theory of Memory Formation
"Skyrmions" Could Provide a Way to Bypass the Limits to Moore's Law
Neuroscientists Plant False Memories in the Brains of Mice
Be the first to comment on "Engineers Use Voltage to Control Magnetic Memory"

redpajama_set_name: RedPajamaCommonCrawl


To handle the vendor units which manufacture products to ensure right quality.
Ensure units have access to the latest specifications and drawings for all products based on changes made.
Assist in establishing new products at the respective units. Responsible for PPAP, prepare quality plans and process control for all new products.
Responsible for product quality at vendor factories. To review failed inspection to identify problems affecting the quality of merchandise and make disposition for re-inspection to ensure that quality standards are met.
To ensure size and other specifications for manufacturing are adhered to and production/fit is in-line with approval samples.
Do analysis of change notes and assign the responsibility for quality failures / damages / shortages hampering installation at site.
Tracking of Customer satisfaction opportunities/customer complaints to ensure the RCA is done and CAPA is done to improve the process.
To develop training program and conducting training sessions on quality standards, quality control systems and procedures, production technology and problem solving.
Education	BE- Mech or M.Tech. MBA is added qualification.


text:
Q: Wix Managed bootstrapper I have some ExecPackages chained in my bundle.wxs. I have a PackageGroup section for installing .Net Framework 4.0. This has been hooked in the beginning of the chain as a PackageGroupRef.
When I double click on the bootstrapper, a .Net framework installation window pops up which installs .Net Fwk. After the installation of .Net, I would expect the bootstrapper to display the managed UI and continue with the actual installation activities.
But, the issue is that it just stops after the .Net framework installation. I have to execute the bootstrapper a second time for the UI to pop up and resume the installation. The bundle.wxs content goes like this:
     <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
             xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
             xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
          <Bundle Name="My-Installer"
                  Version="3.0"
                  Manufacturer="XXXX"
                  HelpUrl="XXXX"
                  UpdateUrl="XXXX"
                  UpgradeCode="XXXX">
            <!--Compressed="no"-->

            <!--Custom dialog is a WPF form-->
            <BootstrapperApplicationRef Id='ManagedBootstrapperApplicationHost'>
              <Payload Name='BootstrapperCore.config' SourceFile='..\MyBootstrapperCustomUI\MyBootstrapperCustomUI\MyBootstrapperCustomUI.BootstrapperCore.config' />
              <Payload SourceFile='..\MyBootstrapperCustomUI\MyBootstrapperCustomUI\bin\$(var.Configuration)\MyBootstrapperCustomUI.dll' />
            </BootstrapperApplicationRef>

            <Chain>
              <PackageGroupRef Id='Netfx4Full' />
              <ExePackage Id="MyPackage1"..../>
              <ExePackage Id="MyPackage2"..../>
            </Chain>
     <Fragment>
         <WixVariable Id="WixMbaPrereqPackageId" Value="Netfx4Full" />
         <WixVariable Id="WixMbaPrereqLicenseUrl" Value="NetfxLicense.rtf" />
         <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"   Value="Version" Variable="Netfx4FullVersion" />
         <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full" Value="Version" Variable="Netfx4x64FullVersion" Win64="yes" />
         <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v3.5" Value="Version" Variable="Netfx35Version"/>
         <PackageGroup Id="Netfx4Full">
              <ExePackage Id="Netfx35" Cache="no" Compressed="no" PerMachine="yes" Permanent="yes" Vital="yes" SourceFile="..\MyApp\dotNETFramework3.5SP1\dotnetfx35.exe" Name="MyApp\dotNETFramework3.5SP1\dotnetfx35.exe" DetectCondition="Netfx35Version AND (Netfx35Version >= v3.5.30729.1)" InstallCommand="/q /norestart" UninstallCommand="/q /norestart"
InstallCondition="(NOT Netfx35Version OR (Netfx35Version < v3.5.30729.1)) AND NOT VersionNT >= v6.0"/><!--donot install if win7-->

              <ExePackage Id="Netfx4Full" Cache="no" Compressed="no" PerMachine="yes" Permanent="yes" Vital="yes" SourceFile="..\MyApp\dotNETFramework4.0\dotNetFx40_Full_x86_x64.exe" Name="MyApp\dotNETFramework4.0\dotNetFx40_Full_x86_x64.exe" InstallCommand="/passive /norestart" DetectCondition="Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)" />
        </PackageGroup>
      </Fragment>

</Wix>
</Bundle>


SoundWave Quartet is a local group whos members are or have been members of the Olympia Chorus of Sweet Adelines International. The quartet has won numerous awards at regional competitions and enjoy performing. The routinely entertain at local events and parties and never disappoint. If you want to learn more about Soundwave please visit their website for pictures and video.


text:
Q: Trying to reference a formula in another sheet using the Index-Match method in Excel (Office 2016) I am trying to reference a formula in another sheet using the Index-Match method. I am referencing this formula every time a certain Feature appears in my main list. For instance, if the Castle Feature appears, the Description column index-matches from a Feature list on another sheet.
The referenced formula is meant to randomize the Creature that owns the Castle. My problem is that because all of my Castles are referencing the same formula, they all end up owned by the same Creature.
There are 700 rows being calculated and 110 different features. Just copying the formula for each one isn't an option. It needs to be dynamic based on the feature on that particular row.
All Descriptions are pulled from the same place: Features! via
=index(featuredetails,match(i2,featurelist,0),10)

Description Formula on Features sheet:
="It's a "&index(creatures,randbetween(1,counta(creatures)),1)&" Castle"

Sheet 1 (the way it is)
 1. | Feature | Description |
 2. | Castle | It's a Goblin Castle |
 3. | Castle | It's a Goblin Castle |

Sheet 1 (the way I want it)
 1. | Feature | Description |
 2. | Castle | It's a Goblin Castle |
 3. | Castle | It's a **KOBOLD** Castle |

Hopefully that's enough explanation.
I would prefer a formula solution. I'm trying to keep my project office 365 friendly.


text:
Looking For Frederick Maryland 38 Female Adult Womens 38 Register Login Contact Us
Looking for Frederick Maryland 38 female adult womens 38 I Wants Sexual Encounters
My name is. Someone who isn't interested in interfering with your life, but is there to enhance it; a safe, discreet friend to explore some new boundaries with, and have some fun along the way, then keep watching: About ME: I do not have the time desire for a relationship, but find myself with a lot of free time during the day and am seeking a deserving female who is not getting her needs fulfilled to join me for some discreet fun, a little exploration, and hopefully some intellectually satisfying conversation. Re: im going to take a GAMBLE and hope you see this m4w I need to know its you, if it is you. I am fit, blonde hair, blue eyes. But worth the visit.
Aeriell
Seeking: I Am Search Real Sex Dating
City: Pompton Plains, Seminole County
Relation Type: Horney Ladys Ready Nude Teens
They also claimed that the victim had ridden a train from Texas. Willing to pay for bar tabs and dinner check if need be.
The decedent had apparently hitchhiked to Alaska Osasco wanting to lick you with another man and was then murdered by his companion. Within three years, it had been reprinted nine times, with 11, copies circulating in the United States.
Investigators estimate that he had died hours or a few days before. Marylwnd couple settled in New Bedford, Massachusetts an abolitionist center, full of former slaves inlater moving to Lynn, Massachusettsin I'm chill, laid back, discreet.
Looking for frederick maryland 38 female adult womens 38
First published inthe book is a classroom reader, containing essays, speeches, and dialogues, to assist students in learning reading and grammar. I find myself regarded and treated at every turn with the kindness and deference paid to white people. He and his wife provided lodging and resources in their home to more than four hundred escaped slaves. Two stainless steel surgical rods had been implanted in the man's lower back around the s.
He completed his spine surgery fellowship at the Spine Institute of Arizona in Loooing.
He has a special interest in motion preservation, endoscopic spinal fusion, robotic computer assisted image guidance and complex Lolking reconstruction. Wanting a long term FWB.
In this denial of the feale to participate in government, not merely the degradation of woman and the perpetuation of a great injustice happens, but Mayland maiming and repudiation of one-half of the moral and intellectual power of the government of the world. Strikingly, he expressed the belief that "[a] discussion of the rights of animals would be regarded with far more complacency Douglass sailed back from England the following month, traveling through Canada to avoid detection.
Smith volunteers his time to teach residents and conducts research in academic spine surgery. Protopsaltis Marylanf his fellowship in spine Looking for Frederick Maryland 38 female adult womens 38 at New York University and is a fellow of the American Academy of Orthopaedic Surgeons.
Searching hookers
Salari was chief resident during his training at Lookint Workout friends Fgederick fitness Dearne valley Hospital and then Old whores to date a spine surgery fellowship at Stanford University. He served as an assistant professor in the orthopedic surgery department at the University of Southern California and was co-director of the USC Center for Spinal Surgery. Thomas sent Douglass to work for Edward Coveya poor farmer who had a reputation as a "slave-breaker.
He completed his fellowship in spine surgery at Washington University in St. Weight and eye color could not be ascertained. When I womdns to church, I am met by no upturned nose and scornful lip to tell me, 'We don't allow niggers in here!
InDouglass met and fell in love with Anna Murraya free black woman in Baltimore about five years older than he. Garrison had burned copies of the Constitution to express his opinion. Investigators believe he was killed elsewhere before his body was deposited at the location.
What country have I? His research interests include early onset scoliosis, adult spinal deformity and minimally invasive surgical techniques. After the raid, which took place between OctoberDouglass, fearing guilt by association as well as arrest as a co-conspirator, fled for a brief time to Canada before proceeding onward to Femalr on a ly-planned lecture tour, arriving near the end of November.
I live and work in Ypsilanti, not too far outside fpr Arbor. The area he was found in is accessible from the Chickasabogue Creek near Route 43, and is popular with fishermen.
Douglass published three versions of his autobiography during his lifetime and revised the third of theseeach time expanding on the one. On September 3,Douglass successfully escaped by boarding a northbound train of the Philadelphia, Wilmington and Baltimore Railroad. Fernandez uses robotic guidance technology.
Themistocles S. As word spread, the interest among slaves in learning to read was so great that in any week, more than 40 slaves would attend lessons. InDouglass delivered a speech in Elmira, New Yorkthen a station on the Underground Railroadin which a black congregation would form years later, becoming the region's largest church by Reply with aand maybe we can plan something.
It commemorates womejs speech there on October 9, The depot was located at President and Fleet streets, east of "The Basin" of the Baltimore harboron the northwest branch of the Patapsco River. His clinical work focuses on spinal deformities, degeneration, Big tits from tulsa and tumors.
Douglass believed that attacking federal property would enrage the American public. Lloyd Garrison 's weekly newspaper, The Liberator.
Lonely Girls hair. His hand was broken in the attack; it healed improperly and bothered him for the rest of his life. Love older women, always have. The property owner claimed to have found the remains while gardening, and stated that he had seldom visited Marylanv property since Instead of a democratic government, I am under a monarchical government.
Instead of the bright, blue sky demale America, I am covered with the soft, grey fog of the Emerald Isle [Ireland]. Prasad is a surgeon in the department of neurological surgery and orthopedic surgery. A new world had opened upon me. They were married on September 15,by a black Presbyterian minister, just eleven days after Douglass had reached New York.
Looking for a sexy mature woman that femmale host while I'm living in VA. His age could only be estimated that he was above 18 years old.
Douglass supported the amendment, which would grant suffrage to black men.
I Am Look For A Man
Wanting Real Dating
Ready Dick
Huntington IN Sex Dating


text:
CE mark approval for percutaneous coronary intervention optimisation system
Digital | Medical Devices
St Jude Medical launches Ilumien Optis combining Fractional Flow Reserve and intravascular Optical Coherence Tomography
St Jude Medical has announced CE mark approval for its Ilumien Optis PCI Optimisation System.
The technology is designed to provide physicians with a comprehensive coronary artery disease assessment and is the only device that integrates both Fractional Flow Reserve (FFR) technology and intravascular Optical Coherence Tomography (OCT) imaging technology into one system.
The system provides enhancements to the original Ilumien solution, including first-of-its-kind stent planning software tools to aid in the treatment of coronary artery disease (CAD).
Featuring a faster, high-powered laser, the Ilumien Optis offers twice the resolution for microscopic examination of disease inside the artery to assist with stent placement. The real-time, three-dimensional 3D reconstruction offers a 360-degree panoramic view of the vessel, making it easier for physicians to visualise the area they are treating.
"OCT technology has become increasingly important to help diagnose and treat patients with coronary artery disease," said Dr Giulio Guagliumi from the cardiovascular department at Ospedale Papa Giovanni XXIII in Bergamo, Italy.
"The Ilumien Optis system is a significant advancement in intravascular imaging technology, allowing physicians to comprehensively assess more vessel in less time and more easily plan their PCI procedure. The three-dimensional format provides a more true-to-life perspective of the arteries, which allows for individual decision-making and precise guidance of stent placement to optimise coronary interventions."
Commonly known as coronary angioplasty, percutaneous coronary intervention (PCI) is a non-surgical procedure used to treat narrowed coronary arteries of the heart found in patients with CAD.
The OCT technology in the new system uses the Dragonfly Duo Imaging Catheter to capture near-infrared light imaging and measure important vessel characteristics otherwise invisible or difficult to assess with older imaging technology. When used with the Ilumien Optis system, the Dragonfly Duo catheter offers faster, longer pull-backs, which allow the physician to assess more of the patient's artery in less time.
The wireless PressureWire Aeris technology that is integrated into the platform measures pressure differences in blood flow within the coronary arteries leading to the heart, and determines the severity of any narrowings or blockages. The FFR pressure guidewire is directed along the vessel, taking measurements as the guidewire is pulled back through the artery. Knowing which specific blockages are causing the patient's blood flow to be ineffective helps guide the interventional cardiologist in determining which lesions warrant stenting, resulting in improved patient outcomes and reduced healthcare costs.
The FFR and OCT measurements captured by the system allow physicians to more easily differentiate plaque build-up and determine if the narrowed arteries are causing a restriction in blood flow, ultimately assisting in stent placement. The automated stent planning tools provide immediate information for assessment and real-time analysis, which is intended to streamline workflow, potentially helping physicians diagnose their patients more quickly.
St Jude Medical UK Ltd
NICE publishes latest Medtech Innovation Briefings
St Jude Medical expands portfolio of MRI-compatible devices to high voltage in Europe
World's first and only 'multiPoint pacing' pacemaker approved in Europe
Large-scale study confirms growing body of clinical evidence for Quadripolar System
St Jude Medical Nanostim leadless pacemaker receives innovation award
St Jude Medical announces start of European post-approval trial for Nanostim Leadless Pacemaker
St Jude Medical announces implant of world's-first leadless pacemaker in the UK
St Jude Medical gets CE Mark approval for 25mm Portico Transcatheter Aortic Heart Valve
Kidney patient among first to receive pioneering treatment for high blood pressure
St Jude Medical unveils world\'s-first leadless pacemaker
St Jude Medical gains approval for cardiac resynchronisation therapy defibrillator
Portable ultrasound system now comes with 2D Intracardiac Echo technology
CE Mark approval for first quadripolar CRT pacemaker
Approval for next-generation treatment for high-risk aortic stenosis patients


text:
Darlington 22°c
Our Facebook feedsThe Northern Echo
Our Twitter feedsFollow our reporters on Twitter
NHS & Health
CineSecrets
The North-East At War
BusinessIQ
Ask Fiona
Send Your Obituary
Jonny Howson: 'Last season was a failure - but we're good enough to improve this term'
Jonny Howson admits Middlesbrough failed last season
By Scott Wilson scottwilsonecho Chief Sports Writer
Jonny Howson sets off on a run during Middlesbrough's pre-season win at Gateshead (Picture: Tom Banks)
JONNY HOWSON has branded Middlesbrough's efforts last season as a "failure", and expressed confidence that the core of the squad that remains at the Riverside is capable of improving on their efforts under Tony Pulis.
Boro missed out on the play-offs on the final weekend last term, with a run of six successive defeats in March and April scuppering their hopes of making it back to the Premier League.
A failure to secure promotion cost Pulis his job, and resulted in the appointment of Jonathan Woodgate as head coach earlier this summer.
Woodgate is determined to oversee a radical overhaul of Boro's playing style, and having helped his new boss claim his first pre-season victory as he opened the scoring at Gateshead on Wednesday night, Howson is confident there is sufficient quality in the squad to improve on last season's efforts.
"We're starting from a pretty good place, but we can't hide from what happened last season," said the 31-year-old, who found himself lining up at right-back two days ago, having also filled in as a wing-back under Pulis. "The bottom line is that we failed last season.
"With that squad, I personally believe that we should have been in the play-offs as an absolute minimum, but if you look back, I think that six-game run killed us. We missed out, and it was a disappointment.
"But we weren't too far away and a lot of the lads are still here. We've had two or three that have left, but we know the core of the squad is there. We have to aim for an improvement now. We have to improve on what we did last season to be successful. We'll see how that goes."
While Wednesday's game only pitched Boro against opponents that will spend next season playing in National League North, it nevertheless provided a first domestic glimpse of Woodgate's plans in action.
The Teessider wants his side to be bold and adventurous in attack, and is also urging his players to press high up the field when they do not have possession. It is a marked shift from the tactics employed by Pulis last season, although Howson expects a degree of flexibility to still be important.
"It's exciting," he said. "We're under a new management regime, asking different things, and we have to put those into practice.
"It's still very early days, but the message is that we want to play a different way this season. Each to their own – Tony Pulis had his way of playing, and the new manager has his own way that he wants to play. As good players, you've got to be able to adapt.
"Certainly, in the Championship though, the message might be to move the ball and get the high press on, but I'm sure there may be some games this season where we have to play in a different way. Because of circumstances, we might have to change, and as a good unit or a good team, you have to be able to adapt to different situations."
Boro return to action on Sunday when they head to Victoria Park to take on National League side Hartlepool United.
Sunderland want to keep McGeouch as well as land Walsall captain Dobson
Does Steve Bruce really appreciate the scale of the fury that is about to be unleashed at Newcastle?
Boro will have to act fast to land Portsmouth winger while Cardiff join Assombalonga chase
Adam Clayton: 'Every training session, every fitness drill - we've had the ball at our feet'
Steve Bruce to sanction striker signing in his first move as Newcastle United boss
FC Halifax Town v Darlington friendly moved to Blackwell Meadows
Darlington's Andrew Wilson tees offs shortly after Tiger Woods at The Open
Durham must cope without Bancroft
Spanish striker exits Newcastle United


TBM has been awarded several honours for the quality and performance of their management over the years.
SME Excellence and SME Leader: a IAPMEI initiative in a partnership with banks and Tourism of Portugal, to distinguish a number of SMES with outstanding performances and risk profiles in the universe of Portuguese companies.
As of 2015 TBM is classified as a Large Company.