11月 12

solrcloud 搭建

可参考文章:
http://shiyanjun.cn/archives/100.html
http://distinctplace.com/howto/2014/06/30/dealing-with-multiple-config-sets-in-solrcloud/
 
我,caodan,终于又弄好了新版本的solrcloud,没想到单机转个cloud还这么麻烦,弄了整整两天。
 
首先,之前使用的是solr5.0.0,因为用5.3.0 smartcn组件总是出错,现在我终于给他搞定了。
直接把analysis-extras\lucene-libs\lucene-analyzers-smartcn-5.3.1.jar 复制到 solr_setup\server\solr-webapp\webapp\WEB-INF\lib 下面,注意,不要复制到 solr_setup\server\lib下面,因为那样会导致加载失败。
复制完之后,用中文就很简单了,直接定义fieldtype
    <fieldType name="text_chinese" class="solr.TextField" positionIncrementGap="100">
      <analyzer>
        <tokenizer class="solr.HMMChineseTokenizerFactory"/>
        <filter class="solr.PorterStemFilterFactory"/>
      </analyzer>
    </fieldType>
 
接下来,为了建立solrcloud,需要参考 solr reference book,跟着里面的Setting Up an External ZooKeeper Ensemble那个做。
注意,solr -e 参数只是内置的傻瓜参考样本。没法用于产品的,不要去使用 -e 选项。 -e cloud只是给小白建立example看着玩玩用的。
下面那句话 bin/solr start -cloud -s <path to solr home for new node> -p 8987 -z localhost:2181 才是真材实料的布置环境。
 
好了先说布置 zookeeper,先去下载zookeeper,安装好。
然后配置zoo.cfg,这个好配置,注意clientPort是给solr连接用的,下面 server.1=localhost:2888:3888 的两个端口,是给不同zookeeper之间通信用的。
假设有三个node,同时配置三个zookeeper,有点傻瓜的时必须在syncLimit的时间内把他们同时打开,要不就会同步失败。
 
接下来就用 solr -cloud -z localhost:2181 -p 8983 命令去启动solr去连接zookeeper。
不要去指定 -s 选项,那是用来指定solr home的,如果需要多个solr就多复制几份,不要在一个solr安装目录下弄多个solr home,直接用默认的 solr_setup\server\solr 才靠谱。
可以把每个solr指定到每一个zookeeper上,
solr -cloud -z localhost:2182 -p 8984
solr -cloud -z localhost:2183 -p 8985
 
然后就是创建collection,这真是烦死大爷了,solrcloud的配置文件包括 schema.xml 和 solrconfig.xml 都是上传到 zookeeper进行管理的,不像单机版那样直接配置在本地,所以需要使用如下命令创建collection
 
solr create -c test -d myconf -shards 1 -replicationFactor 1
 
其中 myconf 指的是 solr_sepup\server\solr\configsets\ 下面的一个目录,比如 solr_sepup\server\solr\configsets\myconf,可以参考目录下的其他文件比如 basic_configs 来建立
同时zookeeper上还需要制定一个 configname,这个name默认跟collection name相同,所以上面的命令其实会调用接口

http://localhost:8983/solr/admin/collections?action=CREATE&name=test&numShards=1&replicationFactor=1&maxShardsPerNode=1&collection.configName=test

根据文章说的 http://distinctplace.com/howto/2014/06/30/dealing-with-multiple-config-sets-in-solrcloud/

用命令可以创建单独的configset

zkcli.sh -zkhost localhost:9983 -cmd upconfig -confdir /opt/solr/collection2/conf -confname myconf1

创建collection的时候可以单独指定 collection.configName,假如 configName 已经存在的话,注意这个zkcli必须用solr自带的

 

下面解决一些问题:

1. 恶心的事情,发布solr cloud,遇到问题,解析localhost变成ip 169.254.X.X,

万能的谷歌告诉我们:http://comments.gmane.org/gmane.comp.jakarta.lucene.solr.user/107193

关键看这个网址:http://wiki.apache.org/solr/SolrCloud#SolrCloud_Instance_Params

把 solr.xml 中的host值直接指定

2.zookeeper自带的zkcli是没有solr命令的,solr的zkcli有自己的script。我总是用原始的zkcli一直无法上传configset害死我了,具体看如下网址:

https://cwiki.apache.org/confluence/display/solr/Command+Line+Utilities

The zkcli.sh provided by Solr is not the same as the zkCli.sh included in ZooKeeper distributions !

7月 02

在MyEclipse中调试 solr

1. 首先下载solr源码最新版本

2. 搜索ant安装,在本地安装ant

3. 执行:

ant ivy-bootstrap

ant eclipse

这样就会出现elipse工程 .project 文件,导入到MyEclipse中

4. 安装 run-jetty-run插件

5. 设定 jetty webapp的 run configuration 参数

port: 9983 (用来调试)

Context: /solr (这个与StartSolrJetty类中的设定一致

WebApp dir:/solr/webapp/web (注意,这个要添加一个 /solr,相比于StartSolrJetty中的设定

 

最后,VM arguments要添加一条 -Dsolr.solr.home=/eclipse-build/main/solr 就是solrhome

这个是找了半天从编译后的版本找到的,这个home也可以直接设定为其他真实数据的目录,这样就直接在真实数据上调试。

 

参考文章:http://www.656463.com/article/EzmaYv.htm

但是这篇写的太复杂了,只要完成几步就行,不用配置那些繁琐的过程

————————— 关于如何编译发布 —————————

1. 在源代码根目录运行 ant compile

2. 进入到根目录下的 /solr,运行 ant dist

3. 把原来的solr.war 解压缩,jar -xvf solr.war

4. 用生成的dist中的替换 solr-core 替换 /WEB-INF/lib下面的那个文件,重新压缩 solr.war,

jar   -cvf   ../solr.war   */

8月 25

github使用记录

屌丝了,没用过github,记录怎么用。

用egit创建repository注意:

1.github首先有一个本地库,commit是到本地的,这个跟svn不一样。push/pull才是跟服务器交换数据。所以用egit新建的时候,是首先在本地创建reposity。设工程名为A,把代码拷到 /A/A/下面,.git就放在 /A/ 下面,这样两层方便管理。

2.首先commit一次,创建好本地库。然后使用 Push Branch… 创建一个master分支,提交到服务器。否则服务器没有初始分支,本地也没有配置stream,什么都不能用。

3.如果Push to Upstream 不能用,需要打开project_name/.git/config

原内容为

[core]
    symlinks = false
    repositoryformatversion = 0
    filemode = false
    logallrefupdates = true

添加:

[remote “origin”]
url = https://github.com/XXX/XXX.git
fetch = +refs/heads/*:refs/remotes/origin/*

[branch “master”]
remote = origin
merge = refs/heads/master

3月 23

Centos 问题

1. 启动ipv6

除了常能搜到的修改network的配置之外,还需要作如下修改:

https://www.mail-archive.com/centos@centos.org/msg20391.html

Try looking inside /etc/modprobe.conf for these lines:
alias net-pf-10 off
alias ipv6 off

将他们删除即可,否则会出现Kernel is not compiled with IPv6 support

10月 19

Strut2配置备忘

几千年没玩“技术”了,现在的技术已经和五年前完全不同了。虽然现在不像以前那么喜欢了,但是最近工程要用,也没法子。

初次设置搞个备忘吧。

MyEclipse可以自动配置strut2,新建工程teststrut2,然后deploy到自带的MyEclipse tomcat 7上。

在工程上点击右键,出来的菜单上MyEclipse->Project Facets->Install Struts 2

构建一个strut2最基本流程貌似包含4部分:

(1).引发action的页面

(2).用于处理action的类

(3).显示action处理结果的jsp文件

(4).struts.xml中的相关配置,把(1)、(2)、(3)三个部分联系起来。

先说(1),把工程默认的index.jsp改成如下

​<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <body>
    This is my JSP page. <br>
    <form name="test" method="POST" action="testaction.action"> 【1】【testaction】
    
    <s:textfield name="username" /> 【2】【username】
    <input type="submit" name="submit" value="submit">
    </form>
  </body>
</html>

注意:<%@ taglib prefix="s" uri="/struts-tags" %> 这句引用struts标签库,需要手打,(讨厌……)。其中prefix规定了s,所以后面s:textfield前缀就是s。其他testaction.action用于转入第(2)部分,经过测试,大小写敏感。所以用一个标志【1】暂时先记住这个位置,后面会有更多标志,同号标志表示内容必须相同。

现在开始第(2)部分,处理action的类,代码如下:

package com.test.struts2.action;  【3】【com.test.struts2.action】
import com.opensymphony.xwork2.ActionSupport;
public final class TestAction extends ActionSupport {
    private String username; 【2】【username】
    public String execute(){
        if(username.compareTo("lhxu")==0)
            return "success";  【4】【success,other】
        else
            return "other";
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

注意事项:第一个package名字自己规定,第二句所有类都要引用。getUsername和setUsername我一开始以为要自己输入了,那样的话就太麻烦了!我就因为误输入为SetUsername把s大写了,直接出错。后来发现MyEclipse的sourse菜单中可以直接自动生成Getter和Setter函数,我就喜欢自动!~~ 这个第(2)部分的action类检测用户输入的username,如果是lhxu,则将结果引导为hellolhxu.jsp,显示hello lhxu,否则将结果引导为helloothers.jsp,显示hello guys。第(3)部分显示结果不赘述。

第(4)部分:

?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <package name="com.test.struts2.action" 【2】 extends="struts-default">
        <action name="testaction" 【1】 class="com.test.struts2.action.TestAction">
            <result name="success">/hellolhxu.jsp</result> 【3】
            <result name="other">/helloothers.jsp</result>
        </action>
    </package>
</struts>

配置struts.xml,注意【1】testaction与(1)中【1】相同,大小写敏感!!其余【2】、【3】、【4】也要相同。

最后,有一点,因为(1)中jsp文件用了struts标签,所以要修改web.xml文件,把strut2的filter的url-pattern参数由默认的 *.action 改成 /* ,否则strut2的filter只关心*.action文件,而不会处理*.jsp文件,导致jsp中的strut标签无法被处理,产生The Struts dispatcher cannot be found​错误。这是浪费一小时绳命的教训。

9月 25

工程性组件记录

定时器 Quartz

总体界面 bootstrap http://getbootstrap.com/

表格 DataTable https://datatables.net/

bootstrap 和 DataTable 整一块

http://datatables.net/blog/Twitter_Bootstrap

 

http://blog.csdn.net/huangbiao86/article/details/6428608

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
原来是tomcat找不到MYSQL JAR包的问题。后来又把mysql-connector-java-5.1.7-bin.jar导入到tomcat的lib目录下面就ok了,嘿……
在java项目中,只需要引入mysql-connector-java-5.1.7-bin.jar就可以运行java项目。
在web项目中,当Class.forName("om.mysql.jdbc.Driver");时myeclipse是不会去查找字符串,不会去查找驱动的。所以只需要把mysql-connector-java-5.1.7-bin.jar拷贝到tomcat下lib目录就可以了。
6月 01

discuz 建立私人BBS

搭了一个Discuz,但是想让他成为私人论坛,这就要求在用户未登录情况下不显示论坛任何内容。

设置用户权限:系统用户组,游客-禁止访问任何页面。出来的效果很不幸,论坛上面的一部分内容竟然还在,并且透露了论坛部分内容。为了去掉这些东西,害我通宵搞了一晚上,累死了。

 

首先通过HTML匹配发现最头上那些东西位于template/header.htm里面,但是愣是找不到那里输出了这个htm。

进入member.php,折腾了很久,发现调用member_'.$mod.'.php',$mod是传入的操作,然后去看./source/module/member/member_logging.php,发现它创建了logging_ctl类,整站搜索发现该类位于./source/class/class_member.php,尝试在on_login中寻找,无果。

​又调试了半天,终于发现关键在于template函数,搜到这个函数,又跟进,尝试修改template函数里面的生成文件名,失败。但是通过分析checktplrefresh函数,里面调用了$template->parse_template,赫然发现Discuz竟然是用一种神奇的方式,把php首先通过一种奇怪的符号嵌入在html里,然后在服务器上替换成php,难怪header.htm看起来好奇怪的样子,在注释里面夹杂了很多php。

唉,最后还是去改header.htm吧,在header那个div之前加上<!–{if $_G[‘uid’]>0}–>,同时别忘了<!–{/if}–>,终于实现了目标。即用户登陆后header正常显示,用户没登陆时不显示header。

12月 29

关于C++指针的一些思考

长时间看学术问题,很少关注编程序时的所谓技术问题了,但是今天碰到了一个有趣的问题,引起了我的一些思考。

其实指针这个玩意应该可以被算作C++被人诟病的一个非常主要的原因了吧。读了博很少编程序了,C++真的要用起来有些东西还是不太了解。

今天的程序具体如下:

class CWord
{
public:
	string word;
	string type;
    //这里有一些其他成员
	
    //下面这两个继承自CStatic,与一些复杂的界面操作有关系
	CMyStatic * p_stc_word;
	CMyStatic * p_stc_group;

	void DestroyUI()
	{
		if(p_stc_word)
			delete p_stc_word;
		
		if(p_stc_group)
			delete p_stc_group;

		p_stc_word = NULL;
		p_stc_group = NULL;
	}

	CWord()
	{
		Init();
	}

	~CWord()
	{
         //关键的话在这里,这个导致了严重的错误
         DestroyUI();
	}

//另外有一个类,里面有一个CWord的数组
class CSentence
{
private:	
	vector < CWord > _vsen;
public:
    CWord & get_element(int i) {return _vsen[i];}   //为了尽量简化,就不检测越界之类的了,只是一个示例而已
}sen;

//然后悲剧发生了
//有一个函数 A
//调用了A之后,cw被销毁了,于是调用了~CWord,于是_vsen[0]中的两个CMyStatic被删掉了……
//这个错误让我想了半天,囧
void A()
{
    CWord cw = sen.get_element(0);
}

下面记录一下对以上内容的几点思考:

​1. 首先原来的程序如果改成 CWord & cw = sen.get_element(0);这样的话,其实cw就不会被销毁了,也不会出现错误了,但是当时没有想到,太麻痹大意

​2. 其实这样的get_element本身就是错误的,也是随手一写。我觉得应该改成get_element_text直接获取CWord里面的word成员更好一写,这样可以避免类的拷贝,因为我的目的本来就是只要word的内容,却把整个CWord复制出来了。

3.唉,关于指针的销毁,这个真是令人头疼。其实究其根本原因,我认为是我错误的在析构函数中调用了DestroyUI,这样导致了析构函数不可控。所以如果一旦存在CWord类的复制,很有可能导致两个CMyStatic在莫名其妙的情况下被删掉。下面有几种解决方案,都是水木上的人讨论的:

方案1:谁产生谁销毁,CMyStatic * 应该都由CWord产生,并有CWord销毁。但是事实上这样很难弄,因为我这个里面的CMyStatic其实是动态控件,和界面之间有非常复杂的交互,如果CWord自己创建CMyStatic,那么每次拷贝就要产生新的CMyStatic,把旧的CMyStatic删掉。但是事实上,sen._vsen里面每一个CWord之间是有依存关系的,他们在界面上依次按前后顺序显示CMyStatic,如果其中一个CMyStatic被改动了,其他所有的都要重新显示,这样会导致界面不停地闪烁。而且CMyStatic在界面上的位置会动态变化,也不好计算。

方案2:把析构函数中的DestroyUI拿掉,在外面调用DestroyUI。我现在把程序改成这样了,唉,这样其实也很容易出错。因为每一次界面的复杂操作都会伴随着CMyStatic控件的删除和重建,需要非常carefully coding!很有可能会漏删或者多删。本着宁可内存泄露也不可多删的原则就这样将就了吧。

方案3:有人说用shared_ptr,没用过~查了一下,应该可行。感觉应该也不方便

综上所述,算是体会到了C++的程序一旦涉及了指针,就是一个真正的无底洞。如果指针+多线程,那真的是灾难。难怪别的程序要自动垃圾回收!Java也不是一无是处的哈哈。

4月 29

解决Visual Studio包含了额外的引用文件后 Intellisense 失效问题

2013@3@28 加一个链接!http://blogs.msdn.com/b/vcblog/archive/2011/03/29/10146895.aspx

要是再有人因为Intellisense失效而搜到本博客,本人建议直接换装VS2012,装完之后万事大吉!否则VS2010版本及以下没有很好的解决办法。

假设我的工程包含了 E:\dlib-17.46\dlib\svm.h 文件,并且这个dlib的目录不是我的工程目录,这样就会出现 Intellisense 失效的问题。

对于严重依赖点一下自动列出成员变量的偶来说,这个是绝对不可以容忍的极其严重的问题!!

查了一下,发现原来是我把include目录设置成了整个VS环境include(就是工具-选项那里设置)了,这样的设置会导致 Intellisense 失效。

正确的做法应该是在工程项目属性里设置,打开“工程属性” – "C/C++" – "常规" – "附加包含目录",在这里写入include目录之后,发现 Intellisense 回来了。

真挫!

 

另一个可能的原因是下面这个:

当您使用 #include 指令多次引用头文件,而该头文件的含义因为各种宏状态(通过 #define 指令定义)而更改时。也就是说,当您数次包括一个使用情况在不同宏状态下不同的头文件时,IntelliSense 将无法一直工作。

貌似我在 "stdafx.h"里添加了 #ifdef _WIN64,下次记得不能在"stdafx.h"里弄这些个东西了,为了代码支持linux只要把"stdafx.h"里面的东西统统删掉就行了