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\t\tDebt");
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+"\t\t"+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 }

 

posted @ 2017-08-22 16:16  七月晓晓翁  阅读(2332)  评论(0编辑  收藏  举报