Search in sources :

Example 51 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class HelixAccountServiceTest method generateRefAccountsForDeprecationTest.

/**
 * Randomly generates a collection of {@link Account}s, which do not have the same id or name with needed container status.
 * @param idToRefAccountMap A map from id to {@link Account} to populate with the generated {@link Account}s.
 * @param idToRefContainerMap A map from name to {@link Account} to populate with the generated {@link Account}s.
 * @param accountIdSet A set of ids that could not be used to generate {@link Account}s.
 * @param accountCount The number of {@link Account}s to generate.
 * @param timestamp timestamp for delete trigger time.
 */
static void generateRefAccountsForDeprecationTest(Map<Short, Account> idToRefAccountMap, Map<Short, Map<Short, Container>> idToRefContainerMap, Set<Short> accountIdSet, int accountCount, long timestamp) {
    idToRefAccountMap.clear();
    idToRefContainerMap.clear();
    for (int i = 0; i < accountCount; i++) {
        short accountId = Utils.getRandomShort(random);
        if (!accountIdSet.add(accountId)) {
            i--;
            continue;
        }
        String accountName = UUID.randomUUID().toString();
        Account.AccountStatus accountStatus = random.nextBoolean() ? Account.AccountStatus.ACTIVE : Account.AccountStatus.INACTIVE;
        Map<Short, Container> idToContainers = new HashMap<>();
        List<Container> containers = new ArrayList<>();
        List<ContainerBuilder> containerBuilders = AccountTestUtils.generateContainerBuilders(4, accountId);
        containerBuilders.get(0).setStatus(Container.ContainerStatus.ACTIVE);
        containerBuilders.get(1).setStatus(Container.ContainerStatus.INACTIVE);
        containerBuilders.get(2).setStatus(Container.ContainerStatus.DELETE_IN_PROGRESS);
        containerBuilders.get(2).setDeleteTriggerTime(timestamp);
        containerBuilders.get(3).setStatus(Container.ContainerStatus.DELETE_IN_PROGRESS);
        containerBuilders.get(3).setDeleteTriggerTime(timestamp + 10000);
        containers.addAll(containerBuilders.stream().map(containerBuilder -> containerBuilder.build()).collect(Collectors.toList()));
        idToContainers = containers.stream().collect(Collectors.toMap(Container::getId, Function.identity()));
        Account account = new AccountBuilder(accountId, accountName, accountStatus).containers(containers).build();
        assertEquals("Wrong number of generated containers for the account", 4, account.getAllContainers().size());
        idToRefAccountMap.put(accountId, account);
        idToRefContainerMap.put(accountId, idToContainers);
    }
    assertEquals("Wrong number of generated accounts", accountCount, idToRefAccountMap.size());
}
Also used : Account(com.github.ambry.account.Account) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Container(com.github.ambry.account.Container)

Example 52 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class MySqlAccountServiceIntegrationTest method testConflictingUpdatesWithContainers.

/**
 * Tests name/id conflicts in Containers
 */
@Test
public void testConflictingUpdatesWithContainers() throws Exception {
    List<Container> containersList = new ArrayList<>();
    containersList.add(new ContainerBuilder((short) 1, "c1", ContainerStatus.ACTIVE, "c1", (short) 1).build());
    containersList.add(new ContainerBuilder((short) 2, "c2", ContainerStatus.ACTIVE, "c2", (short) 1).build());
    Account accountToUpdate = new AccountBuilder((short) 1, "a", Account.AccountStatus.ACTIVE).containers(containersList).build();
    AccountServiceMetrics accountServiceMetrics = mySqlAccountService.accountServiceMetrics;
    // write account (1,a) with containers (1,c1), (2,c2)
    mySqlAccountService.updateAccounts(Collections.singletonList(accountToUpdate));
    assertEquals("Mismatch in number of containers", 2, mySqlAccountService.getAccountById(accountToUpdate.getId()).getAllContainers().size());
    // case A: Verify that changing name of container (1,c1) to (1,c3) replaces existing record
    Container containerToUpdate = new ContainerBuilder((short) 1, "c3", ContainerStatus.ACTIVE, "c3", (short) 1).build();
    accountToUpdate = new AccountBuilder(accountToUpdate).addOrUpdateContainer(containerToUpdate).build();
    mySqlAccountService.updateAccounts(Collections.singletonList(accountToUpdate));
    assertEquals("Mismatch in container information", containerToUpdate, mySqlAccountService.getAccountById((short) 1).getContainerById((short) 1));
    // case B: Verify addition of new container (3,c3) conflicts in name with existing container (1,c3)
    containerToUpdate = new ContainerBuilder((short) 3, "c3", ContainerStatus.ACTIVE, "c3", (short) 1).build();
    accountToUpdate = new AccountBuilder(accountToUpdate).containers(Collections.singletonList(containerToUpdate)).build();
    assertUpdateAccountsFails(Collections.singletonList(accountToUpdate), AccountServiceErrorCode.ResourceConflict, mySqlAccountService);
    accountToUpdate = new AccountBuilder(accountToUpdate).removeContainer(containerToUpdate).build();
    assertEquals("UpdateAccountErrorCount in metrics should be 1", 1, accountServiceMetrics.updateAccountErrorCount.getCount());
    // case C: Verify addition of new container (3,c4) is successful
    containerToUpdate = new ContainerBuilder((short) 3, "c4", ContainerStatus.ACTIVE, "c4", (short) 1).build();
    accountToUpdate = new AccountBuilder(accountToUpdate).addOrUpdateContainer(containerToUpdate).build();
    mySqlAccountService.updateAccounts(Collections.singletonList(accountToUpdate));
    assertEquals("Mismatch in container information", containerToUpdate, mySqlAccountService.getAccountById((short) 1).getContainerById((short) 3));
    // case D: Verify updating name of container (3,c4) to c2 conflicts in name with existing container (2,c2)
    containerToUpdate = new ContainerBuilder(mySqlAccountService.getAccountById((short) 1).getContainerById((short) 3)).setName("c2").build();
    accountToUpdate = new AccountBuilder(accountToUpdate).addOrUpdateContainer(containerToUpdate).build();
    assertUpdateAccountsFails(Collections.singletonList(accountToUpdate), AccountServiceErrorCode.ResourceConflict, mySqlAccountService);
    assertEquals("UpdateAccountErrorCount in metrics should be 2", 2, accountServiceMetrics.updateAccountErrorCount.getCount());
}
Also used : Container(com.github.ambry.account.Container) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 53 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class MySqlAccountServiceIntegrationTest method testContainerFetchOnDemand.

/**
 * Container on-demand fetch for multiple account services.
 */
@Test
public void testContainerFetchOnDemand() throws Exception {
    MySqlAccountService producerAccountService = mySqlAccountService;
    // Create second account service with scheduled polling disabled
    mySqlConfigProps.setProperty(UPDATER_POLLING_INTERVAL_SECONDS, "0");
    accountServiceConfig = new MySqlAccountServiceConfig(new VerifiableProperties(mySqlConfigProps));
    MySqlAccountStore consumerAccountStore = spy(new MySqlAccountStoreFactory(new VerifiableProperties(mySqlConfigProps), new MetricRegistry()).getMySqlAccountStore());
    MySqlAccountStoreFactory mockMySqlAccountStoreFactory = mock(MySqlAccountStoreFactory.class);
    when(mockMySqlAccountStoreFactory.getMySqlAccountStore()).thenReturn(consumerAccountStore);
    AccountServiceMetrics accountServiceMetrics = new AccountServiceMetrics(new MetricRegistry());
    // Note: for these tests, consumer must NOT be notified of changes
    MySqlAccountService consumerAccountService = new MySqlAccountService(accountServiceMetrics, accountServiceConfig, mockMySqlAccountStoreFactory, null);
    // Add new account "a1" on producer account service
    short accountId = 101;
    String accountName = "a1";
    int onDemandContainerFetchCount = 0;
    Container container = new ContainerBuilder((short) 1, "c1", ContainerStatus.ACTIVE, DESCRIPTION, accountId).build();
    Account account = new AccountBuilder(accountId, accountName, Account.AccountStatus.ACTIVE).containers(Collections.singletonList(container)).build();
    producerAccountService.updateAccounts(Collections.singletonList(account));
    // Test getContainer on consumer account service should fail since account doesn't exist
    assertNull("Expected null since Account doesn't exist in consumerAccountService cache", consumerAccountService.getContainerByName(accountName, "c1"));
    assertNull("Expected null since Account doesn't exist in consumerAccountService cache", consumerAccountService.getContainerById(accountId, (short) 1));
    // Fetch and update cache in consumer account service
    consumerAccountService.fetchAndUpdateCache();
    assertEquals("Account mismatch", account, consumerAccountService.getAccountByName(accountName));
    assertEquals("Container mismatch", container, consumerAccountService.getContainerByName(accountName, "c1"));
    assertEquals("Container mismatch", container, consumerAccountService.getContainerById(accountId, (short) 1));
    // Add new container in producer account service
    producerAccountService.updateContainers(accountName, Collections.singletonList(new ContainerBuilder((short) -1, "c2", ContainerStatus.ACTIVE, DESCRIPTION, accountId).build()));
    Container newContainer = producerAccountService.getContainerByName(accountName, "c2");
    // Test getContainerByName() on consumer account service is successful (by fetching from mysql on demand)
    assertEquals("getContainerByName() expected to fetch container from MySql db", newContainer, consumerAccountService.getContainerByName(accountName, "c2"));
    verify(consumerAccountStore).getContainerByName(eq((int) accountId), eq(newContainer.getName()));
    assertEquals("Number of on-demand container requests should be 1", ++onDemandContainerFetchCount, accountServiceMetrics.onDemandContainerFetchCount.getCount());
    // verify in-memory cache is updated with the fetched container "c2"
    assertEquals("Container c2 should be present in consumer account service", newContainer, consumerAccountService.getAccountByName(accountName).getContainerByName(newContainer.getName()));
    // Add new container in producer account service
    producerAccountService.updateContainers(accountName, Collections.singletonList(new ContainerBuilder((short) -1, "c3", ContainerStatus.ACTIVE, DESCRIPTION, accountId).build()));
    newContainer = producerAccountService.getContainerById(accountId, (short) 3);
    // Test getContainerById() on consumer account service is successful (by fetching from mysql on demand)
    assertEquals("getContainerById() expected to fetch container from MySql db", newContainer, consumerAccountService.getContainerById(accountId, (short) 3));
    verify(consumerAccountStore).getContainerById(eq((int) accountId), eq((int) newContainer.getId()));
    assertEquals("Number of on-demand container requests should be 2", ++onDemandContainerFetchCount, accountServiceMetrics.onDemandContainerFetchCount.getCount());
    // verify in-memory cache is updated with the fetched container "c3"
    assertEquals("Container c3 should be present in consumer account service", newContainer, consumerAccountService.getAccountByName(accountName).getContainerById(newContainer.getId()));
}
Also used : MySqlAccountServiceConfig(com.github.ambry.config.MySqlAccountServiceConfig) VerifiableProperties(com.github.ambry.config.VerifiableProperties) MetricRegistry(com.codahale.metrics.MetricRegistry) MySqlAccountStoreFactory(com.github.ambry.account.mysql.MySqlAccountStoreFactory) Container(com.github.ambry.account.Container) MySqlAccountStore(com.github.ambry.account.mysql.MySqlAccountStore) Test(org.junit.Test)

Example 54 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class HelixAccountServiceTest method testUpdateContainer.

/**
 * Test updating an existing container (id specified).
 */
@Test
public void testUpdateContainer() throws Exception {
    assumeTrue(!useNewZNodePath);
    accountService = mockHelixAccountServiceFactory.getAccountService();
    assertEquals("The number of account in HelixAccountService is incorrect", 0, accountService.getAllAccounts().size());
    // add an account with single container
    accountService.updateAccounts(Collections.singletonList(refAccount));
    // 1. Update existing container (success case)
    Container modifiedContainer = new ContainerBuilder(refContainer).setDescription("Different than before").build();
    Collection<Container> updatedContainers = accountService.updateContainers(refAccountName, Collections.singleton(modifiedContainer));
    assertEquals("Mismatch in return count", 1, updatedContainers.size());
    assertEquals("Mismatch in container data", modifiedContainer, updatedContainers.iterator().next());
    // 2. Update container with invalid name
    Container badContainer = new ContainerBuilder(refContainerId, "Unknown container", ContainerStatus.ACTIVE, "foo", refAccountId).build();
    try {
        accountService.updateContainers(refAccountName, Collections.singleton(badContainer));
        fail("should fail because container is not found");
    } catch (AccountServiceException e) {
        assertEquals("Mismatch in error code", AccountServiceErrorCode.NotFound, e.getErrorCode());
    }
    // 3. Update container with valid name and wrong id
    badContainer = new ContainerBuilder(refContainer).setId((short) (refContainerId + 7)).build();
    try {
        accountService.updateContainers(refAccountName, Collections.singleton(badContainer));
        fail("should fail due to wrong id");
    } catch (AccountServiceException e) {
        assertEquals("Mismatch in error code", AccountServiceErrorCode.ResourceConflict, e.getErrorCode());
    }
}
Also used : Container(com.github.ambry.account.Container) Test(org.junit.Test)

Example 55 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class AccountDao method getContainerById.

/**
 * Gets container by its Id and parent account Id.
 * @param accountId the id for the parent account.
 * @param containerId the id of the container.
 * @return {@link Container} if found in mysql db or {@code null} if it doesn't exist.
 * @throws SQLException
 */
public synchronized Container getContainerById(int accountId, int containerId) throws SQLException {
    long startTimeMs = System.currentTimeMillis();
    ResultSet rs = null;
    try {
        PreparedStatement getContainerByIdStatement = dataAccessor.getPreparedStatement(getContainerByIdSql, false);
        getContainerByIdStatement.setInt(1, accountId);
        getContainerByIdStatement.setInt(2, containerId);
        rs = getContainerByIdStatement.executeQuery();
        List<Container> containers = convertContainersResultSet(rs);
        dataAccessor.onSuccess(Read, System.currentTimeMillis() - startTimeMs);
        return containers.isEmpty() ? null : containers.get(0);
    } catch (SQLException e) {
        dataAccessor.onException(e, Read);
        throw e;
    } finally {
        closeQuietly(rs);
    }
}
Also used : Container(com.github.ambry.account.Container) SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement)

Aggregations

Container (com.github.ambry.account.Container)119 Account (com.github.ambry.account.Account)88 Test (org.junit.Test)61 ArrayList (java.util.ArrayList)30 RestServiceException (com.github.ambry.rest.RestServiceException)20 ContainerBuilder (com.github.ambry.account.ContainerBuilder)17 JSONObject (org.json.JSONObject)17 VerifiableProperties (com.github.ambry.config.VerifiableProperties)16 HashSet (java.util.HashSet)15 HashMap (java.util.HashMap)14 Properties (java.util.Properties)14 AccountBuilder (com.github.ambry.account.AccountBuilder)13 RestRequest (com.github.ambry.rest.RestRequest)13 ByteBuffer (java.nio.ByteBuffer)13 Map (java.util.Map)13 MetricRegistry (com.codahale.metrics.MetricRegistry)12 TestUtils (com.github.ambry.utils.TestUtils)12 Collections (java.util.Collections)12 List (java.util.List)12 Assert (org.junit.Assert)12