Main.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. package me.yoqi.servermanager;
  2. import java.io.BufferedReader;
  3. import java.io.ByteArrayInputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.FileReader;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.io.InputStreamReader;
  10. import java.util.ArrayList;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Map;
  14. import com.google.common.base.Charsets;
  15. /**
  16. * Created by mou.sunm on 2018/07/02.
  17. */
  18. public class Main {
  19. // 参数
  20. public static final double alpha = 10.;
  21. public static final double beta = 0.5;
  22. public static final int T = 98;
  23. public static final int EXEC_LIMIT = 100000;
  24. // 静态数据
  25. private int num_app; // app数 9338
  26. private int num_inst; // inst数 68219
  27. private int num_mac; // machine数 6000
  28. private int num_k; // 资源种类 200
  29. private List<Integer> cpuIter; //[0, 1, 2, ... 97]
  30. private Map<String, Integer> appIndex; //app_1,app_2字符串用0,1等数字替换,{app_1=0, app_2=1,...,app_4=3}
  31. private Map<String, Integer> machineIndex;//{machine_1=0, machine_2=1,
  32. private String[] apps; //[app_1, app_2, app_3, app_4,
  33. private String[] machines;//[machine_1, machine_2, machine_3, machine_4,
  34. private Map<String, Integer> inst2AppIndex;//{inst_157=49}
  35. private double[][] appResources;// app 9338*200
  36. private double[][] machineResources;// 主机 6000*200
  37. private Map<Integer, Integer>[] appInterference;//9338 限制条件[{}, {}, {3517=2}, {}, {5600=1, 6747=2, 7707=2, 4830=2},
  38. // 动态数据
  39. private Map<String, Integer> inst2Machine;// 部署 {inst_33717=5456, inst_33713=3427, inst_33716=3983,
  40. private Map<String, Integer> inst2MachineRemine;
  41. private double[][] machineResourcesUsed;//6000*200
  42. private Map<Integer, Integer>[] machineHasApp;//6000 [{}, {},{6004=1, 9126=1, 1598=1}, {}, {}, {},
  43. /**
  44. * 先对disk排序,然后first fit
  45. */
  46. private void run() {
  47. while(inst2Machine.size()>0) {
  48. }
  49. }
  50. private void sortInstanceByDisk(ArrayList<Integer> instance) {
  51. for(int i=0;i<instance.size();i++) {
  52. int appIt = inst2AppIndex.get(i);
  53. }
  54. }
  55. private void sort(ArrayList<Integer> list) {
  56. }
  57. // 读取数据
  58. protected void init(BufferedReader bufferedReader) throws IOException {
  59. cpuIter = new ArrayList<Integer>();
  60. for (int i = 0; i < T; i++)
  61. cpuIter.add(i);
  62. /** Read app_resources */
  63. num_app = Integer.parseInt(bufferedReader.readLine());// 9338
  64. apps = new String[num_app];
  65. for (int i = 0; i < num_app; i++) {// 循环app表每一行
  66. // appId,resources
  67. String line = bufferedReader.readLine();
  68. String[] parts = line.split(",", -1);
  69. List<Double> resources = new ArrayList<Double>();
  70. for (String x : parts[1].split("\\|", -1))// cpu
  71. resources.add(Double.parseDouble(x));
  72. for (String x : parts[2].split("\\|", -1))// mem
  73. resources.add(Double.parseDouble(x));
  74. for (int j = 3; j < parts.length; j++) // disk/P/M/PM
  75. resources.add(Double.parseDouble(parts[j]));
  76. if (i == 0) {
  77. num_k = resources.size();
  78. appIndex = new HashMap<String, Integer>();
  79. appResources = new double[num_app][num_k];
  80. }
  81. if (num_k != resources.size())
  82. throw new IOException("[DEBUG 2]Invaild problem");
  83. if (appIndex.containsKey(parts[0]))
  84. throw new IOException("[DEBUG 3]Invaild problem");
  85. appIndex.put(parts[0], i);
  86. apps[i] = parts[0];// [app_1, app_2, app_3, app_4]
  87. for (int j = 0; j < num_k; j++)
  88. appResources[i][j] = resources.get(j);
  89. }
  90. /** Read machine_resources */
  91. num_mac = Integer.parseInt(bufferedReader.readLine());// 6000
  92. machineResources = new double[num_mac][num_k];
  93. machineResourcesUsed = new double[num_mac][num_k];
  94. machineIndex = new HashMap<String, Integer>();// {machine_3791=3790,
  95. // machine_3792=3791}
  96. machineHasApp = new Map[num_mac];
  97. machines = new String[num_mac];
  98. for (int i = 0; i < num_mac; i++) {
  99. // machineId,resources
  100. String line = bufferedReader.readLine();
  101. String[] parts = line.split(",", -1);
  102. if (machineIndex.containsKey(parts[0]))
  103. throw new IOException("[DEBUG 4]Invaild problem");
  104. machineIndex.put(parts[0], i);
  105. machines[i] = parts[0];
  106. machineHasApp[i] = new HashMap<Integer, Integer>();
  107. double cpu = Double.parseDouble(parts[1]);
  108. double mem = Double.parseDouble(parts[2]);
  109. for (int j = 0; j < T; j++) {
  110. machineResources[i][j] = cpu;
  111. machineResources[i][T + j] = mem;
  112. }
  113. for (int j = 3; j < parts.length; j++)
  114. machineResources[i][2 * T + j - 3] = Double.parseDouble(parts[j]);
  115. for (int j = 0; j < num_k; j++)
  116. machineResourcesUsed[i][j] = 0.;
  117. }
  118. /** Read app_interference */
  119. int icnt = Integer.parseInt(bufferedReader.readLine());// 35242
  120. appInterference = new Map[num_app];
  121. for (int i = 0; i < num_app; i++)
  122. appInterference[i] = new HashMap<Integer, Integer>();
  123. for (int i = 0; i < icnt; i++) {
  124. String line = bufferedReader.readLine();
  125. String[] parts = line.split(",", -1);
  126. if (!appIndex.containsKey(parts[0]) || !appIndex.containsKey(parts[1]))
  127. throw new IOException("[DEBUG 8]Invaild problem");
  128. int app1 = appIndex.get(parts[0]);
  129. int app2 = appIndex.get(parts[1]);
  130. int limit = Integer.parseInt(parts[2]);
  131. Map<Integer, Integer> inter = appInterference[app1];
  132. if (inter.containsKey(app2))
  133. throw new IOException("[DEBUG 9]Invaild problem");
  134. if (app1 == app2)
  135. limit += 1; // self-interference +1 here
  136. inter.put(app2, limit);
  137. }
  138. /** Read instance_deploy */
  139. num_inst = Integer.parseInt(bufferedReader.readLine());// 68219
  140. inst2AppIndex = new HashMap<String, Integer>();// 68219*2 {inst_33717=8766, inst_33718=2956}
  141. inst2Machine = new HashMap<String, Integer>();// {inst_33717=5456, inst_33713=3427}
  142. for (int i = 0; i < num_inst; i++) {
  143. String line = bufferedReader.readLine();
  144. String[] parts = line.split(",", -1);
  145. if (inst2AppIndex.containsKey(parts[0]))
  146. throw new IOException("[DEBUG 5]Invaild problem");
  147. if (!appIndex.containsKey(parts[1]))
  148. throw new IOException("[DEBUG 6]Invaild problem");
  149. inst2AppIndex.put(parts[0], appIndex.get(parts[1]));
  150. if (!"".equals(parts[2])) {
  151. if (!machineIndex.containsKey(parts[2]))
  152. throw new IOException("[DEBUG 7]Invaild problem");
  153. toMachine(parts[0], machineIndex.get(parts[2]), false);
  154. }
  155. }
  156. System.out.println("finisl");
  157. }
  158. private String toMachine(String inst, int machineIt) {
  159. return toMachine(inst, machineIt, true);
  160. }
  161. private String toMachine(String inst, int machineIt, boolean doCheck) {
  162. int appIt = inst2AppIndex.get(inst);
  163. Map<Integer, Integer> hasApp = machineHasApp[machineIt];
  164. if (doCheck) {
  165. // 检查互斥规则,初始数据这里有冲突
  166. int nowHas = 0;
  167. if (hasApp.containsKey(appIt))
  168. nowHas = hasApp.get(appIt);
  169. for (Integer conditionalApp : hasApp.keySet()) {
  170. if (hasApp.get(conditionalApp) <= 0)
  171. continue;
  172. if (!appInterference[conditionalApp].containsKey(appIt))
  173. continue;
  174. if (nowHas + 1 > appInterference[conditionalApp].get(appIt)) {
  175. return "App Interference, inst: " + inst + ", " + apps[conditionalApp] + " -> " + apps[appIt] + ", "
  176. + (nowHas + 1) + " > " + appInterference[conditionalApp].get(appIt);
  177. }
  178. }
  179. //初始数据这里有冲突
  180. for (Integer checkApp : hasApp.keySet()) {
  181. if (!appInterference[appIt].containsKey(checkApp))
  182. continue;
  183. if (hasApp.get(checkApp) > appInterference[appIt].get(checkApp)) {
  184. return "App Interference, inst: " + inst + ", " + apps[appIt] + " -> " + apps[checkApp] + ", "
  185. + (nowHas + 1) + " > " + appInterference[appIt].get(checkApp);
  186. }
  187. }
  188. // 检查资源限制,初始数据这里没有冲突
  189. for (int i = 0; i < num_k; i++)
  190. if (dcmp(machineResourcesUsed[machineIt][i] + appResources[appIt][i]
  191. - machineResources[machineIt][i]) > 0) {
  192. String res = "Resource Limit: inst: " + inst + ", " + "machine: " + machines[machineIt] + ", app: "
  193. + apps[appIt] + ", resIter: " + i + ", " + machineResourcesUsed[machineIt][i] + " + "
  194. + appResources[appIt][i] + " > " + machineResources[machineIt][i];
  195. System.out.println(res);
  196. return res;
  197. }
  198. }
  199. // 将inst放入新的machine
  200. inst2Machine.put(inst, machineIt);
  201. if (!hasApp.containsKey(appIt))
  202. hasApp.put(appIt, 0);
  203. hasApp.put(appIt, hasApp.get(appIt) + 1);
  204. for (int i = 0; i < num_k; i++)
  205. machineResourcesUsed[machineIt][i] += appResources[appIt][i];
  206. return "success";
  207. }
  208. /**
  209. * 把实例inst 移除主机,撤销消耗资源
  210. *
  211. * @param inst 实例id
  212. */
  213. private void pickInstance(String inst) {
  214. if (!inst2Machine.containsKey(inst))
  215. return;
  216. int appIt = inst2AppIndex.get(inst);
  217. int fromMachine = inst2Machine.get(inst);
  218. // 更新machineHasApp
  219. Map<Integer, Integer> fromHasApp = machineHasApp[fromMachine];
  220. fromHasApp.put(appIt, fromHasApp.get(appIt) - 1);
  221. if (fromHasApp.get(appIt) <= 0)
  222. fromHasApp.remove(appIt);
  223. // 更新machineResourcesUsed
  224. for (int i = 0; i < num_k; i++)
  225. machineResourcesUsed[fromMachine][i] -= appResources[appIt][i];
  226. // 更新inst2Machine
  227. inst2Machine.remove(inst);
  228. }
  229. private int dcmp(double x) {
  230. if (Math.abs(x) < 1e-9)
  231. return 0;
  232. return x < 0. ? -1 : 1;
  233. }
  234. public static void main(String[] args) throws Exception {
  235. if (args.length != 5 && args.length != 2) {
  236. System.err.println(
  237. "传入参数有误,使用方式为:java -cp xxx.jar app_resources.csv machine_resources.csv instance_deploy.csv app_interference.csv result.csv");
  238. return;
  239. }
  240. System.out.println("-------开始部署啦--------");
  241. long startTime = System.currentTimeMillis(); // 获取开始时间
  242. InputStream problem;
  243. InputStream result;
  244. // app_resources.csv
  245. // machine_resources.csv
  246. // instance_deploy.csv
  247. // app_interference.csv
  248. // result.csv
  249. if (args.length == 5) {
  250. // 将赛题拼成评测数据
  251. StringBuffer sb = new StringBuffer();
  252. for (int i = 0; i < 4; i++) {
  253. List<String> lines = new ArrayList<String>();
  254. BufferedReader bs = new BufferedReader(new FileReader(new File(args[i])));
  255. for (String line = bs.readLine(); line != null; line = bs.readLine())
  256. lines.add(line);
  257. sb.append("" + lines.size()).append("\n");
  258. for (String line : lines)
  259. sb.append(line).append("\n");
  260. }
  261. String alldata = sb.toString();
  262. problem = new ByteArrayInputStream(alldata.getBytes());
  263. result = new FileInputStream(args[4]);
  264. } else {
  265. problem = new FileInputStream(args[0]);
  266. result = new FileInputStream(args[1]);
  267. }
  268. // 评测
  269. Main evaluator = new Main();
  270. evaluator.init(new BufferedReader(new InputStreamReader(problem, Charsets.UTF_8)));
  271. // evaluator.run();
  272. long endTime = System.currentTimeMillis(); // 获取结束时间
  273. System.out.println("程序运行时间:" + (endTime - startTime) / 1000 + "s"); // 输出程序运行时间
  274. System.out.println("-------部署结束啦--------");
  275. }
  276. }