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 }