知识图谱02:RDF

1、安装MySQL5,并新建movies库

2、导入数据
https://github.com/neohope/kg-demo-for-movie/tree/master/data/movies.sql

3、下载d2rq,并配置好JDK环境变量
http://d2rq.org/

4、利用d2rq生成mapping

generate-mapping -u movie -p password -o movies_mapping.ttl jdbc:mysql:///movies

5、手工编辑ttl,任务如下
设置正确的域名
修正类名与属性名
删除一些不需要的字段
修改前后的数据可以在这里找到
https://github.com/neohope/kg-demo-for-movie/tree/master/data/movies_mapping.ttl
https://github.com/neohope/kg-demo-for-movie/tree/master/data/movies_mapping_ok.ttl

6、输出RDF文件,用于后续的教程

dump-rdf.bat -o movies_mapping.nt movies_mapping_ok.ttl

7、启动d2r服务

d2r-server.bat movies_mapping_ok.ttl

8、访问及浏览数据
http://localhost:2020/

9、查询
http://localhost:2020/snorql/

#周星驰演过的电影
SELECT ?title WHERE {
  ?aPerson rdf:type :Person.
  ?aPerson :personName '周星驰'.
  ?aPerson :hasActedIn ?aMovie.
  ?aMovie :movieTitle ?title
}
LIMIT 10


#英雄的演员
SELECT ?actor WHERE {
  ?aMovie rdf:type :Movie.
  ?aMovie :movieTitle '英雄'.
  ?aPerson :hasActedIn ?aMovie.
  ?aPerson :personName ?actor
}
LIMIT 10


#巩俐参演的,评分高于7的电影
SELECT ?title WHERE {
  ?aPerson rdf:type :Person.
  ?aPerson  :personName '巩俐'.
  ?aPerson  :hasActedIn ?aMovie.
  ?aMovie :movieTitle ?title.
  ?aMovie :movieRating ?rating.
  FILTER (?rating>=7)
}
LIMIT 10

10、通过python访问
https://github.com/neohope/kg-demo-for-movie/tree/master/src/query-d2rq.py

参考链接:
https://zhuanlan.zhihu.com/knowledgegraph
https://github.com/SimmerChan/KG-demo-for-movie

知识图谱01:本体建模

1、下载Protege工具

https://protege.stanford.edu/

2、安装JDK,并在配置好JDK环境变量

3、打开Protege

4、在Active Ontology页面,填写两个IRI,我分别填写了下面的数值

#Ontology IRI
http://www.neohope.com/hansen/ontologies/2018/movies
#Ontology Version IRI
http://www.neohope.com/hansen/ontologies/2018/movies/1.0.0

5、在Entities页面,切换到Classes,新建三个Class

Genre
Movie
Person

6、Entities页面,切换到Data properties,新建以下属性

genereId{Domain=Genre,Ranges=xsd:string}
genereName{Domain=Genre,Ranges=xsd:string}
movieId{Domain=Movie,Ranges=xsd:string}
movieIntroduction{Domain=Movie,Ranges=xsd:string}
movieRating{Domain=Movie,Ranges=xsd:string}
movieReleaseDate{Domain=Movie,Ranges=xsd:string}
movieTitile{Domain=Movie,Ranges=xsd:string}
personAppellation{Domain=Person,Ranges=xsd:string}
->personEnglishName{Domain=Person,Ranges=xsd:string}
->personName{Domain=Person,Ranges=xsd:string}
personBiography{Domain=Person,Ranges=xsd:string}
personbirthDay{Domain=Person,Ranges=xsd:string}
personBirthPlace{Domain=Person,Ranges=xsd:string}
personDeathDay{Domain=Person,Ranges=xsd:string}
personId{Domain=Person,Ranges=xsd:string}

7、Entities页面,切换到Object Properties,新建以下属性

hasActedIn{Domain=Person,Range=Movie,InverseOf=hasActor}
hasActor{Domain=Movie,Range=Person}
hasGenre{Domain=Person,Range=Genre}

8、保存为Movies.owl,这个文件可以在后面jena的例子中用到

9、建模后的结果,可以在这里获取:
https://github.com/neohope/kg-demo-for-movie/tree/master/protege

参考链接:
https://zhuanlan.zhihu.com/knowledgegraph
https://github.com/SimmerChan/KG-demo-for-movie

搭建WebRTC视频会议服务04

本节说明一下遗留的一些内容:

1、开启GPU加速

如果需要GPU加速,除了Intel指定的硬件外,还需要:
https://software.intel.com/en-us/intel-media-server-studio
有社区版,大家感兴趣的可以自己试一下。

2、开启VCA加速

如果需要支持VCA(Intel Visual Compute Accelerator)卡加速,请参考
https://software.intel.com/en-us/webrtc-conference-server-guide-mcu-installation#section2_3_10

3、支持集群

如果需要支持集群,请参考
https://software.intel.com/en-us/webrtc-conference-server-guide-mcu-installation#section2_3_8

咋说呢,总体上感觉这个集群方案有些过于复杂,需要用的时候再看吧。

搭建WebRTC视频会议服务03

本节运行一下WebRTC自带的两个Demo。

大家可以解压CS_WebRTC_Client_SDK_JavaScript.v4.1,看一下,里面有两个Demo。

第一个Demo是conference,已经集成到MCU Server里面了,当我们运行bin/start-all.sh命令时,就会启动了。
我们可以通过Chrome访问https://172.16.172.80:3004,就可以看到自己的视频。
再打开一个Chrome访问https://172.16.172.80:3004,就可以看到两路视频合并为一路视频输出了。
由于https证书为自签名,所以浏览器会给出安全提示,将证书加入可信范围,跳过就好了,全部功能只在Chrome成功过。

本节重点看下第二个Demo,是P2P。这个Demo需要两个服务的支持,一个是在第一节我们安装的Peer Server,另一个是需要安装一个turnserver。

1、下载coturn
https://github.com/coturn/coturn/releases

2、安装依赖库
2.1、安装levent
https://sourceforge.net/projects/levent/files/release-2.0.22-stable/

./configure 
make
make install

2.2、安装openssl-devel

sudo yum install openssl openssl-libs openssl-devel 

2.3、安装

yum install sqlite-devel

3、编译coturn

./configure 
make

4、编写coturn配置文件

vi path_to_coturn/bin/urnserver.conf
#新增以下内容
listening-device=enp0s3
listening-port=3478
relay-device=enp0s3
min-port=59000
max-port=65000
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=demo
realm=demo
stale-nonce
user=demo:demo
cert=path_to_coturn/examples/etc/turn_server_cert.pem
pkey=path_to_coturn/examples/etc/turn_server_pkey.pem
no-loopback-peers
no-multicast-peers
mobility
no-cli

5、启动coturn

cd path_to_coturn/bin
sudo ./turnserver

6、启动PeerServer

cd PeerServer-Release-4.1
node peerserver.js

7、编辑本地页面peercall.html的以下部分

    var serverAddress='https://172.16.172.80:8096';
    const signaling = new SignalingChannel();
    let publicationForCamera;
    let publicationForScreen;
    var p2p = new Ics.P2P.P2PClient({
      audioEncodings: true,
      videoEncodings: [{codec:{name: 'h264'}}, {codec: {name: 'vp9'}}, {codec: {name: 'vp8'}}],
      rtcConfiguration:{
        iceServers: [{
          urls: "stun:172.16.172.80:3478"
        }, {
          urls: ["turn:172.16.172.80:3478?transport=udp",
            "turn:172.16.172.80:3478?transport=tcp"
          ],
          credential: "demo",
          username: "demo"
        }]
      },
    }, signaling);

8、测试
现在用两个Chrome页面浏览本地页面peercall.html,也能使用部分功能,但如果使用全部功能,还是要部署到HTTP服务器的。

9、为了支持Chrome分享桌面,需要安装并配置插件
9.1、修改插件中域名配置
CS_WebRTC_Client_SDK_JavaScript.v4.1\screen-sharing-chrome-extension\manifest.json

     "externally_connectable": {
      "matches": ["*://172.16.172.80/*", "*://localhost/*"]
   },

9.2、打开扩展管理
Chrome->Settings->Entensions
9.3、开启Developer mode
9.4、Load unpacked
选择CS_WebRTC_Client_SDK_JavaScript.v4.1\screen-sharing-chrome-extension
9.5、安装后,会有一个插件ID
我的插件ID为:ongdcdianlnmjiegeandlohjbogjndmc

10、编辑本地页面peercall.html的以下部分

    extensionId:'ongdcdianlnmjiegeandlohjbogjndmc'

11、部署网站
将页面部署到你熟悉的HTTP服务器,加入HTTPS证书,并要在HTTP头中允许CORS。

'Access-Control-Allow-Origin', '*'

一个偷懒的办法是,将MCU-Release-v4.1/extras/basic_example复制一份,按规则替换了静态资源。
修改下面几个文件;

package.json修改包描述
quickfix2spdybug47.js删除
samplertcservice.js删除不需要的API,然后修改端口为HTTP4001、HTTPS4004

然后启动了网站。

node samplertcservice.js

12、测试
这样访问https://172.16.172.80:4004即可。
第一个页面,Login左边填写User01,点击登录
第二个页面,Login左边填写User02,点击登录
第一个页面,SetRemoteId为User02
第二个页面,SetRemoteId为User01
第一个页面,SendData数据“123”,第二个页面可以看到。
第一个页面,Share Camera/Share Screen,第二个页面可以看到。

PS:
如果看不到,建议检查以下几件事情
A、必须HTTPS访问
B、Chrom和FF的控制台是否有报错
C、是否证书和HTTPS网站加入了可信列表
D、是否证书和HTTPS的地址是一致的

PS:
如果是Chrome插件有问题,主要确认
A、必须是HTTPS访问
B、网页的Chrome插件ID,与Chrome中插件ID是否一致
C、插件配置中的通配域名,是否与你的域名一致
D、是否证书和HTTPS网站加入了可信列表
E、是否证书和HTTPS的地址是一致的
F、是否打开了开发者模式

13、关闭页面
可以查看PeerServer的日志

搭建WebRTC视频会议服务02

本节开始安装MCU Server。
MCU Server有两种工作模式,一种是通过GPU,一种是通过CPU,由于我用的是虚拟机,所以这里用的是CPU。
MCU Server是自带自签名证书的域名与实际域名不匹配,所以大家要生成自己的证书。

1、权限配置
1.1、/etc/security/limits.conf

* hard nproc unlimited
* soft nproc unlimited
* hard nofile 163840
* soft nofile 163840
* hard stack 1024
* soft stack 1024

1.2、/etc/pam.d/login

session required pam_limits.so

1.3、/etc/security/limits.d/xx-nproc.conf

* hard nproc unlimited
* soft nproc unlimited

1.4、/etc/sysctl.conf

fs.file-max=200000
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.core.rmem_default=16777216
net.core.wmem_default=16777216
net.ipv4.udp_mem=4096 87380 16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_mem=8388608 8388608 16777216

1.5、启用设置

sudo  /sbin/sysctl -p
ulimit -a

2、解压文件

tar -xf CS_WebRTC_Conference_Server_MCU.v4.1.tgz
mv Release-v4.1 /neohope/webrtc/MCU-Release-v4.1

3、编译依赖库
3.1、Cisco OpenH264

cd /neohope/webrtc/MCU-Release-v4.1/video_agent
#编译并安装依赖库
install_deps.sh
#关闭支持
#uninstall_openh264.sh
#开启支持
#install_openh264.sh

3.2、ffmpeg with libfdk_aac

cd /neohope/webrtc/MCU-Release-v4.1/audio_agent
compile_ffmpeg_with_libfdkaac.sh
mv ffmpeg_libfdkaac_lib/* lib/

4、初始化服务
4.1、生成证书

#生成RSA私钥
openssl genrsa -out ryans-key.pem 2048

Generating RSA private key, 2048 bit long modulus
..........................................................+++
................................................................................                                                                              

........................................+++
e is 65537 (0x10001)

#生成CSR(certificate signing request) 
openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:SH
Locality Name (eg, city) [Default City]:SH
Organization Name (eg, company) [Default Company Ltd]:NEOHOPE
Organizational Unit Name (eg, section) []:RD
Common Name (eg, your name or your server's hostname) []:172.16.172.80
Email Address []:NEOHOPE@YAHOO.COM

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

#生成自签名证书
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem

Signature ok
subject=/C=CN/ST=SH/L=SH/O=NEOHOPE/OU=RD/CN=172.16.172.80/emailAddress=NEOHOPE@Y                                                                              
AHOO.COM
Getting Private key

#转换为p12格式
#openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem -certfile ca-cert.pem -out ryans.pfx
openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem -out ryans.pfx

Enter Export Password:
Verifying - Enter Export Password:

4.2、安装证书

cp ryans.pfx ../MCU-Release-v4.1/extras/basic_example/cert/certificate.pfx 
cp ryans.pfx ../MCU-Release-v4.1/portal/cert/certificate.pfx 
#cp ryans.pfx ../MCU-Release-v4.1/webrtc_agent/cert/certificate.pfx 
cp ryans.pfx ../MCU-Release-v4.1/management_console/cert/certificate.pfx 

#然后分别到basic_example、portal、management_console下面,执行
node initcert.js

5、初始化服务

#非GPU加速
bin/init-all.sh
#GPU加速
#bin/init-all.sh --hardware

6、开启服务

bin/start-all.sh
starting nuve, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-nuve.stdout
starting cluster-manager, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-cluster-manager.stdout
starting audio-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-audio-agent.stdout
starting conference-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-conference-agent.stdout
2018-10-11 00:24:30.336  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:30.366  - INFO: ErizoAgent - conference agent join cluster ok.
2018-10-11 00:24:30.415  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:30.429  - INFO: ErizoAgent - as rpc server ok.
2018-10-11 00:24:30.431  - INFO: ErizoAgent - as monitoring target ok.
starting recording-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-recording-agent.stdout
2018-10-11 00:24:32.547  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
starting sip-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-sip-agent.stdout
2018-10-11 00:24:33.886  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:33.914  - INFO: ErizoAgent - sip agent join cluster ok.
2018-10-11 00:24:33.961  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:33.970  - INFO: ErizoAgent - as rpc server ok.
2018-10-11 00:24:33.973  - INFO: ErizoAgent - as monitoring target ok.
starting streaming-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-streaming-agent.stdout
2018-10-11 00:24:35.160  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:35.187  - INFO: ErizoAgent - streaming agent join cluster ok.
2018-10-11 00:24:35.235  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:35.246  - INFO: ErizoAgent - as rpc server ok.
2018-10-11 00:24:35.262  - INFO: ErizoAgent - as monitoring target ok.
starting video-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-video-agent.stdout
2018-10-11 00:24:36.529  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:36.563  - INFO: ErizoAgent - video agent join cluster ok.
2018-10-11 00:24:36.603  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:36.616  - INFO: ErizoAgent - as rpc server ok.
2018-10-11 00:24:36.631  - INFO: ErizoAgent - as monitoring target ok.
starting webrtc-agent, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-webrtc-agent.stdout
2018-10-11 00:24:37.938  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:37.964  - INFO: ErizoAgent - webrtc agent join cluster ok.
2018-10-11 00:24:37.999  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:38.020  - INFO: ErizoAgent - as rpc server ok.
2018-10-11 00:24:38.024  - INFO: ErizoAgent - as monitoring target ok.
starting management-console, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-management-console.stdout
Start management-console HTTP server
starting portal, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-portal.stdout
2018-10-11 00:24:40.691  - INFO: AmqpClient - Connecting to rabbitMQ server OK, hostPort: { host: 'localhost', port: 5672 }
2018-10-11 00:24:40.715  - INFO: Main - portal initializing as rpc client ok
2018-10-11 00:24:40.733  - INFO: Main - portal join cluster ok, with rpcID: portal-089f86b5d0a4c156d6b5@172.16.172.80
2018-10-11 00:24:40.734  - INFO: ClusterWorker - Join cluster woogeen-cluster OK.
2018-10-11 00:24:40.741  - INFO: Main - portal initializing as rpc server ok
2018-10-11 00:24:40.748  - INFO: Main - portal-089f86b5d0a4c156d6b5@172.16.172.80 as monitor ready
starting sip-portal, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-sip-portal.stdout
starting app, stdout -> /home/neohope/webrtc/MCU-Release-v4.1/logs/woogeen-app.stdout

7、测试服务,访问地址
7.1、你可以用浏览器浏览这个页面,可以看到自己的输入和输出视频画面
https://172.16.172.80:3004/

7.2、你可以用多个浏览器浏览这个页面,可以看到多路视频被合并为一个视频画面了。
https://172.16.172.80:3004/

7.3、如果不想合并多路视频,而是直接获取单个视频,可以用这个链接
https://172.16.172.80:3004/?forward=true

7.4、你可以用这个URL加入某个视频会议的房间
https://172.16.172.80:3004/?room=root_id
房间ID,在启动时,会输出到命令行及日志。

7.5、可以进入管理页面
https://172.16.172.80:3300/console/
需要输入Service_ID及Service_KEY。
可以在MCU-Release-v4.1/extras/basic_example/samplertcservice.js,查找这行代码即可得到:

icsREST.API.init('_service_ID_', '_service_KEY_', 'http://localhost:3000/', true);

8、停止服务

bin/stop-all.sh
stopping nuve
stopping cluster-manager
stopping audio-agent
stopping conference-agent
stopping recording-agent
stopping sip-agent
stopping streaming-agent
stopping video-agent
stopping webrtc-agent
stopping management-console
stopping portal.
stopping sip-portal
stopping app

搭建WebRTC视频会议服务01

本系列主要是描述了,在虚拟机中通过CentOS7+Intel Collaboration Suite4.1实现WebRTC视频的基本步骤。

1、安装CentOS7,并配置网络信息
A、通过网卡1(HostOnly),实现主机与虚拟机的通讯
B、通过网卡2(NAT),实现虚拟机的外网访问

2、下载Intel Collaboration Suite4.1,并解压,将需要的组件上传到虚拟机
https://software.intel.com/en-us/webrtc-sdk

3、安装中间件
3.1、Node.js
https://nodejs.org/dist/8.12.0/

#官方文档上要的版本为node-v6.9.5-linux-x64,但实际要求v8以上
tar -xf node-v8.12.0-linux-x64.tar.gz
mv node-v8.12.0-linux-x64 /home/neohope/
ln -s /home/neohope/webrtc/node-v8.12.0-linux-x64/bin/node /usr/bin/node
ln -s /home/neohope/webrtc/node-v8.12.0-linux-x64/bin/npm /usr/bin/npm

3.2、Erlang
https://bintray.com/rabbitmq/rpm/erlang/19.3.6.11-2

#前两步骤主要是为了偷懒,安装依赖包
yum install erlang
yum erase erlang-erts
rpm -ivh erlang-19.3.6.11-2.el7.centos.x86_64.rpm

3.3、Rabbitmq
http://www.rabbitmq.com/download.html

#注意Erlang版本依赖
rpm -ivh erlang-19.3.6.11-2.el7.centos.x86_64.rpm
#配置为自动启动
chkconfig rabbitmq-server on
#开启服务
service rabbitmq-server start

3.4、MongoDB
http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/RPMS/

#官方要的mongodb版本很低
rpm -ivh mongo-10gen-2.4.9-mongodb_1.x86_64.rpm
rpm -ivh mongo-10gen-server-2.4.9-mongodb_1.x86_64.rpm

4、安装Peer Server
4.1、安装

tar –zxvf CS_WebRTC_Conference_Server_Peer.v4.1.tgz
mv PeerServer-Release-4.1 /home/neohope/
cd /home/neohope/PeerServer-Release-4.1
npm install

4.2、测试

cd /home/neohope/PeerServer-Release-4.1
node peerserver.js
#测试完毕后ctrl+c退出

《硅谷来信》摘录

最近听完了吴军博士的《硅谷来信》,收获不少,将部分内容摘录于此:

1、专业人员要适当了解大局,管理者要注重细节

2、引擎和刹车
引擎应该是自下而上的,公司才会有源源不断的动力。
高层要想办法调动基层的动力,而不是在后面催促大家前进。高层要做的事情是,在适时的时候刹车。

3、五级工程师划分
第五级:能独立解决问题,完成工程工作;
第四级:能指导和带领其他人一同完成更有影响力的工作;
第三级:能独立设计和实现产品,并且在市场上获得成功;
第二级:能设计和实现别人不能做出的产品,也就是说他的作用很难取代;
第一级:开创一个产业。

4、努力和天分的关系
从0到50靠经验;
从50到90靠努力;
从90到100靠天份。

5、确认公司价值观和企业文化
技术和产品稳定性,工程师文化,谷歌
用户体验,产品经理文化,腾讯,苹果,Facebook
销售业绩,结果导向,销售文化,阿里与亚马逊

6、不同人员用不同管理方式
能力低,积极性高,新人居多,给予培训带教和指导,引导和培养
能力低,积极性低,PIP计划
能力高,积极性高,给予新的挑战,防止倦怠,给予机会,给予培训
能力高,积极性低,调整岗位,给予许诺,调整态度

新员工,bootcamp计划,新兵训练营
待提升员工,pip(performance improvement plan)计划,能力提升计划
A、加强实践管理,严格考勤
B、制定周计划,并严格执行
C、一对一专业指导
D、给予介绍自己工作的机会

7、招合适的人
主要看:人品、能力、主动性
一个原则:录用的人,高于目前平均水平

8、工作时阻碍进步的常见问题
A、工作和职业要分清
B、不做工作的主人
C、被语言暴力激怒
D、疏于沟通

SQL Server连接占线

使用ADO及ODBC连接SQL Server时,如果连接没有处理好,很容易出现下面的错误:

[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt.
连接占线导致另一个hstmt。

[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another command.
连接占线导致另一个命令。

产生这个错误的原因是,在同一个connection中,同时操作了多个数据集。

解决这个问题有两个方法
1、不要在一个connection中,同时打开多个数据集
2、在SQL SERVER2005以上版本,可以使用MARS (Multiple Active ResultSet)。在连接字符串中加上”Mars_Connection=yes;”就可以支持多数据集了。

关于MARS,可以参考这个:
http://msdn2.microsoft.com/en-us/library/ms345109.aspx

浅谈CPP智能指针

智能指针其实并不是指针,而是一个特殊对象。
在智能指针对象生命期即将结束时,它会调用析构函数释放有它管理的堆内存。
访问智能指针管理对象的方法,使用操作符“->”(重载)。
访问智能指针本来的方法,使用操作符“.”。

我们常见的智能指针有以下几种:

C98
std::auto_ptr
第一代智能指针,有些操作比如“=”坑比较多,不推荐使用。

C11
std::unique_ptr
独占对象,并保证指针所指对象生命周期与其一致。

std::shared_ptr
可共享指针对象,可以赋值给shared_ptr或weak_ptr。
通过引用计数的方式控制生命周期,当指针所指对象的所有的shared_ptr生命周期结束时(引用计数为0时)会被销毁。

std::weak_ptr
可以指向shared_ptr,但并不影响引用计数。
不影像所指对象的生命周期,在引用所指对象时,先用需要lock()才能使用。

Boost
不共享对象,类似于std::unique_ptr
boost::scoped_ptr
boost::scoped_array

共享对象,类似于std::shared_ptr
boost::shared_ptr
boost::shared_array

共享对象,但不改变对象引用计数,类似于std::weak_ptr
boost::weak_ptr

侵入式引用计数,要求使用对象自己实现计数功能
boost::intrusive_ptr

下面给一个例子,说明一下std下的四种智能指针。
1、SmartPointerTest.cpp

#include <memory>
#include <iostream>
#include "MyTest.h"

using namespace std;

void test_auto_ptr()
{
	std::auto_ptr<MyTest> auto_ptr_01(new MyTest("tom", 20));

	if (auto_ptr_01.get())
	{
		auto_ptr_01->sayHello();
		auto_ptr_01.get()->_name = "jerry";
		auto_ptr_01->sayHello();
		(*auto_ptr_01)._age += 1;
		auto_ptr_01->sayHello();
	}
	
	//auto_ptr_02会抢占auto_ptr_01的对象
	//此后auto_ptr_01不指向MyTest对象
	std::auto_ptr<MyTest> auto_ptr_02 = auto_ptr_01;
	if (auto_ptr_01.get())
	{
		cout << "auto_ptr_01 is released" << endl;
	}
	auto_ptr_02->sayHello();

	//只是释放所有权,并不释放内存
	//MyTest* test = auto_ptr_02.release();

	//释放内存
	auto_ptr_02.reset();
	if (!auto_ptr_01.get())
	{
		cout <<"auto_ptr_02 is released"<< endl;
	}
	
}

void test_unique_ptr()
{
	//独占对象
	//保证指针所指对象生命周期与其一致
	unique_ptr<MyTest> unique_ptr_01(new MyTest("tom", 20));
	unique_ptr_01->sayHello();

	//不允许直接做右值
	//unique_ptr<int> unique_ptr_02 = unique_ptr_01;

	//需要通过move来处理
	unique_ptr<MyTest> unique_ptr_03 = move(unique_ptr_01);
	if (!unique_ptr_01)cout << "unique_ptr_01 is empty" << endl;
	unique_ptr_03->sayHello();

	//释放指针
	unique_ptr_03.reset();
	if (!unique_ptr_03)cout << "unique_ptr_03 is empty" << endl;
}

void test_shared_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	shared_ptr<MyTest> shared_ptr_02 = shared_ptr_01;
	shared_ptr_01->sayHello();
	shared_ptr_02->sayHello();

	shared_ptr_01.reset();
	if (!shared_ptr_01)cout << "shared_ptr_01 is empty" << endl;
	shared_ptr_02->sayHello();

	shared_ptr_02.reset();
	if (!shared_ptr_02)cout << "shared_ptr_02 is empty" << endl;
}

void test_weak_ptr()
{
	shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20));
	weak_ptr<MyTest> weak_ptr_01 = shared_ptr_01;
	shared_ptr_01->sayHello();
	weak_ptr_01.lock()->sayHello();

	weak_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_01 is empty" << endl;
	shared_ptr_01->sayHello();
	
	weak_ptr<MyTest> weak_ptr_02 = shared_ptr_01;
	weak_ptr<MyTest> weak_ptr_03 = weak_ptr_02;
	if(weak_ptr_01.lock())weak_ptr_02.lock()->sayHello();
	shared_ptr_01.reset();
	if (!weak_ptr_01.lock())cout << "weak_ptr_02 is empty" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	test_auto_ptr();
	test_unique_ptr();
	test_shared_ptr();
	test_weak_ptr();

	return 0;
}

2、MyTest.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class MyTest
{
public:
	MyTest(string name, int age);
	~MyTest();
	void sayHello();

public:
	string _name;
	int _age;
};

3、MyTest.cpp

#include "stdafx.h"
#include "MyTest.h"

MyTest::MyTest(string name, int age)
{
	_name = name;
	_age = age;
}

MyTest::~MyTest()
{
}

void MyTest::sayHello()
{
	cout << "Hello " << _name<< "! You are "<< _age <<" years old." << endl;
}

PS:
聪明的你有没有发下,CPP的智能指针,与JVM内存中的四种引用方式,强引用、软引用、弱引用,虚引用,有很多相似的地方呢?

编译ss-qt5

1、安装依赖

sudo apt-get install qt5-default
sudo apt-get install cmake
sudo apt-get install libbotan-2-dev
sudo apt-get install libqrencode-dev
sudo apt-get install libzbar-dev

2、编译libQtShadowsocks

wget https://github.com/shadowsocks/libQtShadowsocks/archive/v2.1.0.tar.gz
tar -xvf libQtShadowsocks-2.1.0.tar.gz
cd libQtShadowsocks-2.1.0
make build
cd build
cmake .. -DCMAKE_INATALL_PREFIX=/usr -DUSE_BOTAN2=ON
make -j4
make
sudo make install

3、编译shadowsocks-qt5

git clone https://github.com/shadowsocks/shadowsocks-qt5.git
cd shadowsocks-qt5
make build
cd build
cmake .. -DCMAKE_INATALL_PREFIX=/usr
make -j4
make

4、运行

ss-qt5
Posted in QT | Tagged