FileDocCategorySizeDatePackage
DisplaySync.javaAPI DocAndroid 1.5 API11857Wed May 06 22:41:08 BST 2009com.android.ddmuilib.log.event

DisplaySync

public class DisplaySync extends SyncCommon

Fields Summary
private org.jfree.data.time.TimePeriodValues[]
mDatasetsSync
private List[]
mTooltipsSync
private org.jfree.chart.labels.CustomXYToolTipGenerator[]
mTooltipGenerators
private org.jfree.data.time.TimeSeries[]
mDatasetsSyncTickle
private org.jfree.data.time.TimeSeries
mDatasetError
Constructors Summary
public DisplaySync(String name)

        super(name);
    
Methods Summary
public org.eclipse.swt.widgets.ControlcreateComposite(org.eclipse.swt.widgets.Composite parent, com.android.ddmlib.log.EventLogParser logParser, ILogColumnListener listener)
Creates the UI for the event display.

param
parent the parent composite.
param
logParser the current log parser.
return
the created control (which may have children).

        Control composite = createCompositeChart(parent, logParser, "Sync Status");
        resetUI();
        return composite;
    
intgetDisplayType()
Gets display type

return
display type as an integer

        return DISPLAY_TYPE_SYNC;
    
private intgetHeightFromDetails(java.lang.String details)
Generate the height for an event. Height is somewhat arbitrarily the count of "things" that happened during the sync. When network traffic measurements are available, code should be modified to use that instead.

param
details The details string associated with the event
return
The height in arbirary units (0-100)

        if (details == null) {
            return 1; // Arbitrary
        }
        int total = 0;
        String parts[] = details.split("[a-zA-Z]");
        for (String part : parts) {
            if ("".equals(part)) continue;
            total += Integer.parseInt(part);
        }
        if (total == 0) {
            total = 1;
        }
        return total;
    
private java.lang.StringgetTextFromDetails(int auth, java.lang.String details, int eventSource)
Generates the tooltips text for an event. This method decodes the cryptic details string.

param
auth The authority associated with the event
param
details The details string
param
eventSource server, poll, etc.
return
The text to display in the tooltips


        StringBuffer sb = new StringBuffer();
        sb.append(AUTH_NAMES[auth]).append(": \n");

        Scanner scanner = new Scanner(details);
        Pattern charPat = Pattern.compile("[a-zA-Z]");
        Pattern numPat = Pattern.compile("[0-9]+");
        while (scanner.hasNext()) {
            String key = scanner.findInLine(charPat);
            int val = Integer.parseInt(scanner.findInLine(numPat));
            if (auth == GMAIL && "M".equals(key)) {
                sb.append("messages from server: ").append(val).append("\n");
            } else if (auth == GMAIL && "L".equals(key)) {
                sb.append("labels from server: ").append(val).append("\n");
            } else if (auth == GMAIL && "C".equals(key)) {
                sb.append("check conversation requests from server: ").append(val).append("\n");
            } else if (auth == GMAIL && "A".equals(key)) {
                sb.append("attachments from server: ").append(val).append("\n");
            } else if (auth == GMAIL && "U".equals(key)) {
                sb.append("op updates from server: ").append(val).append("\n");
            } else if (auth == GMAIL && "u".equals(key)) {
                sb.append("op updates to server: ").append(val).append("\n");
            } else if (auth == GMAIL && "S".equals(key)) {
                sb.append("send/receive cycles: ").append(val).append("\n");
            } else if ("Q".equals(key)) {
                sb.append("queries to server: ").append(val).append("\n");
            } else if ("E".equals(key)) {
                sb.append("entries from server: ").append(val).append("\n");
            } else if ("u".equals(key)) {
                sb.append("updates from client: ").append(val).append("\n");
            } else if ("i".equals(key)) {
                sb.append("inserts from client: ").append(val).append("\n");
            } else if ("d".equals(key)) {
                sb.append("deletes from client: ").append(val).append("\n");
            } else if ("f".equals(key)) {
                sb.append("full sync requested\n");
            } else if ("r".equals(key)) {
                sb.append("partial sync unavailable\n");
            } else if ("X".equals(key)) {
                sb.append("hard error\n");
            } else if ("e".equals(key)) {
                sb.append("number of parse exceptions: ").append(val).append("\n");
            } else if ("c".equals(key)) {
                sb.append("number of conflicts: ").append(val).append("\n");
            } else if ("a".equals(key)) {
                sb.append("number of auth exceptions: ").append(val).append("\n");
            } else if ("D".equals(key)) {
                sb.append("too many deletions\n");
            } else if ("R".equals(key)) {
                sb.append("too many retries: ").append(val).append("\n");
            } else if ("b".equals(key)) {
                sb.append("database error\n");
            } else if ("x".equals(key)) {
                sb.append("soft error\n");
            } else if ("l".equals(key)) {
                sb.append("sync already in progress\n");
            } else if ("I".equals(key)) {
                sb.append("io exception\n");
            } else if (auth == CONTACTS && "p".equals(key)) {
                sb.append("photos uploaded from client: ").append(val).append("\n");
            } else if (auth == CONTACTS && "P".equals(key)) {
                sb.append("photos downloaded from server: ").append(val).append("\n");
            } else if (auth == CALENDAR && "F".equals(key)) {
                sb.append("server refresh\n");
            } else if (auth == CALENDAR && "s".equals(key)) {
                sb.append("server diffs fetched\n");
            } else {
                sb.append(key).append("=").append(val);
            }
        }
        if (eventSource == 0) {
            sb.append("(server)");
        } else if (eventSource == 1) {
            sb.append("(local)");
        } else if (eventSource == 2) {
            sb.append("(poll)");
        } else if (eventSource == 3) {
            sb.append("(user)");
        }
        return sb.toString();
    
voidnewEvent(com.android.ddmlib.log.EventContainer event, com.android.ddmlib.log.EventLogParser logParser)
Updates the display with a new event.

param
event The event
param
logParser The parser providing the event.

        super.newEvent(event, logParser); // Handle sync operation
        try {
            if (event.mTag == EVENT_TICKLE) {
                int auth = getAuth(event.getValueAsString(0));
                if (auth >= 0) {
                    long msec = (long)event.sec * 1000L + (event.nsec / 1000000L);
                    mDatasetsSyncTickle[auth].addOrUpdate(new FixedMillisecond(msec), -1);
                }
            }
        } catch (InvalidTypeException e) {
        }
    
voidprocessSyncEvent(com.android.ddmlib.log.EventContainer event, int auth, long startTime, long stopTime, java.lang.String details, boolean newEvent, int syncSource)
Callback to process a sync event.

        if (!newEvent) {
            // Details arrived for a previous sync event
            // Remove event before reinserting.
            int lastItem = mDatasetsSync[auth].getItemCount();
            mDatasetsSync[auth].delete(lastItem-1, lastItem-1);
            mTooltipsSync[auth].remove(lastItem-1);
        }
        double height = getHeightFromDetails(details);
        height = height / (stopTime - startTime + 1) * 10000;
        if (height > 30) {
            height = 30;
        }
        mDatasetsSync[auth].add(new SimpleTimePeriod(startTime, stopTime), height);
        mTooltipsSync[auth].add(getTextFromDetails(auth, details, syncSource));
        mTooltipGenerators[auth].addToolTipSeries(mTooltipsSync[auth]);
        if (details.indexOf('x") >= 0 || details.indexOf('X") >= 0) {
            long msec = (long)event.sec * 1000L + (event.nsec / 1000000L);
            mDatasetError.addOrUpdate(new FixedMillisecond(msec), -1);
        }
    
voidresetUI()
Resets the display.

        super.resetUI();
        XYPlot xyPlot = mChart.getXYPlot();

        XYBarRenderer br = new XYBarRenderer();
        mDatasetsSync = new TimePeriodValues[NUM_AUTHS];
        mTooltipsSync = new List[NUM_AUTHS];
        mTooltipGenerators = new CustomXYToolTipGenerator[NUM_AUTHS];

        TimePeriodValuesCollection tpvc = new TimePeriodValuesCollection();
        xyPlot.setDataset(tpvc);
        xyPlot.setRenderer(0, br);

        XYLineAndShapeRenderer ls = new XYLineAndShapeRenderer();
        ls.setBaseLinesVisible(false);
        mDatasetsSyncTickle = new TimeSeries[NUM_AUTHS];
        TimeSeriesCollection tsc = new TimeSeriesCollection();
        xyPlot.setDataset(1, tsc);
        xyPlot.setRenderer(1, ls);

        mDatasetError = new TimeSeries("Errors", FixedMillisecond.class);
        xyPlot.setDataset(2, new TimeSeriesCollection(mDatasetError));
        XYLineAndShapeRenderer errls = new XYLineAndShapeRenderer();
        errls.setBaseLinesVisible(false);
        errls.setSeriesPaint(0, Color.RED);
        xyPlot.setRenderer(2, errls);

        for (int i = 0; i < NUM_AUTHS; i++) {
            br.setSeriesPaint(i, AUTH_COLORS[i]);
            ls.setSeriesPaint(i, AUTH_COLORS[i]);
            mDatasetsSync[i] = new TimePeriodValues(AUTH_NAMES[i]);
            tpvc.addSeries(mDatasetsSync[i]);
            mTooltipsSync[i] = new ArrayList<String>();
            mTooltipGenerators[i] = new CustomXYToolTipGenerator();
            br.setSeriesToolTipGenerator(i, mTooltipGenerators[i]);
            mTooltipGenerators[i].addToolTipSeries(mTooltipsSync[i]);

            mDatasetsSyncTickle[i] = new TimeSeries(AUTH_NAMES[i] + " tickle",
                    FixedMillisecond.class);
            tsc.addSeries(mDatasetsSyncTickle[i]);
            ls.setSeriesShape(i, ShapeUtilities.createUpTriangle(2.5f));
        }