/******************************************************************************* * Copyright (c) 2007, 2012 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.register; import java.util.concurrent.ExecutionException; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; import org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters; import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IMnemonic; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServices; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.osgi.framework.InvalidSyntaxException; import org.osgi.util.tracker.ServiceTracker; @ThreadSafeAndProhibitedFromDsfExecutor("fSession#getExecutor") public class SyncRegisterDataAccess { abstract public class RegistersServiceQuery<V, K extends IDMContext> extends Query<V> { final protected K fDmc; public RegistersServiceQuery(K dmc) { fDmc = dmc; } @Override protected void execute(final DataRequestMonitor<V> rm) { /* * We're in another dispatch, so we must guard against executor * shutdown again. */ final DsfSession session = DsfSession.getSession(fDmc.getSessionId()); if (session == null) { rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Debug session already shut down.", null)); //$NON-NLS-1$ rm.done(); return; } /* * Guard against a disposed service */ IRegisters service = getService(); if (service == null) { rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$ rm.done(); return; } doExecute(service, rm); } abstract protected void doExecute(IRegisters registersService, DataRequestMonitor<V> rm); } /** * The session that this data access operates in. */ private final DsfSession fSession; /** * Need to use the OSGi service tracker here (instead of DsfServiceTracker), * because we're accessing it in non-dispatch thread. DsfServiceTracker is * not thread-safe. */ @ThreadSafe private ServiceTracker fServiceTracker; public SyncRegisterDataAccess(DsfSession session) { fSession = session; } @ThreadSafe private synchronized IRegisters getService() { String serviceId = DsfServices.createServiceFilter(IRegisters.class, fSession.getId()); if (fServiceTracker == null) { try { fServiceTracker = new ServiceTracker(DsfUIPlugin.getBundleContext(), DsfUIPlugin .getBundleContext().createFilter(serviceId), null); fServiceTracker.open(); } catch (InvalidSyntaxException e) { return null; } } return (IRegisters) fServiceTracker.getService(); } @ThreadSafe public synchronized void dispose() { if (fServiceTracker != null) { fServiceTracker.close(); } } public class GetBitFieldValueQuery extends RegistersServiceQuery<IBitFieldDMData, IBitFieldDMContext> { public GetBitFieldValueQuery(IBitFieldDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IBitFieldDMData> rm) { service.getBitFieldData( fDmc, new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(getData()); rm.done(); } }); } } public IBitFieldDMContext getBitFieldDMC(Object element) { if (element instanceof IDMVMContext) { IDMContext dmc = ((IDMVMContext) element).getDMContext(); return DMContexts.getAncestorOfType(dmc, IBitFieldDMContext.class); } return null; } public IBitFieldDMData readBitField(Object element) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IBitFieldDMContext dmc = getBitFieldDMC(element); if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to request the value from service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetBitFieldValueQuery query = new GetBitFieldValueQuery(dmc); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public class SetBitFieldValueQuery extends RegistersServiceQuery<Object, IBitFieldDMContext> { private String fValue; private String fFormatId; public SetBitFieldValueQuery(IBitFieldDMContext dmc, String value, String formatId) { super(dmc); fValue = value; fFormatId = formatId; } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) { // Write the bit field using a string/format style. service.writeBitField( fDmc, fValue, fFormatId, new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(new Object()); rm.done(); } }); } } public void writeBitField(Object element, String value, String formatId) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IBitFieldDMContext dmc = getBitFieldDMC(element); if (dmc == null) return; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ SetBitFieldValueQuery query = new SetBitFieldValueQuery(dmc, value, formatId); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { /* * Return value is irrelevant, any error would come through with an * exception. */ query.get(); } catch (InterruptedException e) { assert false; } catch (ExecutionException e) { assert false; /* * View must be shutting down, no need to show erro dialog. */ } } public class SetBitFieldValueMnemonicQuery extends RegistersServiceQuery<Object, IBitFieldDMContext> { IMnemonic fMnemonic; public SetBitFieldValueMnemonicQuery(IBitFieldDMContext dmc, IMnemonic mnemonic) { super(dmc); fMnemonic = mnemonic; } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) { // Write the bit field using the mnemonic style. service.writeBitField( fDmc, fMnemonic, new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(new Object()); rm.done(); } }); } } public void writeBitField(Object element, IMnemonic mnemonic) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IBitFieldDMContext dmc = getBitFieldDMC(element); if (dmc == null) return; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ SetBitFieldValueMnemonicQuery query = new SetBitFieldValueMnemonicQuery(dmc, mnemonic); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { /* * Return value is irrelevant, any error would come through with an * exception. */ query.get(); } catch (InterruptedException e) { assert false; } catch (ExecutionException e) { /* * View must be shutting down, no need to show erro dialog. */ } } public IRegisterGroupDMContext getRegisterGroupDMC(Object element) { if (element instanceof IDMVMContext) { IDMContext dmc = ((IDMVMContext) element).getDMContext(); return DMContexts.getAncestorOfType(dmc, IRegisterGroupDMContext.class); } return null; } public IRegisterDMContext getRegisterDMC(Object element) { if (element instanceof IDMVMContext) { IDMContext dmc = ((IDMVMContext) element).getDMContext(); return DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class); } return null; } public IFormattedDataDMContext getFormattedDMC(Object element) { if (element instanceof IDMVMContext) { IDMContext dmc = ((IDMVMContext) element).getDMContext(); IRegisterDMContext regdmc = DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class); return DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class); } return null; } public class GetRegisterGroupValueQuery extends RegistersServiceQuery<IRegisterGroupDMData, IRegisterGroupDMContext> { public GetRegisterGroupValueQuery(IRegisterGroupDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterGroupDMData> rm) { service.getRegisterGroupData( fDmc, new DataRequestMonitor<IRegisterGroupDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(getData()); rm.done(); } }); } } public IRegisterGroupDMData readRegisterGroup(Object element) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IRegisterGroupDMContext dmc = getRegisterGroupDMC(element); if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to request the value from service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetRegisterGroupValueQuery query = new GetRegisterGroupValueQuery(dmc); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public class GetRegisterValueQuery extends RegistersServiceQuery<IRegisterDMData, IRegisterDMContext> { public GetRegisterValueQuery(IRegisterDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterDMData> rm) { service.getRegisterData( fDmc, new DataRequestMonitor<IRegisterDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(getData()); rm.done(); } }); } } public IRegisterDMData readRegister(Object element) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IRegisterDMContext dmc = getRegisterDMC(element); if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to request the value from service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetRegisterValueQuery query = new GetRegisterValueQuery(dmc); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public class SetRegisterValueQuery extends RegistersServiceQuery<Object, IRegisterDMContext> { private String fValue; private String fFormatId; public SetRegisterValueQuery(IRegisterDMContext dmc, String value, String formatId) { super(dmc); fValue = value; fFormatId = formatId; } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) { /* * Write the bit field using a string/format style. */ service.writeRegister( fDmc, fValue, fFormatId, new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(new Object()); rm.done(); } }); } } public void writeRegister(Object element, String value, String formatId) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IRegisterDMContext dmc = getRegisterDMC(element); if (dmc == null) return; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ SetRegisterValueQuery query = new SetRegisterValueQuery(dmc, value, formatId); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { /* * Return value is irrelevant, any error would come through with an * exception. */ query.get(); } catch (InterruptedException e) { assert false; } catch (ExecutionException e) { /* * View must be shutting down, no need to show erro dialog. */ } } public class GetSupportFormatsValueQuery extends RegistersServiceQuery<String[], IFormattedDataDMContext> { public GetSupportFormatsValueQuery(IFormattedDataDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<String[]> rm) { service.getAvailableFormats(fDmc, rm); } } public String[] getSupportedFormats(Object element) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IFormattedDataDMContext dmc = null; if (element instanceof IDMVMContext) { IDMContext vmcdmc = ((IDMVMContext) element).getDMContext(); IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class); dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class); } if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetSupportFormatsValueQuery query = new GetSupportFormatsValueQuery(dmc); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public class GetFormattedValueValueQuery extends RegistersServiceQuery<String, IFormattedDataDMContext> { private String fFormatId; public GetFormattedValueValueQuery(IFormattedDataDMContext dmc, String formatId) { super(dmc); fFormatId = formatId; } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<String> rm) { /* * Convert to the proper formatting DMC then go get the formatted * value. */ FormattedValueDMContext formDmc = service.getFormattedValueContext(fDmc, fFormatId); service.getFormattedExpressionValue( formDmc, new DataRequestMonitor<FormattedValueDMData>(ImmediateExecutor.getInstance(), rm) { @Override protected void handleSuccess() { /* * All good set return value. */ rm.setData(getData().getFormattedValue()); rm.done(); } }); } } public String getFormattedRegisterValue(Object element, String formatId) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IFormattedDataDMContext dmc = null; if (element instanceof IDMVMContext) { IDMContext vmcdmc = ((IDMVMContext) element).getDMContext(); IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class); dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class); } if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(dmc, formatId); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public String getFormattedBitFieldValue(Object element, String formatId) { /* * Get the DMC and the session. If element is not an register DMC, or * session is stale, then bail out. */ IFormattedDataDMContext dmc = null; if (element instanceof IDMVMContext) { IDMContext vmcdmc = ((IDMVMContext) element).getDMContext(); IBitFieldDMContext bitfielddmc = DMContexts.getAncestorOfType(vmcdmc, IBitFieldDMContext.class); dmc = DMContexts.getAncestorOfType(bitfielddmc, IFormattedDataDMContext.class); } if (dmc == null) return null; DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session == null) return null; /* * Create the query to write the value to the service. Note: no need to * guard agains RejectedExecutionException, because * DsfSession.getSession() above would only return an active session. */ GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(dmc, formatId); session.getExecutor().execute(query); /* * Now we have the data, go and get it. Since the call is completed now * the ".get()" will not suspend it will immediately return with the * data. */ try { return query.get(); } catch (InterruptedException e) { assert false; return null; } catch (ExecutionException e) { return null; } } public class GetRegisterGroupDataQuery extends RegistersServiceQuery<IRegisterGroupDMData, IRegisterGroupDMContext> { public GetRegisterGroupDataQuery(IRegisterGroupDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterGroupDMData> rm) { service.getRegisterGroupData(fDmc, rm); } } public IRegisterGroupDMData getRegisterGroupDMData(Object element) { IRegisterGroupDMContext dmc = null; if (element instanceof IDMVMContext) { dmc = DMContexts.getAncestorOfType( ((IDMVMContext) element).getDMContext(), IRegisterGroupDMContext.class); } if (dmc != null) { DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session != null) { GetRegisterGroupDataQuery query = new GetRegisterGroupDataQuery(dmc); session.getExecutor().execute(query); try { return query.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { } } } return null; } public class GetRegisterDataQuery extends RegistersServiceQuery<IRegisterDMData, IRegisterDMContext> { public GetRegisterDataQuery(IRegisterDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterDMData> rm) { service.getRegisterData(fDmc, rm); } } public IRegisterDMData getRegisterDMData(Object element) { IRegisterDMContext dmc = null; if (element instanceof IDMVMContext) { dmc = DMContexts.getAncestorOfType( ((IDMVMContext) element).getDMContext(), IRegisterDMContext.class ); } if (dmc != null) { DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session != null) { GetRegisterDataQuery query = new GetRegisterDataQuery(dmc); session.getExecutor().execute(query); try { return query.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { } } } return null; } public class GetBitFieldQuery extends RegistersServiceQuery<IBitFieldDMData, IBitFieldDMContext> { public GetBitFieldQuery(IBitFieldDMContext dmc) { super(dmc); } @Override protected void doExecute(IRegisters service, final DataRequestMonitor<IBitFieldDMData> rm) { service.getBitFieldData(fDmc, rm); } } public IBitFieldDMData getBitFieldDMData(Object element) { IBitFieldDMContext dmc = null; if (element instanceof IDMVMContext) { dmc = DMContexts.getAncestorOfType( ((IDMVMContext) element).getDMContext(), IBitFieldDMContext.class ); } if (dmc != null) { DsfSession session = DsfSession.getSession(dmc.getSessionId()); if (session != null) { GetBitFieldQuery query = new GetBitFieldQuery(dmc); session.getExecutor().execute(query); try { return query.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { } } } return null; } }