Cleanup temporary permission auditing process

This commit is contained in:
Luck 2018-02-16 12:35:25 +00:00
parent 4fda89d5c8
commit 0b5588a7dd
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
5 changed files with 41 additions and 14 deletions

View File

@ -679,24 +679,30 @@ public abstract class PermissionHolder {
* @return true if permissions had expired and were removed * @return true if permissions had expired and were removed
*/ */
public boolean auditTemporaryPermissions() { public boolean auditTemporaryPermissions() {
Set<Node> removed = new HashSet<>();
// audit temporary nodes first, but don't track ones which are removed // audit temporary nodes first, but don't track ones which are removed
// we don't call events for transient nodes // we don't call events for transient nodes
this.transientNodes.auditTemporaryNodes(null); boolean transientWork = this.transientNodes.auditTemporaryNodes(null);
ImmutableCollection<Node> before = getEnduringNodes().values(); ImmutableCollection<Node> before = getEnduringNodes().values();
Set<Node> removed = new HashSet<>();
if (!this.enduringNodes.auditTemporaryNodes(removed)) { boolean enduringWork = this.enduringNodes.auditTemporaryNodes(removed);
return false; if (enduringWork) {
// invalidate
invalidateCache();
// call event
ImmutableCollection<Node> after = getEnduringNodes().values();
for (Node r : removed) {
this.plugin.getEventFactory().handleNodeRemove(r, this, before, after);
}
} }
invalidateCache(); if (transientWork && !enduringWork) {
ImmutableCollection<Node> after = getEnduringNodes().values(); invalidateCache();
for (Node r : removed) {
this.plugin.getEventFactory().handleNodeRemove(r, this, before, after);
} }
return true;
return transientWork || enduringWork;
} }
private Optional<Node> getAlmostEquals(Node node, NodeMapType type) { private Optional<Node> getAlmostEquals(Node node, NodeMapType type) {

View File

@ -394,7 +394,7 @@ public abstract class ConfigurateDao extends AbstractDao {
save = true; save = true;
} }
if (save) { if (save | user.auditTemporaryPermissions()) {
saveUser(user); saveUser(user);
} }
} else { } else {

View File

@ -262,7 +262,7 @@ public class MongoDao extends AbstractDao {
save = true; save = true;
} }
if (save) { if (save | user.auditTemporaryPermissions()) {
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user)); c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user));
} }
} else { } else {

View File

@ -359,8 +359,8 @@ public class SqlDao extends AbstractDao {
Set<Node> nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet()); Set<Node> nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
user.setEnduringNodes(nodes); user.setEnduringNodes(nodes);
// Save back to the store if data was changed // Save back to the store if data they were given any defaults or had permissions expire
if (this.plugin.getUserManager().giveDefaultIfNeeded(user, false)) { if (this.plugin.getUserManager().giveDefaultIfNeeded(user, false) | user.auditTemporaryPermissions()) {
// This should be fine, as the lock will be acquired by the same thread. // This should be fine, as the lock will be acquired by the same thread.
saveUser(user); saveUser(user);
} }

View File

@ -26,6 +26,7 @@
package me.lucko.luckperms.common.tasks; package me.lucko.luckperms.common.tasks;
import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
@ -40,6 +41,9 @@ public class ExpireTemporaryTask implements Runnable {
public void run() { public void run() {
boolean groupChanges = false; boolean groupChanges = false;
for (Group group : this.plugin.getGroupManager().getAll().values()) { for (Group group : this.plugin.getGroupManager().getAll().values()) {
if (shouldSkip(group)) {
continue;
}
if (group.auditTemporaryPermissions()) { if (group.auditTemporaryPermissions()) {
this.plugin.getStorage().saveGroup(group); this.plugin.getStorage().saveGroup(group);
groupChanges = true; groupChanges = true;
@ -47,6 +51,9 @@ public class ExpireTemporaryTask implements Runnable {
} }
for (User user : this.plugin.getUserManager().getAll().values()) { for (User user : this.plugin.getUserManager().getAll().values()) {
if (shouldSkip(user)) {
continue;
}
if (user.auditTemporaryPermissions()) { if (user.auditTemporaryPermissions()) {
this.plugin.getStorage().saveUser(user); this.plugin.getStorage().saveUser(user);
if (!groupChanges) { if (!groupChanges) {
@ -59,4 +66,18 @@ public class ExpireTemporaryTask implements Runnable {
this.plugin.getUpdateTaskBuffer().request(); this.plugin.getUpdateTaskBuffer().request();
} }
} }
// return true if the holder's io lock is currently held, false otherwise
private static boolean shouldSkip(PermissionHolder holder) {
// if the holder is currently being manipulated by the storage dao,
// don't attempt to audit temporary permissions
if (!holder.getIoLock().tryLock()) {
// if #tryLock returns false, it means it's held by something else
return true;
}
// immediately release the lock & return false
holder.getIoLock().unlock();
return false;
}
} }