├── src └── main │ ├── resources │ ├── data │ │ ├── CONSEQUENCE │ │ ├── ResultData │ │ └── RANDOMBS.xml │ ├── images │ │ ├── BS.png │ │ ├── Logo.png │ │ └── icon.png │ ├── SIMULATION.properties │ └── log4j.properties │ └── java │ └── cn │ └── edu │ └── tju │ └── simulation │ ├── main │ └── EdgeSim.java │ ├── tool │ ├── ToolKit.java │ ├── GetRandomPoint.java │ └── StringHandler.java │ ├── file │ ├── ContentWriter.java │ ├── StateFileReader.java │ ├── ParameterFileReader.java │ ├── XMLReader.java │ ├── ResultDateWiriter.java │ ├── ContentReader.java │ ├── CaseFileWriter.java │ ├── CaseFileReader.java │ ├── RandomBSReader.java │ └── Parameter.java │ ├── user │ ├── MobilityModel.java │ ├── SimpleMobilityModel.java │ ├── MobilityModelGenerator.java │ ├── SameTypeMobilityModel.java │ └── Users.java │ ├── handler │ ├── Pretreatment.java │ └── RequestHandler.java │ ├── swing │ ├── map │ │ ├── MapCanvas.java │ │ ├── NetworkAdjust.java │ │ └── Map.java │ ├── menubar │ │ ├── Paramater.java │ │ ├── AddContent.java │ │ ├── AddNetwork.java │ │ ├── ViewContent.java │ │ ├── ViewNetwork.java │ │ ├── ButtonAddBS.java │ │ ├── FileChooser.java │ │ └── MenuBar.java │ ├── operator │ │ ├── Operator.java │ │ └── Signal.java │ ├── chart │ │ ├── TimeLineChart.java │ │ ├── NumberLineChart.java │ │ ├── TrafficLoadLineChart.java │ │ ├── PythonInterpreter.java │ │ ├── DelayLineChart.java │ │ ├── BaseLineChart.java │ │ ├── Latency.py │ │ ├── Traffic.py │ │ └── HitRate.py │ └── log │ │ └── Log.java │ ├── content │ ├── ContentService.java │ ├── Content.java │ ├── CachingSingleContent.java │ ├── SingleContent.java │ ├── SingleLocalHobby.java │ └── LocalHobby.java │ ├── algorithm │ ├── KnapsackAlgorithm.java │ ├── OneTimeAlgorithm.java │ ├── RealTimeAlgorithm.java │ ├── LFUAlgorithm.java │ ├── GreedyAlgorithm.java │ ├── LRUAlgorithm.java │ └── FIFOAlgorithm.java │ ├── wirelessnetwork │ ├── RelationalWirelessNetwork.java │ ├── SameTypeWirelessNetwork.java │ ├── WirelessAccessPoint.java │ ├── WirelessNetworkGroup.java │ ├── AddWirelessNetworkInterface.java │ ├── BaseStation.java │ └── WirelessNetwork.java │ ├── cache │ ├── Query.java │ └── Cache.java │ ├── mno │ └── MobileNetworkOperator.java │ ├── logger │ ├── Log.java │ ├── LogFileFilter.java │ └── CustomDailyRollingFileAppender.java │ ├── data │ └── Data.java │ ├── state │ ├── StateQueue.java │ └── State.java │ └── controller │ └── Controller.java ├── settings.gradle ├── .travis.yml ├── EdgeSim Operation Manual.pdf ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── vcs.xml ├── misc.xml ├── gradle.xml └── encodings.xml ├── readme.txt ├── LICENSE ├── README.md ├── gradlew.bat └── gradlew /src/main/resources/data/CONSEQUENCE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'EdgeSim' 2 | 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk10 5 | 6 | script: true 7 | -------------------------------------------------------------------------------- /EdgeSim Operation Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/EdgeSim Operation Manual.pdf -------------------------------------------------------------------------------- /src/main/resources/images/BS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/resources/images/BS.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/resources/images/Logo.png -------------------------------------------------------------------------------- /src/main/resources/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/resources/images/icon.png -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/main/EdgeSim.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/main/EdgeSim.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/tool/ToolKit.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/tool/ToolKit.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/ContentWriter.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/file/ContentWriter.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/user/MobilityModel.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/user/MobilityModel.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/StateFileReader.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/file/StateFileReader.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/handler/Pretreatment.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/handler/Pretreatment.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/map/MapCanvas.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/map/MapCanvas.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/content/ContentService.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/content/ContentService.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/handler/RequestHandler.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/handler/RequestHandler.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/map/NetworkAdjust.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/map/NetworkAdjust.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/Paramater.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/menubar/Paramater.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/operator/Operator.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/operator/Operator.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/ParameterFileReader.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/file/ParameterFileReader.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/TimeLineChart.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/chart/TimeLineChart.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/AddContent.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/menubar/AddContent.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/AddNetwork.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/menubar/AddNetwork.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/ViewContent.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/menubar/ViewContent.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/ViewNetwork.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/menubar/ViewNetwork.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/user/SimpleMobilityModel.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/user/SimpleMobilityModel.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/KnapsackAlgorithm.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/algorithm/KnapsackAlgorithm.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/NumberLineChart.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/chart/NumberLineChart.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/user/MobilityModelGenerator.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/user/MobilityModelGenerator.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/TrafficLoadLineChart.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/swing/chart/TrafficLoadLineChart.java -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/RelationalWirelessNetwork.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/wirelessnetwork/RelationalWirelessNetwork.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/SameTypeWirelessNetwork.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaofeiTJU/EdgeSim/HEAD/src/main/java/cn/edu/tju/simulation/wirelessnetwork/SameTypeWirelessNetwork.java -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/cache/Query.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.cache; 2 | 3 | import cn.edu.tju.simulation.content.SingleLocalHobby; 4 | 5 | 6 | public interface Query { 7 | Boolean query(SingleLocalHobby singleContent); 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 18 21:57:16 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip 7 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/OneTimeAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.algorithm; 2 | 3 | /** 4 | * 5 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 6 | * 7 | */ 8 | public interface OneTimeAlgorithm{ 9 | public void setCache(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/mno/MobileNetworkOperator.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.mno; 2 | 3 | import cn.edu.tju.simulation.cache.Cache; 4 | 5 | /** 6 | * MNO 7 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 8 | * 9 | */ 10 | public class MobileNetworkOperator extends Cache { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/XMLReader.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | 4 | /** 5 | * xml file parsing interface 6 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 7 | * 8 | */ 9 | public interface XMLReader{ 10 | /** 11 | * Parse the XML document 12 | * @param fileName Full path name of the file 13 | */ 14 | public void parserXML(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/tool/GetRandomPoint.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.tool; 2 | 3 | 4 | /** 5 | * According to the network topology, get a random point 6 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 7 | * 8 | */ 9 | public class GetRandomPoint { 10 | // public SameWirelessNetworks BSs = Main.BSs; 11 | 12 | public void getPoint(){ 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/logger/Log.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.logger; 2 | 3 | import org.apache.log4j.Logger; 4 | 5 | /** 6 | * 7 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 8 | * 9 | */ 10 | public class Log{ 11 | 12 | private static Logger logger = Logger.getLogger(Log.class); 13 | 14 | public static Logger getLogger(){ 15 | 16 | return logger; 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/WirelessAccessPoint.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.wirelessnetwork; 2 | 3 | /** 4 | * Hot spot < to be finished > 5 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 6 | * 7 | */ 8 | public class WirelessAccessPoint extends WirelessNetwork{ 9 | 10 | @Override 11 | public int countUserOfNetwork() { 12 | // TODO Auto-generated method stub 13 | return 0; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/RealTimeAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.algorithm; 2 | 3 | import cn.edu.tju.simulation.content.SingleLocalHobby; 4 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 5 | 6 | /** 7 | * 8 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 9 | * 10 | */ 11 | public interface RealTimeAlgorithm{ 12 | public void setCache(WirelessNetwork network,SingleLocalHobby requestContent); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/SIMULATION.properties: -------------------------------------------------------------------------------- 1 | USER_TO_BS_DELAY=10 2 | BS_TO_BS_DELAY=5 3 | BS_TO_MNO_DELAY=20 4 | MNO_TO_CLOUD_DELAY=100 5 | PATH=D\:\\\\EdgeCahing 6 | Radius=3 7 | TimeSlicesMaxNumber=100 8 | RequestProbability=0.6 9 | ZIPF_SAMPLE=5000 10 | ZIPF_CONEFFICIENT=0.54 11 | TRANSMISSION_POWER=40 12 | GAUSSIAN_WHITE_NOISE_POWER=-174 13 | EXPONENT=4 14 | BANDWIDTH=10 15 | PATH_LOSS=0.01 16 | BSMinWaveInterval=0.7 17 | UserMinWaveInterval=0.8 18 | UserMaxWaveInterval=1.2 19 | BSMaxWaveInterval=1.3 20 | ContentSizePerTimeSlice=1 21 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/operator/Signal.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.operator; 2 | 3 | /** 4 | * Mark the components 5 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 6 | * 7 | */ 8 | public class Signal { 9 | /** 10 | * Add base station button 11 | */ 12 | public static Boolean Button_BS_Click = false; 13 | /** 14 | * Number of base station combination 15 | */ 16 | public static int BSFileNumber; 17 | /** 18 | * Judge whether to save 19 | */ 20 | public static Boolean SAVE = false; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/WirelessNetworkGroup.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.wirelessnetwork; 2 | 3 | /** 4 | * 5 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 6 | * 7 | */ 8 | public class WirelessNetworkGroup { 9 | public SameTypeWirelessNetwork BS; 10 | 11 | public WirelessNetworkGroup(){ 12 | this.BS = new SameTypeWirelessNetwork("BaseStation"); 13 | } 14 | 15 | public int getBSAmount(){ 16 | return BS.getAmount(); 17 | } 18 | 19 | public void clearAllCache(){ 20 | BS.clearAllCache(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/AddWirelessNetworkInterface.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.wirelessnetwork; 2 | 3 | /** 4 | * The class that implements this interface must implement the following methods 5 |  * Used to limit supported wireless network types 6 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 7 | * 8 | */ 9 | public interface AddWirelessNetworkInterface { 10 | /** 11 | * Add a base station to the wireless network collection 12 | * @param bs 13 | */ 14 | public void addWirelessNetwork(WirelessNetwork noAddedNetwork); 15 | } 16 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/ButtonAddBS.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.menubar; 2 | 3 | import javax.swing.JButton; 4 | 5 | /** 6 | * Add base station button 7 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 8 | * 9 | */ 10 | @SuppressWarnings("serial") 11 | public class ButtonAddBS extends JButton{ 12 | private Boolean click; 13 | 14 | public ButtonAddBS(String name){ 15 | this.click = false; 16 | this.setText(name); 17 | } 18 | 19 | public Boolean getClick() { 20 | return click; 21 | } 22 | 23 | public void setClick(Boolean click) { 24 | this.click = click; 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | - completed update 2 | - adds a cross-base station for the requested content. Strategy: we cannot replace cached content when it is being downloaded. In this strategy, five cache algorithms are changed. 3 | - refines the objects contained in the program. 4 | -A record of time delay and flow data is added in the emulator. These records can not only generate line graphs, but also can be saved as text. 5 | - the next thing to do: 6 | - associate user movement with time slice. According to the mobile model, to plan the user's mobile trajectory in advance. 7 | - the size of the content directly reads the actual data, in bytes. And the initial content can be applied to the next experiment. -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/logger/LogFileFilter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.logger; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | 6 | import org.apache.log4j.helpers.LogLog; 7 | 8 | /** 9 | * 10 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 11 | * 12 | */ 13 | public class LogFileFilter implements FileFilter { 14 | private String logName; 15 | 16 | public LogFileFilter(String logName){ 17 | this.logName = logName; 18 | } 19 | 20 | public boolean accept(File file) { 21 | if(logName == null || file.isDirectory()){ 22 | return false; 23 | }else{ 24 | LogLog.debug(file.getName()); 25 | return file.getName().startsWith(logName); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/content/Content.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.content; 2 | 3 | import java.util.Collections; 4 | import java.util.Comparator; 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * 9 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 10 | * 11 | */ 12 | public class Content{ 13 | private LinkedList content; 14 | 15 | public Content(){ 16 | this.content = new LinkedList(); 17 | } 18 | 19 | public void clear(){ 20 | this.content.clear(); 21 | } 22 | 23 | public void addSingleContent(SingleContent singleContent){ 24 | this.content.add(singleContent); 25 | } 26 | 27 | public void sortByPopularity(){ 28 | if (this.content != null) { 29 | Collections.sort(this.content, new Comparator() { 30 | public int compare(SingleContent contentOne, SingleContent contentTwo) { 31 | return contentOne.getPopularity() == contentTwo.getPopularity() ? 0 : 32 | (contentOne.getPopularity() > contentTwo.getPopularity() ? -1 : 1); 33 | } 34 | }); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/user/SameTypeMobilityModel.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.user; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * The same type of user collection's class 8 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 9 | * 10 | */ 11 | public class SameTypeMobilityModel{ 12 | /** 13 | * User's collection 14 | */ 15 | private List mobilityModelList; 16 | /** 17 | * User's type 18 | */ 19 | private String type; 20 | 21 | public void clearMobilityModel(){ 22 | this.mobilityModelList.clear(); 23 | } 24 | 25 | public SameTypeMobilityModel(String Type){ 26 | this.mobilityModelList = new ArrayList(); 27 | this.type = Type; 28 | } 29 | 30 | public List getMobilityModelList() { 31 | return mobilityModelList; 32 | } 33 | 34 | public void setUsers(List users) { 35 | this.mobilityModelList = users; 36 | } 37 | public String getType() { 38 | return type; 39 | } 40 | public void setType(String type) { 41 | this.type = type; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Xiaofei Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/content/CachingSingleContent.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.content; 2 | 3 | 4 | public class CachingSingleContent { 5 | private SingleContent singleContent; 6 | 7 | public CachingSingleContent(SingleContent cachingSingleContent){ 8 | this.singleContent = cachingSingleContent; 9 | } 10 | 11 | @Override 12 | public boolean equals(Object obj){ 13 | if(obj instanceof SingleLocalHobby){ 14 | SingleLocalHobby slh = (SingleLocalHobby)obj; 15 | if(this.singleContent == slh.getSingleContent()){ 16 | return true; 17 | }else{ 18 | return false; 19 | } 20 | }else if(obj instanceof SingleContent){ 21 | SingleContent sc = (SingleContent)obj; 22 | if(this.singleContent == sc){ 23 | return true; 24 | }else{ 25 | return false; 26 | } 27 | }else{ 28 | return false; 29 | } 30 | } 31 | 32 | 33 | public String getName(){ 34 | return this.singleContent.getName(); 35 | } 36 | 37 | public long getSize(){ 38 | return this.singleContent.getSize(); 39 | } 40 | 41 | public SingleContent getSingleContent() { 42 | return singleContent; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/PythonInterpreter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.chart; 2 | 3 | import java.io.IOException; 4 | 5 | 6 | public class PythonInterpreter { 7 | private static String path = PythonInterpreter.class.getClassLoader().getResource("").getPath().substring(1,PythonInterpreter.class.getClassLoader().getResource("").getPath().indexOf("/out")); 8 | private static final String PY_HITRATRE_URL = path + "/src/main/java/cn/edu/tju/simulation/swing/chart/HitRate.py"; 9 | private static final String PY_LATENCY_URL = path + "/src/main/java/cn/edu/tju/simulation/swing/chart/Latency.py"; 10 | private static final String PY_TRAFFIC_URL = path + "/src/main/java/cn/edu/tju/simulation/swing/chart/Traffic.py"; 11 | 12 | public static void interpreter(){ 13 | try { 14 | System.out.println(PythonInterpreter.class.getClassLoader().getResource("").getPath()); 15 | 16 | Runtime.getRuntime().exec("cmd /k python "+ PY_HITRATRE_URL); 17 | Runtime.getRuntime().exec("cmd /k python "+ PY_LATENCY_URL); 18 | Runtime.getRuntime().exec("cmd /k python "+ PY_TRAFFIC_URL); 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/user/Users.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.user; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import cn.edu.tju.simulation.state.State; 7 | 8 | /** 9 | * 10 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 11 | * 12 | */ 13 | public class Users { 14 | private SameTypeMobilityModel simpleUsers; 15 | 16 | public Users(){ 17 | this.simpleUsers = new SameTypeMobilityModel("SimpleUser"); 18 | } 19 | 20 | public List generateStateList(){ 21 | List simpleUserList = this.simpleUsers.getMobilityModelList(); 22 | List stateList = new ArrayList(); 23 | 24 | for (int i = 0; i < simpleUserList.size(); i++) { 25 | State state = simpleUserList.get(i).generateState(); 26 | if (state != null) { 27 | stateList.add(state); 28 | } 29 | } 30 | return stateList; 31 | } 32 | 33 | public int getSimpleUsersAmount(){ 34 | return simpleUsers.getMobilityModelList().size(); 35 | } 36 | 37 | public List getSimpleUsers() { 38 | return simpleUsers.getMobilityModelList(); 39 | } 40 | 41 | public void setSimpleUsers(SameTypeMobilityModel simpleUsers) { 42 | this.simpleUsers = simpleUsers; 43 | } 44 | 45 | public String getSimpleUsersType(){ 46 | return simpleUsers.getType(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/tool/StringHandler.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.tool; 2 | 3 | import java.awt.geom.Point2D; 4 | 5 | import cn.edu.tju.simulation.wirelessnetwork.BaseStation; 6 | 7 | /** 8 | * String processing class 9 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 10 | * 11 | */ 12 | public class StringHandler { 13 | /** 14 | * A line state to generate an array 15 | * @param line One line in the status file 16 | * @return 17 | */ 18 | public static String[] array(String line) { 19 | if (line != null) { 20 | String[] state = line.split(" "); 21 | state[1]=state[1]+" "+state[2]; 22 | state[2]=state[3]; 23 | return state; 24 | } else { 25 | return null; 26 | } 27 | } 28 | 29 | /** 30 | * Read the base station information in the file to generate the base station 31 | * @param line 32 | * @return 33 | */ 34 | public static BaseStation readBS(String line){ 35 | String [] networkInfo= line.split(" "); 36 | int ID = Integer.parseInt(networkInfo[0]); 37 | int x = (int)Double.parseDouble(networkInfo[1]); 38 | int y = (int)Double.parseDouble(networkInfo[2]); 39 | int radius = Integer.parseInt(networkInfo[3]); 40 | int cacheSize = Integer.parseInt(networkInfo[4]); 41 | 42 | return new BaseStation(ID,new Point2D.Double(x,y),true,cacheSize,radius); 43 | } 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/map/Map.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.map; 2 | 3 | import javax.swing.JScrollPane; 4 | 5 | import cn.edu.tju.simulation.controller.Controller; 6 | 7 | /** 8 | * Drawing container (contains canvas) 9 | * 10 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 11 | * 12 | */ 13 | @SuppressWarnings("serial") 14 | public class Map extends JScrollPane { 15 | /** 16 | * Canvas 17 | */ 18 | private MapCanvas mapCanvas; 19 | /** 20 | * Controller 21 | */ 22 | private Controller controller; 23 | 24 | public Map() { 25 | // Set the horizontal and vertical scroll bar are always appear 26 | this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 27 | this.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 28 | Initial(); 29 | } 30 | 31 | public void Initial() { 32 | mapCanvas = new MapCanvas(); 33 | this.setViewportView(mapCanvas); 34 | } 35 | 36 | public MapCanvas getMapCanvas() { 37 | return mapCanvas; 38 | } 39 | 40 | public void setMapCanvas(MapCanvas mapCanvas) { 41 | this.mapCanvas = mapCanvas; 42 | } 43 | 44 | public Controller getController() { 45 | return controller; 46 | } 47 | 48 | public void setController(Controller controller) { 49 | this.controller = controller; 50 | mapCanvas.setController(controller); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/log/Log.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.log; 2 | 3 | import javax.swing.BorderFactory; 4 | import javax.swing.JScrollPane; 5 | import javax.swing.JTextArea; 6 | 7 | import cn.edu.tju.simulation.controller.Controller; 8 | 9 | /** 10 | * Log container 11 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 12 | * 13 | */ 14 | @SuppressWarnings("serial") 15 | public class Log extends JScrollPane { 16 | /** 17 | * Controller 18 | */ 19 | private Controller controller; 20 | /** 21 | * Log 22 | */ 23 | private JTextArea text; 24 | 25 | public Log() { 26 | this.setBorder(BorderFactory.createTitledBorder(getBorder(), "Log")); 27 | 28 | text = new JTextArea(); 29 | this.add(text); 30 | text.setOpaque(false); 31 | text.setText("Welcome to use Edge Caching Simulation!"); 32 | text.setEditable(false); 33 | Initial(); 34 | 35 | } 36 | 37 | public void Initial() { 38 | this.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 39 | this.setViewportView(text); 40 | } 41 | 42 | public void append(String str){ 43 | text.append("\n"+str); 44 | text.setCaretPosition(text.getDocument().getLength()); 45 | } 46 | 47 | public Controller getController() { 48 | return controller; 49 | } 50 | 51 | public void setController(Controller controller) { 52 | this.controller = controller; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | ---- 4 | ## About EdgeSim 5 | An open-source simulator of edge computing and caching. 6 | 7 | ---- 8 | ## Features 9 | This simulator system contains three models: Content, Base Station and User: 10 | * Reflects the local popularity of downloadable content and user preferences 11 | * Content popularity is supported by zipF distribution, size and other system. 12 | Besides, parameters are supported by real data sets. 13 | * Communication model is a large-scale path-loss model. 14 | * Base stations can work together. 15 | * The whole simulation process is continuous in terms of time slices. 16 | * The line chart which can be used directly in the paper can be directly generated. In addition, the simulator stores the result as a file. 17 | * EdgeSim is very scalable 18 | 19 | ---- 20 | ## Installation 21 | First of all, you may need to pre-install JDK10. If you want to generate a professional version of the results chart via the emulator directly, you may need to pre-install the python environment and download the matplotlib and numpy. 22 | ```python 23 | pip install numpy 24 | ``` 25 | ```python 26 | pip install matplotlib 27 | ``` 28 | ---- 29 | ## Chat 30 | Welcome everyone to perfect this system, if you have any questions or ideas, please feel free to contact me. [New Issue](https://github.com/XiaofeiTJU/EdgeSim/issues/new). 31 | 32 | ---- 33 | ## License 34 | EdgeSim is available under the terms of [the MIT License](https://github.com/XiaofeiTJU/EdgeSim/blob/master/LICENSE). 35 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/LFUAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.algorithm; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | import cn.edu.tju.simulation.content.CachingSingleContent; 7 | import cn.edu.tju.simulation.content.ContentService; 8 | import cn.edu.tju.simulation.content.SingleContent; 9 | import cn.edu.tju.simulation.content.SingleLocalHobby; 10 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 11 | 12 | /** 13 | * 14 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 15 | * 16 | */ 17 | public class LFUAlgorithm implements RealTimeAlgorithm{ 18 | LinkedList watingCachingContent; 19 | 20 | public LFUAlgorithm(){ 21 | watingCachingContent = new LinkedList(); 22 | } 23 | 24 | public void setCache(WirelessNetwork requestedNetwork,SingleLocalHobby requestContent){ 25 | long remainingSize = requestedNetwork.getCacheSize(); 26 | LinkedList cachingContentList = requestedNetwork.getCacheContent(); 27 | List list = requestedNetwork.getContent().getContentList(); 28 | ContentService.sortMySingleContentByRequestedAmount(requestedNetwork.getContent().getContentList()); 29 | //request have not init 30 | 31 | cachingContentList.clear(); 32 | 33 | for(int i = 0 ; i > dataMap = Controller.getInstance().getResultDataList(); 30 | Iterator it = Controller.getInstance().getResultDataList().keySet().iterator(); 31 | while(it.hasNext()){ 32 | String key = it.next(); 33 | XYSeries series = new XYSeries(key); 34 | List dataList = dataMap.get(key); 35 | series.add(0,0); 36 | for (Data data2 : dataList) { 37 | if(yais_max_value == 0 || yais_max_value < data2.getLatency()){ 38 | yais_max_value = data2.getLatency(); 39 | } 40 | series.add(data2.getTimeSlice()+1,data2.getLatency()); 41 | } 42 | collection.addSeries(series); 43 | } 44 | yais_space = (int)(yais_max_value/6); 45 | generateLineChart("Time Slice","Latency(s)",new NumberTickUnit(xais_space), new NumberTickUnit(yais_space),yais_min_value, yais_max_value, collection); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### Configuration ### 2 | log4j.rootLogger = debug,console,debug,info,error 3 | 4 | ### Output information to the console ### 5 | log4j.appender.console = org.apache.log4j.ConsoleAppender 6 | log4j.appender.console.Target = System.out 7 | log4j.appender.console.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.console.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n 9 | 10 | ### Output DEBUG level above the log to = D://EdgeCahing/logs/error.log### 11 | log4j.appender.debug = cn.edu.tju.simulation.logger.CustomDailyRollingFileAppender 12 | log4j.appender.debug.File = log/debug.log 13 | log4j.appender.debug.Append = true 14 | log4j.appender.debug.Threshold = DEBUG 15 | log4j.appender.debug.layout = org.apache.log4j.PatternLayout 16 | log4j.appender.debug.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %l ] - [ %p ] %m%n 17 | 18 | ### Output INFO level above the log to = D://EdgeCahing/logs/error.log### 19 | log4j.appender.info = cn.edu.tju.simulation.logger.CustomDailyRollingFileAppender 20 | log4j.appender.info.File = log/info.log 21 | log4j.appender.info.Append = true 22 | log4j.appender.info.Threshold = INFO 23 | log4j.appender.info.layout = org.apache.log4j.PatternLayout 24 | log4j.appender.info.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %l ] - [ %p ] %m%n 25 | 26 | 27 | ### Output ERROR level above the log to=D://EdgeCahing/logs/error.log ### 28 | log4j.appender.error = cn.edu.tju.simulation.logger.CustomDailyRollingFileAppender 29 | log4j.appender.error.File =log/error.log 30 | log4j.appender.error.Append = true 31 | log4j.appender.error.Threshold = ERROR 32 | log4j.appender.error.layout = org.apache.log4j.PatternLayout 33 | log4j.appender.error.layout.ConversionPattern =%-d{yyyy-MM-dd HH\:mm\:ss} [ %l ] - [ %p ] %m%n -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/ResultDateWiriter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileWriter; 7 | import java.io.IOException; 8 | import java.util.HashMap; 9 | import java.util.Iterator; 10 | import java.util.LinkedList; 11 | 12 | import cn.edu.tju.simulation.controller.Controller; 13 | import cn.edu.tju.simulation.data.Data; 14 | /** 15 | * 16 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 17 | * 18 | */ 19 | public class ResultDateWiriter { 20 | 21 | public void write(){ 22 | BufferedWriter bw = null; 23 | FileWriter fw = null; 24 | try { 25 | fw = new FileWriter(new File("src/main/resources/data/ResultData")); 26 | bw = new BufferedWriter(fw); 27 | HashMap> dataMap = Controller.getInstance().getResultDataList(); 28 | Iterator it = dataMap.keySet().iterator(); 29 | while(it.hasNext()){ 30 | String algorithm = it.next(); 31 | bw.write("Algorithm:" + algorithm+"\r\n"); 32 | 33 | Iterator mIt = dataMap.get(algorithm).iterator(); 34 | int i = 0; 35 | while(mIt.hasNext()){ 36 | i++; 37 | Data data = mIt.next(); 38 | bw.write(data.getTimeSlice()+"," +data.getHitRate()+","+data.getLatency()+","+data.getSaveTraffic()+" "); 39 | if(i % 8 == 0){ 40 | bw.write("\r\n"); 41 | } 42 | } 43 | bw.write("\r\n"); 44 | } 45 | bw.flush(); 46 | fw.flush(); 47 | } catch (FileNotFoundException e) { 48 | e.printStackTrace(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | }finally{ 52 | try { 53 | if(fw != null){ 54 | fw.close(); 55 | } 56 | if(bw != null){ 57 | bw.close(); 58 | } 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/content/SingleLocalHobby.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.content; 2 | 3 | public class SingleLocalHobby { 4 | private SingleContent singleContent; 5 | private int localHobbyValue; 6 | 7 | public void addRequestedAmount() { 8 | this.singleContent.addRequestAmount(1); 9 | } 10 | 11 | public void addLocalHobbyValue() { 12 | this.localHobbyValue++; 13 | } 14 | 15 | @Override 16 | public boolean equals(Object obj){ 17 | if(obj instanceof CachingSingleContent){ 18 | CachingSingleContent csc = (CachingSingleContent)obj; 19 | if(this.singleContent == csc.getSingleContent()){ 20 | return true; 21 | }else{ 22 | return false; 23 | } 24 | }else if(obj instanceof SingleContent){ 25 | SingleContent sc = (SingleContent)obj; 26 | if(this.singleContent == sc){ 27 | return true; 28 | }else{ 29 | return false; 30 | } 31 | }else{ 32 | return false; 33 | } 34 | } 35 | 36 | public String getName() { 37 | return this.singleContent.getName(); 38 | } 39 | 40 | public long getSize() { 41 | return this.singleContent.getSize(); 42 | } 43 | 44 | public int getTimeSlotNumber() { 45 | return this.singleContent.getTimeSlotNumber(); 46 | } 47 | 48 | public SingleLocalHobby(SingleContent singleContent, int localHobbyValue) { 49 | this.singleContent = singleContent; 50 | this.localHobbyValue = localHobbyValue; 51 | } 52 | 53 | public SingleLocalHobby(SingleContent singleContent) { 54 | this.singleContent = singleContent; 55 | this.localHobbyValue = singleContent.getPopularity(); 56 | } 57 | 58 | public SingleContent getSingleContent() { 59 | return singleContent; 60 | } 61 | 62 | public void setSingleContent(SingleContent singleContent) { 63 | this.singleContent = singleContent; 64 | } 65 | 66 | public int getLocalHobbyValue() { 67 | return localHobbyValue; 68 | } 69 | 70 | public void setLocalHobbyValue(int popularity) { 71 | this.localHobbyValue = popularity; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/ContentReader.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import javax.xml.parsers.DocumentBuilder; 9 | import javax.xml.parsers.DocumentBuilderFactory; 10 | import javax.xml.parsers.ParserConfigurationException; 11 | 12 | import org.w3c.dom.Document; 13 | import org.xml.sax.SAXException; 14 | 15 | import cn.edu.tju.simulation.content.SingleContent; 16 | 17 | /** 18 | * Read XML file, initialize multimedia 19 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 20 | * 21 | */ 22 | public class ContentReader { 23 | /** 24 | * Read content.xml 25 | * @return 26 | */ 27 | public List read() { 28 | List mediaList = new ArrayList(); 29 | SingleContent tempMedia = null; 30 | try { 31 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 32 | DocumentBuilder db = dbf.newDocumentBuilder(); 33 | Document document = db.parse("src/main/resources/data/CONTAINT.xml"); 34 | 35 | // for (int i = 0; i < containt.getLength(); i++) { 36 | for (int i = 0; i < 3000; i++) { 37 | tempMedia = new SingleContent(); 38 | tempMedia.setName(document.getElementsByTagName("name").item(i).getFirstChild().getNodeValue()); 39 | String size = document.getElementsByTagName("size").item(i).getFirstChild().getNodeValue(); 40 | if(size.equals("0")){ 41 | tempMedia.setSize(Integer.parseInt("1")); 42 | }else{ 43 | tempMedia.setSize(Integer.parseInt(size)); 44 | } 45 | tempMedia.setPopularity(Integer.parseInt(document.getElementsByTagName("popularity").item(i).getFirstChild().getNodeValue())); 46 | 47 | mediaList.add(tempMedia); 48 | } 49 | 50 | } catch (FileNotFoundException e) { 51 | e.printStackTrace(); 52 | } catch (IOException e) { 53 | e.printStackTrace(); 54 | } catch (ParserConfigurationException e) { 55 | e.printStackTrace(); 56 | } catch (SAXException e) { 57 | e.printStackTrace(); 58 | } 59 | return mediaList; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/GreedyAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.algorithm; 2 | 3 | import java.util.List; 4 | 5 | import cn.edu.tju.simulation.content.ContentService; 6 | import cn.edu.tju.simulation.content.SingleLocalHobby; 7 | import cn.edu.tju.simulation.controller.Controller; 8 | import cn.edu.tju.simulation.wirelessnetwork.SameTypeWirelessNetwork; 9 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 10 | 11 | /** 12 | * Use the Greedy Algorithm to configure the cache 13 | * 14 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 15 | * 16 | */ 17 | public class GreedyAlgorithm implements OneTimeAlgorithm{ 18 | Controller controller = Controller.getInstance(); 19 | List list = null; 20 | SameTypeWirelessNetwork BSs = null; 21 | 22 | public GreedyAlgorithm(){ 23 | Controller controller = Controller.getInstance(); 24 | BSs = controller.getWirelessNetworkGroup().BS; 25 | 26 | 27 | } 28 | 29 | /** 30 | * Configure cache 31 | * @param controller 32 | */ 33 | public void setCache() { 34 | for (int i = 0; i < BSs.getAmount(); i++) { 35 | WirelessNetwork network = BSs.getNetwork(i); 36 | list = ContentService.sortByAverageHobby(network.getCanBeCachedContent()); 37 | // list = ContentService.sortByHobby(network.getCanBeCachedContent()); 38 | } 39 | 40 | for (int i = 0; i < BSs.getAmount(); i++) { 41 | WirelessNetwork network = BSs.getNetwork(i); 42 | long size = network.getCacheSize(); 43 | for(int n = 0 ; n < list.size() ; n ++){ 44 | SingleLocalHobby singleContent = list.get(n); 45 | if (size >= singleContent.getSize() && size > 0) { 46 | if(network.addCacheContent(singleContent)){ 47 | size -= singleContent.getSize(); 48 | } 49 | } 50 | } 51 | 52 | int maxPopularity = 0; 53 | 54 | for(int j = 0;j cachingContentList = network.getCacheContent(); 24 | CachingSingleContent includeContent = include(cachingContentList,requestContent); 25 | 26 | if (includeContent != null) { 27 | cachingContentList.remove(includeContent); 28 | cachingContentList.addFirst(includeContent); 29 | } else if (network.getCacheSize() >= requestContent.getSize()) { 30 | if (remainingSize >= requestContent.getSize()) { 31 | cachingContentList.addFirst(new CachingSingleContent(requestContent.getSingleContent())); 32 | } else { 33 | while(cachingContentList.size()!=0){ 34 | remainingSize += cachingContentList.getLast().getSize(); 35 | cachingContentList.removeLast(); 36 | if(remainingSize >= requestContent.getSize()){ 37 | cachingContentList.addFirst(new CachingSingleContent(requestContent.getSingleContent())); 38 | break; 39 | } 40 | } 41 | } 42 | 43 | } 44 | Controller.getInstance().appendLog("debug", "LRU is Updating Cache", null); 45 | } 46 | 47 | public CachingSingleContent include(List cacheContent, SingleLocalHobby content) { 48 | Iterator it = cacheContent.iterator(); 49 | while (it.hasNext()) { 50 | CachingSingleContent csc = it.next(); 51 | if (csc.getSingleContent() == content.getSingleContent()) { 52 | return csc; 53 | } 54 | } 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/CaseFileWriter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStreamWriter; 7 | import java.util.Iterator; 8 | 9 | import cn.edu.tju.simulation.controller.Controller; 10 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 11 | 12 | /** 13 | * Save the case file. The case file is used to record the configuration of the network system. 14 | * For example, you designed the network topology and configured the radius, cache size, and other information for each base station. When you do the next simulation, you want to call this case directly, and you can choose to save it as a case file. 15 | * 16 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 17 | * 18 | */ 19 | public class CaseFileWriter { 20 | 21 | public Boolean write(Controller controller , File file){ 22 | 23 | FileOutputStream fos = null; 24 | OutputStreamWriter out = null; 25 | try { 26 | fos = new FileOutputStream(file); 27 | out = new OutputStreamWriter(fos); 28 | out.write("#WirelessNetwork\r\n"); 29 | 30 | Iterator it = controller.getWirelessNetworkGroup().BS.getIterator(); 31 | while(it.hasNext()){ 32 | WirelessNetwork network = (WirelessNetwork) it.next(); 33 | out.write(network.getNumber()+" "+network.getLocation().getX()+" "+network.getLocation().getY()+" "+network.getRadius()+" "+network.getCacheSize()+"\r\n"); 34 | } 35 | out.write("#WirelessNetworkWave\r\n"); 36 | out.write(Parameter.BSMinWaveInterval+" "+Parameter.BSMaxWaveInterval); 37 | 38 | return true; 39 | } catch (IOException e1) { 40 | e1.printStackTrace(); 41 | }finally{ 42 | try { 43 | if(out!=null){ 44 | out.close(); 45 | }if(fos!=null){ 46 | fos.close(); 47 | } 48 | } catch (IOException e1) { 49 | e1.printStackTrace(); 50 | } 51 | } 52 | return false; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/BaseStation.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.wirelessnetwork; 2 | 3 | import java.awt.geom.Point2D; 4 | import java.util.ArrayList; 5 | import java.util.LinkedList; 6 | 7 | import cn.edu.tju.simulation.content.CachingSingleContent; 8 | import cn.edu.tju.simulation.content.LocalHobby; 9 | import cn.edu.tju.simulation.state.State; 10 | import cn.edu.tju.simulation.user.MobilityModel; 11 | 12 | /** 13 | * Base station 14 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 15 | * 16 | */ 17 | public class BaseStation extends WirelessNetwork{ 18 | 19 | @Override 20 | public int countUserOfNetwork() { 21 | //The size of the user's collection in the current network 22 | return userOfNetwork.size(); 23 | } 24 | 25 | /** 26 | * Generate a base station with a cache 27 | * @param number ID of base station 28 | * @param location The midpoint of the base station 29 | */ 30 | public BaseStation(int number,Point2D.Double location,Boolean Cache,long CacheSize,int Radius){ 31 | this.hasCache =Cache; 32 | if(this.hasCache == true){ 33 | cacheContent = new LinkedList(); 34 | }else{ 35 | cacheContent =null; 36 | } 37 | this.cacheRequestAmount = 0; 38 | this.hitAmount = 0; 39 | this.number = number; 40 | this.location = location; 41 | this.type = "BS"; 42 | this.cacheSize = CacheSize; 43 | this.radius = Radius; 44 | this.content = new LocalHobby(); 45 | this.userOfNetwork = new ArrayList(); 46 | this.relationalWirelessNetwork = new RelationalWirelessNetwork(); 47 | this.statesQueue = new ArrayList(); 48 | } 49 | 50 | public BaseStation(Point2D.Double location,Boolean Cache,long CacheSize,int Radius){ 51 | this.hasCache =Cache; 52 | if(this.hasCache == true){ 53 | cacheContent = new LinkedList(); 54 | }else{ 55 | cacheContent =null; 56 | } 57 | this.number = -1; 58 | this.cacheRequestAmount = 0; 59 | this.hitAmount = 0; 60 | this.location = location; 61 | this.type = "BS"; 62 | this.cacheSize = CacheSize; 63 | this.radius = Radius; 64 | this.content = new LocalHobby(); 65 | this.userOfNetwork = new ArrayList(); 66 | this.relationalWirelessNetwork = new RelationalWirelessNetwork(); 67 | this.statesQueue = new ArrayList(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/algorithm/FIFOAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.algorithm; 2 | 3 | import cn.edu.tju.simulation.content.CachingSingleContent; 4 | import cn.edu.tju.simulation.content.SingleLocalHobby; 5 | import cn.edu.tju.simulation.controller.Controller; 6 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 7 | 8 | import java.util.Iterator; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | public class FIFOAlgorithm implements RealTimeAlgorithm { 13 | 14 | public void setCache(WirelessNetwork network, SingleLocalHobby requestContent) { 15 | long remainingSize = network.getRemainingCacheSize(); 16 | LinkedList cachingContentList = network.getCacheContent(); 17 | CachingSingleContent includeContent = include(cachingContentList,requestContent); 18 | 19 | if (includeContent != null) { 20 | cachingContentList.remove(includeContent); 21 | cachingContentList.addLast(includeContent); 22 | 23 | } else if (network.getCacheSize() >= requestContent.getSize()) { 24 | 25 | if (remainingSize >= requestContent.getSize()) { 26 | cachingContentList.addLast(new CachingSingleContent(requestContent.getSingleContent())); 27 | } else { 28 | while(cachingContentList.size()!=0){ 29 | remainingSize += cachingContentList.getFirst().getSize(); 30 | cachingContentList.removeFirst(); 31 | if(remainingSize >= requestContent.getSize()){ 32 | cachingContentList.addFirst(new CachingSingleContent(requestContent.getSingleContent())); 33 | break; 34 | } 35 | } 36 | } 37 | 38 | 39 | 40 | } 41 | Controller.getInstance().appendLog("debug", "FIFO is Updating Cache", null); 42 | } 43 | 44 | public CachingSingleContent include(List cacheContent, SingleLocalHobby content) { 45 | Iterator it = cacheContent.iterator(); 46 | while (it.hasNext()) { 47 | CachingSingleContent csc = it.next(); 48 | if (csc.getSingleContent() == content.getSingleContent()) { 49 | return csc; 50 | } 51 | } 52 | return null; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/state/StateQueue.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.state; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | 8 | import org.apache.log4j.Logger; 9 | 10 | import cn.edu.tju.simulation.controller.Controller; 11 | import cn.edu.tju.simulation.file.Parameter; 12 | import cn.edu.tju.simulation.user.MobilityModel; 13 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 14 | 15 | /** 16 | * 17 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 18 | * 19 | */ 20 | public class StateQueue { 21 | private HashMap> stateQueueMap; 22 | /** 23 | * Log 24 | */ 25 | private static Logger logger = Logger.getLogger(StateQueue.class); 26 | 27 | public void generateStateQueue(){ 28 | Controller controller = Controller.getInstance(); 29 | controller.appendLog("debug","Create status...",logger); 30 | 31 | stateQueueMap.clear(); 32 | 33 | for(int i = 0; i < Parameter.TimeSlicesMaxNumber; i++){ 34 | List list = new ArrayList(); 35 | if(i == 0){ 36 | this.stateQueueMap.put(i, controller.getUsers().generateStateList()); 37 | }else{ 38 | List simpleUserList = controller.getUsers().getSimpleUsers(); 39 | for(int k = 0 ; k < simpleUserList.size() ; k++){ 40 | State state = simpleUserList.get(k).generateState(); 41 | if(state != null ){ 42 | list.add(state); 43 | } 44 | } 45 | this.stateQueueMap.put(i,list); 46 | } 47 | } 48 | } 49 | 50 | public void assignStateToNetwork(int key){ 51 | Controller controller = Controller.getInstance(); 52 | Iterator it = controller.getWirelessNetworkGroup().BS.getIterator(); 53 | while(it.hasNext()){ 54 | it.next().getStatesQueue().clear(); 55 | } 56 | 57 | //choose one state queue 58 | List stateList = controller.getStateQueue().getStateList(key); 59 | 60 | Iterator mIt = stateList.iterator(); 61 | while(mIt.hasNext()){ 62 | State state = mIt.next(); 63 | state.getUser().getWirelessNetwork().getStatesQueue().add(state); 64 | } 65 | } 66 | 67 | public StateQueue(){ 68 | this.stateQueueMap = new HashMap>(); 69 | } 70 | 71 | public Iterator getStateListIterator(int times){ 72 | return stateQueueMap.get(times).iterator(); 73 | } 74 | 75 | public List getStateList(int times){ 76 | return stateQueueMap.get(times); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/CaseFileReader.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | import cn.edu.tju.simulation.controller.Controller; 9 | import cn.edu.tju.simulation.tool.StringHandler; 10 | 11 | /** 12 | * Open the case file. The case file is used to record the configuration of the network system. 13 | * For example, you designed the network topology and configured the radius, cache size, and other information for each base station. When you do the next simulation, you want to call this case directly, and you can choose to save it as a case file. 14 | * 15 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 16 | * 17 | */ 18 | public class CaseFileReader { 19 | 20 | public Boolean read(Controller controller,File file){ 21 | FileReader fileReader = null; 22 | BufferedReader bufferedReader = null; 23 | controller.getWirelessNetworkGroup().BS.clear(); 24 | if(file.exists()){ 25 | try { 26 | fileReader = new FileReader(file); 27 | } catch (FileNotFoundException e1) { 28 | e1.printStackTrace(); 29 | } 30 | bufferedReader = new BufferedReader(fileReader); 31 | String line; 32 | Boolean checkNetwork = false; 33 | Boolean checkNetworkWave = false; 34 | try { 35 | while ((line = bufferedReader.readLine()) != null) { 36 | if(line.equals("#WirelessNetwork")){ 37 | checkNetwork = true; 38 | continue; 39 | }else if(!line.equals("#WirelessNetwork") && !line.equals("#WirelessNetworkWave") && checkNetwork ==true){ 40 | controller.getWirelessNetworkGroup().BS.addWirelessNetwork(StringHandler.readBS(line)); 41 | continue; 42 | }else if(line.equals("#WirelessNetworkWave")){ 43 | checkNetworkWave = true; 44 | checkNetwork = false; 45 | }else if(!line.equals("#WirelessNetwork") && !line.equals("#WirelessNetworkWave") && checkNetworkWave ==true){ 46 | String Wave []= line.split(" "); 47 | Parameter.BSMinWaveInterval = Float.parseFloat(Wave[0]); 48 | Parameter.BSMaxWaveInterval = Float.parseFloat(Wave[1]); 49 | } 50 | } 51 | if(checkNetwork == false && checkNetworkWave == true){ 52 | return true; 53 | }else{ 54 | return false; 55 | } 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | }finally{ 59 | try { 60 | if (bufferedReader != null) { 61 | bufferedReader.close(); 62 | } 63 | if (fileReader != null) { 64 | fileReader.close(); 65 | } 66 | } catch (IOException e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | } 71 | return false; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/state/State.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.state; 2 | 3 | import cn.edu.tju.simulation.content.SingleLocalHobby; 4 | import cn.edu.tju.simulation.user.MobilityModel; 5 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 6 | 7 | /** 8 | * Status 9 | * 10 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin 11 | * University 12 | * 13 | */ 14 | public class State implements Cloneable { 15 | /** 16 | * The user to whom this status belongs 17 | */ 18 | private MobilityModel user; 19 | /** 20 | * Whether this user request content 21 | */ 22 | private Boolean request; 23 | /** 24 | * Download content in this state 25 | */ 26 | private SingleLocalHobby requestSingleContent; 27 | /** 28 | * Download time 29 | */ 30 | private double latency; 31 | 32 | private int remainingTimeSlotNumber; 33 | 34 | /** 35 | * 36 | * @param mobilityModel 37 | * State belongs to the user 38 | * @param latency 39 | * The time this state occurred 40 | * @param media 41 | * Download content in this state 42 | */ 43 | public State(MobilityModel user, SingleLocalHobby requestSingleContent) { 44 | this.user = user; 45 | this.latency = requestSingleContent.getSize() / user.getDownloadRate(); 46 | System.out.println(requestSingleContent.getSize() + "KB " + user.getDownloadRate()+"KB/s"); 47 | System.out.println(this.latency + "s"); 48 | this.request = true; 49 | this.requestSingleContent = requestSingleContent; 50 | this.remainingTimeSlotNumber = requestSingleContent.getTimeSlotNumber(); 51 | } 52 | 53 | @Override 54 | public Object clone() { 55 | State state = null; 56 | try { 57 | state = (State) super.clone(); 58 | } catch (CloneNotSupportedException e) { 59 | e.printStackTrace(); 60 | } 61 | return state; 62 | } 63 | 64 | public void cutTimeSlotNumber() { 65 | this.remainingTimeSlotNumber--; 66 | } 67 | 68 | public double getLatency() { 69 | return latency; 70 | } 71 | 72 | public void setLatency(double time) { 73 | this.latency = time; 74 | } 75 | 76 | public SingleLocalHobby getRequestSingleContent() { 77 | return requestSingleContent; 78 | } 79 | 80 | public void setRequestSingleContent(SingleLocalHobby requestSingleContent) { 81 | this.requestSingleContent = requestSingleContent; 82 | } 83 | 84 | public WirelessNetwork getNetwork() { 85 | return this.user.getWirelessNetwork(); 86 | } 87 | 88 | public MobilityModel getUser() { 89 | return user; 90 | } 91 | 92 | public Boolean getRequest() { 93 | return request; 94 | } 95 | 96 | public int getRemainingTimeSlotNumber() { 97 | return remainingTimeSlotNumber; 98 | } 99 | 100 | public void setRemainingTimeSlotNumber(int remainingTimeSlotNumber) { 101 | this.remainingTimeSlotNumber = remainingTimeSlotNumber; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/content/LocalHobby.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.content; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | public class LocalHobby { 11 | private List contentList; 12 | 13 | public LocalHobby(){ 14 | this.contentList = new ArrayList(); 15 | } 16 | 17 | public SingleLocalHobby getSingleContentByName(String name){ 18 | for (SingleLocalHobby sc : contentList) { 19 | if(sc.getSingleContent().getName().equals(name)){ 20 | return sc; 21 | } 22 | } 23 | return null; 24 | } 25 | 26 | public SingleLocalHobby getSingleLocalHobbyBySingleContent(SingleContent isc){ 27 | Iterator it = this.contentList.iterator(); 28 | while(it.hasNext()){ 29 | SingleLocalHobby sh = it.next(); 30 | if(sh.getSingleContent() == isc){ 31 | return sh; 32 | } 33 | } 34 | return null; 35 | } 36 | 37 | 38 | public void setContentList(List content) { 39 | this.contentList = content; 40 | } 41 | 42 | public void clear(){ 43 | this.contentList.clear(); 44 | } 45 | 46 | public void addSingleContent(SingleLocalHobby singleContent){ 47 | this.contentList.add(singleContent); 48 | } 49 | 50 | public void addSingleContentAmount(SingleContent singleContent){ 51 | for(int i = 0 ;i () { 62 | public int compare(SingleLocalHobby contentOne, SingleLocalHobby contentTwo) { 63 | return contentOne.getLocalHobbyValue() == contentTwo.getLocalHobbyValue() ? 0 : 64 | (contentOne.getLocalHobbyValue() > contentTwo.getLocalHobbyValue() ? -1 : 1); 65 | } 66 | }); 67 | } 68 | } 69 | 70 | public void fluctuatePopularity(float min ,float max,List contentList){ 71 | if(max >= min){ 72 | Random r = new Random(); 73 | this.contentList.clear(); 74 | for(int j =0;j getContentList(){ 87 | return this.contentList; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/resources/data/ResultData: -------------------------------------------------------------------------------- 1 | Algorithm:LRU 2 | 0,0.009677419,16.45906943044355,14171 1,0.0033898305,17.361226606638414,4830 2,0.0034129692,17.01016002737486,112654 3,0.0063897762,16.858457717651753,62186 4,0.0065789474,16.37702700966283,69993 5,0.0031746032,16.165676669973543,11950 6,0.0069444445,16.47152483904804,33645 7,0.009063444,16.820801272973316,91632 3 | 8,0.0,16.260942338823202,0 9,0.013559322,16.92295087394067,142900 10,0.0031847134,15.708269058519134,3517 11,0.0064102565,16.038455278445515,11173 12,0.0033898305,16.592500882768356,1618 13,0.0032573289,16.69434548045602,386 14,0.0,16.77389475334449,0 15,0.009287925,16.10471995130287,74921 4 | 16,0.0,16.37981416524944,0 17,0.015923567,16.930695163216562,27113 18,0.0,16.939094847353235,0 19,0.003267974,16.47876668028323,25728 20,0.0031847134,17.107266371417193,49729 21,0.010344828,16.99080010775862,86269 22,0.00729927,16.820791276992093,12561 23,0.010067114,16.529875821448552,20343 5 | 24,0.006688963,17.951083690426408,31599 25,0.0,16.569432831661093,0 26,0.0034482758,16.764185973419536,15489 27,0.0,16.778794297226913,0 28,0.016666668,16.504193793402777,68553 29,0.0077220076,16.704541455518008,24692 30,0.0035714286,16.12848656063987,8440 31,0.0032258064,16.290049563172047,5487 6 | 32,0.0033557047,16.358626739024043,99874 33,0.0034129692,16.65001066552902,9966 34,0.0036101083,16.532117272111925,12661 35,0.006451613,16.13385206653226,66936 36,0.006535948,15.982117630038115,12800 37,0.0,16.96226936284175,0 38,0.00754717,15.611519752358491,17857 39,0.003322259,16.546974494739754,43966 7 | 40,0.014134276,16.17477708149294,97826 41,0.0,16.788611860409898,0 42,0.006329114,16.273188208728904,26029 43,0.0100334445,16.07339133918616,70738 44,0.003215434,16.51107084840568,6997 8 | Algorithm:KNAPSACK 9 | 0,0.12258065,15.330037172379026,66373 1,0.07118644,16.683260504943497,33057 2,0.11604095,15.88388016389363,54430 3,0.11821086,15.740246855031947,62030 4,0.108552635,15.357290167557565,55890 5,0.11746032,15.022819527116402,66053 6,0.13194445,15.22152483904804,49656 7,0.12688822,15.642553538834338,73688 10 | 8,0.10810811,15.179861257742122,42293 9,0.14915255,15.567018670550857,67195 10,0.12420382,14.498077975716578,62277 11,0.13141026,14.788455278445516,74781 12,0.13220339,15.304365289548018,66348 13,0.14983714,15.228547434853418,58528 14,0.16722408,15.101653950668897,84430 15,0.13003096,14.897289610745602,61215 11 | 16,0.11904762,15.189337974773235,56039 17,0.11464968,15.943434016719747,54989 18,0.10377359,15.901358998296624,45897 19,0.14379086,15.073537922113287,73255 20,0.089171976,16.247393759952228,45292 21,0.113793105,15.956317349137928,48399 22,0.13138686,15.579915364583329,66008 23,0.110738255,15.523164412052573,62866 12 | 24,0.11371238,16.88084957671404,48890 25,0.09698997,15.599533166109248,46893 26,0.13448276,15.453841145833344,58943 27,0.0945946,15.832848351280976,39309 28,0.083333336,15.837527126736108,41556 29,0.13127413,15.469020219996782,54161 30,0.13571429,14.807057989211302,55348 31,0.1,15.322307627688179,42136 13 | 32,0.11409396,15.251244188688474,61969 33,0.0784983,15.899157423208191,36658 34,0.15162455,15.051972867779794,60091 35,0.11935484,15.00481980846775,58295 36,0.10130719,15.034405211737463,51933 37,0.13564669,15.60580248587014,65321 38,0.116981134,14.517180129716978,54797 39,0.11960133,15.38418379706533,56103 14 | 40,0.12720849,15.044035032022984,43939 41,0.104234524,15.746266583536928,53769 42,0.10759494,15.26052998088081,51923 43,0.12374582,14.936267593366765,54244 44,0.1221865,15.3213602374732,64291 15 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/RandomBSReader.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | import java.awt.geom.Point2D; 4 | import java.io.IOException; 5 | 6 | import javax.xml.parsers.DocumentBuilder; 7 | import javax.xml.parsers.DocumentBuilderFactory; 8 | import javax.xml.parsers.ParserConfigurationException; 9 | 10 | import org.w3c.dom.Document; 11 | import org.w3c.dom.Element; 12 | import org.w3c.dom.Node; 13 | import org.w3c.dom.NodeList; 14 | import org.xml.sax.SAXException; 15 | 16 | import cn.edu.tju.simulation.controller.Controller; 17 | import cn.edu.tju.simulation.swing.operator.Signal; 18 | import cn.edu.tju.simulation.wirelessnetwork.BaseStation; 19 | 20 | /** 21 | * Read the pre-saved network system. The pre-saved network system is stored in RANDOMBS.xml, 22 | * which contains a variety of different topologies, each reading is random. 23 | * 24 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 25 | */ 26 | public class RandomBSReader implements XMLReader{ 27 | public void parserXML() { 28 | try { 29 | Controller controller = Controller.getInstance(); 30 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 31 | DocumentBuilder db = dbf.newDocumentBuilder(); 32 | Document document = db.parse("src/main/resources/data/RANDOMBS.xml"); 33 | NodeList randombss = document.getChildNodes(); 34 | 35 | for (int i = 0; i < randombss.getLength(); i++) { 36 | Node randombs = randombss.item(i); 37 | Node group = null; 38 | if (randombs instanceof Element) { 39 | NodeList groups = randombs.getChildNodes(); 40 | while (true) { 41 | int random = (int) (Math.random() * 10); 42 | group = groups.item(random); 43 | if(group instanceof Element && random != Signal.BSFileNumber && random < groups.getLength()){ 44 | group = groups.item(random); 45 | Signal.BSFileNumber = random ; 46 | break; 47 | } 48 | } 49 | 50 | NodeList BSs = group.getChildNodes(); 51 | 52 | for (int k = 0; k < BSs.getLength(); k++) { 53 | Node BSMeta = BSs.item(k); 54 | NodeList BSInfo = BSMeta.getChildNodes(); 55 | 56 | int location_x = 0, location_y = 0, CacheSize = 0, Radius = 0; 57 | Boolean Cache = null; 58 | if (BSMeta instanceof Element) { 59 | for (int n = 0; n < BSInfo.getLength(); n++) { 60 | Node item = BSInfo.item(n); 61 | if (item instanceof Element) { 62 | if (item.getNodeName().equals("location_x")) { 63 | location_x = Integer.parseInt(item.getTextContent()); 64 | } else if (item.getNodeName().equals("location_y")) { 65 | location_y = Integer.parseInt(item.getTextContent()); 66 | } else if (item.getNodeName().equals("Cache")) { 67 | Cache = Boolean.parseBoolean(item.getTextContent()); 68 | } else if (item.getNodeName().equals("CacheSize")) { 69 | CacheSize = Integer.parseInt(item.getTextContent()); 70 | } else if (item.getNodeName().equals("Radius")) { 71 | Radius = Integer.parseInt(item.getTextContent()); 72 | } 73 | 74 | } 75 | } 76 | controller.getWirelessNetworkGroup().BS.addWirelessNetwork(new BaseStation(controller.getWirelessNetworkGroup().getBSAmount(),new Point2D.Double(location_x, location_y),Cache, CacheSize, Radius)); 77 | } 78 | } 79 | } 80 | } 81 | } catch (ParserConfigurationException e) { 82 | e.printStackTrace(); 83 | } catch (SAXException e) { 84 | e.printStackTrace(); 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/BaseLineChart.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.chart; 2 | 3 | 4 | import org.jfree.chart.ChartFactory; 5 | import org.jfree.chart.ChartFrame; 6 | import org.jfree.chart.JFreeChart; 7 | import org.jfree.chart.axis.NumberAxis; 8 | import org.jfree.chart.axis.NumberTickUnit; 9 | import org.jfree.chart.plot.PlotOrientation; 10 | import org.jfree.chart.plot.XYPlot; 11 | import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; 12 | import org.jfree.chart.title.LegendTitle; 13 | import org.jfree.chart.ui.HorizontalAlignment; 14 | import org.jfree.chart.ui.RectangleEdge; 15 | import org.jfree.data.xy.XYSeriesCollection; 16 | 17 | import java.awt.*; 18 | import java.text.NumberFormat; 19 | 20 | /** 21 | * The base class of the line chart 22 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 23 | * 24 | */ 25 | public abstract class BaseLineChart { 26 | private JFreeChart chart; 27 | private ChartFrame chartFrame; 28 | 29 | public BaseLineChart() { 30 | 31 | } 32 | 33 | protected void generateLineChart(String xAisTitle, String yAisTitle, 34 | NumberTickUnit xAisSpace, NumberTickUnit yAisSpace, double yaisMinValue, double yAisMaxValue, 35 | XYSeriesCollection collection) { 36 | this.chart = ChartFactory.createXYLineChart(null, xAisTitle, yAisTitle, 37 | collection, PlotOrientation.VERTICAL, true, true, false); 38 | 39 | this.chart.getPlot().setBackgroundPaint(SystemColor.white); 40 | 41 | LegendTitle legend = chart.getLegend(); 42 | legend.setPosition(RectangleEdge.RIGHT); 43 | legend.setHorizontalAlignment(HorizontalAlignment.LEFT); 44 | 45 | XYPlot plot = (XYPlot) chart.getPlot(); 46 | NumberAxis numberAxisX = (NumberAxis) chart.getXYPlot().getDomainAxis(); 47 | numberAxisX.setAutoRangeIncludesZero(false); 48 | 49 | numberAxisX.setTickUnit(xAisSpace); 50 | numberAxisX.setAxisLineVisible(false); 51 | numberAxisX.setTickMarkInsideLength(4f); 52 | numberAxisX.setTickMarkOutsideLength(0); 53 | 54 | NumberAxis numberAxisY = (NumberAxis) chart.getXYPlot().getRangeAxis(); 55 | numberAxisY.setTickUnit(yAisSpace); 56 | numberAxisY.setRangeWithMargins(yaisMinValue, yAisMaxValue); 57 | numberAxisY.setAutoRangeIncludesZero(true); 58 | numberAxisY.setAxisLineVisible(false); 59 | numberAxisY.setTickMarkInsideLength(4f); 60 | numberAxisY.setTickMarkOutsideLength(0); 61 | numberAxisY.setNumberFormatOverride(NumberFormat.getNumberInstance()); 62 | 63 | XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot 64 | .getRenderer(); 65 | // renderer.setBaseItemLabelsVisible(true); 66 | renderer.setDefaultItemLabelsVisible(true); 67 | renderer.setDefaultShapesVisible(true); 68 | // renderer.setBaseShapesVisible(true); 69 | renderer.setDrawOutlines(true); 70 | 71 | renderer.setSeriesOutlineStroke(0, new BasicStroke(5F)); 72 | renderer.setSeriesOutlineStroke(1, new BasicStroke(5F)); 73 | renderer.setSeriesOutlineStroke(2, new BasicStroke(5F)); 74 | renderer.setSeriesOutlineStroke(3, new BasicStroke(5F)); 75 | renderer.setSeriesOutlineStroke(4, new BasicStroke(5F)); 76 | 77 | renderer.setSeriesPaint(0, Color.RED); 78 | renderer.setSeriesPaint(1, Color.BLUE); 79 | renderer.setSeriesPaint(2, new Color(255, 125, 11)); 80 | renderer.setSeriesPaint(3, new Color(0, 161, 59)); 81 | renderer.setSeriesPaint(4, new Color(148, 103, 189)); 82 | 83 | renderer.setSeriesStroke(0, new BasicStroke(4.0F)); 84 | renderer.setSeriesStroke(1, new BasicStroke(4.0F)); 85 | renderer.setSeriesStroke(2, new BasicStroke(4.0F)); 86 | renderer.setSeriesStroke(3, new BasicStroke(4.0F)); 87 | renderer.setSeriesStroke(4, new BasicStroke(2.0F)); 88 | renderer.setSeriesStroke(5, new BasicStroke(2.0F)); 89 | 90 | // renderer.setUseFillPaint(true); 91 | 92 | this.chartFrame = new ChartFrame("Line Chart", chart); 93 | chartFrame.pack(); 94 | chartFrame.setSize(800, 600); 95 | chartFrame.setLocation(300, 200); 96 | chartFrame.setVisible(true); 97 | } 98 | 99 | public abstract void draw(); 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/Latency.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pylab as plt 2 | from matplotlib.ticker import MultipleLocator 3 | from matplotlib.ticker import FormatStrFormatter 4 | import sys 5 | import os 6 | 7 | #this is the Absolute path 8 | # DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("\src")] + "main\resources\data\ResultData") 9 | #Relative path , which determined by the caller 10 | DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("src")]) + "src\main\\resources\data\ResultData" 11 | 12 | class Algorithm_Data: 13 | def __init__(self, Algorithm): 14 | self.Algorithm = Algorithm 15 | self.Data = [0] 16 | ''' 17 | Read result file 18 | ''' 19 | algorithm_data_list = [] 20 | with open(DATA_FILE_PATH, encoding='utf-8') as ResultData_Reader: 21 | for line in ResultData_Reader: 22 | if "Algorithm" in line.split(" ")[0]: 23 | algorithm = Algorithm_Data(line.split(":")[1]) 24 | algorithm_data_list.append(algorithm) 25 | else: 26 | line_data = line.split(" ") 27 | for data in line_data: 28 | data = data.split(",") 29 | if len(data) == 4: 30 | algorithm_data_list[-1].Data.append(float(data[2])) 31 | 32 | ''' 33 | line chart 34 | ''' 35 | # set the image size of the output 36 | figsize = 7.5, 6 37 | figure, ax = plt.subplots(num="DELAY", figsize=figsize) 38 | 39 | ''' 40 | set the scale 41 | ''' 42 | #set the coordinate range of value 43 | plt.ylim(0, 50) 44 | plt.xlim(0, len(algorithm_data_list[-1].Data)+1) 45 | #set the scale 46 | #set the x major scale label to a multiple of 5 47 | xmajorLocator = MultipleLocator(20); 48 | #set the format of the x-axis label text 49 | xmajorFormatter = FormatStrFormatter('%3.0f') 50 | #Set the x-axis minor scale label to a multiple of 1 51 | xminorLocator = MultipleLocator(1) 52 | #Load x-axis settings 53 | ax.xaxis.set_major_locator(xmajorLocator) 54 | ax.xaxis.set_major_formatter(xmajorFormatter) 55 | #Set the y-axis main scale label to a multiple of 0.05% 56 | ymajorLocator = MultipleLocator(10) 57 | #Set the format of the y-axis label text 58 | ymajorFormatter = FormatStrFormatter('%3.0f') 59 | #Set this y-axis minor tick label to a multiple of 0.2 60 | yminorLocator = MultipleLocator(1) 61 | #Load y-axis settings 62 | # ax.yaxis.set_major_locator(ymajorLocator) 63 | # ax.yaxis.set_major_formatter(ymajorFormatter) 64 | # # Shows the position of the subscale label, but no label text 65 | # ax.xaxis.set_minor_locator(xminorLocator) 66 | # ax.yaxis.set_minor_locator(yminorLocator) 67 | # ax.xaxis.grid(True, which='major') # The grid of the x-axis uses the major scale 68 | # ax.yaxis.grid(True, which='minor') # The grid of the y-axis uses the minor scale 69 | 70 | ''' 71 | Set the font of the axis 72 | ''' 73 | font = {'family': 'Times New Roman', 74 | 'weight': 'normal', 75 | 'size': 18, 76 | } 77 | # Set the font of the scale value 78 | label_font = {'family': 'Times New Roman', 79 | 'weight': 'bold', 80 | 'size': 16,} 81 | plt.xlabel(label_font) 82 | plt.ylabel(label_font) 83 | ''' 84 | Drawing 85 | ''' 86 | for algorithm in algorithm_data_list: 87 | if "KNAPSACK" in algorithm.Algorithm: 88 | plt.plot(algorithm.Data, color = 'red', marker= "o", linewidth=2, markersize = 10, label=algorithm.Algorithm) 89 | elif "GREEDY" in algorithm.Algorithm: 90 | plt.plot(algorithm.Data, color = 'blue', marker= ">", linewidth=2, markersize = 10, label=algorithm.Algorithm) 91 | elif "LFU" in algorithm.Algorithm: 92 | plt.plot(algorithm.Data, color = 'orange', marker= "p",linewidth=2, markersize = 10, linestyle="--", label=algorithm.Algorithm) 93 | elif "LRU" in algorithm.Algorithm: 94 | plt.plot(algorithm.Data, color = 'green', marker= "*", linewidth=2, markersize = 10, linestyle=":", label=algorithm.Algorithm) 95 | else: 96 | plt.plot(algorithm.Data, linewidth=2, label=algorithm.Algorithm) 97 | 98 | 99 | 100 | plt.xlabel("Time Silce", font) 101 | plt.ylabel("Delay(s)", font) 102 | 103 | ''' 104 | Set legend 105 | ''' 106 | font_legend = {'family': 'Times New Roman', 'weight': 'bold', 'size': 12} 107 | plt.legend(prop=font_legend, loc=1, numpoints=1, ncol = 1) 108 | 109 | ltext = plt.gca().get_legend().get_texts() 110 | 111 | plt.show() 112 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/Traffic.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pylab as plt 2 | from matplotlib.ticker import MultipleLocator 3 | from matplotlib.ticker import FormatStrFormatter 4 | import sys 5 | import os 6 | 7 | #this is the Absolute path 8 | # DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("\src")] + "main\resources\data\ResultData") 9 | #Relative path , which determined by the caller 10 | DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("src")]) + "src\main\\resources\data\ResultData" 11 | 12 | class Algorithm_Data: 13 | def __init__(self, Algorithm): 14 | self.Algorithm = Algorithm 15 | self.Data = [0] 16 | ''' 17 | Read result file 18 | ''' 19 | algorithm_data_list = [] 20 | with open(DATA_FILE_PATH, encoding='utf-8') as ResultData_Reader: 21 | for line in ResultData_Reader: 22 | if "Algorithm" in line.split(" ")[0]: 23 | algorithm = Algorithm_Data(line.split(":")[1]) 24 | algorithm_data_list.append(algorithm) 25 | else: 26 | line_data = line.split(" ") 27 | for data in line_data: 28 | data = data.split(",") 29 | if len(data) == 4: 30 | algorithm_data_list[-1].Data.append(float(data[3])/1024/1024) 31 | 32 | ''' 33 | line chart 34 | ''' 35 | # set the image size of the output 36 | figsize = 7.5, 6 37 | figure, ax = plt.subplots(num="TRAFFIC AFFLOAD", figsize=figsize) 38 | 39 | ''' 40 | set the scale 41 | ''' 42 | #set the coordinate range of value 43 | plt.ylim(0, 0.4) 44 | plt.xlim(0, len(algorithm_data_list[-1].Data)) 45 | #set the scale 46 | #set the x major scale label to a multiple of 5 47 | xmajorLocator = MultipleLocator(2); 48 | #set the format of the x-axis label text 49 | xmajorFormatter = FormatStrFormatter('%3.0f') 50 | #Set the x-axis minor scale label to a multiple of 1 51 | # xminorLocator = MultipleLocator(2) 52 | #Load x-axis settings 53 | ax.xaxis.set_major_locator(xmajorLocator) 54 | ax.xaxis.set_major_formatter(xmajorFormatter) 55 | #Set the y-axis main scale label to a multiple of 0.05% 56 | ymajorLocator = MultipleLocator(0.1) 57 | #Set the format of the y-axis label text 58 | ymajorFormatter = FormatStrFormatter('%.2f') 59 | #Set this y-axis minor tick label to a multiple of 0.2 60 | # yminorLocator = MultipleLocator(0.2) 61 | #Load y-axis settings 62 | ax.yaxis.set_major_locator(ymajorLocator) 63 | ax.yaxis.set_major_formatter(ymajorFormatter) 64 | # Shows the position of the subscale label, but no label text 65 | # 66 | # ax.xaxis.set_minor_locator(xminorLocator) 67 | # ax.yaxis.set_minor_locator(yminorLocator) 68 | # ax.xaxis.grid(True, which='minor') # The grid of the x-axis uses the major scale 69 | # ax.yaxis.grid(True, which='minor') # The grid of the y-axis uses the minor scale 70 | 71 | ''' 72 | Set the font of the axis 73 | ''' 74 | font = {'family': 'Times New Roman', 75 | 'weight': 'normal', 76 | 'size': 18, 77 | } 78 | # Set the font of the scale value 79 | label_font = {'family': 'Times New Roman', 80 | 'weight': 'bold', 81 | 'size': 16,} 82 | plt.xlabel(label_font) 83 | plt.ylabel(label_font) 84 | ''' 85 | Drawing 86 | ''' 87 | for algorithm in algorithm_data_list: 88 | if "KNAPSACK" in algorithm.Algorithm: 89 | plt.plot(algorithm.Data, color = 'red', marker= "o", linewidth=2, markersize = 10, label=algorithm.Algorithm) 90 | elif "GREEDY" in algorithm.Algorithm: 91 | plt.plot(algorithm.Data, color = 'blue', marker= ">", linewidth=2, markersize = 10, label=algorithm.Algorithm) 92 | elif "LFU" in algorithm.Algorithm: 93 | plt.plot(algorithm.Data, color = 'orange', marker= "p",linewidth=2, markersize = 10, linestyle="--", label=algorithm.Algorithm) 94 | elif "LRU" in algorithm.Algorithm: 95 | plt.plot(algorithm.Data, color = 'green', marker= "*", linewidth=2, markersize = 10, linestyle=":", label=algorithm.Algorithm) 96 | else: 97 | plt.plot(algorithm.Data, linewidth=2, label=algorithm.Algorithm) 98 | 99 | 100 | 101 | plt.xlabel("Time Silce", font) 102 | plt.ylabel("Traffic Load(GB)", font) 103 | 104 | ''' 105 | Set legend 106 | ''' 107 | font_legend = {'family': 'Times New Roman', 'weight': 'bold', 'size': 12} 108 | plt.legend(prop=font_legend, loc=1, numpoints=1, ncol = 1) 109 | ltext = plt.gca().get_legend().get_texts() 110 | 111 | plt.show() 112 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/wirelessnetwork/WirelessNetwork.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.wirelessnetwork; 2 | 3 | import java.awt.geom.Point2D; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | import cn.edu.tju.simulation.cache.Cache; 8 | import cn.edu.tju.simulation.cache.Query; 9 | import cn.edu.tju.simulation.content.ContentService; 10 | import cn.edu.tju.simulation.content.LocalHobby; 11 | import cn.edu.tju.simulation.content.SingleContent; 12 | import cn.edu.tju.simulation.content.SingleLocalHobby; 13 | import cn.edu.tju.simulation.controller.Controller; 14 | import cn.edu.tju.simulation.file.Parameter; 15 | import cn.edu.tju.simulation.state.State; 16 | import cn.edu.tju.simulation.user.MobilityModel; 17 | 18 | /** 19 | * Wireless network 20 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 21 | * 22 | */ 23 | public abstract class WirelessNetwork extends Cache implements Query{ 24 | /** 25 | * Number of wireless networks 26 | */ 27 | public int number; 28 | 29 | /** 30 | * Central coordinates of wireless networks 31 | */ 32 | public Point2D.Double location; 33 | /** 34 | * Radius of the wireless network 35 | */ 36 | public int radius; 37 | 38 | /** 39 | * The type of wireless network 40 | */ 41 | public String type; 42 | 43 | /** 44 | * A collection of users that can connect to the current network 45 | */ 46 | public List userOfNetwork; 47 | /** 48 | * Adjacent network collection 49 | */ 50 | public RelationalWirelessNetwork relationalWirelessNetwork ; 51 | /** 52 | * Status queues within the network 53 | */ 54 | public List statesQueue; 55 | /** 56 | * Network's own popularity 57 | */ 58 | public LocalHobby content; 59 | 60 | public abstract int countUserOfNetwork(); 61 | 62 | public List getCanBeCachedContent(){ 63 | return ContentService.sortByHobby(this.content.getContentList()); 64 | } 65 | 66 | public void clearCache(){ 67 | if(cacheContent != null){ 68 | this.cacheContent.clear(); 69 | this.cacheRequestAmount = 0; 70 | this.hitAmount = 0; 71 | } 72 | } 73 | 74 | public void addHobbyByRequestContent(SingleContent isc){ 75 | Iterator it = this.content.getContentList().iterator(); 76 | while(it.hasNext()){ 77 | SingleLocalHobby mc = it.next(); 78 | if(mc.getSingleContent() == isc){ 79 | mc.addLocalHobbyValue(); 80 | break; 81 | } 82 | } 83 | } 84 | 85 | public Boolean query(SingleLocalHobby singleContent){ 86 | return dealQuery(this, singleContent); 87 | } 88 | 89 | public void fluctuatePopularity(){ 90 | this.content.fluctuatePopularity(Parameter.BSMinWaveInterval, Parameter.BSMaxWaveInterval, Controller.getInstance().getOriginalContentList()); 91 | } 92 | 93 | public int getNumber() { 94 | return number; 95 | } 96 | public Point2D.Double getLocation() { 97 | return location; 98 | } 99 | public int getRadius() { 100 | return radius; 101 | } 102 | 103 | public void setRadius(int radius) { 104 | this.radius = radius; 105 | } 106 | 107 | public String getType() { 108 | return type; 109 | } 110 | public List getUserOfNetwork() { 111 | return userOfNetwork; 112 | } 113 | 114 | public List getStatesQueue() { 115 | return statesQueue; 116 | } 117 | 118 | public void setStatesQueue(List statesQueue) { 119 | this.statesQueue = statesQueue; 120 | } 121 | 122 | public LocalHobby getContent() { 123 | return content; 124 | } 125 | 126 | public void setContent(LocalHobby content) { 127 | this.content = content; 128 | } 129 | 130 | public void setNumber(int number) { 131 | this.number = number; 132 | } 133 | 134 | public void setLocation(Point2D.Double location) { 135 | this.location = location; 136 | } 137 | 138 | public void setType(String type) { 139 | this.type = type; 140 | } 141 | 142 | public void setUserOfNetwork(List inwireless_simpleuser) { 143 | this.userOfNetwork = inwireless_simpleuser; 144 | } 145 | 146 | public RelationalWirelessNetwork getRelationalWirelessNetwork() { 147 | return relationalWirelessNetwork; 148 | } 149 | 150 | public void setRelationalWirelessNetwork( 151 | RelationalWirelessNetwork relationalWirelessNetwork) { 152 | this.relationalWirelessNetwork = relationalWirelessNetwork; 153 | } 154 | 155 | 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/chart/HitRate.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pylab as plt 2 | from matplotlib.ticker import MultipleLocator 3 | from matplotlib.ticker import FormatStrFormatter 4 | import sys 5 | import os 6 | 7 | #this is the Absolute path 8 | # DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("/src")] + "/src/main/resources/data/ResultData") 9 | #Relative path , which determined by the caller 10 | print(sys.argv[0]) 11 | DATA_FILE_PATH = str(sys.argv[0][0:sys.argv[0].index("src")]) + "src\main\\resources\data\ResultData" 12 | 13 | 14 | class Algorithm_Data: 15 | def __init__(self, Algorithm): 16 | self.Algorithm = Algorithm 17 | self.Data = [0] 18 | ''' 19 | Read result file 20 | ''' 21 | algorithm_data_list = [] 22 | with open(DATA_FILE_PATH, encoding='utf-8') as ResultData_Reader: 23 | for line in ResultData_Reader: 24 | if "Algorithm" in line.split(" ")[0]: 25 | algorithm = Algorithm_Data(line.split(":")[1]) 26 | algorithm_data_list.append(algorithm) 27 | else: 28 | line_data = line.split(" ") 29 | for data in line_data: 30 | data = data.split(",") 31 | if len(data) == 4: 32 | algorithm_data_list[-1].Data.append(float(data[1])*100) 33 | 34 | ''' 35 | line chart 36 | ''' 37 | # set the image size of the output 38 | figsize = 7.5, 6 39 | figure, ax = plt.subplots(num="HIT RATE", figsize=figsize) 40 | 41 | ''' 42 | set the scale 43 | ''' 44 | #set the coordinate range of value 45 | plt.ylim(0, 20) 46 | plt.xlim(0, len(algorithm_data_list[-1].Data)) 47 | #set the scale 48 | #set the x major scale label to a multiple of 5 49 | xmajorLocator = MultipleLocator(20); 50 | #set the format of the x-axis label text 51 | xmajorFormatter = FormatStrFormatter('%3.0f') 52 | #Set the x-axis minor scale label to a multiple of 1 53 | # xminorLocator = MultipleLocator(2) 54 | #Load x-axis settings 55 | ax.xaxis.set_major_locator(xmajorLocator) 56 | ax.xaxis.set_major_formatter(xmajorFormatter) 57 | #Set the y-axis main scale label to a multiple of 0.05% 58 | ymajorLocator = MultipleLocator(5) 59 | #Set the format of the y-axis label text 60 | ymajorFormatter = FormatStrFormatter('%.1f%%') 61 | #Set this y-axis minor tick label to a multiple of 0.2 62 | # yminorLocator = MultipleLocator(1) 63 | #Load y-axis settings 64 | ax.yaxis.set_major_locator(ymajorLocator) 65 | ax.yaxis.set_major_formatter(ymajorFormatter) 66 | # Shows the position of the subscale label, but no label text 67 | 68 | # ax.xaxis.set_minor_locator(xminorLocator) 69 | # ax.yaxis.set_minor_locator(yminorLocator) 70 | # ax.xaxis.grid(True, which='major') # The grid of the x-axis uses the major scale 71 | # ax.yaxis.grid(True, which='major') # The grid of the y-axis uses the minor scale 72 | 73 | 74 | ''' 75 | Set the font of the axis 76 | ''' 77 | font = {'family': 'Times New Roman', 78 | 'weight': 'normal', 79 | 'size': 18, 80 | } 81 | label_font = {'family': 'Times New Roman', 82 | 'weight': 'bold', 83 | 'size': 16, 84 | } 85 | # Set the font of the scale value 86 | label_font = {'family': 'Times New Roman', 87 | 'weight': 'bold', 88 | 'size': 16,} 89 | plt.xlabel(label_font) 90 | plt.ylabel(label_font) 91 | 92 | ''' 93 | Drawing 94 | ''' 95 | for algorithm in algorithm_data_list: 96 | if "KNAPSACK" in algorithm.Algorithm: 97 | plt.plot(algorithm.Data, color = 'red', marker= "o", linewidth=2, markersize = 10, label=algorithm.Algorithm) 98 | elif "GREEDY" in algorithm.Algorithm: 99 | plt.plot(algorithm.Data, color = 'blue', marker= ">", linewidth=2, markersize = 10, label=algorithm.Algorithm) 100 | elif "LFU" in algorithm.Algorithm: 101 | plt.plot(algorithm.Data, color = 'orange', marker= "p",linewidth=2, markersize = 10, linestyle="--", label=algorithm.Algorithm) 102 | elif "LRU" in algorithm.Algorithm: 103 | plt.plot(algorithm.Data, color = 'green', marker= "*", linewidth=2, markersize = 10, linestyle=":", label=algorithm.Algorithm) 104 | else: 105 | plt.plot(algorithm.Data, linewidth=2, label=algorithm.Algorithm) 106 | 107 | 108 | plt.xlabel("Time", font) 109 | plt.ylabel("Hit Rate", font) 110 | 111 | ''' 112 | Set legend 113 | ''' 114 | font_legend = {'family': 'Times New Roman', 'weight': 'bold', 'size': 12} 115 | plt.legend(prop=font_legend, loc=1, numpoints=1, ncol = 1) 116 | 117 | ltext = plt.gca().get_legend().get_texts() 118 | 119 | plt.show() 120 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/cache/Cache.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.cache; 2 | 3 | import java.util.Iterator; 4 | import java.util.LinkedList; 5 | 6 | import cn.edu.tju.simulation.content.CachingSingleContent; 7 | import cn.edu.tju.simulation.content.SingleContent; 8 | import cn.edu.tju.simulation.content.SingleLocalHobby; 9 | import cn.edu.tju.simulation.user.MobilityModel; 10 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetwork; 11 | 12 | /** 13 | * Cache abstract classes that contain all the properties and methods for 14 | * caching. When the base station inherits this class, we can configure the base 15 | * station cache. 16 | * 17 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin 18 | * University 19 | */ 20 | public abstract class Cache { 21 | /** 22 | * Indicates whether there is a cache 23 | */ 24 | public Boolean hasCache = false; 25 | /** 26 | * the size of the cache 27 | */ 28 | public long cacheSize; 29 | /** 30 | * A list of contents in the cache, each cached content is an object that 31 | * contains the following properties: content; Status (being downloaded or 32 | * not downloaded); Number of remaining time slices. 33 | **/ 34 | public LinkedList cacheContent; 35 | /** 36 | * The number of requests that the cache receives. 37 | */ 38 | public int cacheRequestAmount; 39 | /** 40 | * The number of hit resources 41 | */ 42 | public int hitAmount; 43 | 44 | /** 45 | * Processing the request in the cache, returns true if the cache contains 46 | * the requested content, or false if not included. This method specifically 47 | * refers to the user directly query the base station. 48 | */ 49 | public boolean dealQuery(Object object, SingleLocalHobby singleContent) { 50 | if (cacheContent != null) { 51 | if (object instanceof WirelessNetwork) { 52 | if (cacheContent.contains(singleContent)) { 53 | return true; 54 | } else { 55 | return false; 56 | } 57 | } else if (object instanceof MobilityModel) { 58 | if (cacheContent.contains(singleContent)) { 59 | return true; 60 | } else { 61 | return false; 62 | } 63 | }else{ 64 | return false; 65 | } 66 | } else { 67 | return false; 68 | } 69 | } 70 | 71 | public Boolean removeCacheContent(SingleContent sc) { 72 | Iterator it = this.cacheContent.iterator(); 73 | while (it.hasNext()) { 74 | CachingSingleContent csc = it.next(); 75 | if (csc.getSingleContent().getName().equals(sc.getName())) { 76 | it.remove(); 77 | return true; 78 | } 79 | } 80 | return false; 81 | } 82 | 83 | public Boolean removeCacheContent(int index) { 84 | this.cacheContent.remove(index); 85 | return true; 86 | } 87 | 88 | public Boolean addCacheContent(SingleLocalHobby sc) { 89 | this.cacheContent.add(new CachingSingleContent(sc.getSingleContent())); 90 | return true; 91 | } 92 | 93 | public long getRemainingCacheSize() { 94 | if (cacheContent.size() == 0) { 95 | return this.cacheSize; 96 | } else { 97 | long remainingCachesize = this.cacheSize; 98 | Iterator it = cacheContent.iterator(); 99 | while (it.hasNext()) { 100 | CachingSingleContent cachingSingleContent = it.next(); 101 | remainingCachesize -= cachingSingleContent.getSize(); 102 | } 103 | return remainingCachesize; 104 | } 105 | } 106 | 107 | /** 108 | * A new request arrives and the number of requests is incremented by 1. 109 | */ 110 | public void addRequestAmount() { 111 | cacheRequestAmount += 1; 112 | } 113 | 114 | /** 115 | * Initialize the number of requests and hits. 116 | */ 117 | public void resetAmountOfRequestAndHits() { 118 | this.cacheRequestAmount = 0; 119 | this.hitAmount = 0; 120 | } 121 | 122 | /** 123 | * The request is hit and the number of hits is incremented by 1. 124 | */ 125 | public void addHitAmount() { 126 | cacheRequestAmount += 1; 127 | hitAmount += 1; 128 | } 129 | 130 | /** 131 | * See if this base station caontains a cache 132 | * 133 | * @return True means there is a cache, or false means there is no cache. 134 | */ 135 | public Boolean getHasCache() { 136 | return hasCache; 137 | } 138 | 139 | public long getCacheSize() { 140 | return cacheSize; 141 | } 142 | 143 | public LinkedList getCacheContent() { 144 | return cacheContent; 145 | } 146 | 147 | public void setCacheContent(LinkedList cacheContent) { 148 | this.cacheContent = cacheContent; 149 | } 150 | 151 | public int getRequestAmount() { 152 | return cacheRequestAmount; 153 | } 154 | 155 | public int getHitAmount() { 156 | return hitAmount; 157 | } 158 | 159 | public void setCacheSize(long cacheSize) { 160 | this.cacheSize = cacheSize; 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/file/Parameter.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.file; 2 | 3 | /** 4 | * Class of all parameters. This class corresponds to SIMULATION.xml, and each static attribute in the class corresponds to a key value in the file. 5 | * You can also easily understand that the configuration file is mapped to this class. 6 | * 7 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 8 | * 9 | */ 10 | 11 | public class Parameter { 12 | /** 13 | * Transmission delay from user to base station 14 | */ 15 | public static int USER_TO_BS_DELAY; 16 | /** 17 | * Transmission delay between base station and base station 18 | */ 19 | public static int BS_TO_BS_DELAY; 20 | /** 21 | * Base station to MNO transmission delay 22 | */ 23 | public static int BS_TO_MNO_DELAY; 24 | /** 25 | * MNO to the Internet delay 26 | */ 27 | public static int MNO_TO_CLOUD_DELAY; 28 | /** 29 | * File path of state set 30 | */ 31 | public static String PATH = null; 32 | /** 33 | * ZIPF 34 | */ 35 | public static int ZIPF_SAMPLE; 36 | /** 37 | * ZIPF 38 | */ 39 | public static double ZIPF_CONEFFICIENT; 40 | /** 41 | * The default radius of the base station. 42 | */ 43 | public static int Radius; 44 | /** 45 | * The probability that a user will generate a request at a time slice. 46 | */ 47 | public static float RequestProbability; 48 | /** 49 | * The maximum number of time slices that the system supports by default. 50 | */ 51 | public static int TimeSlicesMaxNumber; 52 | /** 53 | * The minimum value of the default base station's fluctuation range. 54 | */ 55 | public static float BSMinWaveInterval; 56 | /** 57 | * The maximum value of the default base station's fluctuation range. 58 | */ 59 | public static float BSMaxWaveInterval; 60 | /** 61 | * The minimum value of the default user's fluctuation range. 62 | */ 63 | public static float UserMinWaveInterval; 64 | /** 65 | * The maximum value of the default user's fluctuation range. 66 | */ 67 | public static float UserMaxWaveInterval; 68 | 69 | 70 | public static float TRANSMISSION_POWER; 71 | 72 | public static float GAUSSIAN_WHITE_NOISE_POWER; 73 | 74 | public static float EXPONENT; 75 | 76 | public static float BANDWIDTH; 77 | 78 | public static float PATH_LOSS; 79 | 80 | 81 | public static void setPATH_LOSS(String pATH_LOSS) { 82 | PATH_LOSS = Float.parseFloat(pATH_LOSS); 83 | } 84 | public static void setTRANSMISSION_POWER(String tRANSMISSION_POWER) { 85 | TRANSMISSION_POWER = Float.parseFloat(tRANSMISSION_POWER); 86 | } 87 | public static void setGAUSSIAN_WHITE_NOISE_POWER( 88 | String gAUSSIAN_WHITE_NOISE_POWER) { 89 | GAUSSIAN_WHITE_NOISE_POWER = Float.parseFloat(gAUSSIAN_WHITE_NOISE_POWER); 90 | } 91 | public static void setEXPONENT(String eXPONENT) { 92 | EXPONENT = Float.parseFloat(eXPONENT); 93 | } 94 | public static void setBANDWIDTH(String bANDWIDTH) { 95 | BANDWIDTH = Float.parseFloat(bANDWIDTH); 96 | } 97 | public void setUSER_TO_BS_DELAY(String uSER_TO_BS_DELAY) { 98 | USER_TO_BS_DELAY = Integer.parseInt(uSER_TO_BS_DELAY); 99 | } 100 | public void setBS_TO_BS_DELAY(String bS_TO_BS_DELAY) { 101 | BS_TO_BS_DELAY = Integer.parseInt(bS_TO_BS_DELAY); 102 | } 103 | public void setBS_TO_MNO_DELAY(String bS_TO_MNO_DELAY) { 104 | BS_TO_MNO_DELAY = Integer.parseInt(bS_TO_MNO_DELAY); 105 | } 106 | public void setMNO_TO_CLOUD_DELAY(String mNO_TO_CLOUD_DELAY) { 107 | MNO_TO_CLOUD_DELAY = Integer.parseInt(mNO_TO_CLOUD_DELAY); 108 | } 109 | public void setPATH(String pATH) { 110 | PATH = pATH; 111 | } 112 | public void setRadius(String radius) { 113 | Radius = Integer.parseInt(radius); 114 | } 115 | 116 | public static void setZIPF_SAMPLE(String zIPF_SAMPLE) { 117 | ZIPF_SAMPLE = Integer.parseInt(zIPF_SAMPLE); 118 | } 119 | public static void setZIPF_CONEFFICIENT(String zIPF_CONEFFICIENT) { 120 | ZIPF_CONEFFICIENT = Double.parseDouble(zIPF_CONEFFICIENT); 121 | } 122 | public void setRequestProbability(String requestProbability) { 123 | RequestProbability = Float.parseFloat(requestProbability); 124 | } 125 | 126 | public static void setTimeSlicesMaxNumber(String timeSlicesMaxNumber) { 127 | TimeSlicesMaxNumber = Integer.parseInt(timeSlicesMaxNumber); 128 | } 129 | 130 | public void setBSMinWaveInterval(String bSMinWaveInterval) { 131 | BSMinWaveInterval = Float.parseFloat(bSMinWaveInterval); 132 | } 133 | 134 | public void setBSMaxWaveInterval(String bSMaxWaveInterval) { 135 | BSMaxWaveInterval = Float.parseFloat(bSMaxWaveInterval); 136 | } 137 | 138 | public void setUserMinWaveInterval(String userMinWaveInterval) { 139 | UserMinWaveInterval = Float.parseFloat(userMinWaveInterval); 140 | } 141 | 142 | public void setUserMaxWaveInterval(String userMaxWaveInterval) { 143 | UserMaxWaveInterval = Float.parseFloat(userMaxWaveInterval); 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/resources/data/RANDOMBS.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 400 6 | 250 7 | true 8 | 1000 9 | 100 10 | 11 | 12 | 300 13 | 250 14 | true 15 | 1000 16 | 100 17 | 18 | 19 | 20 | 21 | 450 22 | 250 23 | true 24 | 1000 25 | 180 26 | 27 | 28 | 400 29 | 230 30 | true 31 | 1000 32 | 120 33 | 34 | 35 | 460 36 | 230 37 | true 38 | 1000 39 | 120 40 | 41 | 42 | 480 43 | 250 44 | true 45 | 1200 46 | 110 47 | 48 | 49 | 440 50 | 300 51 | true 52 | 1300 53 | 110 54 | 55 | 56 | 57 | 58 | 500 59 | 270 60 | true 61 | 1300 62 | 130 63 | 64 | 65 | 200 66 | 230 67 | true 68 | 1300 69 | 140 70 | 71 | 72 | 300 73 | 230 74 | true 75 | 1300 76 | 130 77 | 78 | 79 | 250 80 | 310 81 | true 82 | 1300 83 | 110 84 | 85 | 86 | 87 | 88 | 4400 89 | 240 90 | true 91 | 1300 92 | 150 93 | 94 | 95 | 300 96 | 220 97 | true 98 | 1300 99 | 150 100 | 101 | 102 | 500 103 | 230 104 | true 105 | 1200 106 | 150 107 | 108 | 109 | 250 110 | 300 111 | true 112 | 1100 113 | 150 114 | 115 | 116 | 117 | 118 | 400 119 | 290 120 | true 121 | 1400 122 | 140 123 | 124 | 125 | 500 126 | 220 127 | true 128 | 1300 129 | 140 130 | 131 | 132 | 600 133 | 220 134 | true 135 | 1000 136 | 140 137 | 138 | 139 | 700 140 | 220 141 | true 142 | 1000 143 | 140 144 | 145 | 146 | 147 | 148 | 200 149 | 300 150 | true 151 | 900 152 | 140 153 | 154 | 155 | 300 156 | 250 157 | true 158 | 1000 159 | 140 160 | 161 | 162 | 400 163 | 200 164 | true 165 | 1000 166 | 140 167 | 168 | 169 | 170 | 171 | 300 172 | 300 173 | true 174 | 1000 175 | 150 176 | 177 | 178 | 300 179 | 400 180 | true 181 | 1000 182 | 150 183 | 184 | 185 | 370 186 | 370 187 | true 188 | 1000 189 | 300 190 | 191 | 192 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/swing/menubar/MenuBar.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.swing.menubar; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.File; 6 | 7 | import javax.swing.JFileChooser; 8 | import javax.swing.JMenu; 9 | import javax.swing.JMenuBar; 10 | import javax.swing.JMenuItem; 11 | import javax.swing.JOptionPane; 12 | 13 | import org.apache.log4j.Logger; 14 | 15 | import cn.edu.tju.simulation.controller.Controller; 16 | import cn.edu.tju.simulation.file.CaseFileReader; 17 | import cn.edu.tju.simulation.file.CaseFileWriter; 18 | import cn.edu.tju.simulation.swing.operator.Signal; 19 | 20 | /** 21 | * Menu bar 22 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 23 | * 24 | */ 25 | @SuppressWarnings("serial") 26 | public class MenuBar extends JMenuBar implements ActionListener{ 27 | /** 28 | * Menu Options - File 29 | */ 30 | private JMenu file; 31 | /** 32 | * Mednu Options -View 33 | */ 34 | private JMenu view; 35 | /** 36 | * Menu Options - Help 37 | */ 38 | private JMenu help; 39 | private JMenu configure; 40 | /** 41 | * Menu Sub-Options - File - Opens file 42 | */ 43 | private JMenuItem openFile; 44 | /** 45 | * Menu sub-options - File - Save file 46 | */ 47 | private JMenuItem saveFile; 48 | /** 49 | * Menu sub-options - View - View Base Station 50 | */ 51 | private JMenuItem viewBS; 52 | /** 53 | * Menu sub-options - View - View content 54 | */ 55 | private JMenuItem viewContent; 56 | /** 57 | * Menu Sub-Options - Help - About Edge Caching Simulation 58 | */ 59 | private JMenuItem viewHelp; 60 | private JMenuItem paramater; 61 | 62 | /** 63 | * Controller 64 | */ 65 | private Controller controller; 66 | /** 67 | * Log 68 | */ 69 | private static Logger logger = Logger.getLogger(MenuBar.class); 70 | 71 | 72 | public MenuBar(){ 73 | initial(); 74 | addListener(); 75 | } 76 | 77 | public void initial(){ 78 | //Menu option 79 | this.file = new JMenu("File"); 80 | this.view = new JMenu("View"); 81 | this.help = new JMenu("Help"); 82 | this.configure = new JMenu("Configure"); 83 | 84 | //Menu sub-options 85 | this.openFile =new JMenuItem("Open File..."); 86 | this.saveFile =new JMenuItem("Save As..."); 87 | this.viewContent = new JMenuItem("Content"); 88 | this.viewHelp = new JMenuItem("About Edge Caching Simulation"); 89 | this.viewBS = new JMenuItem("Base Station"); 90 | this.paramater = new JMenuItem("Paramater"); 91 | 92 | //Add menu sub-options 93 | this.file.add(openFile); 94 | this.file.add(saveFile); 95 | this.view.add(viewContent); 96 | this.view.add(viewBS); 97 | this.help.add(viewHelp); 98 | this.configure.add(paramater); 99 | 100 | //Add menu 101 | this.add(file); 102 | this.add(view); 103 | this.add(configure); 104 | this.add(help); 105 | } 106 | 107 | public void addListener(){ 108 | openFile.addActionListener(this); 109 | saveFile.addActionListener(this); 110 | viewHelp.addActionListener(this); 111 | viewContent.addActionListener(this); 112 | viewBS.addActionListener(this); 113 | paramater.addActionListener(this); 114 | } 115 | 116 | public void actionPerformed(ActionEvent e) { 117 | if(e.getSource().equals(openFile)){ 118 | openFileClicked(); 119 | }else if(e.getSource().equals(saveFile)){ 120 | saveFileClicked(); 121 | }else if(e.getSource().equals(viewHelp)){ 122 | JOptionPane.showMessageDialog(null, "Information about me", "About Edge Caching Simulation",JOptionPane.INFORMATION_MESSAGE); 123 | }else if(e.getSource().equals(viewContent)){ 124 | ViewContent content = new ViewContent(getRootPane().getParent()); 125 | content.setContent(content); 126 | }else if(e.getSource().equals(paramater)){ 127 | Paramater paramater = new Paramater(getRootPane().getParent(),controller); 128 | paramater.setParamater(paramater); 129 | }else if(e.getSource().equals(viewBS)){ 130 | ViewNetwork network = new ViewNetwork(getRootPane().getParent(), controller); 131 | network.setViewNetwork(network); 132 | } 133 | } 134 | 135 | public void openFileClicked(){ 136 | JFileChooser filechooser = new JFileChooser(); 137 | filechooser.showOpenDialog(null); 138 | File file = filechooser.getSelectedFile(); 139 | if(file != null){ 140 | CaseFileReader reader = new CaseFileReader(); 141 | if(reader.read(controller,file)){ 142 | controller.appendLog("debug","Read file successfully",logger); 143 | //Read completed 144 | }else{ 145 | JOptionPane.showMessageDialog(null,"Incorrect file format or incorrect formatting","Failed to read the file",JOptionPane.ERROR_MESSAGE); 146 | controller.appendLog("debug","Failed to read the file",logger); 147 | } 148 | } 149 | } 150 | 151 | public void saveFileClicked(){ 152 | JFileChooser filechooser = new JFileChooser(); 153 | int option = filechooser.showSaveDialog(null); 154 | //If the user chose to save file 155 | if(option==JFileChooser.APPROVE_OPTION){ 156 | File file = filechooser.getSelectedFile(); 157 | //Obtain the file name from the file name input box 158 | String fname = filechooser.getName(file); 159 | //If the user fill in the file name without the suffix we developed, then we add it suffix 160 | if(fname.indexOf(".txt") == -1){ 161 | file = new File(filechooser.getCurrentDirectory(),fname+".txt"); 162 | } 163 | CaseFileWriter writer = new CaseFileWriter(); 164 | if(writer.write(controller, file)){ 165 | //Saved successfully! 166 | Signal.SAVE = true; 167 | } 168 | } 169 | } 170 | 171 | public JMenu getFile() { 172 | return file; 173 | } 174 | 175 | public void setFile(JMenu file) { 176 | this.file = file; 177 | } 178 | 179 | public JMenu getHelp() { 180 | return help; 181 | } 182 | 183 | public void setHelp(JMenu help) { 184 | this.help = help; 185 | } 186 | 187 | public JMenuItem getOpenFile() { 188 | return openFile; 189 | } 190 | 191 | public void setOpenFile(JMenuItem openFile) { 192 | this.openFile = openFile; 193 | } 194 | 195 | public JMenuItem getSaveFile() { 196 | return saveFile; 197 | } 198 | 199 | public void setSaveFile(JMenuItem saveFile) { 200 | this.saveFile = saveFile; 201 | } 202 | 203 | public JMenuItem getViewHelp() { 204 | return viewHelp; 205 | } 206 | 207 | public void setViewHelp(JMenuItem viewHelp) { 208 | this.viewHelp = viewHelp; 209 | } 210 | 211 | public Controller getController() { 212 | return controller; 213 | } 214 | 215 | public void setController(Controller controller) { 216 | this.controller = controller; 217 | } 218 | 219 | public JMenuItem getViewBS() { 220 | return viewBS; 221 | } 222 | 223 | public void setViewBS(JMenuItem viewBS) { 224 | this.viewBS = viewBS; 225 | } 226 | 227 | 228 | } 229 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/controller/Controller.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.controller; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import org.apache.log4j.Logger; 8 | 9 | 10 | import cn.edu.tju.simulation.content.LocalHobby; 11 | import cn.edu.tju.simulation.content.SingleContent; 12 | import cn.edu.tju.simulation.content.SingleLocalHobby; 13 | import cn.edu.tju.simulation.data.Data; 14 | import cn.edu.tju.simulation.file.ContentReader; 15 | import cn.edu.tju.simulation.file.ParameterFileReader; 16 | import cn.edu.tju.simulation.handler.RequestHandler; 17 | import cn.edu.tju.simulation.state.StateQueue; 18 | import cn.edu.tju.simulation.swing.log.Log; 19 | import cn.edu.tju.simulation.swing.map.Map; 20 | import cn.edu.tju.simulation.swing.menubar.MenuBar; 21 | import cn.edu.tju.simulation.swing.operator.Operator; 22 | import cn.edu.tju.simulation.user.Users; 23 | import cn.edu.tju.simulation.wirelessnetwork.WirelessNetworkGroup; 24 | 25 | /** 26 | * This is a controller class, and at the beginning of the program, 27 | * it points to all objects that can be used by developers. 28 | * Developers can access any of the components on the UI, 29 | * as well as some parameters and methods for computing. 30 | * 31 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 32 | * 33 | */ 34 | public class Controller { 35 | /** 36 | * The original content, the user and base station's "area popularity" from the property is generated. 37 | */ 38 | private LocalHobby originalContent; 39 | /** 40 | * The collection of all wireless networks in the network system, which may contain various types of networks. 41 | */ 42 | private WirelessNetworkGroup wirelessNetworkGroup; 43 | /** 44 | * A collection of users, which contains a variety of mobile models. 45 | */ 46 | private Users users; 47 | /** 48 | * The processing class for the request. From the beginning of the simulation, to the end, 49 | * it is responsible for "sending" all users' requests to the base station, and counting the hit status of the cache. 50 | */ 51 | private RequestHandler requestHandler; 52 | /** 53 | * The menu bar on the UI. 54 | */ 55 | private MenuBar menuBar; 56 | /** 57 | * The drawing panel on the UI. 58 | */ 59 | private Map mapPanel; 60 | /** 61 | * The operation panel on the UI 62 | */ 63 | private Operator operationPanel; 64 | /** 65 | * The log panel on the UI 66 | */ 67 | private Log logPanel; 68 | /** 69 | * The results of the simulation experiment are stored in this property. 70 | */ 71 | private HashMap> resultDataList; 72 | /** 73 | * Instance of the controller 74 | */ 75 | private static Controller controller; 76 | /** 77 | * The status queue, which contains the request status of all users. 78 | * It has nothing to do with the time slice, which contains all the states of all users in the entire time stream. 79 | */ 80 | private StateQueue stateQueue; 81 | /** 82 | * Log 83 | */ 84 | private static Logger logger = Logger.getLogger(Controller.class); 85 | 86 | public Controller(){ 87 | initial(); 88 | } 89 | 90 | /** 91 | * Associate all the panels with the controller and instantiate other properties. 92 | * @param menuBar The menu bar on the UI. 93 | * @param map The drawing panel on the UI. 94 | * @param parameterConfiguration The operation panel on the UI 95 | * @param log The log panel on the UI 96 | * @param controller Instance of the controller 97 | */ 98 | public void initialController(MenuBar menuBar,Map map,Operator parameterConfiguration,Log log,Controller controller){ 99 | this.menuBar =menuBar; 100 | this.mapPanel = map; 101 | this.operationPanel = parameterConfiguration; 102 | this.logPanel = log; 103 | 104 | Controller.controller = controller; 105 | 106 | menuBar.setController(this); 107 | map.setController(this); 108 | log.setController(this); 109 | parameterConfiguration.setController(this); 110 | 111 | wirelessNetworkGroup = new WirelessNetworkGroup(); 112 | users = new Users(); 113 | requestHandler = new RequestHandler(); 114 | resultDataList = new HashMap>(); 115 | stateQueue = new StateQueue(); 116 | } 117 | 118 | /** 119 | * Read a and initialize the popularity and size for the original content. 120 | * Popularity conforms to power law. 121 | * The size distribution corresponds to the size distribution of the files in the true dataset. 122 | */ 123 | public void initial(){ 124 | Boolean readStatus = new ParameterFileReader().read(); 125 | if (readStatus) { 126 | logger.debug("Load initial parameters successfully����"); 127 | } else { 128 | logger.debug("Failed to load initial parameters����"); 129 | } 130 | 131 | logger.debug("Initialize the popularity according to power law distribution"); 132 | 133 | this.originalContent = new LocalHobby(); 134 | List list = new ContentReader().read(); 135 | 136 | List temp = new ArrayList(); 137 | for (SingleContent mySingleContent : list) { 138 | temp.add(new SingleLocalHobby(mySingleContent)); 139 | } 140 | this.originalContent.setContentList(temp); 141 | } 142 | 143 | /** 144 | * Gets the instance of the controller. 145 | * @return Instance of the controller 146 | */ 147 | public static Controller getInstance(){ 148 | return controller; 149 | } 150 | 151 | /** 152 | * Check if there is a user in the system. If there is, return true, or false. 153 | * @return There is a user, return true, or false. 154 | */ 155 | public Boolean hasUsers(){ 156 | if(this.users.getSimpleUsersAmount()!=0){ 157 | return true; 158 | }else{ 159 | return false; 160 | } 161 | } 162 | 163 | /** 164 | * Add a log to the log panel and write the log in the log file. 165 | * @param type: "debug" or "info" or "error" 166 | * @param text: Contents of the log 167 | * @param logger: The log object of the class that is writing this log. 168 | * This allows us to find the recorder from the log. 169 | */ 170 | public void appendLog(String type,String text,Logger logger){ 171 | this.logPanel.append(text); 172 | if(logger != null){ 173 | if(type.equals("debug")){ 174 | logger.debug(text); 175 | }else if(type.equals("info")){ 176 | logger.info(text); 177 | }else if(type.equals("error")){ 178 | logger.error(text); 179 | } 180 | } 181 | } 182 | 183 | /** 184 | * Reset the emulator. Clear all users and base stations. 185 | */ 186 | public void clearAll(){ 187 | this.users.getSimpleUsers().clear(); 188 | this.wirelessNetworkGroup.BS.clear(); 189 | } 190 | 191 | public List getOriginalContentList(){ 192 | return this.originalContent.getContentList(); 193 | } 194 | 195 | public RequestHandler getRequestHandler() { 196 | return requestHandler; 197 | } 198 | 199 | public Operator getOperationPanel() { 200 | return operationPanel; 201 | } 202 | 203 | public Log getLogPanel() { 204 | return logPanel; 205 | } 206 | 207 | public HashMap> getResultDataList() { 208 | return resultDataList; 209 | } 210 | 211 | public Users getUsers() { 212 | return users; 213 | } 214 | 215 | public WirelessNetworkGroup getWirelessNetworkGroup() { 216 | return wirelessNetworkGroup; 217 | } 218 | 219 | public StateQueue getStateQueue() { 220 | return stateQueue; 221 | } 222 | 223 | public LocalHobby getOriginalContent() { 224 | return originalContent; 225 | } 226 | 227 | public void setOriginalContent(LocalHobby originalContent) { 228 | this.originalContent = originalContent; 229 | } 230 | 231 | 232 | 233 | } 234 | -------------------------------------------------------------------------------- /src/main/java/cn/edu/tju/simulation/logger/CustomDailyRollingFileAppender.java: -------------------------------------------------------------------------------- 1 | package cn.edu.tju.simulation.logger; 2 | 3 | import java.io.File; 4 | import java.io.FilenameFilter; 5 | import java.io.IOException; 6 | import java.io.InterruptedIOException; 7 | import java.io.Serializable; 8 | import java.net.URI; 9 | import java.text.SimpleDateFormat; 10 | import java.util.ArrayList; 11 | import java.util.Calendar; 12 | import java.util.Collections; 13 | import java.util.Date; 14 | import java.util.GregorianCalendar; 15 | import java.util.List; 16 | import java.util.Locale; 17 | import java.util.TimeZone; 18 | 19 | import org.apache.log4j.FileAppender; 20 | import org.apache.log4j.Layout; 21 | import org.apache.log4j.helpers.LogLog; 22 | import org.apache.log4j.spi.LoggingEvent; 23 | 24 | /** 25 | * 26 | * @author Wenkai Li ,School of Computer Science and Technology ,Tianjin University 27 | * 28 | */ 29 | public class CustomDailyRollingFileAppender extends FileAppender { 30 | // The code assumes that the following constants are in a increasing 31 | // sequence. 32 | static final int TOP_OF_TROUBLE = -1; 33 | static final int TOP_OF_MINUTE = 0; 34 | static final int TOP_OF_HOUR = 1; 35 | static final int HALF_DAY = 2; 36 | static final int TOP_OF_DAY = 3; 37 | static final int TOP_OF_WEEK = 4; 38 | static final int TOP_OF_MONTH = 5; 39 | 40 | /** 41 | The date pattern. By default, the pattern is set to 42 | "'.'yyyy-MM-dd" meaning daily rollover. 43 | */ 44 | private String datePattern = "'.'yyyy-MM-dd"; 45 | /** 46 | There is one backup file by default. 47 | */ 48 | protected int maxBackupIndex = 1; 49 | 50 | /** 51 | The log file will be renamed to the value of the 52 | scheduledFilename variable when the next interval is entered. For 53 | example, if the rollover period is one hour, the log file will be 54 | renamed to the value of "scheduledFilename" at the beginning of 55 | the next hour. 56 | 57 | The precise time when a rollover occurs depends on logging 58 | activity. 59 | */ 60 | private String scheduledFilename; 61 | 62 | /** 63 | The next time we estimate a rollover should occur. 64 | */ 65 | private long nextCheck = System.currentTimeMillis() - 1; 66 | 67 | Date now = new Date(); 68 | 69 | SimpleDateFormat sdf; 70 | 71 | RollingCalendar rc = new RollingCalendar(); 72 | 73 | int checkPeriod = TOP_OF_TROUBLE; 74 | 75 | // The gmtTimeZone is used only in computeCheckPeriod() method. 76 | static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); 77 | 78 | /** 79 | The default constructor does nothing. */ 80 | public CustomDailyRollingFileAppender() { 81 | } 82 | 83 | /** 84 | Instantiate a DailyRollingFileAppender and open the 85 | file designated by filename. The opened filename will 86 | become the ouput destination for this appender. 87 | 88 | */ 89 | public CustomDailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException { 90 | super(layout, filename, true); 91 | this.datePattern = datePattern; 92 | activateOptions(); 93 | } 94 | 95 | /** 96 | The DatePattern takes a string in the same format as 97 | expected by {@link SimpleDateFormat}. This options determines the 98 | rollover schedule. 99 | */ 100 | public void setDatePattern(String pattern) { 101 | datePattern = pattern; 102 | } 103 | 104 | /** 105 | Set the maximum number of backup files to keep around. 106 | 107 |

The MaxBackupIndex option determines how many backup 108 | files are kept before the oldest is erased. This option takes 109 | a positive integer value. If set to zero, then there will be no 110 | backup files and the log file will be truncated when it reaches 111 | MaxFileSize. 112 | */ 113 | public void setMaxBackupIndex(int maxBackups) { 114 | this.maxBackupIndex = maxBackups; 115 | } 116 | 117 | /** 118 | Returns the value of the MaxBackupIndex option. 119 | */ 120 | public int getMaxBackupIndex() { 121 | return maxBackupIndex; 122 | } 123 | 124 | /** Returns the value of the DatePattern option. */ 125 | public String getDatePattern() { 126 | return datePattern; 127 | } 128 | 129 | @Override 130 | public void activateOptions() { 131 | super.activateOptions(); 132 | if (datePattern != null && fileName != null) { 133 | now.setTime(System.currentTimeMillis()); 134 | sdf = new SimpleDateFormat(datePattern); 135 | int type = computeCheckPeriod(); 136 | printPeriodicity(type); 137 | rc.setType(type); 138 | File file = new File(fileName); 139 | scheduledFilename = fileName 140 | + sdf.format(new Date(file.lastModified())); 141 | 142 | } else { 143 | LogLog.error("Either File or DatePattern options are not set for appender ["+ name + "]."); 144 | } 145 | } 146 | 147 | void printPeriodicity(int type) { 148 | switch (type) { 149 | case TOP_OF_MINUTE: 150 | LogLog.debug("Appender [" + name + "] to be rolled every minute."); 151 | break; 152 | case TOP_OF_HOUR: 153 | LogLog.debug("Appender [" + name + "] to be rolled on top of every hour."); 154 | break; 155 | case HALF_DAY: 156 | LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight."); 157 | break; 158 | case TOP_OF_DAY: 159 | LogLog.debug("Appender [" + name + "] to be rolled at midnight."); 160 | break; 161 | case TOP_OF_WEEK: 162 | LogLog.debug("Appender [" + name + "] to be rolled at start of week."); 163 | break; 164 | case TOP_OF_MONTH: 165 | LogLog.debug("Appender [" + name + "] to be rolled at start of every month."); 166 | break; 167 | default: 168 | LogLog.warn("Unknown periodicity for appender [" + name + "]."); 169 | } 170 | } 171 | 172 | // This method computes the roll over period by looping over the 173 | // periods, starting with the shortest, and stopping when the r0 is 174 | // different from from r1, where r0 is the epoch formatted according 175 | // the datePattern (supplied by the user) and r1 is the 176 | // epoch+nextMillis(i) formatted according to datePattern. All date 177 | // formatting is done in GMT and not local format because the test 178 | // logic is based on comparisons relative to 1970-01-01 00:00:00 179 | // GMT (the epoch). 180 | 181 | int computeCheckPeriod() { 182 | RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, 183 | Locale.getDefault()); 184 | // set sate to 1970-01-01 00:00:00 GMT 185 | Date epoch = new Date(0); 186 | if (datePattern != null) { 187 | for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) { 188 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat( 189 | datePattern); 190 | simpleDateFormat.setTimeZone(gmtTimeZone); // do all date 191 | // formatting in GMT 192 | String r0 = simpleDateFormat.format(epoch); 193 | rollingCalendar.setType(i); 194 | Date next = new Date(rollingCalendar.getNextCheckMillis(epoch)); 195 | String r1 = simpleDateFormat.format(next); 196 | // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1); 197 | if (r0 != null && r1 != null && !r0.equals(r1)) { 198 | return i; 199 | } 200 | } 201 | } 202 | return TOP_OF_TROUBLE; // Deliberately head for trouble... 203 | } 204 | 205 | /** 206 | Rollover the current file to a new file. 207 | */ 208 | void rollOver() throws IOException { 209 | 210 | List files = getAllFiles(); 211 | Collections.sort(files); 212 | if (files.size() >= maxBackupIndex) { 213 | int index = 0; 214 | int diff = files.size() - (maxBackupIndex - 1); 215 | for (ModifiedTimeSortableFile file : files) { 216 | if (index >= diff) 217 | break; 218 | 219 | file.delete(); 220 | index++; 221 | } 222 | } 223 | 224 | /* Compute filename, but only if datePattern is specified */ 225 | if (datePattern == null) { 226 | errorHandler.error("Missing DatePattern option in rollOver()."); 227 | return; 228 | } 229 | LogLog.debug("maxBackupIndex=" + maxBackupIndex); 230 | 231 | String datedFilename = fileName + sdf.format(now); 232 | // It is too early to roll over because we are still within the 233 | // bounds of the current interval. Rollover will occur once the 234 | // next interval is reached. 235 | if (scheduledFilename.equals(datedFilename)) { 236 | return; 237 | } 238 | 239 | // close current file, and rename it to datedFilename 240 | this.closeFile(); 241 | 242 | File target = new File(scheduledFilename); 243 | if (target.exists()) { 244 | target.delete(); 245 | } 246 | 247 | File file = new File(fileName); 248 | boolean result = file.renameTo(target); 249 | if (result) { 250 | LogLog.debug(fileName + " -> " + scheduledFilename); 251 | } else { 252 | LogLog.error("Failed to rename [" + fileName + "] to [" 253 | + scheduledFilename + "]."); 254 | } 255 | 256 | try { 257 | // This will also close the file. This is OK since multiple 258 | // close operations are safe. 259 | this.setFile(fileName, true, this.bufferedIO, this.bufferSize); 260 | } catch (IOException e) { 261 | errorHandler.error("setFile(" + fileName + ", true) call failed."); 262 | } 263 | scheduledFilename = datedFilename; 264 | } 265 | 266 | /** 267 | * This method differentiates DailyRollingFileAppender from its 268 | * super class. 269 | * 270 | *

Before actually logging, this method will check whether it is 271 | * time to do a rollover. If it is, it will schedule the next 272 | * rollover time and then rollover. 273 | * */ 274 | @Override 275 | protected void subAppend(LoggingEvent event) { 276 | long n = System.currentTimeMillis(); 277 | if (n >= nextCheck) { 278 | now.setTime(n); 279 | nextCheck = rc.getNextCheckMillis(now); 280 | try { 281 | rollOver(); 282 | } catch (IOException ioe) { 283 | if (ioe instanceof InterruptedIOException) { 284 | Thread.currentThread().interrupt(); 285 | } 286 | LogLog.error("rollOver() failed.", ioe); 287 | } 288 | } 289 | super.subAppend(event); 290 | } 291 | 292 | /** 293 | * This method searches list of log files 294 | * based on the pattern given in the log4j configuration file 295 | * and returns a collection 296 | * @return List<ModifiedTimeSortableFile> 297 | */ 298 | private List getAllFiles() { 299 | List files = new ArrayList(); 300 | FilenameFilter filter = new FilenameFilter() { 301 | public boolean accept(File dir, String name) { 302 | String directoryName = dir.getPath(); 303 | LogLog.debug("directory name: " + directoryName); 304 | File file = new File(fileName); 305 | String perentDirectory = file.getParent(); 306 | if (perentDirectory != null) 307 | { 308 | String localFile = fileName.substring(directoryName.length()); 309 | return name.startsWith(localFile); 310 | } 311 | return name.startsWith(fileName); 312 | } 313 | }; 314 | File file = new File(fileName); 315 | String perentDirectory = file.getParent(); 316 | if (file.exists()) { 317 | if (file.getParent() == null) { 318 | String absolutePath = file.getAbsolutePath(); 319 | perentDirectory = absolutePath.substring(0, absolutePath.lastIndexOf(fileName)); 320 | 321 | } 322 | } 323 | File dir = new File(perentDirectory); 324 | String[] names = dir.list(filter); 325 | 326 | for (int i = 0; i < names.length; i++) { 327 | files.add(new ModifiedTimeSortableFile(dir + System.getProperty("file.separator") + names[i])); 328 | } 329 | return files; 330 | } 331 | } 332 | 333 | /** 334 | * The Class ModifiedTimeSortableFile extends java.io.File class and 335 | * implements Comparable to sort files list based upon their modified date 336 | */ 337 | class ModifiedTimeSortableFile extends File implements Serializable, Comparable { 338 | private static final long serialVersionUID = 1373373728209668895L; 339 | 340 | public ModifiedTimeSortableFile(String parent, String child) { 341 | super(parent, child); 342 | // TODO Auto-generated constructor stub 343 | } 344 | 345 | public ModifiedTimeSortableFile(URI uri) { 346 | super(uri); 347 | // TODO Auto-generated constructor stub 348 | } 349 | 350 | public ModifiedTimeSortableFile(File parent, String child) { 351 | super(parent, child); 352 | } 353 | 354 | public ModifiedTimeSortableFile(String string) { 355 | super(string); 356 | } 357 | 358 | @Override 359 | public int compareTo(File anotherPathName) { 360 | long thisVal = this.lastModified(); 361 | long anotherVal = anotherPathName.lastModified(); 362 | return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); 363 | } 364 | } 365 | 366 | /** 367 | * RollingCalendar is a helper class to DailyRollingFileAppender. 368 | * Given a periodicity type and the current time, it computes the 369 | * start of the next interval. 370 | * */ 371 | class RollingCalendar extends GregorianCalendar { 372 | private static final long serialVersionUID = -3560331770601814177L; 373 | 374 | int type = CustomDailyRollingFileAppender.TOP_OF_TROUBLE; 375 | 376 | RollingCalendar() { 377 | super(); 378 | } 379 | 380 | RollingCalendar(TimeZone tz, Locale locale) { 381 | super(tz, locale); 382 | } 383 | 384 | void setType(int type) { 385 | this.type = type; 386 | } 387 | 388 | public long getNextCheckMillis(Date now) { 389 | return getNextCheckDate(now).getTime(); 390 | } 391 | 392 | public Date getNextCheckDate(Date now) { 393 | this.setTime(now); 394 | 395 | switch (type) { 396 | case CustomDailyRollingFileAppender.TOP_OF_MINUTE: 397 | this.set(Calendar.SECOND, 0); 398 | this.set(Calendar.MILLISECOND, 0); 399 | this.add(Calendar.MINUTE, 1); 400 | break; 401 | case CustomDailyRollingFileAppender.TOP_OF_HOUR: 402 | this.set(Calendar.MINUTE, 0); 403 | this.set(Calendar.SECOND, 0); 404 | this.set(Calendar.MILLISECOND, 0); 405 | this.add(Calendar.HOUR_OF_DAY, 1); 406 | break; 407 | case CustomDailyRollingFileAppender.HALF_DAY: 408 | this.set(Calendar.MINUTE, 0); 409 | this.set(Calendar.SECOND, 0); 410 | this.set(Calendar.MILLISECOND, 0); 411 | int hour = get(Calendar.HOUR_OF_DAY); 412 | if (hour < 12) { 413 | this.set(Calendar.HOUR_OF_DAY, 12); 414 | } else { 415 | this.set(Calendar.HOUR_OF_DAY, 0); 416 | this.add(Calendar.DAY_OF_MONTH, 1); 417 | } 418 | break; 419 | case CustomDailyRollingFileAppender.TOP_OF_DAY: 420 | this.set(Calendar.HOUR_OF_DAY, 0); 421 | this.set(Calendar.MINUTE, 0); 422 | this.set(Calendar.SECOND, 0); 423 | this.set(Calendar.MILLISECOND, 0); 424 | this.add(Calendar.DATE, 1); 425 | break; 426 | case CustomDailyRollingFileAppender.TOP_OF_WEEK: 427 | this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek()); 428 | this.set(Calendar.HOUR_OF_DAY, 0); 429 | this.set(Calendar.MINUTE, 0); 430 | this.set(Calendar.SECOND, 0); 431 | this.set(Calendar.MILLISECOND, 0); 432 | this.add(Calendar.WEEK_OF_YEAR, 1); 433 | break; 434 | case CustomDailyRollingFileAppender.TOP_OF_MONTH: 435 | this.set(Calendar.DATE, 1); 436 | this.set(Calendar.HOUR_OF_DAY, 0); 437 | this.set(Calendar.MINUTE, 0); 438 | this.set(Calendar.SECOND, 0); 439 | this.set(Calendar.MILLISECOND, 0); 440 | this.add(Calendar.MONTH, 1); 441 | break; 442 | default: 443 | throw new IllegalStateException("Unknown periodicity type."); 444 | } 445 | return getTime(); 446 | } 447 | 448 | } 449 | --------------------------------------------------------------------------------