赵志浩
Published on 2022-11-20 / 25 Visits
1
0

Cat客户端代码

基本上是如下的代码块就可以确认Cat的客户端的逻辑了:

一、Cat.newTransaction() 时,

1、将调用DefaultMessageProducer的newTransaction(String type, String name)方法。

I、初次调用时,将会调用DefaultMessageManager类中的setup()方法,目的是初始化Context ctx;类。ctx = new Context("Unknown", m_hostName, "");ctx = new Context(m_domain.getId(), m_hostName, m_domain.getIp());

II、Context类中包含 MessageTree m_tree; Stack<Transaction> m_stack; 属性,首次初始化该类,便是初始化对应的m_tree = new DefaultMessageTree(); m_tree.setDomain(domain); 等。以及初始化m_stack.m_stack = new Stack<Transaction>();

III、MessageTree类的数据结构,包含了对应的:private Message m_message; 以及一些其他的private String m_messageId;等等属性。

IIII、此时我们初始化了对应的Context ctx后,便将并将当前的ctx类,放入到当前DefaultMessageManager的ThreadLocal属性中。m_context.set(ctx);    private ThreadLocal<DefaultMessageManager.Context> m_context = new ThreadLocal<Context>()

OK,此时我们首次初始化的环节基本做完了。

2、setup()方法执行完成后,则 new 对应的Transaction(),DefaultTransaction transaction = new DefaultTransaction(type, name, m_manager);

new DefaultTransaction()时,则传递了对应的DefaultMessageManager给到Transaction中。

DefaultTransaction类的主要属性是:private List<Message> m_children; private MessageManager m_manager;等

3、执行m_manager.start(transaction, false); 执行 m_manage.start()方法时,会执行ctx.start()方法,执行ctx.start()方法时的具体逻辑为,

判断该context中的m_stack是否为空,为空则表示当前是首次添加Transaction到context中,则此时将context中的m_tree.setMessage(transaction);

并将改context中的m_stack.push(transaction); 也就是将Transaction添加到Context的message属性中,且添加到对应的m_stack中。

II、那么当第二次newTransaction并执行start()方法时,由于此时m_stack已经不在为空,所以此时只需要将transaction添加到m_stack中即可。而不再赋值message属性为当前的transaction。

只有首次添加的Transaction到context中时,才会添加到context的message属性中。

除了将对应的Transaction添加到堆栈外,还会判断该if (!(transaction instanceof ForkedTransaction))  transaction 是否 instanceof ForkedTransaction,如果是,则将该Transaction也添加到对应上一个Transaction的child当中。

这块逻辑debug后可知:当你实例化第二个Transaction时,也就是DefaultTransaction时,此时instanceof ForkedTransaction是为true的。也就是所有的Transaction最终都会添加到父的Transaction的child当中。最终第一个Transaction的child就是一堆大的子集。

此时DefaultMessageProducer中new Transaction()并实例化完成,则此时return出来即可。

二、当我们执行Cat.logEvent()时。

1、调用DefaultMessageProducer的logEvent()方法。主要做两件事,1、Event event = newEvent(type, name); 2、event.addData(nameValuePairs);event.setStatus(status); event.complete(); 主要是执行complete()

I、判断m_manager.hasContext()是否初始过,未初始化则执行:m_manager.hasContext。已经初始化过则不在初始化Context。

II、DefaultEvent event = new DefaultEvent(type, name, m_manager);

实例化完对应的DefaultEvent后,则执行event.complete()方法。

2、event.complete()。主要对应代码是执行:m_manager.add(this);

也就是将该DefaultEvent自身,添加到对应的m_manage.add()当中。

I、查看该m_manage.add()的代码,此处代码主要的操作是,Transaction parent = m_stack.peek(); 从当前context的m_stack属性中,peek()查看堆栈顶部的对象,但不从堆栈中移除它。

II、得到当前堆栈顶部的Transaction对象后,则将该Event添加到该Transaction的m_children属性当中。private List<Message> m_children;

此时Event便是成为了当前该Transaction的一个m_children的子集。

三、那么当我们调用Transaction的compleate()方法时,主要执行的操作是什么呢?

1、执行Transaction.compleate()方法时,主要操作是,Transaction current = m_stack.pop(); 从当前context的stack堆栈中移除顶部这个Transaction并做一些check操作。

2、如果该Transaction.compleate()时,该Transaction本身就是堆栈的最后一个栈帧,则此时表示当前该线程ThreadLocal的Context中的MessageTree m_tree;中的Message(Transaction)

已经是在执行最终的Transaction的complete()提交了。

也就是该Context任务也就是完成了。也可以说是该线程本批次的整个的Context都已经完成了。此时则需要进行提交即可了。

将该Context中的MessageTree m_tree属性,执行一下copy。MessageTree tree = m_tree.copy(); 然后, manager.flush(tree, true);

manage.flush()主要逻辑是:MessageSender sender = m_transportManager.getSender();   然后 sender.send(tree); 。也就是通过TCPSocketSend将该MessageTree发送出去即可。

发送完成后,则一系列操作完成,此时m_context.remove(); 也就是清除当前该DefaultMessageManager中private ThreadLocal<DefaultMessageManager.Context> m_context = new ThreadLocal<Context>()

m_context所对应的context的引用关系。此时一整个链路算是上传完成。

简单总结一下对应的操作则是:

Context中包含了MessageTree 和 Stack<Transaction> 

MessageTree中的属性message主要对应的是初始的第一个Transaction。Transaction中包含了List<Message> m_children。

在对应的Transaction中的Cat.logevent等操作。全部都会记录到对应的Transaction下的m_children属性中。

而如果是实例化了多个Transaction,则多个Transaction都是在对应的Context中的Stack中存储的,Event和Transaction的关联是通过从Stack中取最上层的堆栈中Transaction来进行的绑定。

当一个Transaction执行完成调用complete后,则会移除该Transaction在Stack中的位置。

当该Transaction移出后,Stack中为空了,表示当前是Stack中的最后一个Transaction,则此时表明当前整个线程对应的执行是完毕了。则此时提交该MessageTree,flush 刷新并发送到远端。主要是发送该MessageTree下的message(Transaction)。

flush后,则ThreadLocal<Context> m_context = new ThreadLocal<Context>() m_context.remove() ,清除对应的context的引用。

原创声明:作者:赵志浩、个人博客地址:https://zhaozhihao.com

原创声明:笔名:陈咬金、 博客园地址:https://www.cnblogs.com/zh94/


Comment