In this paper, starting from purpose of moored floating column: segmentfault.com/blog/camile
This article is participating in “Java Theme Month – Java Development in Action”, see the activity link for details
In the Go language, there is a keyword called defer — it executes before the return function. There are similar utility classes in ZStack, so let’s take a look.
Demo code
private void handle(APICreateInstanceOfferingMsg msg) {
APICreateInstanceOfferingEvent evt = new APICreateInstanceOfferingEvent(msg.getId());
String type = msg.getType() == null ? UserVmInstanceOfferingFactory.type.toString() : msg.getType();
InstanceOfferingFactory f = getInstanceOfferingFactory(type);
InstanceOfferingVO vo = new InstanceOfferingVO();
if(msg.getResourceUuid() ! =null) {
vo.setUuid(msg.getResourceUuid());
} else {
vo.setUuid(Platform.getUuid());
}
HostAllocatorStrategyType allocType = msg.getAllocatorStrategy() == null ? HostAllocatorStrategyType
.valueOf(HostAllocatorConstant.LEAST_VM_PREFERRED_HOST_ALLOCATOR_STRATEGY_TYPE) : HostAllocatorStrategyType.valueOf(msg.getAllocatorStrategy());
vo.setAllocatorStrategy(allocType.toString());
vo.setName(msg.getName());
vo.setCpuNum(msg.getCpuNum());
vo.setCpuSpeed(msg.getCpuSpeed());
vo.setDescription(msg.getDescription());
vo.setState(InstanceOfferingState.Enabled);
vo.setMemorySize(msg.getMemorySize());
vo.setDuration(InstanceOfferingDuration.Permanent);
vo.setType(type);
InstanceOfferingInventory inv = new SQLBatchWithReturn<InstanceOfferingInventory>() {
@Override
@Deferred
protected InstanceOfferingInventory scripts(a) {
Defer.guard(() -> dbf.remove(vo));
InstanceOfferingInventory inv = f.createInstanceOffering(vo, msg);
acntMgr.createAccountResourceRef(msg.getSession().getAccountUuid(), vo.getUuid(), InstanceOfferingVO.class);
tagMgr.createTagsFromAPICreateMessage(msg, vo.getUuid(), InstanceOfferingVO.class.getSimpleName());
return inv;
}
}.execute();
evt.setInventory(inv);
bus.publish(evt);
logger.debug("Successfully added instance offering: " + printer.print(inv));
}
Copy the code
The ZStack ManageNode(MN for short) responds to a request to create a compute specification.
- Create a record in DB
- add
The current account
With theCalculation specification
The associated - Create the corresponding
The system labels
- Reply to the message and print a line of log
In this code, we can see that defer.guard (() -> dbf.remove(vo)) is done when logic 2 and 3 are executed; , which is executed when an exception occurs in the execution of the following logic, thus removing dirty data.
How to use
The way to use Defer is also simple: if you want to use it in a function, add an @Deferred Annotation to it, and then use it within that function.
There are two common uses:
- Defer.guard: Runable is executed when this function throws an exception.
- Deferred. Defer: Execute before this function returns. We can use it to release local locks.
In order to avoid awkward understanding for readers unfamiliar with ZStack, it is suggested to refer to its Case. Here, we will present a relatively simple Case:
public class TestDefer1 {
CLogger logger = Utils.getLogger(TestDefer1.class);
int count = 0;
@Before
public void setUp(a) throws Exception {}@Deferred
private void case1(a) {
count++;
Defer.guard(new Runnable() { // When an exception is caught, the anonymous Runable statement is executed
@Override
public void run(a) { count--; }});// Throw an exception
throw new CloudRuntimeException("Roll back count");
}
@Test(expected = CloudRuntimeException.class)
public void test(a) {
case1();
Assert.assertEquals(0, count); }}Copy the code
implementation
Defer’s library is very small. Its essence is encapsulated by AOP provided by Spring, ThreadLocal provided by Java, and a Stack data structure: A Stack data structure is deposited for the current thread executing the function, and each Runable filled in by Defer is put in, and its behavior is determined based on the function called to Defer.
The Runable put here comes from an action that is done with reflection when the system is started. Therefore, it does not affect the performance in use.