Archive for 算法-编程

先看看上次没看完的client的初始化。 NewAPIClientFromFlags里 getServerHost(opts.Hosts, opts.TLSOptions),如果参数有指定用参数的,如果没指定用os.Getenv("DOCKER_HOST"). 设置customHeaders,环境变量如果有设置DOCKER_API_VERSION,设置api版本 newHTTPClient(host, opts.TLSOptions)返回一个http.client client.NewClient(host, verStr, httpClient, customHeaders)初始化一个新的Client对象,Client是啥, client/interface_stable.go package client // APIClient is an interface that clients that talk with a docker server must implement. type APIClient interface { CommonAPIClient apiClientExperimental } // Ensure that Client always implements APIClient. var _ APIClient = &Client{} APIClient是个接口类型,看了一下包含了好多函数,应该是所有命令集中都是调的这里的。Client就是一个APIClient接口类型的实现。这样写一句应该能保证,不然编译不过,哈哈 会玩。。 client的命令都是在上一篇的AddCommands里边集中添加,对应各个目录里边的cmd.go里的NewCommand方法进行添加。 client.Ping( 在client/ping.go里, 先req, err := cli.buildRequest("GET", fmt.Sprintf("%s/_ping", cli.basePath), nil, nil),构造请求 serverResp, err := cli.doRequest(ctx, req),发送请求返回结果,都在request.go里边,普通的http请求。 然后ping.APIVersion和ping.Experimental都是根据返回的header来判断的,Experimental具体干啥的还不清楚 client.UpdateClientVersion,这个仅仅是改了一下client的版本,可能请求是带上这个版本,服务端会根据这个版本进行不同操作返回吧。还不确定。cli.version = v 这个样整个dockerCli就初始化完了。核心就是那个Client,各种请求的定义都在里边。 再看看具体命令的执行,看个docker info命令,感觉这个应该简单点。 system.NewSystemCommand(dockerCli), system.NewVersionCommand(dockerCli), 正好还有个version,先看看这个。在runVersion(里边, ctx := context.Background() 先创建一个空context,versionTemplate 格式化模板,如果提供opts.format参数,就使用提供的模板。上边有这个操作 APIVersion := dockerCli.Client().ClientVersion() 这里找了一下Client()返回dockerCli.client就是上边提到的初始化的那个,client.APIClient类型的 ClientVersion() 在client/client.go里边定义:func (cli *Client) ClientVersion() string返回Client .version字段。也和之前的一样 下边就是版本不统一,api版本低的话会让cli的版本也低,然后会跟随打印出来。api版本高的话,可能兼容的,这个也不确定。 dockerCli.Client().ServerVersion(ctx)然后请求server的版本。cli.get(ctx, "/version", nil, nil)走接口请求. 最后就是渲染模板,进行打印。 types 都在api/types定义的。可能会公用到吧,不太清楚。 总的来说就是client解析参数,然后找到对应的处理方法,发送请求给server,然后server返回。这个和官方提供的api是用的一样的。我记得之前搭建docker环境的时候踩过一个坑,配置api的访问接口的时候,把socket给去掉了,只留个ip:port的,本地命令就没法执行了。本地默认好像走的socket文件的。 其他client端的命令就不看了 ,应该都是一样的。下边就看看server的。

Continue

先看docker/cmd/docker/docker.go 主要就三行 dockerCli := command.NewDockerCli(stdin, stdout, stderr) cmd := newDockerCommand(dockerCli) if err := cmd.Execute(); err != nil { NewDockerCli( 在docker/cli/command/cli.go里返回一个DockerCli实例 type DockerCli struct { configFile *configfile.ConfigFile in *InStream out *OutStream err io.Writer keyFile string client client.APIClient hasExperimental bool defaultVersion string } 设置一些client都用的些东西。初始化了in,out,err,其他字段先不管,按流程看。 newDockerCommand 先实例化一个ClientOptions, type ClientOptions struct { Common *CommonOptions ConfigDir string Version bool } 然后用了一个cobra库,应该就是管理命令行参数的。 PersistentPreRunE里边,一些参数设置。 daemon启动废弃了,所以就不设置这些参数啥的了。 opts.Common.SetDefaultOptions(flags)设置CommonOptions的一些默认参数. dockerPreRun(opts)里opts.ConfigDir可以通过设置配置文件路径,这个是默认的:configDir = os.Getenv("DOCKER_CONFIG"), 参数肯定优先级高,哈哈,SetDir会替换成参数里的。config参数的定义在newDockerCommand的最下边。 func Enable() { os.Setenv("DEBUG", "1") logrus.SetLevel(logrus.DebugLevel) } 根据参数是否开启debug dockerCli.Initialize(opts)进行dockerCli的初始化,之前只是初始化输入输出,还有其他字段要初始化。 LoadDefaultConfigFile初始化configFile字段,看名字基本就知道啥功能了。文件路径是环境变量定义的configDir = os.Getenv("DOCKER_CONFIG"),怎么load的就不看了.再往下好像是证书相关的配置需要设置参数。 NewAPIClientFromFlags(opts.Common, cli.configFile)是初始化dockerCli的client字段。具体怎么初始化的,这个等后边看。内容挺多的 cli.defaultVersion初始化另一个字段,就是client的版本.keyFile初始化, ping操作主要是获取api的版本,如果ping.APIVersion为空,就默认1.24,是1。24之前不支持这个字段,因为现在肯定大于1.24了。HasExperimental初始化 如果api版本小于客户端版本,应该是不能使用,需要把客户端版本降级。UpdateClientVersion操作。这个也后边集中分析一下。 return isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()) HasExperimental这个也是ping的时候返回的,这里主要还是版本判断,过了,cobra参数也看不太懂。 opts.Common.InstallFlags(flags)设置了一些参数,一些指定host,key,版本啥参数.与client连接server有关的设置。 cmd.AddCommand(newDaemonCommand()) 之前好像启动client和daemon是一个文件,现在分开了。这里看的是client的代码,使用之前的daemon参数进行启动的时候,提示新版本已经分开了。 commands.AddCommands(cmd, dockerCli) docker/cli/commands/commands.go 这里就是添加命令参数了。注释分类挺清楚的,分别在不同文件里边。 这个后边再细看,都差不多,命令定义都在command目录下 cmd.Execute(); 这个应该就是cobra一切设置完了 开始监听参数并执行相应方法了。

Continue

直接从makefile入手找到hack/make.sh,具体怎么编译的不看,只找入口. 看make.sh要编译的东西主要应该就看俩就行了,一个是clien,一个是daemon。 binary-client binary-daemon dynbinary test-unit test-integration-cli test-docker-py cross tgz 其他一些测试用的,不管,还有一些不知道。以后再说。 然后往下翻发现都在hack/make/目录里边对应的文件。 俩文件样子差不多,binary-client 二进制名为docker ,binary-daemon为dockerd。源码目录分别对应 docker/cmd/docker,docker/cmd/dockerd 搞定,后边再接着看。

Continue

一直在调试ios的react-native的程序,好久没在Android下编译过,今天搞了一下。编译通过了,程序启动报了个错误“Unfortunately, app has stopped” adb logcat 能看到log。github有解决方式 编辑android/app/src/main/AndroidManifest.xml文件 application标签里加个属性android:name=".MainApplication" 然后就好了

Continue

这俩软件直接brew install安装的。 opam需要配置 opam init 初始化opam目录,~/.opam .bash_profile里添加. ~/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true 设置一些环境变量。 vim ~/.ocamlinit 添加 let () = try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH") with Not_found -> () ;; 这些配置提示,在执行opam init 的时候会显示。 opam switch可以查看已经安装的版本编译器,并可以切换 $ opam switch 4.01.0 $ eval `opam config env` 安装utop opam install core utop 然后会装特么的一堆包。 再次配置.ocamlinit 就是初始导入,以后启动解析器的时候就不用导入了 #use "topfind";; #thread;; #camlp4o;; #require "core.top";; #require "core.syntax";; open Core.Std;; 可以用utop愉快的玩耍了

Continue

安装管网提示一步步安装的。还有个mono的东西,没用。 brew update brew install openssl 第二部下载安装包,点击安装。安装完目录添加到path。 创建一个hello world例子工程

mkdir hwapp
cd hwapp
dotnet new --lang f#
运行例子 dotnet restore dotnet run 就输出f#版的hello world了

Continue

那些开源的都不太靠谱,同事推荐这个druid解析sql。试了一下确实给力。 打包方法: git clone https://github.com/alibaba/druid.git mvn install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true 会安装到.m2目录,copy一个项目用 target/druid-1.0.27-SNAPSHOT-sources.jar 示例代码:

import java.util.*;

import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import py4j.GatewayServer;


public class SQLParser {
    public static List get_tables(String sql){

        MySqlStatementParser parser = new MySqlStatementParser(sql);
        List statementList = parser.parseStatementList();
        SQLStatement statemen = statementList.get(0);

        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
        statemen.accept(visitor);
        Map result = visitor.getTables();
        System.out.println("Tables : " + result);

        List list = new ArrayList<>();
        for ( TableStat.Name name : result.keySet() ) {
            System.out.println( name );
            list.add(name.getName());
        }
        return list;

    }

    public static void main(String[] args){
        GatewayServer gatewayServer = new GatewayServer(new SQLParser());
        gatewayServer.start();
        System.out.println("Gateway Server Started");

    }
}
打包命令: javac -cp .:./py4j0.10.4.jar:./druid-1.0.27-SNAPSHOT.jar:$CLASSPATH SQLParser.java java -cp .:./py4j0.10.4.jar:./druid-1.0.27-SNAPSHOT.jar:$CLASSPATH SQLParser

Continue

上一篇使用antlr解析的,发现不行,官方提供的语法文件bug太多,多到不能用的程度,还是得用专门的开源库。这次选jsqlparser了。 从github下载一个源码,mvn package 打一个jar包。将jsqlparser-0.9.6.jar拷贝到工作目录。  

import java.util.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.util.TablesNamesFinder;


public class ParserTest {
    public static void main(String[] args){
        System.out.println("Hello World!");

        String sql = "select NVL( (SELECT 1 FROM DUAL), 1) AS A from TEST1,test";
        try{
            Select selectStatement = (Select) CCJSqlParserUtil.parse(sql);
            TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
            List tableList = tablesNamesFinder.getTableList(selectStatement);
            for(String s : tableList) {
                System.out.println(s);
            }
        }catch(Exception e){
            String sql1 = " TEST1";
            //e.printStacktrace();
        }

    }
}
这是调用解析table name的代码。 编译运行 javac -cp ./jsqlparser-0.9.6.jar ParserTest.java java -cp .:./jsqlparser-0.9.6.jar:$CLASSPATH ParserTest 还挺好用。

Continue

做个项目要解析mysql sql语句,使用开源的库发现问题很多,不太适合。推荐的几个项目都是项目里边集成的,语言也不符合,太麻烦。只能自己搞了,选择antlr的原因是官方提供mysql解析的语法,做起来比较简单。   安装: curl -O http://www.antlr.org/download/antlr-4.5.3-complete.jar 然后写一个shell脚本antlr,用来执行命令 #!/bin/bash java -cp .:./antlr-4.5.3-complete.jar:$CLASSPATH org.antlr.v4.Tool $* 从https://github.com/antlr/grammars-v4.git clone一些已经写好的sql语法文件。   生成Python版的解析代码。 ./antlr  -Dlanguage=Python2  MySQLLexer.g4 ./antlr  -Dlanguage=Python2 -visitor  MySQLParser.g4 第二个加参数是为了生成MySQLGrammarVisitor。   然后参照例子写了个函数包起来就能用。这工具做的好,原因就是不用研究太深就能用。

Continue

selenium安装 去官网下载一个jar包,然后运行:java -jar selenium-server-standalone-2.53.1.jar 然后写代码就行了,会打开一个浏览器窗口。看看有办法静默打开不,好像phantomjs模式可以,这个还要安装。    

# coding: utf-8

# from selenium import selenium
from selenium.webdriver.common.by import By

from selenium import webdriver

from selenium.webdriver.phantomjs.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Firefox()
# browser = WebDriver()

browser.get('http://baidu.com/')
print browser.title
f = browser.find_element_by_id('kw')
f.send_keys(u'谷歌')

f = browser.find_element_by_id('su')
f.click()
WebDriverWait(browser, 10).until(EC.title_contains(u"谷歌"))

print browser.title
# browser.quit()

Continue