Sunday, 20 November 2016

如何转换MP3的ID3标签?

mp3文件ID3标签包括歌曲的名字、歌手名字等等。如果这些在播放器里显示为乱码,可按下述步骤修改:

在CentOS6.8系统下:

安装工具包:yum install python-mutagen

显示mp3文件标签:mid3v2 a.mp3

核实mp3文件标签是否为GB18030 编码:mid3iconv -p -e GB18030 -d a.mp3  (若显示为汉字则是)

将当前目录下全部mp3文件标签转换为Unicode编码:find . -name "*mp3" -print0 | xargs -0 mid3iconv -e GB18030 -d

参见:http://ask.xmodulo.com/convert-mp3-id3-tag-encodings-linux.html

Monday, 14 March 2016

How to work with Apache Ignite?

First of all, don't try to build from the source unless you know how to. I have tried following the instruction (BUILDING FROM SOURCE), it simply does not work!

Here is the way working for me:

1. Create a MAVEN project with following files


<1> pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.ignite</groupId>
    <artifactId>ignite-test</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.ignite</groupId>
            <artifactId>ignite-core</artifactId>
            <version>1.5.0.final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ignite</groupId>
            <artifactId>ignite-spring</artifactId>
            <version>1.5.0.final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ignite</groupId>
            <artifactId>ignite-indexing</artifactId>
            <version>1.5.0.final</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ignite</groupId>
            <artifactId>ignite-log4j</artifactId>
            <version>1.5.0.final</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>config</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.4.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <executable>java</executable>
                    <arguments>
                        <argument>-Xms1G</argument>
                        <argument>-Xmx1G</argument>
                        <argument>-classpath</argument>
                        <classpath />
                        <argument>my.ignite.Test</argument>
                    </arguments>
                    <workingDirectory>${project.build.outputDirectory}</workingDirectory>        
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

<2> src\main\java\my\ignite\Test.java

package my.ignite;

import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;

public class Test {

    public static void main(String[] args) throws IgniteException {
        Ignition.start("ignite.xml");
    }
}

<3> config\ignite.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- Datasource for sample in-memory H2 database. -->
    <bean id="h2-example-db" class="org.h2.jdbcx.JdbcDataSource">
        <property name="URL" value="jdbc:h2:tcp://localhost/mem:ExampleDb" />
        <property name="user" value="sa" />
    </bean>

    <bean abstract="false" id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
        <!-- Enable client mdoe. -->
        <property name="clientMode" value="false"/>
        <!-- Set to true to enable distributed class loading for examples, default is false. -->
        <property name="peerClassLoadingEnabled" value="true"/>

        <!-- Enable task execution events for examples. -->
        <property name="includeEventTypes">
            <list>
                <!--Task execution events-->
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_STARTED"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FINISHED"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FAILED"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_TIMEDOUT"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_SESSION_ATTR_SET"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_REDUCED"/>

                <!--Cache events-->
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_READ"/>
                <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_REMOVED"/>
            </list>
        </property>

        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <!--
                        Ignite provides several options for automatic discovery that can be used
                        instead os static IP based discovery. For information on all options refer
                        to our documentation: http://apacheignite.readme.io/docs/cluster-config
                    -->
                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
                        <!--bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"-->
                        <property name="addresses">
                            <list>
                                <value>127.0.0.1:47500..47509</value>
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

<4> config\java.util.logging.properties

handlers=java.util.logging.ConsoleHandler, org.apache.ignite.logger.java.JavaLoggerFileHandler
.level=INFO
java.util.logging.ConsoleHandler.formatter=org.apache.ignite.logger.java.JavaLoggerFormatter
java.util.logging.ConsoleHandler.level=INFO
org.apache.ignite.logger.java.JavaLoggerFileHandler.formatter=org.apache.ignite.logger.java.JavaLoggerFormatter
org.apache.ignite.logger.java.JavaLoggerFileHandler.pattern=ignite-%{id8}.%g.log
org.apache.ignite.logger.java.JavaLoggerFileHandler.level=INFO
org.apache.ignite.logger.java.JavaLoggerFileHandler.limit=10485760
org.apache.ignite.logger.java.JavaLoggerFileHandler.count=10

2. mvn compile

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ignite-test 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ ignite-test ---
[debug] execute contextualize
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ ignite-test ---
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.641s
[INFO] Finished at: Mon Mar 14 20:31:27 GMT 2016
[INFO] Final Memory: 4M/15M
[INFO] ------------------------------------------------------------------------

3. mvn exec:exec

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ignite-test 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.4.0:exec (default-cli) @ ignite-test ---
[20:31:34]    __________  ________________
[20:31:34]   /  _/ ___/ |/ /  _/_  __/ __/
[20:31:34]  _/ // (7 7    // /  / / / _/
[20:31:34] /___/\___/_/|_/___/ /_/ /___/
[20:31:34]
[20:31:34] ver. 1.5.0-final#20151229-sha1:f1f8cda2
[20:31:34] 2015 Copyright(C) Apache Software Foundation
[20:31:34]
[20:31:34] Ignite documentation: http://ignite.apache.org
[20:31:34]
[20:31:34] Quiet mode.
[20:31:34]   ^-- To see **FULL** console log here add -DIGNITE_QUIET=false or "-v" to ignite.{sh|bat}
[20:31:34]
[20:31:34] OS: Windows 7 6.1 x86
[20:31:34] VM information: Java(TM) SE Runtime Environment 1.7.0_80-b15 Oracle Corporation Java HotSpot(TM) Client VM 24.80-b11
[20:31:37] Configured plugins:
[20:31:37]   ^-- None
[20:31:37]
[20:31:38] Security status [authentication=off, tls/ssl=off]
[20:31:51] Performance suggestions for grid  (fix if possible)
[20:31:51] To disable, set -DIGNITE_PERFORMANCE_SUGGESTIONS_DISABLED=true
[20:31:51]   ^-- Disable peer class loading (set 'peerClassLoadingEnabled' to false)
[20:31:51]   ^-- Disable grid events (remove 'includeEventTypes' from configuration)
[20:31:51]
[20:31:51] To start Console Management & Monitoring run ignitevisorcmd.{sh|bat}
[20:31:51]
[20:31:51] Ignite node started OK (id=c9abb969)
[20:31:51] Topology snapshot [ver=1, servers=1, clients=0, CPUs=4, heap=1.0GB]

Sunday, 28 February 2016

How to build Role-Based Access Control in SQL?


Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise. (see here for more detail)

In above diagram, we model the relationship between User (u), Group/Role (g), and Permission (p) by three tables, i.e. u_g, g_p, and g_g, which are flexible enough to cover any trees or networks. All the following statements are true in this model:

  • a user can be linked to many groups;
  • a group can be linked to many users;
  • a permission can be linked to many groups;
  • a group can be linked to many permissions;
  • a group can be linked to many children groups;
  • a group can be linked to many parent groups;


However, the difficult part of this model is how to deal with hierarchies of roles/groups in SQL (see here, here, and here for detail) due to the recursive nature of navigating between group (g_g) relationship.

One solution is to use SQL stored routines. Followings are my design in MySQL and you can simply:

  • call get_permisions('u2');
  • call get_users('p1');

to get all permissions of a user or all users who have a permission.

-----------------------------------------------------------------------------------------------------

DROP PROCEDURE IF EXISTS test.get_users;
CREATE PROCEDURE test.`get_users`(p VARCHAR(20))
BEGIN
      SELECT group_concat(gID)
        INTO @groups
        FROM g_p
       WHERE pID = p;

      SELECT DISTINCT uID
        FROM u_g
       WHERE FIND_IN_SET(gID, parents(@groups)) > 0;
   END;

DROP PROCEDURE IF EXISTS test.get_permisions;
CREATE PROCEDURE test.`get_permisions`(u VARCHAR(20))
BEGIN
      SELECT group_concat(gID)
        INTO @groups
        FROM u_g
       WHERE uID = u;

      SELECT DISTINCT pID
        FROM g_p
       WHERE FIND_IN_SET(gID, children(@groups)) > 0;
   END;

DROP FUNCTION IF EXISTS test.children;
CREATE FUNCTION test.`children`(parents VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
BEGIN
      DECLARE x   VARCHAR(255);
      SET @@SESSION.max_sp_recursion_depth = 25;
      CALL get_children(parents, x);
      RETURN x;
   END;

DROP PROCEDURE IF EXISTS test.get_children;
CREATE PROCEDURE test.`get_children`(IN  parents    VARCHAR(255),
                                     OUT children   VARCHAR(255))
BEGIN
      DECLARE x   VARCHAR(255);
      SET children = parents;

      SELECT group_concat(DISTINCT child)
        INTO x
        FROM g_g
       WHERE FIND_IN_SET(parent, parents);

      IF (x IS NOT NULL)
      THEN
         CALL get_children(x, x);
         SET children = concat(parents, ',', x);
      END IF;
   END;

DROP FUNCTION IF EXISTS test.parents;
CREATE FUNCTION test.`parents`(children VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
BEGIN
      DECLARE x   VARCHAR(255);
      SET @@SESSION.max_sp_recursion_depth = 25;
      CALL get_parents(children, x);
      RETURN x;
   END;



DROP PROCEDURE IF EXISTS test.get_parents;
CREATE PROCEDURE test.`get_parents`(IN  children   VARCHAR(255),
                                    OUT parents    VARCHAR(255))
BEGIN
      DECLARE x   VARCHAR(255);
      SET parents = children;

      SELECT group_concat(DISTINCT parent)
        INTO x
        FROM g_g
       WHERE FIND_IN_SET(child, children);

      IF (x IS NOT NULL)
      THEN
         CALL get_parents(x, x);
         SET parents = concat(children, ',', x);
      END IF;
   END;

Sunday, 10 January 2016

How to install Windows 7 on a computer that has no CD drive?


  1. create an ISO image of Windows 7 DVD
  2. download "Windows USB/DVD Download Tool"
  3. install above tool on a Windows computer
  4. run the tool and pick up the ISO as the source and an USB stick as destination to build the bootable USB
  5. insert the bootable USB stick into the computer that has no CD drive
  6. boot the computer from the USB stick