/******************************************************************************* * Copyright (c) 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.orion.server.tests.metastore; import static org.junit.Assert.fail; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore; import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStoreMigration; import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStoreUtil; import org.eclipse.orion.server.core.OrionConfiguration; import org.eclipse.orion.server.core.metastore.IMetaStore; import org.eclipse.orion.server.core.metastore.UserInfo; import org.json.JSONObject; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests to ensure that a SimpleMetaStore can be migrated successfully concurrently from separate threads. Only one thread can * do the migration, the others should be blocked. If one thread completes the migration the other threads should figure out that * migration no longer needs to be completed. See Bugzilla 451012. * * @author Anthony Hunter */ public class SimpleMetaStoreLiveMigrationConcurrencyTests extends AbstractSimpleMetaStoreMigrationTests { protected static int THREAD_COUNT = 4; public final static String USER_NAME = "concurrency"; protected Thread readUserThread(int number) { Runnable runnable = new Runnable() { public void run() { try { Logger logger = LoggerFactory.getLogger("org.eclipse.orion.server.config"); //$NON-NLS-1$ IMetaStore metaStore = getMetaStore(); // read the user UserInfo userInfo = metaStore.readUser(USER_NAME); if (userInfo == null) { logger.debug("Meta File Error, could not read user " + USER_NAME); } } catch (CoreException e) { Logger logger = LoggerFactory.getLogger("org.eclipse.orion.server.config"); //$NON-NLS-1$ logger.debug("Meta File Error, cannot read JSON file from disk, reason: " + e.getLocalizedMessage()); //$NON-NLS-1$ } } }; Thread thread = new Thread(runnable, "LiveMigrationConcurrencyThread-" + number); thread.start(); return thread; } protected IMetaStore getMetaStore() { // use the currently configured metastore if it is an SimpleMetaStore IMetaStore metaStore = null; try { metaStore = OrionConfiguration.getMetaStore(); } catch (NullPointerException e) { // expected when the workbench is not running } if (metaStore instanceof SimpleMetaStore) { return metaStore; } fail("Orion Server is not running with a Simple Metadata Storage."); return null; } /** * Tests creating properties in the metadata store in multiple concurrently running threads. * @throws Exception */ @Test public void testSimpleMetaStoreCreatePropertyConcurrency() throws Exception { // create the user on disk at the previous version of the metadata testUserId = USER_NAME; int version = SimpleMetaStoreMigration.VERSION7; String workspaceName = SimpleMetaStore.DEFAULT_WORKSPACE_NAME; // create metadata on disk String workspaceId = SimpleMetaStoreUtil.encodeWorkspaceId(testUserId, workspaceName); List<String> workspaceIds = new ArrayList<String>(); workspaceIds.add(workspaceId); List<String> projectNames = new ArrayList<String>(); for (int i = 0; i < 50; i++) { projectNames.add("Project" + i); } // create metadata on disk JSONObject newUserJSON = createUserJson(version, testUserId, workspaceIds); createUserMetaData(newUserJSON, testUserId); JSONObject newWorkspaceJSON = createWorkspaceJson(version, testUserId, workspaceName, projectNames); createWorkspaceMetaData(version, newWorkspaceJSON, testUserId, workspaceName); for (int i = 0; i < 50; i++) { File defaultContentLocation = getProjectDefaultContentLocation(testUserId, workspaceName, projectNames.get(i)); JSONObject newProjectJSON = createProjectJson(version, testUserId, workspaceName, projectNames.get(i), defaultContentLocation); createProjectMetaData(version, newProjectJSON, testUserId, workspaceName, projectNames.get(i)); } // add properties to the user in multiple threads Thread threads[] = new Thread[THREAD_COUNT]; for (int i = 0; i < threads.length; i++) { threads[i] = readUserThread(i); } for (int i = 0; i < threads.length; i++) { try { threads[i].join(); } catch (InterruptedException e) { // just continue } } } }