001package io.ebeaninternal.server.autotune.service; 002 003import io.ebean.bean.ObjectGraphOrigin; 004import io.ebeaninternal.server.autotune.model.Autotune; 005import io.ebeaninternal.server.autotune.model.Origin; 006import io.ebeaninternal.server.autotune.model.ProfileDiff; 007import io.ebeaninternal.server.autotune.model.ProfileNew; 008import io.ebeaninternal.server.querydefn.OrmQueryDetail; 009 010/** 011 * Event where profiling information is collected and processed for differences 012 * relative to the current query tuning. 013 */ 014public class AutoTuneDiffCollection { 015 016 final Autotune document = new Autotune(); 017 018 final AutoTuneCollection profiling; 019 020 final BaseQueryTuner queryTuner; 021 022 final boolean updateTuning; 023 024 int newCount; 025 026 int diffCount; 027 028 /** 029 * Construct to collect/report the new/diff query tuning entries. 030 */ 031 public AutoTuneDiffCollection(AutoTuneCollection profiling, BaseQueryTuner queryTuner, boolean updateTuning) { 032 this.profiling = profiling; 033 this.queryTuner = queryTuner; 034 this.updateTuning = updateTuning; 035 } 036 037 /** 038 * Return true if there are no new or diff entries. 039 */ 040 public boolean isEmpty() { 041 return newCount == 0 && diffCount == 0; 042 } 043 044 /** 045 * Return the underlying Autotune document object. 046 */ 047 public Autotune getDocument() { 048 return document; 049 } 050 051 /** 052 * Return the number of diff entries. 053 */ 054 public int getDiffCount() { 055 return diffCount; 056 } 057 058 /** 059 * Return the number of new entries. 060 */ 061 public int getNewCount() { 062 return newCount; 063 } 064 065 /** 066 * Return the total new and diff entries. 067 */ 068 public int getChangeCount() { 069 return newCount + diffCount; 070 } 071 072 /** 073 * Write the underlying document as an xml file. 074 */ 075 public void writeFile(String filePrefix) { 076 077 AutoTuneXmlWriter writer = new AutoTuneXmlWriter(); 078 writer.write(document, filePrefix, true); 079 } 080 081 /** 082 * Process checking profiling entries against existing query tuning. 083 */ 084 public void process() { 085 086 for (AutoTuneCollection.Entry entry : profiling.getEntries()) { 087 addToDocument(entry); 088 } 089 } 090 091 /** 092 * Check if the entry is new or diff and add as necessary. 093 */ 094 private void addToDocument(AutoTuneCollection.Entry entry) { 095 096 ObjectGraphOrigin point = entry.getOrigin(); 097 OrmQueryDetail profileDetail = entry.getDetail(); 098 099 // compare with the existing query tuning entry 100 OrmQueryDetail tuneDetail = queryTuner.get(point.getKey()); 101 if (tuneDetail == null) { 102 addToDocumentNewEntry(entry, point); 103 104 } else if (!tuneDetail.isAutoTuneEqual(profileDetail)) { 105 addToDocumentDiffEntry(entry, point, tuneDetail); 106 } 107 } 108 109 /** 110 * Add as a diff entry. 111 */ 112 private void addToDocumentDiffEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, OrmQueryDetail tuneDetail) { 113 114 diffCount++; 115 116 Origin origin = createOrigin(entry, point, tuneDetail.toString()); 117 ProfileDiff diff = document.getProfileDiff(); 118 if (diff == null) { 119 diff = new ProfileDiff(); 120 document.setProfileDiff(diff); 121 } 122 diff.getOrigin().add(origin); 123 } 124 125 /** 126 * Add as a "new" entry. 127 */ 128 private void addToDocumentNewEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point) { 129 130 newCount++; 131 132 ProfileNew profileNew = document.getProfileNew(); 133 if (profileNew == null) { 134 profileNew = new ProfileNew(); 135 document.setProfileNew(profileNew); 136 } 137 Origin origin = createOrigin(entry, point, entry.getOriginalQuery()); 138 profileNew.getOrigin().add(origin); 139 } 140 141 142 /** 143 * Create the XML Origin bean for the given entry and ObjectGraphOrigin. 144 */ 145 private Origin createOrigin(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, String query) { 146 147 Origin origin = new Origin(); 148 origin.setKey(point.getKey()); 149 origin.setBeanType(point.getBeanType()); 150 origin.setDetail(entry.getDetail().toString()); 151 origin.setCallStack(point.getCallOrigin().getFullDescription()); 152 origin.setOriginal(query); 153 154 if (updateTuning) { 155 queryTuner.put(origin); 156 } 157 158 return origin; 159 } 160 161}