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