use of com.google.common.collect.ListMultimap in project android by JetBrains.
the class ProjectResourceRepositoryTest method testInvalidateIds.
// Ensure that we invalidate the id cache when the file is rescanned but ids don't change
// (this was broken)
public void testInvalidateIds() {
// Like testOverlayUpdates1, but rather than testing changes to layout resources (file-based resource)
// perform document edits in value-documents
VirtualFile layoutFile = myFixture.copyFileToProject(LAYOUT, "res/layout/layout1.xml");
VirtualFile res1 = myFixture.copyFileToProject(VALUES, "res/values/values.xml").getParent().getParent();
VirtualFile res2 = myFixture.copyFileToProject(VALUES_OVERLAY1, "res2/values/values.xml").getParent().getParent();
VirtualFile res3 = myFixture.copyFileToProject(VALUES_OVERLAY2, "res3/values/nameDoesNotMatter.xml").getParent().getParent();
myFixture.copyFileToProject(VALUES_OVERLAY2_NO, "res3/values-no/values.xml");
assertNotSame(res1, res2);
assertNotSame(res1, res3);
assertNotSame(res2, res3);
// Just need an empty repository to make it a real module -set-; otherwise with a single
// module we just get a module repository, not a module set repository
LocalResourceRepository other = new LocalResourceRepository("unit test") {
@NonNull
@Override
protected Map<ResourceType, ListMultimap<String, ResourceItem>> getMap() {
return Collections.emptyMap();
}
@Nullable
@Override
protected ListMultimap<String, ResourceItem> getMap(ResourceType type, boolean create) {
return ArrayListMultimap.create();
}
@NotNull
@Override
protected Set<VirtualFile> computeResourceDirs() {
return ImmutableSet.of();
}
};
ModuleResourceRepository module = ModuleResourceRepository.createForTest(myFacet, Arrays.asList(res1, res2, res3));
final ProjectResourceRepository resources = ProjectResourceRepository.createForTest(myFacet, Arrays.asList(module, other));
PsiFile layoutPsiFile = PsiManager.getInstance(getProject()).findFile(layoutFile);
assertNotNull(layoutPsiFile);
assertTrue(resources.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
final ResourceItem item = getFirstItem(resources, ResourceType.ID, "btn_title_refresh");
final long generation = resources.getModificationCount();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(layoutPsiFile);
assertNotNull(document);
WriteCommandAction.runWriteCommandAction(null, () -> {
String string = "<ImageView style=\"@style/TitleBarSeparator\" />";
int offset = document.getText().indexOf(string);
document.deleteString(offset, offset + string.length());
documentManager.commitDocument(document);
});
assertTrue(resources.isScanPending(layoutPsiFile));
ApplicationManager.getApplication().invokeLater(() -> {
assertTrue(generation < resources.getModificationCount());
// Should still be defined:
assertTrue(resources.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
ResourceItem newItem = getFirstItem(resources, ResourceType.ID, "btn_title_refresh");
assertNotNull(newItem.getSource());
// However, should be a different item
assertNotSame(item, newItem);
});
UIUtil.dispatchAllInvocationEvents();
}
use of com.google.common.collect.ListMultimap in project hbase by apache.
the class AccessController method initialize.
void initialize(RegionCoprocessorEnvironment e) throws IOException {
final Region region = e.getRegion();
Configuration conf = e.getConfiguration();
Map<byte[], ListMultimap<String, TablePermission>> tables = AccessControlLists.loadAll(region);
// znode for that table.
for (Map.Entry<byte[], ListMultimap<String, TablePermission>> t : tables.entrySet()) {
byte[] entry = t.getKey();
ListMultimap<String, TablePermission> perms = t.getValue();
byte[] serialized = AccessControlLists.writePermissionsAsBytes(perms, conf);
this.authManager.getZKPermissionWatcher().writeToZookeeper(entry, serialized);
}
initialized = true;
}
use of com.google.common.collect.ListMultimap in project hbase by apache.
the class TestTablePermissions method testBasicWrite.
@Test
public void testBasicWrite() throws Exception {
Configuration conf = UTIL.getConfiguration();
try (Connection connection = ConnectionFactory.createConnection(conf)) {
// add some permissions
addUserPermission(conf, new UserPermission(Bytes.toBytes("george"), TEST_TABLE, null, (byte[]) null, UserPermission.Action.READ, UserPermission.Action.WRITE), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
addUserPermission(conf, new UserPermission(Bytes.toBytes("hubert"), TEST_TABLE, null, (byte[]) null, UserPermission.Action.READ), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
addUserPermission(conf, new UserPermission(Bytes.toBytes("humphrey"), TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER, UserPermission.Action.READ), connection.getTable(AccessControlLists.ACL_TABLE_NAME));
}
// retrieve the same
ListMultimap<String, TablePermission> perms = AccessControlLists.getTablePermissions(conf, TEST_TABLE);
List<TablePermission> userPerms = perms.get("george");
assertNotNull("Should have permissions for george", userPerms);
assertEquals("Should have 1 permission for george", 1, userPerms.size());
TablePermission permission = userPerms.get(0);
assertEquals("Permission should be for " + TEST_TABLE, TEST_TABLE, permission.getTableName());
assertNull("Column family should be empty", permission.getFamily());
// check actions
assertNotNull(permission.getActions());
assertEquals(2, permission.getActions().length);
List<TablePermission.Action> actions = Arrays.asList(permission.getActions());
assertTrue(actions.contains(TablePermission.Action.READ));
assertTrue(actions.contains(TablePermission.Action.WRITE));
userPerms = perms.get("hubert");
assertNotNull("Should have permissions for hubert", userPerms);
assertEquals("Should have 1 permission for hubert", 1, userPerms.size());
permission = userPerms.get(0);
assertEquals("Permission should be for " + TEST_TABLE, TEST_TABLE, permission.getTableName());
assertNull("Column family should be empty", permission.getFamily());
// check actions
assertNotNull(permission.getActions());
assertEquals(1, permission.getActions().length);
actions = Arrays.asList(permission.getActions());
assertTrue(actions.contains(TablePermission.Action.READ));
assertFalse(actions.contains(TablePermission.Action.WRITE));
userPerms = perms.get("humphrey");
assertNotNull("Should have permissions for humphrey", userPerms);
assertEquals("Should have 1 permission for humphrey", 1, userPerms.size());
permission = userPerms.get(0);
assertEquals("Permission should be for " + TEST_TABLE, TEST_TABLE, permission.getTableName());
assertTrue("Permission should be for family " + TEST_FAMILY, Bytes.equals(TEST_FAMILY, permission.getFamily()));
assertTrue("Permission should be for qualifier " + TEST_QUALIFIER, Bytes.equals(TEST_QUALIFIER, permission.getQualifier()));
// check actions
assertNotNull(permission.getActions());
assertEquals(1, permission.getActions().length);
actions = Arrays.asList(permission.getActions());
assertTrue(actions.contains(TablePermission.Action.READ));
assertFalse(actions.contains(TablePermission.Action.WRITE));
// table 2 permissions
try (Connection connection = ConnectionFactory.createConnection(conf);
Table table = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) {
AccessControlLists.addUserPermission(conf, new UserPermission(Bytes.toBytes("hubert"), TEST_TABLE2, null, (byte[]) null, TablePermission.Action.READ, TablePermission.Action.WRITE), table);
}
// check full load
Map<byte[], ListMultimap<String, TablePermission>> allPerms = AccessControlLists.loadAll(conf);
assertEquals("Full permission map should have entries for both test tables", 2, allPerms.size());
userPerms = allPerms.get(TEST_TABLE.getName()).get("hubert");
assertNotNull(userPerms);
assertEquals(1, userPerms.size());
permission = userPerms.get(0);
assertEquals(TEST_TABLE, permission.getTableName());
assertEquals(1, permission.getActions().length);
assertEquals(TablePermission.Action.READ, permission.getActions()[0]);
userPerms = allPerms.get(TEST_TABLE2.getName()).get("hubert");
assertNotNull(userPerms);
assertEquals(1, userPerms.size());
permission = userPerms.get(0);
assertEquals(TEST_TABLE2, permission.getTableName());
assertEquals(2, permission.getActions().length);
actions = Arrays.asList(permission.getActions());
assertTrue(actions.contains(TablePermission.Action.READ));
assertTrue(actions.contains(TablePermission.Action.WRITE));
}
use of com.google.common.collect.ListMultimap in project guice by google.
the class SingletonScope method scope.
/**
* Provides singleton scope with the following properties: - creates no more than one instance per
* Key as a creator is used no more than once, - result is cached and returned quickly on
* subsequent calls, - exception in a creator is not treated as instance creation and is not
* cached, - creates singletons in parallel whenever possible, - waits for dependent singletons to
* be created even across threads and when dependencies are shared as long as no circular
* dependencies are detected, - returns circular proxy only when circular dependencies are
* detected, - aside from that, blocking synchronization is only used for proxy creation and
* initialization,
*
* @see CycleDetectingLockFactory
*/
@Override
public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
/**
* Locking strategy: - volatile instance: double-checked locking for quick exit when scope is
* initialized, - constructionContext: manipulations with proxies list or instance
* initialization - creationLock: singleton instance creation, -- allows to guarantee only one
* instance per singleton, -- special type of a lock, that prevents potential deadlocks, --
* guards constructionContext for all operations except proxy creation
*/
return new Provider<T>() {
/**
* The lazily initialized singleton instance. Once set, this will either have type T or will
* be equal to NULL. Would never be reset to null.
*/
volatile Object instance;
/**
* Circular proxies are used when potential deadlocks are detected. Guarded by itself.
* ConstructionContext is not thread-safe, so each call should be synchronized.
*/
final ConstructionContext<T> constructionContext = new ConstructionContext<T>();
/** For each binding there is a separate lock that we hold during object creation. */
final CycleDetectingLock<Key<?>> creationLock = cycleDetectingLockFactory.create(key);
/**
* The singleton provider needs a reference back to the injector, in order to get ahold of
* InternalContext during instantiation.
*/
final InjectorImpl /* @Nullable */
injector;
{
// If we are getting called by Scoping
if (creator instanceof ProviderToInternalFactoryAdapter) {
injector = ((ProviderToInternalFactoryAdapter) creator).getInjector();
} else {
injector = null;
}
}
@SuppressWarnings("DoubleCheckedLocking")
@Override
public T get() {
// cache volatile variable for the usual case of already initialized object
final Object initialInstance = instance;
if (initialInstance == null) {
// instance is not initialized yet
// first, store the current InternalContext in a map, so that if there is a circular
// dependency error, we can use the InternalContext objects to create a complete
// error message.
// Handle injector being null, which can happen when users call Scoping.scope themselves
final InternalContext context = injector == null ? null : injector.getLocalContext();
// acquire lock for current binding to initialize an instance
final ListMultimap<Thread, Key<?>> locksCycle = creationLock.lockOrDetectPotentialLocksCycle();
if (locksCycle.isEmpty()) {
// this thread now owns creation of an instance
try {
// intentionally reread volatile variable to prevent double initialization
if (instance == null) {
// creator throwing an exception can cause circular proxies created in
// different thread to never be resolved, just a warning
T provided = creator.get();
Object providedNotNull = provided == null ? NULL : provided;
// scope called recursively can initialize instance as a side effect
if (instance == null) {
// detection within the same thread; they are not real instances to cache
if (Scopes.isCircularProxy(provided)) {
return provided;
}
synchronized (constructionContext) {
// guarantee thread-safety for instance and proxies initialization
instance = providedNotNull;
constructionContext.setProxyDelegates(provided);
}
} else {
// safety assert in case instance was initialized
Preconditions.checkState(instance == providedNotNull, "Singleton is called recursively returning different results");
}
}
} catch (RuntimeException e) {
// this helps to prevent potential memory leaks in circular proxies list
synchronized (constructionContext) {
constructionContext.finishConstruction();
}
throw e;
} finally {
// always release our creation lock, even on failures
creationLock.unlock();
}
} else {
if (context == null) {
throw new ProvisionException(ImmutableList.of(createCycleDependenciesMessage(locksCycle, null)));
}
// potential deadlock detected, creation lock is not taken by this thread
synchronized (constructionContext) {
// guarantee thread-safety for instance and proxies initialization
if (instance == null) {
// creating a proxy to satisfy circular dependency across several threads
Dependency<?> dependency = Preconditions.checkNotNull(context.getDependency(), "internalContext.getDependency()");
Class<?> rawType = dependency.getKey().getTypeLiteral().getRawType();
try {
@SuppressWarnings("unchecked") T proxy = (T) constructionContext.createProxy(new Errors(), context.getInjectorOptions(), rawType);
return proxy;
} catch (ErrorsException e) {
// best effort to create a rich error message
Message proxyCreationError = Iterables.getOnlyElement(e.getErrors().getMessages());
Message cycleDependenciesMessage = createCycleDependenciesMessage(locksCycle, proxyCreationError);
// adding stack trace generated by us in addition to a standard one
throw new ProvisionException(ImmutableList.of(cycleDependenciesMessage, proxyCreationError));
}
}
}
}
// at this point we're sure that singleton was initialized,
// reread volatile variable to catch all corner cases
// caching volatile variable to minimize number of reads performed
final Object initializedInstance = instance;
Preconditions.checkState(initializedInstance != null, "Internal error: Singleton is not initialized contrary to our expectations");
@SuppressWarnings("unchecked") T initializedTypedInstance = (T) initializedInstance;
return initializedInstance == NULL ? null : initializedTypedInstance;
} else {
// singleton is already initialized and local cache can be used
@SuppressWarnings("unchecked") T typedInitialIntance = (T) initialInstance;
return initialInstance == NULL ? null : typedInitialIntance;
}
}
/**
* Helper method to create beautiful and rich error descriptions. Best effort and slow. Tries
* its best to provide dependency information from injectors currently available in a global
* internal context.
*
* <p>The main thing being done is creating a list of Dependencies involved into lock cycle
* across all the threads involved. This is a structure we're creating:
*
* <pre>
* { Current Thread, C.class, B.class, Other Thread, B.class, C.class, Current Thread }
* To be inserted in the beginning by Guice: { A.class, B.class, C.class }
* </pre>
*
* When we're calling Guice to create A and it fails in the deadlock while trying to create C,
* which is being created by another thread, which waits for B. List would be reversed before
* printing it to the end user.
*/
private Message createCycleDependenciesMessage(ListMultimap<Thread, Key<?>> locksCycle, /* @Nullable */
Message proxyCreationError) {
// this is the main thing that we'll show in an error message,
// current thread is populate by Guice
StringBuilder sb = new StringBuilder();
Formatter fmt = new Formatter(sb);
fmt.format("Encountered circular dependency spanning several threads.");
if (proxyCreationError != null) {
fmt.format(" %s", proxyCreationError.getMessage());
}
fmt.format("%n");
for (Thread lockedThread : locksCycle.keySet()) {
List<Key<?>> lockedKeys = locksCycle.get(lockedThread);
fmt.format("%s is holding locks the following singletons in the cycle:%n", lockedThread);
for (Key<?> lockedKey : lockedKeys) {
fmt.format("%s%n", Errors.convert(lockedKey));
}
for (StackTraceElement traceElement : lockedThread.getStackTrace()) {
fmt.format("\tat %s%n", traceElement);
}
}
fmt.close();
return new Message(Thread.currentThread(), sb.toString());
}
@Override
public String toString() {
return String.format("%s[%s]", creator, Scopes.SINGLETON);
}
};
}
use of com.google.common.collect.ListMultimap in project MinecraftForge by MinecraftForge.
the class ForgeChunkManager method loadWorld.
static void loadWorld(World world) {
ArrayListMultimap<String, Ticket> newTickets = ArrayListMultimap.create();
tickets.put(world, newTickets);
forcedChunks.put(world, ImmutableSetMultimap.<ChunkPos, Ticket>of());
if (!(world instanceof WorldServer)) {
return;
}
if (dormantChunkCacheSize != 0) {
// only put into cache if we're using dormant chunk caching
dormantChunkCache.put(world, CacheBuilder.newBuilder().maximumSize(dormantChunkCacheSize).<Long, Chunk>build());
}
WorldServer worldServer = (WorldServer) world;
File chunkDir = worldServer.getChunkSaveLocation();
File chunkLoaderData = new File(chunkDir, "forcedchunks.dat");
if (chunkLoaderData.exists() && chunkLoaderData.isFile()) {
ArrayListMultimap<String, Ticket> loadedTickets = ArrayListMultimap.create();
Map<String, ListMultimap<String, Ticket>> playerLoadedTickets = Maps.newHashMap();
NBTTagCompound forcedChunkData;
try {
forcedChunkData = CompressedStreamTools.read(chunkLoaderData);
} catch (IOException e) {
FMLLog.log(Level.WARN, e, "Unable to read forced chunk data at %s - it will be ignored", chunkLoaderData.getAbsolutePath());
return;
}
NBTTagList ticketList = forcedChunkData.getTagList("TicketList", Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < ticketList.tagCount(); i++) {
NBTTagCompound ticketHolder = ticketList.getCompoundTagAt(i);
String modId = ticketHolder.getString("Owner");
boolean isPlayer = ForgeVersion.MOD_ID.equals(modId);
if (!isPlayer && !Loader.isModLoaded(modId)) {
FMLLog.warning("Found chunkloading data for mod %s which is currently not available or active - it will be removed from the world save", modId);
continue;
}
if (!isPlayer && !callbacks.containsKey(modId)) {
FMLLog.warning("The mod %s has registered persistent chunkloading data but doesn't seem to want to be called back with it - it will be removed from the world save", modId);
continue;
}
NBTTagList tickets = ticketHolder.getTagList("Tickets", Constants.NBT.TAG_COMPOUND);
for (int j = 0; j < tickets.tagCount(); j++) {
NBTTagCompound ticket = tickets.getCompoundTagAt(j);
modId = ticket.hasKey("ModId") ? ticket.getString("ModId") : modId;
Type type = Type.values()[ticket.getByte("Type")];
//byte ticketChunkDepth = ticket.getByte("ChunkListDepth");
Ticket tick = new Ticket(modId, type, world);
if (ticket.hasKey("ModData")) {
tick.modData = ticket.getCompoundTag("ModData");
}
if (ticket.hasKey("Player")) {
tick.player = ticket.getString("Player");
if (!playerLoadedTickets.containsKey(tick.modId)) {
playerLoadedTickets.put(modId, ArrayListMultimap.<String, Ticket>create());
}
playerLoadedTickets.get(tick.modId).put(tick.player, tick);
} else {
loadedTickets.put(modId, tick);
}
if (type == Type.ENTITY) {
tick.entityChunkX = ticket.getInteger("chunkX");
tick.entityChunkZ = ticket.getInteger("chunkZ");
UUID uuid = new UUID(ticket.getLong("PersistentIDMSB"), ticket.getLong("PersistentIDLSB"));
// add the ticket to the "pending entity" list
pendingEntities.put(uuid, tick);
}
}
}
for (Ticket tick : ImmutableSet.copyOf(pendingEntities.values())) {
if (tick.ticketType == Type.ENTITY && tick.entity == null) {
// force the world to load the entity's chunk
// the load will come back through the loadEntity method and attach the entity
// to the ticket
world.getChunkFromChunkCoords(tick.entityChunkX, tick.entityChunkZ);
}
}
for (Ticket tick : ImmutableSet.copyOf(pendingEntities.values())) {
if (tick.ticketType == Type.ENTITY && tick.entity == null) {
FMLLog.warning("Failed to load persistent chunkloading entity %s from store.", pendingEntities.inverse().get(tick));
loadedTickets.remove(tick.modId, tick);
}
}
pendingEntities.clear();
// send callbacks
for (String modId : loadedTickets.keySet()) {
LoadingCallback loadingCallback = callbacks.get(modId);
if (loadingCallback == null) {
continue;
}
int maxTicketLength = getMaxTicketLengthFor(modId);
List<Ticket> tickets = loadedTickets.get(modId);
if (loadingCallback instanceof OrderedLoadingCallback) {
OrderedLoadingCallback orderedLoadingCallback = (OrderedLoadingCallback) loadingCallback;
tickets = orderedLoadingCallback.ticketsLoaded(ImmutableList.copyOf(tickets), world, maxTicketLength);
}
if (tickets.size() > maxTicketLength) {
FMLLog.warning("The mod %s has too many open chunkloading tickets %d. Excess will be dropped", modId, tickets.size());
tickets.subList(maxTicketLength, tickets.size()).clear();
}
ForgeChunkManager.tickets.get(world).putAll(modId, tickets);
loadingCallback.ticketsLoaded(ImmutableList.copyOf(tickets), world);
}
for (String modId : playerLoadedTickets.keySet()) {
LoadingCallback loadingCallback = callbacks.get(modId);
if (loadingCallback == null) {
continue;
}
ListMultimap<String, Ticket> tickets = playerLoadedTickets.get(modId);
if (loadingCallback instanceof PlayerOrderedLoadingCallback) {
PlayerOrderedLoadingCallback orderedLoadingCallback = (PlayerOrderedLoadingCallback) loadingCallback;
tickets = orderedLoadingCallback.playerTicketsLoaded(ImmutableListMultimap.copyOf(tickets), world);
playerTickets.putAll(tickets);
}
ForgeChunkManager.tickets.get(world).putAll(ForgeVersion.MOD_ID, tickets.values());
loadingCallback.ticketsLoaded(ImmutableList.copyOf(tickets.values()), world);
}
}
}
Aggregations