Main.java 10 KB

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