Merge "Serialization/Deserialization and a host of other fixes"
[controller.git] / opendaylight / md-sal / sal-dom-xsql / src / main / java / org / opendaylight / controller / md / sal / dom / xsql / XSQLAdapter.java
1 package org.opendaylight.controller.md.sal.dom.xsql;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.InputStream;
6 import java.io.PrintStream;
7 import java.net.ServerSocket;
8 import java.net.Socket;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Calendar;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.concurrent.ConcurrentHashMap;
17
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
20 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
21 import org.opendaylight.controller.md.sal.dom.xsql.jdbc.JDBCResultSet;
22 import org.opendaylight.controller.md.sal.dom.xsql.jdbc.JDBCServer;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.model.api.Module;
25 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
27
28 public class XSQLAdapter extends Thread implements SchemaContextListener {
29
30     private static final int SLEEP = 10000;
31     private static XSQLAdapter a = new XSQLAdapter();
32     private static PrintStream l = null;
33     public boolean stopped = false;
34     private List<String> elementHosts = new ArrayList<String>();
35     private String username;
36     private String password;
37     private String transport = "tcp";
38     private int reconnectTimeout;
39     private int nThreads;
40     private int qsize;
41     private String applicationName = "NQL Adapter";
42     private Map<String, NEEntry> elements = new ConcurrentHashMap<String, XSQLAdapter.NEEntry>();
43     private StringBuffer lastInputString = new StringBuffer();
44     private XSQLBluePrint bluePrint = new XSQLBluePrint();
45     private boolean toCsv = false;
46     private String exportToFileName = null;
47     private XSQLThreadPool threadPool = new XSQLThreadPool(1, "Tasks", 2000);
48     private JDBCServer jdbcServer = new JDBCServer(this);
49     private String pinningFile;
50     private ServerSocket serverSocket = null;
51     private DOMDataBroker domDataBroker = null;
52
53     private XSQLAdapter() {
54         XSQLAdapter.log("Starting Adapter");
55         this.setDaemon(true);
56         try {
57             serverSocket = new ServerSocket(34343);
58         } catch (Exception err) {
59             XSQLAdapter.log(err);
60         }
61         this.start();
62         XSQLAdapter.log("Adapter Started!");
63
64     }
65
66     public static XSQLAdapter getInstance() {
67         return a;
68     }
69
70     public static void main(String args[]) {
71         XSQLAdapter adapter = new XSQLAdapter();
72         adapter.start();
73     }
74
75     public static void log(String str) {
76         try {
77             if (l == null) {
78                 synchronized (XSQLAdapter.class) {
79                     if (l == null) {
80                         l = new PrintStream(
81                                 new FileOutputStream("/tmp/xql.log"));
82                     }
83                 }
84             }
85             l.print(Calendar.getInstance().getTime());
86             l.print(" - ");
87             l.println(str);
88         } catch (Exception err) {
89             err.printStackTrace();
90         }
91     }
92
93     public static void log(Exception e) {
94         try {
95             if (l == null) {
96                 synchronized (XSQLAdapter.class) {
97                     if (l == null) {
98                         l = new PrintStream(
99                                 new FileOutputStream("/tmp/xql.log"));
100                     }
101                 }
102             }
103             l.print(Calendar.getInstance().getTime());
104             l.print(" - ");
105             e.printStackTrace(l);
106         } catch (Exception err) {
107             err.printStackTrace();
108         }
109     }
110
111     @Override
112     public void onGlobalContextUpdated(SchemaContext context) {
113         Set<Module> modules = context.getModules();
114         for (Module m : modules) {
115             if (XSQLODLUtils.createOpenDaylightCache(this.bluePrint, m)) {
116                 this.addRootElement(m);
117             }
118         }
119     }
120
121     public void setDataBroker(DOMDataBroker ddb) {
122         this.domDataBroker = ddb;
123     }
124
125     public XSQLBluePrint getBluePrint() {
126         return this.bluePrint;
127     }
128
129     public List<Object> collectModuleRoots(XSQLBluePrintNode table) {
130         if (table.getParent().isModule()) {
131             try {
132                 List<Object> result = new LinkedList<Object>();
133                 YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier
134                         .builder()
135                         .node(XSQLODLUtils.getPath(table.getODLNode()).get(0))
136                         .toInstance();
137                 DOMDataReadTransaction t = this.domDataBroker
138                         .newReadOnlyTransaction();
139                 Object node = t.read(LogicalDatastoreType.OPERATIONAL,
140                         instanceIdentifier).get();
141                 node = XSQLODLUtils.get(node, "reference");
142                 if (node == null) {
143                     return result;
144                 }
145
146                 // XSQLAdapter.log(""+node);
147                 Map<?, ?> children = XSQLODLUtils.getChildren(node);
148                 for (Object c : children.values()) {
149                     Map<?, ?> sons = XSQLODLUtils.getChildren(c);
150                     for (Object child : sons.values()) {
151                         result.add(child);
152                     }
153                 }
154
155                 return result;
156             } catch (Exception err) {
157                 XSQLAdapter.log(err);
158             }
159         } else {
160             return collectModuleRoots(table.getParent());
161         }
162         return null;
163     }
164
165     public void execute(JDBCResultSet rs) {
166         List<XSQLBluePrintNode> tables = rs.getTables();
167         List<Object> roots = collectModuleRoots(tables.get(0));
168         XSQLBluePrintNode main = rs.getMainTable();
169         List<NETask> tasks = new LinkedList<XSQLAdapter.NETask>();
170
171         for (Object entry : roots) {
172             NETask task = new NETask(rs, entry, main, bluePrint);
173             rs.numberOfTasks++;
174             tasks.add(task);
175         }
176         for (NETask task : tasks) {
177             threadPool.addTask(task);
178         }
179     }
180
181     public void run() {
182         while (!stopped) {
183             try {
184                 Socket s = serverSocket.accept();
185                 new TelnetConnection(s);
186             } catch (Exception err) {
187                 err.printStackTrace();
188                 try {
189                     Thread.sleep(20000);
190                 } catch (Exception err2) {
191                 }
192                 stopped = true;
193             }
194         }
195     }
196
197     public void addRootElement(Object o) {
198         NEEntry entry = new NEEntry(o);
199         elements.put(o.toString(), entry);
200
201     }
202
203     protected void processCommand(StringBuffer inputString, PrintStream sout,
204             TelnetConnection tc) {
205         if (inputString.toString().trim().equals("r")) {
206             sout.println(lastInputString);
207             inputString = lastInputString;
208         }
209         lastInputString = inputString;
210         String input = inputString.toString().trim();
211         if (input.startsWith("setExcel")) {
212             String substr = input.substring("setExcel".length()).trim();
213             if (!substr.equals("")) {
214                 // excelPath01 = substr;
215             }
216             // sout.println("Excel Path="+excelPath01);
217         } else if (input.startsWith("list vrel")) {
218             String substr = input.substring("list vrel".length()).trim();
219             XSQLBluePrintNode node = bluePrint
220                     .getBluePrintNodeByTableName(substr);
221             if (node == null) {
222                 sout.println("Unknown Interface " + substr);
223                 return;
224             }
225             List<String> fld = new ArrayList<String>();
226             for (XSQLBluePrintRelation r : node.getRelations()) {
227                 fld.add(r.toString());
228             }
229             String p[] = (String[]) fld.toArray(new String[fld.size()]);
230             Arrays.sort(p);
231             for (int i = 0; i < p.length; i++) {
232                 sout.println(p[i]);
233             }
234         } else if (input.startsWith("list vfields")) {
235             String substr = input.substring("list vfields".length()).trim();
236             XSQLBluePrintNode node = bluePrint
237                     .getBluePrintNodeByTableName(substr);
238             if (node == null) {
239                 sout.println("Unknown Interface " + substr);
240                 return;
241             }
242             List<String> fld = new ArrayList<String>();
243             for (XSQLColumn c : node.getColumns()) {
244                 fld.add(c.getName());
245             }
246             String p[] = (String[]) fld.toArray(new String[fld.size()]);
247             Arrays.sort(p);
248             for (int i = 0; i < p.length; i++) {
249                 sout.println(p[i]);
250             }
251         } else if (input.startsWith("jdbc")) {
252             String addr = input.substring(5).trim();
253             jdbcServer.connectToClient(addr);
254             sout.println("Connected To " + addr);
255         } else if (input.startsWith("fetch")) {
256             // fetchSize = Integer.parseInt(input.substring(6).trim());
257         } else if (input.startsWith("list vtables")) {
258
259             String iNames[] = bluePrint.getAllTableNames().toArray(
260                     new String[0]);
261             Arrays.sort(iNames);
262             sout.println();
263             for (int i = 0; i < iNames.length; i++) {
264                 sout.println(iNames[i]);
265             }
266         } else if (input.startsWith("cd sid")) {
267             String substr = input.substring("cd sid".length()).trim();
268             for (NEEntry e : elements.values()) {
269                 if (((Module) e.ne).getName().equals(substr)) {
270                     tc.currentModule = (Module) e.ne;
271                 }
272             }
273         } else if (input.equals("list sid")) {
274             String arr[] = new String[elements.size()];
275
276             int i = 0;
277             for (NEEntry entry : elements.values()) {
278                 arr[i] = entry.toString();
279                 i++;
280             }
281             Arrays.sort(arr);
282             for (String s : arr) {
283                 sout.println(s);
284             }
285         } else if (input.equals("help") || input.equals("?")) {
286             // sout.println(getLongDescription());
287         } else if (input.equals("avmdata")) {
288             try {
289                 // myConnection.getManagedData();
290             } catch (Exception err) {
291             }
292         } else if (input.equals("innerjoin")) {
293             // innerJoin = !innerJoin;
294             // sout.println("Inner Join set to "+innerJoin);
295         } else if (input.equals("exit")) {
296             try {
297                 sout.close();
298             } catch (Exception err) {
299             }
300         } else if (input.equals("tocsv")) {
301             toCsv = !toCsv;
302             sout.println("to csv file is " + toCsv);
303         } else if (input.indexOf("filename") != -1) {
304             exportToFileName = input.substring(input.indexOf(" ")).trim();
305             sout.println("Exporting to file:" + exportToFileName);
306         } else if (!input.equals("")) {
307             if (toCsv) {
308                 if (exportToFileName != null) {
309                     try {
310                         PrintStream o = new PrintStream(new File(
311                                 exportToFileName));
312                         executeSql(inputString.toString(), o);
313                         o.close();
314                     } catch (Exception err) {
315                         err.printStackTrace();
316                     }
317                 } else {
318                     try {
319                         String fName = "export-" + System.currentTimeMillis()
320                                 + ".csv";
321                         PrintStream o = new PrintStream(new File(fName));
322                         executeSql(inputString.toString(), o);
323                         o.close();
324                         sout.println("Exported to file " + fName);
325                     } catch (Exception err) {
326                         err.printStackTrace();
327                     }
328
329                 }
330             } else {
331                 executeSql(inputString.toString(), sout);
332             }
333         }
334         sout.println();
335     }
336
337     public void executeSql(String sql, PrintStream out) {
338         JDBCResultSet rs = new JDBCResultSet(sql);
339         try {
340             int count = 0;
341             jdbcServer.execute(rs, this);
342             boolean isFirst = true;
343             int loc = rs.getFields().size() - 1;
344             int totalWidth = 0;
345             for (XSQLColumn c : rs.getFields()) {
346                 if (isFirst) {
347                     isFirst = false;
348                     if (toCsv) {
349                         out.print("\"");
350                     }
351                 }
352
353                 if (!toCsv) {
354                     out.print("|");
355                 }
356
357                 out.print(c.getName());
358
359                 if (!toCsv) {
360                     int cw = c.getCharWidth();
361                     int cnw = c.getName().length();
362                     if (cnw > cw) {
363                         c.setCharWidth(cnw);
364                     }
365                     int gap = cw - cnw;
366                     for (int i = 0; i < gap; i++) {
367                         out.print(" ");
368                     }
369                 }
370
371                 totalWidth += c.getCharWidth() + 1;
372
373                 if (loc > 0) {
374                     if (toCsv) {
375                         out.print("\",\"");
376                     }
377                 }
378                 loc--;
379             }
380
381             if (toCsv) {
382                 out.println("\"");
383             } else {
384                 totalWidth++;
385                 out.println("|");
386                 for (int i = 0; i < totalWidth; i++) {
387                     out.print("-");
388                 }
389                 out.println();
390             }
391
392             while (rs.next()) {
393                 isFirst = true;
394                 loc = rs.getFields().size() - 1;
395                 for (XSQLColumn c : rs.getFields()) {
396                     if (isFirst) {
397                         isFirst = false;
398                         if (toCsv) {
399                             out.print("\"");
400                         }
401                     }
402
403                     if (!toCsv) {
404                         out.print("|");
405                     }
406
407                     Object sValue = rs.getObject(c.toString());
408                     if (sValue == null) {
409                         sValue = "";
410                     }
411                     out.print(sValue);
412
413                     int cw = c.getCharWidth();
414                     int vw = sValue.toString().length();
415                     int gap = cw - vw;
416                     for (int i = 0; i < gap; i++) {
417                         out.print(" ");
418                     }
419
420                     if (loc > 0) {
421                         if (toCsv) {
422                             out.print("\",\"");
423                         }
424                     }
425                     loc--;
426                 }
427                 if (toCsv) {
428                     out.println("\"");
429                 } else {
430                     out.println("|");
431                 }
432                 count++;
433             }
434             out.println("Total Number Of Records=" + count);
435         } catch (Exception err) {
436             err.printStackTrace(out);
437         }
438     }
439
440     public static class NETask implements Runnable {
441
442         private JDBCResultSet rs = null;
443         private Object modelRoot = null;
444         private XSQLBluePrintNode main = null;
445         private XSQLBluePrint bluePrint = null;
446
447         public NETask(JDBCResultSet _rs, Object _modelRoot,
448                 XSQLBluePrintNode _main, XSQLBluePrint _bluePrint) {
449             this.rs = _rs;
450             this.modelRoot = _modelRoot;
451             this.main = _main;
452             this.bluePrint = _bluePrint;
453         }
454
455         public void run() {
456             rs.addRecords(modelRoot, main, true, main.getBluePrintNodeName(),
457                     bluePrint);
458             synchronized (rs) {
459                 rs.numberOfTasks--;
460                 if (rs.numberOfTasks == 0) {
461                     rs.setFinished(true);
462                     rs.notifyAll();
463                 }
464             }
465         }
466     }
467
468     private static class NEEntry {
469         private Object ne = null;
470
471         public NEEntry(Object _ne) {
472             this.ne = _ne;
473         }
474
475         public String toString() {
476             Module m = (Module) ne;
477             return m.getName() + "  [" + m.getNamespace().toString() + "]";
478         }
479     }
480
481     private class TelnetConnection extends Thread {
482
483         private Socket socket = null;
484         private InputStream in = null;
485         private PrintStream out = null;
486         private Module currentModule = null;
487
488         public TelnetConnection(Socket s) {
489             this.socket = s;
490             try {
491                 this.in = s.getInputStream();
492                 this.out = new PrintStream(s.getOutputStream());
493                 this.start();
494             } catch (Exception err) {
495                 XSQLAdapter.log(err);
496             }
497         }
498
499         public void run() {
500             StringBuffer inputString = new StringBuffer();
501             String prompt = "XSQL>";
502             try {
503                 while (!stopped) {
504                     if (currentModule != null) {
505                         prompt = "XQL/" + currentModule.getName() + ">";
506                     }
507                     out.print(prompt);
508                     char c = 0;
509                     byte data[] = new byte[1];
510                     while (c != '\n') {
511                         try {
512                             in.read(data);
513                             c = (char) data[0];
514                             inputString.append(c);
515                         } catch (Exception err) {
516                             err.printStackTrace(out);
517                         }
518                     }
519
520                     processCommand(inputString, out, this);
521                     inputString = new StringBuffer();
522                 }
523             } catch (Exception err) {
524                 try {
525                     socket.close();
526                 } catch (Exception err2) {
527                 }
528             }
529         }
530     }
531 }