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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@
package me.lucko.luckperms.common.tasks;
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.plugin.LuckPermsPlugin;
@ -40,6 +41,9 @@ public class ExpireTemporaryTask implements Runnable {
public void run() {
boolean groupChanges = false;
for (Group group : this.plugin.getGroupManager().getAll().values()) {
if (shouldSkip(group)) {
continue;
}
if (group.auditTemporaryPermissions()) {
this.plugin.getStorage().saveGroup(group);
groupChanges = true;
@ -47,6 +51,9 @@ public class ExpireTemporaryTask implements Runnable {
}
for (User user : this.plugin.getUserManager().getAll().values()) {
if (shouldSkip(user)) {
continue;
}
if (user.auditTemporaryPermissions()) {
this.plugin.getStorage().saveUser(user);
if (!groupChanges) {
@ -59,4 +66,18 @@ public class ExpireTemporaryTask implements Runnable {
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;
}
}