提交 b7390e8e 编写于 作者: S Serge Rider

QM collector model refactoring. Unique session ids.

上级 8161abda
......@@ -17,6 +17,7 @@
package org.jkiss.dbeaver.runtime.qm;
import org.eclipse.core.runtime.IStatus;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceListener;
......@@ -84,7 +85,7 @@ public class QMLogFileWriter implements QMMetaListener, DBPPreferenceListener {
}
@Override
public synchronized void metaInfoChanged(List<QMMetaEvent> events)
public synchronized void metaInfoChanged(@NotNull List<QMMetaEvent> events)
{
if (!enabled || logWriter == null) {
return;
......
......@@ -30,6 +30,7 @@ import org.jkiss.dbeaver.model.qm.QMMetaListener;
import org.jkiss.dbeaver.model.qm.meta.*;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.utils.LongKeyMap;
import java.util.*;
......@@ -44,7 +45,8 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
private static final int MAX_HISTORY_EVENTS = 1000;
// Session map
private Map<String, QMMSessionInfo> sessionMap = new HashMap<>();
private LongKeyMap<QMMSessionInfo> sessionMap = new LongKeyMap<>();
private List<Long> closedSessions = new ArrayList<>();
// External listeners
private List<QMMetaListener> listeners = new ArrayList<>();
......@@ -94,10 +96,6 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
return "Meta info collector";
}
private String makeContextId(DBCExecutionContext context) {
return context.getDataSource().getContainer().getId() + ":" + context.getContextName();
}
public synchronized void addListener(QMMetaListener listener)
{
listeners.add(listener);
......@@ -138,10 +136,9 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
public QMMSessionInfo getSessionInfo(DBCExecutionContext context)
{
String contextId = makeContextId(context);
QMMSessionInfo sessionInfo = sessionMap.get(contextId);
QMMSessionInfo sessionInfo = sessionMap.get(context.getContextId());
if (sessionInfo == null) {
log.warn("Can't find sessionInfo meta information: " + contextId);
log.debug("Can't find sessionInfo meta information: " + context.getContextId() + " (" + context.getContextName() + ")");
}
return sessionInfo;
}
......@@ -156,21 +153,18 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
@Override
public synchronized void handleContextOpen(@NotNull DBCExecutionContext context, boolean transactional)
{
String contextId = makeContextId(context);
final long contextId = context.getContextId();
if (sessionMap.containsKey(contextId)) {
log.debug("Duplicate session '" + contextId + "' open");
log.warn("Duplicate session '" + contextId + "' open");
}
QMMSessionInfo session = new QMMSessionInfo(
context,
transactional,
sessionMap.get(contextId));
transactional);
sessionMap.put(contextId, session);
if (session.getPrevious() != null && !session.getPrevious().isClosed()) {
// Is it really a problem? Maybe better to remove warning at all
// Happens when we have open connection and perform another connection test
log.debug("Previous '" + contextId + "' session wasn't closed");
}
// Remove from closed sessions (in case of re-opened connection)
closedSessions.remove(contextId);
// Notify
fireMetaEvent(session, QMMetaEvent.Action.BEGIN);
}
......@@ -182,9 +176,7 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
session.close();
fireMetaEvent(session, QMMetaEvent.Action.END);
}
// Remove closed context from map (otherwise we'll be out of memory eventually)
String contextId = makeContextId(context);
sessionMap.remove(contextId);
closedSessions.add(context.getContextId());
}
@Override
......@@ -329,6 +321,13 @@ public class QMMCollectorImpl extends DefaultExecutionHandler implements QMMColl
size));
}
}
// Cleanup closed sessions
synchronized (QMMCollectorImpl.this) {
for (Long sessionId : closedSessions) {
sessionMap.remove(sessionId);
}
closedSessions.clear();
}
if (isRunning()) {
this.schedule(EVENT_DISPATCH_PERIOD);
}
......
......@@ -44,6 +44,7 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.CoreCommands;
import org.jkiss.dbeaver.core.CoreMessages;
......@@ -598,7 +599,7 @@ public class QueryLogViewer extends Viewer implements QMMetaListener, DBPPrefere
}
@Override
public void metaInfoChanged(final java.util.List<QMMetaEvent> events) {
public void metaInfoChanged(@NotNull final java.util.List<QMMetaEvent> events) {
if (DBeaverCore.isClosing()) {
return;
}
......
......@@ -26,6 +26,7 @@ import org.jkiss.dbeaver.model.DBPDataSourceInfo;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.exec.DBCExecutionPurpose;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.impl.AbstractExecutionContext;
import org.jkiss.dbeaver.model.meta.Association;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
......@@ -43,15 +44,17 @@ import java.util.Collections;
*/
public class WMIDataSource implements DBPDataSource, DBCExecutionContext, SQLDataSource, IAdaptable//, DBSObjectContainer, DBSObjectSelector
{
private DBPDataSourceContainer container;
private final DBPDataSourceContainer container;
private WMINamespace rootNamespace;
private SQLDialect dialect;
private final SQLDialect dialect;
private final long id;
public WMIDataSource(DBPDataSourceContainer container)
throws DBException
{
this.container = container;
this.dialect = new WMIDialect();
this.id = AbstractExecutionContext.generateContextId();
}
@NotNull
......@@ -80,6 +83,11 @@ public class WMIDataSource implements DBPDataSource, DBCExecutionContext, SQLDat
return new DBCExecutionContext[] { this };
}
@Override
public long getContextId() {
return this.id;
}
@NotNull
@Override
public String getContextName() {
......
......@@ -38,6 +38,14 @@ public interface DBCExecutionContext extends DBPObject,DBPCloseableObject
ERROR
}
/**
* Unique context ID. Generated in the moment of context creation and never changes during context lifetime.
*/
long getContextId();
/**
* Context name. Like MAin, Metadata, Script X, etc.
*/
@NotNull
String getContextName();
......
......@@ -37,13 +37,26 @@ public abstract class AbstractExecutionContext<DATASOURCE extends DBPDataSource>
{
private static final Log log = Log.getLog(AbstractExecutionContext.class);
private static long idSequence = 0;
@NotNull
protected final DATASOURCE dataSource;
protected final String purpose;
protected final long id;
public AbstractExecutionContext(@NotNull DATASOURCE dataSource, String purpose) {
this.dataSource = dataSource;
this.purpose = purpose;
this.id = generateContextId();
}
public static synchronized long generateContextId() {
return idSequence++;
}
@Override
public long getContextId() {
return this.id;
}
@NotNull
......
......@@ -17,6 +17,8 @@
package org.jkiss.dbeaver.model.qm;
import org.jkiss.code.NotNull;
import java.util.List;
/**
......@@ -24,6 +26,11 @@ import java.util.List;
*/
public interface QMMetaListener {
void metaInfoChanged(List<QMMetaEvent> events);
/**
* Notifies listeners about new events.
* Implementation must process all events in sync mode.
* QM collector will clean all closed objects after listeners notification.
*/
void metaInfoChanged(@NotNull List<QMMetaEvent> events);
}
......@@ -34,13 +34,12 @@ public class QMMSessionInfo extends QMMObject {
private SQLDialect sqlDialect;
private boolean transactional;
private QMMSessionInfo previous;
private QMMStatementInfo statementStack;
private QMMStatementExecuteInfo executionStack;
private QMMTransactionInfo transaction;
//private Throwable stack;
public QMMSessionInfo(DBCExecutionContext context, boolean transactional, QMMSessionInfo previous)
public QMMSessionInfo(DBCExecutionContext context, boolean transactional)
{
this.containerId = context.getDataSource().getContainer().getId();
this.containerName = context.getDataSource().getContainer().getName();
......@@ -50,7 +49,6 @@ public class QMMSessionInfo extends QMMObject {
if (context.getDataSource() instanceof SQLDataSource) {
this.sqlDialect = ((SQLDataSource) context.getDataSource()).getSQLDialect();
}
this.previous = previous;
this.transactional = transactional;
if (transactional) {
this.transaction = new QMMTransactionInfo(this, null);
......@@ -244,11 +242,6 @@ public class QMMSessionInfo extends QMMObject {
return transaction;
}
public QMMSessionInfo getPrevious()
{
return previous;
}
public boolean isTransactional()
{
return transactional;
......@@ -257,7 +250,7 @@ public class QMMSessionInfo extends QMMObject {
@Override
public String toString()
{
return "SESSION " + containerId;
return "SESSION " + containerName + " [" + contextName + "]";
}
public SQLDialect getSQLDialect() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册