Skip to content

Commit

Permalink
backup commit - reentrant aspectJ lock
Browse files Browse the repository at this point in the history
  • Loading branch information
zdenek-jonas committed Nov 8, 2023
1 parent ff961bb commit c0fc1d3
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 68 deletions.
7 changes: 5 additions & 2 deletions examples/spring-boot3-simple/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>

Expand Down
20 changes: 0 additions & 20 deletions examples/spring-boot3-simple/src/main/java/module-info.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,90 +9,69 @@
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
* #L%
*/

import org.eclipse.store.integrations.spring.boot.types.concurent.Lockable;
import org.eclipse.store.integrations.spring.boot.types.concurent.Read;
import org.eclipse.store.integrations.spring.boot.types.concurent.Write;
import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager;
import org.microstream.spring.boot.example.model.Root;
import org.springframework.stereotype.Component;

import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;


@Component
@Lockable("myGreatLock")
public class JokesStorage
{
private final EmbeddedStorageManager storageManager;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

public JokesStorage(EmbeddedStorageManager storageManager)
{
this.storageManager = storageManager;
}

public String oneJoke(Integer id) {
String joke;
lock.readLock().lock();
try
{
Root root = (Root) storageManager.root();
if (id > root.getJokes().size()) {
throw new IllegalArgumentException("No jokes with this id");
}
joke = root.getJokes().get(id);
ReentrantReadWriteLock myGreatLock = new ReentrantReadWriteLock();

}
finally
@Read
public String oneJoke(Integer id)
{
String joke;
Root root = (Root) storageManager.root();
if (id > root.getJokes().size())
{
lock.readLock().unlock();
throw new IllegalArgumentException("No jokes with this id");
}
joke = root.getJokes().get(id);
return joke;
}

@Read
public List<String> allJokes()
{
List<String> jokes = null;
lock.readLock().lock();
try
{
Root root = (Root) storageManager.root();
jokes = root.getJokes();
} finally
{
lock.readLock().unlock();
}
return jokes;
Root root = (Root) storageManager.root();
return root.getJokes();
}

@Write
public Integer addNewJoke(String joke)
{
lock.writeLock().lock();
Root root = (Root) storageManager.root();
try
{
root.getJokes().add(joke);
storageManager.storeRoot();
} finally
{
lock.writeLock().unlock();
}
root.getJokes().add(joke);
storageManager.storeRoot();
return root.getJokes().size();
}

@Write
public void addJokes(List<String> jokes)
{
lock.writeLock().lock();
Root root = (Root) storageManager.root();
try
{
root.getJokes().addAll(jokes);
} finally
{
lock.writeLock().unlock();
}
root.getJokes().addAll(jokes);
storageManager.store(root.getJokes());
}
}
8 changes: 7 additions & 1 deletion integrations/spring-boot3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.boot.version>3.0.12</org.springframework.boot.version>
<org.springframework.boot.version>3.1.5</org.springframework.boot.version>
</properties>

<dependencies>
Expand All @@ -42,6 +42,12 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${org.springframework.boot.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
4 changes: 3 additions & 1 deletion integrations/spring-boot3/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@
exports org.eclipse.store.integrations.spring.boot.types.configuration.sql;
exports org.eclipse.store.integrations.spring.boot.types;
exports org.eclipse.store.integrations.spring.boot.types.converter;
exports org.eclipse.store.integrations.spring.boot.types.concurent;

requires transitive spring.beans;
requires transitive spring.beans;
requires transitive spring.boot;
requires transitive spring.boot.autoconfigure;
requires transitive spring.context;
requires transitive spring.core;
requires transitive org.eclipse.store.storage.embedded.configuration;
requires transitive org.eclipse.serializer.configuration;
requires transitive org.aspectj.weaver;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.eclipse.store.integrations.spring.boot.types.concurent;

/*-
* #%L
* spring-boot3
* %%
* Copyright (C) 2023 MicroStream Software
* %%
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* #L%
*/

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Aspect
@Component
public class LockAspect
{
private final ReentrantReadWriteLock globalLock = new ReentrantReadWriteLock();

private final Map<String, ReentrantReadWriteLock> locks = new HashMap<>();

@Around("@annotation(org.eclipse.store.integrations.spring.boot.types.concurent.Read)")
public Object readOperation(ProceedingJoinPoint joinPoint) throws Throwable
{
ReentrantReadWriteLock lock = this.findLock(joinPoint);
lock.readLock().lock();
System.out.println("read lock");
Object proceed;
try
{
proceed = joinPoint.proceed();
} finally
{
System.out.println("read unlock");
lock.readLock().unlock();
}
return proceed;
}

@Around("@annotation(org.eclipse.store.integrations.spring.boot.types.concurent.Write)")
public Object writeOperation(ProceedingJoinPoint joinPoint) throws Throwable
{
ReentrantReadWriteLock lock = this.findLock(joinPoint);
lock.readLock().lock();

System.out.println("write lock");
Object proceed;
try
{
proceed = joinPoint.proceed();
} finally
{
System.out.println("write unlock");
lock.writeLock().unlock();
}
return proceed;
}

private ReentrantReadWriteLock findLock(ProceedingJoinPoint joinPoint)
{
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();

//method annotation first
ReentrantReadWriteLock finalLock;
Lockable annotation = method.getAnnotation(Lockable.class);
if (annotation != null)
{
String lockName = annotation.value();
finalLock = processLockByName(lockName);
} else
{
//class annotation second
Class<?> declaringClass = method.getDeclaringClass();
Lockable classAnnotation = declaringClass.getAnnotation(Lockable.class);
if (classAnnotation != null)
{
String classLockName = classAnnotation.value();
finalLock = processLockByName(classLockName);
} else
{
// no annotation, use global lock
finalLock = globalLock;
}
}
return finalLock;
}

private ReentrantReadWriteLock processLockByName(String lockName)
{
ReentrantReadWriteLock newLock;

if (locks.containsKey(lockName))
{
newLock = locks.get(lockName);
} else
{
newLock = new ReentrantReadWriteLock();
locks.put(lockName, newLock);
}
return newLock;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.eclipse.store.integrations.spring.boot.types.concurent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Lockable
{
String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.eclipse.store.integrations.spring.boot.types.concurent;

/*-
* #%L
* spring-boot3
* %%
* Copyright (C) 2023 MicroStream Software
* %%
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* #L%
*/

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Read
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.eclipse.store.integrations.spring.boot.types.concurent;

/*-
* #%L
* spring-boot3
* %%
* Copyright (C) 2023 MicroStream Software
* %%
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* #L%
*/

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Write
{
}
Loading

0 comments on commit c0fc1d3

Please sign in to comment.