• CloudSim源代码学习——云数据中心(Datacenter)


       1 package org.cloudbus.cloudsim;
       2 
       3 import java.text.DecimalFormat;//十进制
       4 import java.util.ArrayList;
       5 import java.util.HashMap;//哈希映射 
       6 import java.util.Iterator;//迭代器
       7 import java.util.List;
       8 import java.util.Map;
       9 import java.util.Set;
      10 
      11 import org.cloudbus.cloudsim.core.CloudSim;//这个类扩展了CloudSimCore使网络模拟在CloudSim中实现
      12 import org.cloudbus.cloudsim.core.CloudSimTags;//含有多种静态命令,当CloudSim实体接收或发送事件时,表明被执行的一种行为
      13 import org.cloudbus.cloudsim.core.SimEntity;//代表一仿真实体,实体操作事件并可以发送事件到其他实体,要扩展这个类需要加入startEntity(),processEvent()and shutdownEntity()
      14 import org.cloudbus.cloudsim.core.SimEvent;//仿真事件   在实体间传递
      15 
      16 /**
      17  * Datacenter class is {a CloudResource whose hostList
      18  * are virtualized}. It deals with processing of VM queries (i.e., handling
      19  * of VMs) instead of processing Cloudlet-related queries. So, even though an
      20  * AllocPolicy will be instantiated (in the init() method of the superclass,
      21  * it will not be used, as processing of (cloudlets )are handled by the (CloudletScheduler)
      22  * and processing of 【VirtualMachines 】are handled by the【 VmAllocationPolicy】.
      23  *
      24  * @author        Rodrigo N. Calheiros
      25  * @author        Anton Beloglazov
      26  * @since        CloudSim Toolkit 1.0
      27  */
      28 public class Datacenter extends SimEntity {//扩展SimEntity类
      29 
      30     /** The characteristics. *///数据中心特性
      31     private DatacenterCharacteristics characteristics;
      32 
      33     /** The regional cis name. *///局部CIS名称
      34     private String regionalCisName;
      35 
      36     /** The vm provisioner. *///虚拟机供应
      37     private VmAllocationPolicy vmAllocationPolicy;
      38 
      39     /** The last process time. *///上一次处理时间
      40     private double lastProcessTime;
      41 
      42     /** The debts. *///费用
      43     private Map<Integer, Double> debts;
      44 
      45     /** The storage list. *///存储列表
      46     private List<Storage> storageList;
      47 
      48     /** The vm list. *///虚拟机列表
      49     private List<? extends Vm> vmList;
      50 
      51     /** The scheduling interval. *///调度间隔
      52     private double schedulingInterval;
      53 
      54     /**分配一个功率意识的数据中心对象
      55      * Allocates a new PowerDatacenter object.
      56      *
      57      * @param name       the name to be associated with this entity (as
      58      * required by Sim_entity class from simjava package)
      59      * @param characteristics   an object of DatacenterCharacteristics
      60      * @param storageList a LinkedList of storage elements, for data simulation
      61      * @param vmAllocationPolicy the vmAllocationPolicy
      62      *
      63      * @throws Exception This happens when one of the following scenarios occur:
      64      * <ul>
      65      * <li> creating this entity before initializing CloudSim package
      66      * <li> this entity name is <tt>null</tt> or empty
      67      * <li> this entity has <tt>zero</tt> number of PEs (Processing
      68      * Elements). <br>
      69      * No PEs mean the Cloudlets can't be processed.
      70      * A CloudResource must contain【 one or more Machines】.
      71      * A Machine must contain 【one or more PEs】.
      72      * </ul>
      73      *
      74      * @pre name != null
      75      * @pre resource != null
      76      * @post $none
      77      */
      78     public Datacenter(String name, DatacenterCharacteristics characteristics, VmAllocationPolicy vmAllocationPolicy, List<Storage> storageList, double schedulingInterval) throws Exception {
      79         super(name);
      80 
      81         setCharacteristics(characteristics);
      82         setVmAllocationPolicy(vmAllocationPolicy);
      83         setLastProcessTime(0.0);
      84         setDebts(new HashMap<Integer,Double>());
      85         setStorageList(storageList);
      86         setVmList(new ArrayList<Vm>());
      87         setSchedulingInterval(schedulingInterval);
      88 
      89         // If this resource doesn't have any PEs then no useful at all 资源没有PE 则是没有用(不能处理云任务)
      90         if (getCharacteristics().getPesNumber() == 0) {
      91             throw new Exception(super.getName() + " : Error - this entity has no PEs. Therefore, can't process any Cloudlets.");
      92         }
      93 
      94         // stores id of this class类的存储ID
      95         getCharacteristics().setId(super.getId());
      96     }
      97 
      98     /**重写此方法 以创建一个新的不同类型的资源
      99      * Overrides this method when making a new and different type of resource.
     100      * This method is called by {@link #body()} to register other type to
     101      * GIS entity. In doing so, you
     102      * need to create a new child class extending from
     103      * gridsim.CloudInformationService.
     104      * <br>
     105      * <b>NOTE:</b> 【You do not need to override {@link #body()} method, if
     106      * you use this method.】
     107      *
     108      * @pre $none
     109      * @post $none
     110      */
     111     protected void registerOtherEntity() {
     112         // empty. This should be override by a child class 【用一个子类重写】
     113     }
     114 
     115     /**处理时间 服务
     116      * Processes events or services that are available for this PowerDatacenter.
     117      *
     118      * @param ev    a Sim_event object
     119      *
     120      * @pre ev != null
     121      * @post $none
     122      */
     123     @Override
     124     public void processEvent(SimEvent ev) {  //implements org.cloudbus.cloudsim.core.SimEntity.processEvent
     125         int srcId = -1;
     126         //Log.printLine(CloudSim.clock()+"[PowerDatacenter]: event received:"+ev.getTag());
     127 
     128         switch (ev.getTag()) {
     129             // Resource characteristics inquiry 资源特征调查
     130             case CloudSimTags.RESOURCE_CHARACTERISTICS:
     131                 srcId = ((Integer) ev.getData()).intValue();
     132                 sendNow(srcId, ev.getTag(), getCharacteristics());
     133                 break;
     134 
     135                 // Resource dynamic info inquiry 资源动态信息查询
     136             case CloudSimTags.RESOURCE_DYNAMICS:
     137                 srcId = ((Integer) ev.getData()).intValue();
     138                 sendNow(srcId, ev.getTag(), 0);
     139                 break;
     140 
     141             case CloudSimTags.RESOURCE_NUM_PE:
     142                 srcId = ((Integer) ev.getData()).intValue();
     143                 int numPE = getCharacteristics().getPesNumber();
     144                 sendNow(srcId, ev.getTag(), numPE);
     145                 break;
     146 
     147             case CloudSimTags.RESOURCE_NUM_FREE_PE:
     148                 srcId = ((Integer) ev.getData()).intValue();
     149                 int freePesNumber = getCharacteristics().getFreePesNumber();
     150                 sendNow(srcId, ev.getTag(), freePesNumber);
     151                 break;
     152 
     153                 // New Cloudlet arrives 新的云任务到达
     154             case CloudSimTags.CLOUDLET_SUBMIT:
     155                 processCloudletSubmit(ev, false);
     156                 break;
     157 
     158                 // New Cloudlet arrives, but the sender asks for an ack 确认
     159             case CloudSimTags.CLOUDLET_SUBMIT_ACK:
     160                 processCloudletSubmit(ev, true);
     161                 break;
     162 
     163                 // Cancels a previously submitted Cloudlet取消一个先前提交的云任务
     164             case CloudSimTags.CLOUDLET_CANCEL:
     165                 processCloudlet(ev, CloudSimTags.CLOUDLET_CANCEL);
     166                 break;
     167 
     168                 // Pauses a previously submitted Cloudlet暂停一个先前提交的云任务
     169             case CloudSimTags.CLOUDLET_PAUSE:
     170                 processCloudlet(ev, CloudSimTags.CLOUDLET_PAUSE);
     171                 break;
     172 
     173                 // Pauses a previously submitted Cloudlet, but the sender
     174                 // asks for an acknowledgement取消一个先前提交的云任务 发送则者要求确认
     175             case CloudSimTags.CLOUDLET_PAUSE_ACK:
     176                 processCloudlet(ev, CloudSimTags.CLOUDLET_PAUSE_ACK);
     177                 break;
     178 
     179                 // Resumes a previously submitted Cloudlet重启一个先前提交的云任务
     180             case CloudSimTags.CLOUDLET_RESUME:
     181                 processCloudlet(ev, CloudSimTags.CLOUDLET_RESUME);
     182                 break;
     183 
     184                 // Resumes a previously submitted Cloudlet, but the sender
     185                 // asks for an acknowledgement重启一个先前提交的云任务 发送则者要求确认
     186             case CloudSimTags.CLOUDLET_RESUME_ACK:
     187                 processCloudlet(ev, CloudSimTags.CLOUDLET_RESUME_ACK);
     188                 break;
     189 
     190                 // Moves a previously submitted Cloudlet to a different resource移动一个先前提交的云任务 
     191             case CloudSimTags.CLOUDLET_MOVE:
     192                 processCloudletMove((int[]) ev.getData(), CloudSimTags.CLOUDLET_MOVE);
     193                 break;
     194 
     195                 // Moves a previously submitted Cloudlet to a different resource
     196             case CloudSimTags.CLOUDLET_MOVE_ACK:
     197                 processCloudletMove((int[]) ev.getData(), CloudSimTags.CLOUDLET_MOVE_ACK);
     198                 break;
     199 
     200                 // Checks the status of a Cloudlet检查云任务状态
     201             case CloudSimTags.CLOUDLET_STATUS:
     202                 processCloudletStatus(ev);
     203                 break;
     204 
     205                 // Ping packet
     206             case CloudSimTags.INFOPKT_SUBMIT:
     207                 processPingRequest(ev);
     208                 break;
     209 
     210                case CloudSimTags.VM_CREATE:
     211                 processVmCreate(ev, false);
     212                 break;
     213 
     214             case CloudSimTags.VM_CREATE_ACK:
     215                 processVmCreate(ev, true);
     216                 break;
     217 
     218                case CloudSimTags.VM_DESTROY:
     219                    processVmDestroy(ev, false);
     220                    break;
     221 
     222                case CloudSimTags.VM_DESTROY_ACK:
     223                 processVmDestroy(ev, true);
     224                 break;
     225 
     226                case CloudSimTags.VM_MIGRATE:
     227                    processVmMigrate(ev, false);
     228                    break;
     229 
     230                case CloudSimTags.VM_MIGRATE_ACK:
     231                    processVmMigrate(ev, true);
     232                    break;
     233 
     234                case CloudSimTags.VM_DATA_ADD:
     235                    processDataAdd(ev, false);
     236                    break;
     237 
     238                case CloudSimTags.VM_DATA_ADD_ACK:
     239                    processDataAdd(ev, true);
     240                    break;
     241 
     242                case CloudSimTags.VM_DATA_DEL:
     243                    processDataDelete(ev, false);
     244                    break;
     245 
     246                case CloudSimTags.VM_DATA_DEL_ACK:
     247                    processDataDelete(ev, true);
     248                    break;
     249 
     250                case CloudSimTags.VM_DATACENTER_EVENT:
     251                    updateCloudletProcessing();
     252                 checkCloudletCompletion();
     253                    break;
     254 
     255                    // other unknown tags are processed by this method通过这种方法处理其他不知道的标签
     256             default:
     257                 processOtherEvent(ev);
     258                 break;
     259         }
     260     }
     261 
     262     /**处理数据删除文件
     263      * Process data del.
     264      *
     265      * @param ev the ev
     266      * @param ack the ack
     267      */
     268     protected void processDataDelete(SimEvent ev, boolean ack) {
     269         if (ev == null) {
     270             return;
     271         }
     272 
     273         Object[] data = (Object[]) ev.getData();
     274         if (data == null) {
     275             return;
     276         }
     277 
     278         String filename = (String) data[0];
     279         int req_source = ((Integer) data[1]).intValue();
     280         int tag = -1;
     281 
     282         // check if this file can be deleted (do not delete is right now)检查文件是否可以删除
     283         int msg = deleteFileFromStorage(filename);
     284         if (msg == DataCloudTags.FILE_DELETE_SUCCESSFUL) {
     285            tag = DataCloudTags.CTLG_DELETE_MASTER;
     286         } else { // if an error occured, notify user
     287            tag = DataCloudTags.FILE_DELETE_MASTER_RESULT;
     288         }
     289 
     290         if (ack){
     291             // send back to sender
     292             Object pack[] = new Object[2];
     293             pack[0] = filename;
     294             pack[1] = Integer.valueOf(msg);
     295 
     296             sendNow(req_source, tag, pack);
     297         }
     298     }
     299 
     300     /**数据增加
     301      * Process data add.
     302      *
     303      * @param ev the ev
     304      * @param ack the ack
     305      */
     306     protected void processDataAdd(SimEvent ev, boolean ack) {
     307        if (ev == null) {
     308             return;
     309         }
     310 
     311         Object[] pack = (Object[]) ev.getData();
     312         if (pack == null) {
     313             return;
     314         }
     315 
     316         File file = (File) pack[0]; // get the file
     317         file.setMasterCopy(true); // set the file into a master copy
     318         int sentFrom = ((Integer) pack[1]).intValue(); // get sender ID
     319 
     320         /******     // DEBUG
     321          Log.printLine(super.get_name() + ".addMasterFile(): " +
     322          file.getName() + " from " + CloudSim.getEntityName(sentFrom));
     323          *******/
     324 
     325         Object[] data = new Object[3];
     326         data[0] = file.getName();
     327 
     328         int msg = addFile(file); // add the file
     329 
     330         double debit;
     331         if (getDebts().containsKey(sentFrom)) {
     332             debit = getDebts().get(sentFrom);
     333         } else {
     334             debit = 0.0;
     335         }
     336 
     337         debit += getCharacteristics().getCostPerBw() * file.getSize();
     338 
     339         getDebts().put(sentFrom, debit);
     340 
     341         if (ack) {
     342             data[1] = Integer.valueOf(-1); // no sender id
     343             data[2] = Integer.valueOf(msg); // the result of adding a master file
     344             sendNow(sentFrom, DataCloudTags.FILE_ADD_MASTER_RESULT, data);
     345         }
     346     }
     347 
     348     /**
     349      * Processes a ping request.
     350      *
     351      * @param ev  a Sim_event object
     352      *
     353      * @pre ev != null
     354      * @post $none
     355      */
     356     protected void processPingRequest(SimEvent ev) {
     357         InfoPacket pkt = (InfoPacket) ev.getData();
     358         pkt.setTag(CloudSimTags.INFOPKT_RETURN);
     359         pkt.setDestId(pkt.getSrcId());
     360 
     361         // sends back to the sender
     362         sendNow(pkt.getSrcId(), CloudSimTags.INFOPKT_RETURN, pkt);
     363     }
     364 
     365     /**处理事件:用户/代理想知道云任务状态
     366      * Process the event for an User/Broker who wants to know the status of a Cloudlet.
     367      * This PowerDatacenter will then send the status back to the User/Broker.
     368      *
     369      * @param ev   a Sim_event object
     370      *
     371      * @pre ev != null
     372      * @post $none
     373      */
     374     protected void processCloudletStatus(SimEvent ev) {
     375         int cloudletId = 0;
     376         int userId = 0;
     377         int vmId = 0;
     378         int status = -1;
     379 
     380         try{
     381             // if a sender using 【cloudletXXX() methods】
     382             int data[] = (int[]) ev.getData();
     383             cloudletId = data[0];
     384             userId = data[1];
     385             vmId = data[2];
     386 
     387             status = getVmAllocationPolicy().getHost(vmId, userId).getVm(userId, vmId).getCloudletScheduler().getCloudletStatus(cloudletId);
     388         }
     389 
     390         // if a sender using normal 【send() methods】
     391         catch (ClassCastException c) {
     392             try {
     393                 Cloudlet cl = (Cloudlet) ev.getData();
     394                 cloudletId = cl.getCloudletId();
     395                 userId = cl.getUserId();
     396 
     397                 status = getVmAllocationPolicy().getHost(vmId, userId).getVm(userId, vmId).getCloudletScheduler().getCloudletStatus(cloudletId);
     398             }
     399             catch (Exception e) {
     400                 Log.printLine(getName() +
     401                         ": Error in processing CloudSimTags.CLOUDLET_STATUS");
     402                 Log.printLine( e.getMessage() );
     403                 return;
     404             }
     405         }
     406         catch (Exception e) {
     407             Log.printLine(getName() +
     408                     ": Error in processing CloudSimTags.CLOUDLET_STATUS");
     409             Log.printLine( e.getMessage() );
     410             return;
     411         }
     412 
     413         int[] array = new int[3];
     414         array[0] = getId();
     415         array[1] = cloudletId;
     416         array[2] = status;
     417 
     418         int tag = CloudSimTags.CLOUDLET_STATUS;
     419         sendNow(userId, tag, array);
     420     }
     421 
     422     /**
     423      * Here all the method related to 【VM requests 】will be received and forwarded to the related method.
     424      *
     425      * @param ev the received event
     426      *
     427      * @pre $none
     428      * @post $none
     429      */
     430     protected void processOtherEvent(SimEvent ev) {
     431         if (ev == null){
     432             Log.printLine(getName() + ".processOtherEvent(): Error - an event is null.");
     433         }
     434     }
     435 
     436     /**处理事件:用户/代理创建一个虚拟机
     437      * Process the event for an User/Broker who wants to create a VM
     438      * in this PowerDatacenter. This PowerDatacenter will then send the status back to
     439      * the User/Broker.
     440      *
     441      * @param ev   a Sim_event object
     442      * @param ack the ack
     443      *
     444      * @pre ev != null
     445      * @post $none
     446      */
     447     protected void processVmCreate(SimEvent ev, boolean ack) {
     448         Vm vm = (Vm) ev.getData();
     449 
     450          boolean result = getVmAllocationPolicy().allocateHostForVm(vm);
     451 
     452          if (ack) {
     453             int[] data = new int[3];
     454            data[0] = getId();
     455             data[1] = vm.getId();
     456 
     457            if (result) {
     458                data[2] = CloudSimTags.TRUE;
     459            } else {
     460                data[2] = CloudSimTags.FALSE;
     461            }
     462            sendNow(vm.getUserId(), CloudSimTags.VM_CREATE_ACK, data);
     463          }
     464 
     465          if (result) {
     466             double amount = 0.0;
     467             if (getDebts().containsKey(vm.getUserId())) {
     468                 amount = getDebts().get(vm.getUserId());
     469             }
     470             amount += getCharacteristics().getCostPerMem() * vm.getRam();
     471             amount += getCharacteristics().getCostPerStorage() * vm.getSize();
     472 
     473             getDebts().put(vm.getUserId(), amount);
     474 
     475             getVmList().add(vm);
     476 
     477             vm.updateVmProcessing(CloudSim.clock(), getVmAllocationPolicy().getHost(vm).getVmScheduler().getAllocatedMipsForVm(vm));
     478          }
     479 
     480     }
     481 
     482     /**处理事件:用户/代理销毁虚拟机
     483      * Process the event for an User/Broker who wants to destroy a VM
     484      * previously created in this PowerDatacenter. This PowerDatacenter may send,
     485      * upon request, the status back to the User/Broker.
     486      *
     487      * @param ev   a Sim_event object
     488      * @param ack the ack
     489      *
     490      * @pre ev != null
     491      * @post $none
     492      */
     493     protected void processVmDestroy(SimEvent ev, boolean ack) {
     494         Vm vm = (Vm) ev.getData();
     495         getVmAllocationPolicy().deallocateHostForVm(vm);
     496 
     497         if (ack) {
     498             int[] data = new int[3];
     499             data[0] = getId();
     500             data[1] = vm.getId();
     501             data[2] = CloudSimTags.TRUE;
     502 
     503             sendNow(vm.getUserId(),    CloudSimTags.VM_DESTROY_ACK, data);
     504         }
     505 
     506         getVmList().remove(vm);
     507     }
     508 
     509     /**处理事件:用户/代理迁移虚拟机
     510      * Process the event for an User/Broker who wants to migrate a VM.
     511      * This PowerDatacenter will then send the status back to the User/Broker.
     512      * @param ev   a Sim_event object
     513      * @pre ev != null
     514      * @post $none
     515      */
     516     protected void processVmMigrate(SimEvent ev, boolean ack) {
     517         Object tmp = ev.getData();
     518         if (!(tmp instanceof Map<?, ?>)) {
     519             throw new ClassCastException("The data object must be Map<String, Object>");
     520         }
     521 
     522         @SuppressWarnings("unchecked")
     523         Map<String, Object> migrate = (HashMap<String, Object>) tmp;
     524 
     525         Vm vm = (Vm) migrate.get("vm");
     526         Host host = (Host) migrate.get("host");
     527 
     528         getVmAllocationPolicy().deallocateHostForVm(vm);
     529         host.removeMigratingInVm(vm);
     530         boolean result = getVmAllocationPolicy().allocateHostForVm(vm, host);
     531         if (!result) {
     532             Log.printLine("Allocation failed");
     533         }
     534 
     535         if (ack) {
     536             int[] data = new int[3];
     537             data[0] = getId();
     538             data[1] = vm.getId();
     539 
     540             if (result) {
     541                 data[2] = CloudSimTags.TRUE;
     542             } else {
     543                 data[2] = CloudSimTags.FALSE;
     544             }
     545             sendNow(ev.getSource(), CloudSimTags.VM_CREATE_ACK, data);
     546         }
     547 
     548         double amount=0.0;
     549         if (debts.containsKey(vm.getUserId())) {
     550             amount = debts.get(vm.getUserId());
     551         }
     552 
     553         amount += getCharacteristics().getCostPerMem() * vm.getRam();
     554         amount += getCharacteristics().getCostPerStorage() * vm.getSize();
     555 
     556         debts.put(vm.getUserId(), amount);
     557 
     558         Log.formatLine("%.2f: Migration of VM #%d to Host #%d is completed", CloudSim.clock(), vm.getId(), host.getId());
     559         vm.setInMigration(false);
     560     }
     561 
     562     /**基于事件类别处理云任务
     563      * Processes a Cloudlet based on the event type.
     564      *
     565      * @param ev   a Sim_event object
     566      * @param type event type
     567      *
     568      * @pre ev != null
     569      * @pre type > 0
     570      * @post $none
     571      */
     572     protected void processCloudlet(SimEvent ev, int type) {
     573         int cloudletId = 0;
     574         int userId = 0;
     575         int vmId = 0;
     576 
     577         try { // if the sender using 【cloudletXXX() methods】
     578             int data[] = (int[]) ev.getData();
     579             cloudletId = data[0];
     580             userId = data[1];
     581             vmId = data[2];
     582         }
     583 
     584         // if the sender using 【normal send() methods】
     585         catch (ClassCastException c) {
     586             try {
     587                 Cloudlet cl = (Cloudlet) ev.getData();
     588                 cloudletId = cl.getCloudletId();
     589                 userId = cl.getUserId();
     590                 vmId = cl.getVmId();
     591             } catch (Exception e) {
     592                 Log.printLine(super.getName() + ": Error in processing Cloudlet");
     593                 Log.printLine(e.getMessage());
     594                 return;
     595             }
     596         } catch (Exception e) {
     597             Log.printLine(super.getName() + ": Error in processing a Cloudlet.");
     598             Log.printLine( e.getMessage() );
     599             return;
     600         }
     601 
     602         // begins executing ....
     603         switch (type) {
     604             case CloudSimTags.CLOUDLET_CANCEL:
     605                 processCloudletCancel(cloudletId, userId, vmId);
     606                 break;
     607 
     608             case CloudSimTags.CLOUDLET_PAUSE:
     609                 processCloudletPause(cloudletId, userId, vmId, false);
     610                 break;
     611 
     612             case CloudSimTags.CLOUDLET_PAUSE_ACK:
     613                 processCloudletPause(cloudletId, userId, vmId, true);
     614                 break;
     615 
     616             case CloudSimTags.CLOUDLET_RESUME:
     617                 processCloudletResume(cloudletId, userId, vmId, false);
     618                 break;
     619 
     620             case CloudSimTags.CLOUDLET_RESUME_ACK:
     621                 processCloudletResume(cloudletId, userId, vmId, true);
     622                 break;
     623             default:
     624                 break;
     625         }
     626 
     627     }
     628 
     629     /**处理事件:用户/代理移动云任务
     630      * Process the event for an User/Broker who wants to move a Cloudlet.
     631      *
     632      * @param receivedData   information about the migration
     633      * @param type  event tag
     634      *
     635      * @pre receivedData != null
     636      * @pre type > 0
     637      * @post $none
     638      */
     639     protected void processCloudletMove(int[] receivedData, int type) {
     640         updateCloudletProcessing();
     641 
     642         int[] array = receivedData;
     643         int cloudletId = array[0];
     644         int userId = array[1];
     645         int vmId = array[2];
     646         int vmDestId = array[3];
     647         int destId = array[4];
     648 
     649         //get the cloudlet
     650         Cloudlet cl = getVmAllocationPolicy().getHost(vmId, userId).getVm(userId, vmId).getCloudletScheduler().cloudletCancel(cloudletId);
     651 
     652         boolean failed=false;
     653         if (cl == null) {// cloudlet doesn't exist
     654             failed = true;
     655         } else {
     656             // has the cloudlet already finished?
     657             if (cl.getCloudletStatus() == Cloudlet.SUCCESS) {// if yes, send it back to user
     658                 int[] data = new int[3];
     659                 data[0] = this.getId();
     660                 data[1] = cloudletId;
     661                 data[2] = 0;
     662                 sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_SUBMIT_ACK, data);
     663                 sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_RETURN, cl);
     664             }
     665 
     666             // prepare cloudlet for migration
     667             cl.setVmId(vmDestId);
     668 
     669             // the cloudlet will migrate from one vm to another does the destination VM exist?
     670             if (destId == this.getId()) {
     671                 Vm vm = getVmAllocationPolicy().getHost(vmDestId, userId).getVm(userId, vmDestId);
     672                 if (vm == null) {
     673                     failed = true;
     674                 } else {
     675                     double fileTransferTime = predictFileTransferTime(cl.getRequiredFiles()); // time to transfer the files
     676                     vm.getCloudletScheduler().cloudletSubmit(cl, fileTransferTime);
     677                 }
     678             } else {// the cloudlet will migrate from one resource to another
     679                 int tag = ((type == CloudSimTags.CLOUDLET_MOVE_ACK) ? CloudSimTags.CLOUDLET_SUBMIT_ACK : CloudSimTags.CLOUDLET_SUBMIT);
     680                 sendNow(destId, tag, cl);
     681             }
     682         }
     683 
     684         if (type == CloudSimTags.CLOUDLET_MOVE_ACK) {// send ACK if requested
     685             int[] data = new int[3];
     686             data[0] = this.getId();
     687             data[1] = cloudletId;
     688             if (failed) {
     689                 data[2] = 0;
     690             } else {
     691                 data[2] = 1;
     692             }
     693             sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_SUBMIT_ACK, data);
     694         }
     695     }
     696 
     697     /**处理事件:云任务提交
     698      * Processes a Cloudlet submission.
     699      *
     700      * @param ev  a SimEvent object
     701      * @param ack  an acknowledgement
     702      *
     703      * @pre ev != null
     704      * @post $none
     705      */
     706     protected void processCloudletSubmit(SimEvent ev, boolean ack) {
     707         updateCloudletProcessing();
     708 
     709         try {
     710             // gets the Cloudlet object
     711             Cloudlet cl = (Cloudlet) ev.getData();
     712 
     713             // checks whether this Cloudlet has finished or not
     714             if (cl.isFinished()){
     715                 String name = CloudSim.getEntityName(cl.getUserId());
     716                 Log.printLine(getName()+": Warning - Cloudlet #"+cl.getCloudletId()+" owned by "+name+" is already completed/finished.");
     717                 Log.printLine("Therefore, it is not being executed again");
     718                 Log.printLine();
     719 
     720                 // NOTE: If a Cloudlet has finished, then it won't be processed.
     721                 // So, if ack is required, this method sends back a result.
     722                 // If ack is not required, this method don't send back a result.
     723                 // Hence, this might cause CloudSim to be hanged since waiting
     724                 // for this Cloudlet back.
     725                 if (ack) {
     726                     int[] data = new int[3];
     727                     data[0] = getId();
     728                     data[1] = cl.getCloudletId();
     729                     data[2] = CloudSimTags.FALSE;
     730 
     731                     // unique tag = operation tag
     732                     int tag = CloudSimTags.CLOUDLET_SUBMIT_ACK;
     733                     sendNow(cl.getUserId(), tag, data);
     734                 }
     735 
     736                 sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_RETURN, cl);
     737 
     738                 return;
     739             }
     740 
     741             // process this Cloudlet to this CloudResource
     742             cl.setResourceParameter(getId(), getCharacteristics().getCostPerSecond(), getCharacteristics().getCostPerBw());
     743 
     744             int userId = cl.getUserId();
     745             int vmId = cl.getVmId();
     746 
     747             double fileTransferTime = predictFileTransferTime(cl.getRequiredFiles()); //time to transfer the files
     748 
     749             Host host = getVmAllocationPolicy().getHost(vmId, userId);
     750             Vm vm = host.getVm(vmId, userId);
     751             CloudletScheduler scheduler = vm.getCloudletScheduler();
     752             double estimatedFinishTime = scheduler.cloudletSubmit(cl,fileTransferTime);
     753 
     754             //if (estimatedFinishTime > 0.0 && estimatedFinishTime < getSchedulingInterval()) { //if this cloudlet is in the exec queue
     755             if (estimatedFinishTime > 0.0) { //if this cloudlet is in the exec queue
     756                 //double estimatedFinishTime = (cl.getCloudletTotalLength()/(capacity*cl.getPesNumber())); //time to process the cloudlet
     757                 //Log.printLine(estimatedFinishTime+"="+gl.getCloudletLength()+"/("+capacity+"*"+gl.getNumPE()+")");
     758                 estimatedFinishTime += fileTransferTime;
     759                 //estimatedFinishTime += CloudSim.clock();
     760                 //Log.printLine(CloudSim.clock()+": Next event scheduled to +"+estimatedFinishTime);
     761                 send(getId(), estimatedFinishTime, CloudSimTags.VM_DATACENTER_EVENT);
     762             }
     763 
     764         }
     765         catch (ClassCastException c) {
     766             Log.printLine(getName() + ".processCloudletSubmit(): " + "ClassCastException error.");
     767             c.printStackTrace();
     768         }
     769         catch (Exception e) {
     770             Log.printLine(getName() + ".processCloudletSubmit(): " + "Exception error.");
     771             e.printStackTrace();
     772         }
     773 
     774         checkCloudletCompletion();
     775     }
     776 
     777     /**预测文件传输时间
     778      * Predict file transfer time.
     779      *
     780      * @param requiredFiles the required files
     781      *
     782      * @return the double
     783      */
     784     protected double predictFileTransferTime(List<String> requiredFiles) {
     785         double time = 0.0;
     786 
     787         Iterator<String> iter = requiredFiles.iterator();//【迭代器的使用】
     788         while (iter.hasNext()) {
     789             String fileName = iter.next();
     790             for (int i = 0; i < getStorageList().size(); i++) {
     791                 Storage tempStorage = getStorageList().get(i);
     792                 File tempFile = tempStorage.getFile(fileName);
     793                 if (tempFile != null) {
     794                     time += tempFile.getSize() / tempStorage.getMaxTransferRate();
     795                     break;
     796                 }
     797             }
     798         }
     799         return time;
     800     }
     801 
     802     /**处理云任务重启请求
     803      * Processes a Cloudlet resume request.
     804      *
     805      * @param cloudletId  resuming cloudlet ID
     806      * @param userId  ID of the cloudlet's owner
     807      * @param ack $true if an ack is requested after operation
     808      * @param vmId the vm id
     809      *
     810      * @pre $none
     811      * @post $none
     812      */
     813     protected void processCloudletResume(int cloudletId, int userId, int vmId, boolean ack) {
     814         double eventTime = getVmAllocationPolicy().getHost(vmId,userId).getVm(userId, vmId).getCloudletScheduler().cloudletResume(cloudletId);
     815 
     816         boolean status = false;
     817         if (eventTime > 0.0) { //if this cloudlet is in the exec queue
     818             status = true;
     819             if (eventTime > CloudSim.clock()) {
     820                 schedule(getId(), eventTime, CloudSimTags.VM_DATACENTER_EVENT);
     821             }
     822         }
     823 
     824         if (ack) {
     825             int[] data = new int[3];
     826             data[0] = getId();
     827             data[1] = cloudletId;
     828             if (status) {
     829                 data[2] = CloudSimTags.TRUE;
     830             } else {
     831                 data[2] = CloudSimTags.FALSE;
     832             }
     833             sendNow(userId, CloudSimTags.CLOUDLET_RESUME_ACK, data);
     834         }
     835     }
     836 
     837     /**处理云任务暂停请求
     838      * Processes a Cloudlet pause request.
     839      *
     840      * @param cloudletId  resuming cloudlet ID
     841      * @param userId  ID of the cloudlet's owner
     842      * @param ack $true if an ack is requested after operation
     843      * @param vmId the vm id
     844      *
     845      * @pre $none
     846      * @post $none
     847      */
     848     protected void processCloudletPause(int cloudletId, int userId, int vmId, boolean ack) {
     849         boolean status = getVmAllocationPolicy().getHost(vmId,userId).getVm(userId, vmId).getCloudletScheduler().cloudletPause(cloudletId);
     850 
     851         if (ack) {
     852             int[] data = new int[3];
     853             data[0] = getId();
     854             data[1] = cloudletId;
     855             if (status) {
     856                 data[2] = CloudSimTags.TRUE;
     857             } else {
     858                 data[2] = CloudSimTags.FALSE;
     859             }
     860             sendNow(userId, CloudSimTags.CLOUDLET_PAUSE_ACK, data);
     861         }
     862     }
     863 
     864     /**处理云任务取消请求
     865      * Processes a Cloudlet cancel request.
     866      *
     867      * @param cloudletId  resuming cloudlet ID
     868      * @param userId  ID of the cloudlet's owner
     869      * @param vmId the vm id
     870      *
     871      * @pre $none
     872      * @post $none
     873      */
     874     protected void processCloudletCancel(int cloudletId, int userId, int vmId) {
     875         Cloudlet cl = getVmAllocationPolicy().getHost(vmId,userId).getVm(userId, vmId).getCloudletScheduler().cloudletCancel(cloudletId);
     876 
     877         sendNow(userId, CloudSimTags.CLOUDLET_CANCEL, cl);
     878     }
     879 
     880     /**更新处理云任务
     881      * Updates processing of each cloudlet running in this PowerDatacenter. It is necessary because
     882      * Hosts and VirtualMachines are simple objects, not entities. So, they don't receive events
     883      * and updating cloudlets inside them must be called from the outside.
     884      *
     885      * @pre $none
     886      * @post $none
     887      */
     888     protected void updateCloudletProcessing() {
     889         //Log.printLine(CloudSim.clock()+": PowerDatacenter #"+this.get_id()+": updating cloudlet processing.......................................");
     890         //if some time passed since last processing
     891         if (CloudSim.clock() > this.getLastProcessTime()) {
     892             List<? extends Host> list = getVmAllocationPolicy().getHostList();
     893             double smallerTime = Double.MAX_VALUE;
     894             //for each host...
     895             for (int i = 0; i < list.size(); i++) {
     896                 Host host = list.get(i);
     897                 double time = host.updateVmsProcessing(CloudSim.clock());//inform VMs to update processing
     898                 //what time do we expect that the next cloudlet will finish?
     899                 if (time < smallerTime) {
     900                     smallerTime = time;
     901                 }
     902             }
     903             //schedules an event to the next time, if valid
     904             //if (smallerTime > CloudSim.clock() + 0.01 && smallerTime != Double.MAX_VALUE && smallerTime < getSchedulingInterval()) {
     905             if (smallerTime > CloudSim.clock() + 0.01 && smallerTime != Double.MAX_VALUE) {
     906                 schedule(getId(), (smallerTime - CloudSim.clock()), CloudSimTags.VM_DATACENTER_EVENT);
     907             }
     908             setLastProcessTime(CloudSim.clock());
     909         }
     910     }
     911 
     912     /**证实 如果一些任务已经完成
     913      * Verifies if some cloudlet inside this PowerDatacenter already finished.
     914      * If yes, send it to the User/Broker
     915      *
     916      * @pre $none
     917      * @post $none
     918      */
     919     protected void checkCloudletCompletion() {
     920         List<? extends Host> list = getVmAllocationPolicy().getHostList();
     921         for (int i = 0; i < list.size(); i++) {
     922             Host host = list.get(i);
     923             for (Vm vm : host.getVmList()) {
     924                 while (vm.getCloudletScheduler().isFinishedCloudlets()){
     925                     Cloudlet cl = vm.getCloudletScheduler().getNextFinishedCloudlet();
     926                     if (cl != null) {
     927                         sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_RETURN, cl);
     928                     }
     929                 }
     930             }
     931         }
     932     }
     933 
     934    /**实验开始前增加一个文件到资源存储    file  ???
     935     * Adds a file into the resource's storage before the experiment starts.
     936     * If the file is a master file, then it will be registered to the RC when
     937     * the experiment begins.
     938     *
     939     * @param file  a DataCloud file
     940     *
     941     * @return a tag number denoting whether this operation is a success or not
     942     *
     943     * @see CloudSim.datagrid.DataCloudTags#FILE_ADD_SUCCESSFUL
     944     * @see CloudSim.datagrid.DataCloudTags#FILE_ADD_ERROR_EMPTY
     945     */
     946     public int addFile(File file) {
     947         if (file == null) {
     948             return DataCloudTags.FILE_ADD_ERROR_EMPTY;
     949         }
     950 
     951         if (contains(file.getName())) {
     952             return DataCloudTags.FILE_ADD_ERROR_EXIST_READ_ONLY;
     953         }
     954 
     955         // check storage space first
     956         if (getStorageList().size() <= 0) {
     957             return DataCloudTags.FILE_ADD_ERROR_STORAGE_FULL;
     958         }
     959 
     960         Storage tempStorage = null;
     961         int msg = DataCloudTags.FILE_ADD_ERROR_STORAGE_FULL;
     962 
     963         for (int i = 0; i < getStorageList().size(); i++) {
     964             tempStorage = getStorageList().get(i);
     965             if (tempStorage.getAvailableSpace() >= file.getSize()) {
     966                 tempStorage.addFile(file);
     967                 msg = DataCloudTags.FILE_ADD_SUCCESSFUL;
     968                 break;
     969             }
     970         }
     971 
     972         return msg;
     973     }
     974 
     975     /**核实是否资源拥有给定的文件
     976      * Checks whether the resource has the given file.
     977      *
     978      * @param file  a file to be searched
     979      *
     980      * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
     981      */
     982     protected boolean contains(File file) {
     983         if (file == null) {
     984             return false;
     985         }
     986         return contains( file.getName() );
     987     }
     988 
     989     /**
     990      * Checks whether the resource has the given file.
     991      *
     992      * @param fileName  a file name to be searched
     993      *
     994      * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
     995      */
     996     protected boolean contains(String fileName) {
     997         if (fileName == null || fileName.length() == 0) {
     998             return false;
     999         }
    1000 
    1001         Iterator<Storage> it = getStorageList().iterator();
    1002         Storage storage = null;
    1003         boolean result = false;
    1004 
    1005         while (it.hasNext()) {
    1006             storage = it.next();
    1007             if (storage.contains(fileName)) {
    1008                 result = true;
    1009                 break;
    1010             }
    1011         }
    1012 
    1013         return result;
    1014     }
    1015 
    1016     /**删除文件 
    1017      * Deletes the file from the storage. Also, check whether it is
    1018      * possible to delete the file from the storage.
    1019      *
    1020      * @param fileName      the name of the file to be deleted
    1021      *
    1022      * @return the error message as defined in
    1023      * {@link CloudSim.datagrid.DataCloudTags}
    1024      *
    1025      * @see CloudSim.datagrid.DataCloudTags#FILE_DELETE_SUCCESSFUL
    1026      * @see CloudSim.datagrid.DataCloudTags#FILE_DELETE_ERROR_ACCESS_DENIED
    1027      * @see CloudSim.datagrid.DataCloudTags#FILE_DELETE_ERROR
    1028      */
    1029     private int deleteFileFromStorage(String fileName) {
    1030         Storage tempStorage = null;
    1031         File tempFile = null;
    1032         int msg = DataCloudTags.FILE_DELETE_ERROR;
    1033 
    1034         for (int i = 0; i < getStorageList().size(); i++) {
    1035             tempStorage = getStorageList().get(i);
    1036             tempFile = tempStorage.getFile(fileName);
    1037             tempStorage.deleteFile(fileName, tempFile);
    1038             msg = DataCloudTags.FILE_DELETE_SUCCESSFUL;
    1039         } // end for
    1040 
    1041         return msg;
    1042     }
    1043 
    1044     /**打印费用
    1045      * Prints the debts.
    1046      */
    1047     public void printDebts() {
    1048         Log.printLine("*****PowerDatacenter: "+this.getName()+"*****");
    1049         Log.printLine("User id		Debt");
    1050 
    1051         Set<Integer> keys = getDebts().keySet();
    1052         Iterator<Integer> iter = keys.iterator();
    1053         DecimalFormat df = new DecimalFormat("#.##");
    1054         while (iter.hasNext()) {
    1055             int key = iter.next();
    1056             double value = getDebts().get(key);
    1057             Log.printLine(key+"		"+df.format(value));
    1058         }
    1059         Log.printLine("**********************************");
    1060     }
    1061 
    1062     /* (non-Javadoc)
    1063      * @see cloudsim.core.SimEntity#shutdownEntity()
    1064      */
    1065     @Override
    1066     public void shutdownEntity() {
    1067         Log.printLine(getName() + " is shutting down...");
    1068     }
    1069 
    1070     /* (non-Javadoc)
    1071      * @see cloudsim.core.SimEntity#startEntity()
    1072      */
    1073     @Override
    1074     public void startEntity() {
    1075         Log.printLine(getName() + " is starting...");
    1076         // this resource should register to regional GIS.
    1077         // However, if not specified, then register to system GIS (the
    1078         // default CloudInformationService) entity.
    1079         int gisID = CloudSim.getEntityId(regionalCisName);
    1080         if (gisID == -1) {
    1081             gisID = CloudSim.getCloudInfoServiceEntityId();
    1082         }
    1083 
    1084         // send the registration to GIS
    1085         sendNow(gisID, CloudSimTags.REGISTER_RESOURCE, getId());
    1086         // Below method is for a child class to override
    1087         registerOtherEntity();
    1088     }
    1089 
    1090     /**获取主机列表
    1091      * Gets the host list.
    1092      *
    1093      * @return the host list
    1094      */
    1095     @SuppressWarnings("unchecked")
    1096     public <T extends Host> List<T> getHostList() {
    1097         return (List<T>) getCharacteristics().getHostList();
    1098     }
    1099 
    1100     /**获取数据中心特征
    1101      * Gets the characteristics.
    1102      *
    1103      * @return the characteristics
    1104      */
    1105     protected DatacenterCharacteristics getCharacteristics() {
    1106         return characteristics;
    1107     }
    1108 
    1109     /**设置数据中心特征
    1110      * Sets the characteristics.
    1111      *
    1112      * @param characteristics the new characteristics
    1113      */
    1114     protected void setCharacteristics(DatacenterCharacteristics characteristics) {
    1115         this.characteristics = characteristics;
    1116     }
    1117 
    1118     /**获取局部CIS名
    1119      * Gets the regional cis name.
    1120      *
    1121      * @return the regional cis name
    1122      */
    1123     protected String getRegionalCisName() {
    1124         return regionalCisName;
    1125     }
    1126 
    1127     /**
    1128      * Sets the regional cis name.
    1129      *
    1130      * @param regionalCisName the new regional cis name
    1131      */
    1132     protected void setRegionalCisName(String regionalCisName) {
    1133         this.regionalCisName = regionalCisName;
    1134     }
    1135 
    1136     /**虚拟机分配协议
    1137      * Gets the vm allocation policy.
    1138      *
    1139      * @return the vm allocation policy
    1140      */
    1141     public VmAllocationPolicy getVmAllocationPolicy() {
    1142         return vmAllocationPolicy;
    1143     }
    1144 
    1145     /**
    1146      * Sets the vm allocation policy.
    1147      *
    1148      * @param vmAllocationPolicy the new vm allocation policy
    1149      */
    1150     protected void setVmAllocationPolicy(VmAllocationPolicy vmAllocationPolicy) {
    1151         this.vmAllocationPolicy = vmAllocationPolicy;
    1152     }
    1153 
    1154     /**
    1155      * Gets the last process time.
    1156      *
    1157      * @return the last process time
    1158      */
    1159     protected double getLastProcessTime() {
    1160         return lastProcessTime;
    1161     }
    1162 
    1163     /**
    1164      * Sets the last process time.
    1165      *
    1166      * @param lastProcessTime the new last process time
    1167      */
    1168     protected void setLastProcessTime(double lastProcessTime) {
    1169         this.lastProcessTime = lastProcessTime;
    1170     }
    1171 
    1172     /**费用
    1173      * Gets the debts.
    1174      *
    1175      * @return the debts
    1176      */
    1177     protected Map<Integer, Double> getDebts() {
    1178         return debts;
    1179     }
    1180 
    1181     /**
    1182      * Sets the debts.
    1183      *
    1184      * @param debts the debts
    1185      */
    1186     protected void setDebts(Map<Integer, Double> debts) {
    1187         this.debts = debts;
    1188     }
    1189 
    1190     /**存储列表
    1191      * Gets the storage list.
    1192      *
    1193      * @return the storage list
    1194      */
    1195     protected List<Storage> getStorageList() {
    1196         return storageList;
    1197     }
    1198 
    1199     /**
    1200      * Sets the storage list.
    1201      *
    1202      * @param storageList the new storage list
    1203      */
    1204     protected void setStorageList(List<Storage> storageList) {
    1205         this.storageList = storageList;
    1206     }
    1207 
    1208     /**虚拟机列表
    1209      * Gets the vm list.
    1210      *
    1211      * @return the vm list
    1212      */
    1213     @SuppressWarnings("unchecked")
    1214     public <T extends Vm> List<T> getVmList() {
    1215         return (List<T>) vmList;
    1216     }
    1217 
    1218     /**
    1219      * Sets the vm list.
    1220      *
    1221      * @param vmList the new vm list
    1222      */
    1223     protected <T extends Vm> void setVmList(List<T> vmList) {
    1224         this.vmList = vmList;
    1225     }
    1226 
    1227     /**调度间隔
    1228      * Gets the scheduling interval.
    1229      *
    1230      * @return the scheduling interval
    1231      */
    1232     protected double getSchedulingInterval() {
    1233         return schedulingInterval;
    1234     }
    1235 
    1236     /**
    1237      * Sets the scheduling interval.
    1238      *
    1239      * @param schedulingInterval the new scheduling interval
    1240      */
    1241     protected void setSchedulingInterval(double schedulingInterval) {
    1242         this.schedulingInterval = schedulingInterval;
    1243     }
    1244 
    1245 }
  • 相关阅读:
    为调试JavaScript添加输出窗口
    后悔自己没有学好数学
    IEnumeralbe<T>被误用一例
    开发软件真是一件有意思的事情
    在网页上实现WinForm控件:ComboBox
    WinForm异步编程中一个容易忽视的问题
    网页上的DataGridView
    用Excel生成代码
    游戏处女作 打方块
    用GDI+保存Image到流时的一个有趣现象
  • 原文地址:https://www.cnblogs.com/xiaoxiaoweng/p/7412151.html
Copyright © 2020-2023  润新知