作った理由:
- 日ごろ思いつくアイデアを公開したかった。(普段はメールの下書きでためていました。)
- 何でも良いからサービスを 1つ公開したかった。
Java、ClickFramework、DbUtils、MySQL などで動いてます。まだ検索やランキングも動いてなかったり。。
今のとこ、何ら新しいことはないのですが、実験場として色々追加していく予定です。
今後の予定:
- アイデアグラフ(最初はツリー表示でいいかな)
- OpenID 2.0 対応
- メール投稿
my $size = 1000;
my $cache = Cache::Memcached->new({
servers => ['localhost:11211'],
});
my $slabs = $cache->stats('slabs');
my @stat_ids = ();
for my $host (keys %{$slabs->{hosts}}) {
my $slabs_text = $slabs->{hosts}->{$host}->{slabs};
my @lines = split("\n", $slabs_text);
for my $line (@lines) {
($line =~ /STAT ([0-9]+):chunk_size [0-9]+/) or next;
push(@stat_ids, $1);
}
}
for my $stat_id (@stat_ids) {
my $cmd = "cachedump $stat_id $size";
print "[$cmd]\n";
my $cachedump = $cache->stats($cmd);
for my $host (keys %{$cachedump->{hosts}}) {
my $cachedump_text = $cachedump->{hosts}->{$host}->{$cmd};
my @lines = split("\n", $cachedump_text);
for my $line (@lines) {
($line =~ /^ITEM (.+) \[(.+) b; (.+) s\]/) or next;
my ($key, $b, $s) = ($1, $2, $3);
print "\t$key [$b bytes]\n";
}
}
}
> telnet localhost 11211
stats slabs
STAT 1:chunk_size 80
STAT 1:chunks_per_page 13107
STAT 1:total_pages 1
STAT 1:total_chunks 13107
STAT 1:used_chunks 13107
STAT 1:free_chunks 0
STAT 1:free_chunks_end 13065
STAT 2:chunk_size 100
STAT 2:chunks_per_page 10485
STAT 2:total_pages 1
STAT 2:total_chunks 10485
STAT 2:used_chunks 10485
STAT 2:free_chunks 0
STAT 2:free_chunks_end 10447
.....
STAT active_slabs 16
STAT total_malloced 16763844
END
stats cachedump {数字} {ダンプするキーの最大数}
ITEM {キー} [{統計情報}]
.....
END
# 中身も見ずにこういう呼び出しをしてしまってた。
$cache->stats('cachedump', 1, 100);
# こうすりゃ良かったんすね。
$cache->stats('cachedump 1 100');
import java.util.regex.*;
private static Pattern linkPattern = Pattern.compile(
"(https?)(://[\\p{Alnum}\\+\\$\\;\\?\\.%,!#~*/:@&=_-]+)");
public static String link(String s, int length, String suffix) {
StringBuffer buff = new StringBuffer((int) (s.length() * 1.2f));
Matcher m = linkPattern.matcher(s);
while (m.find()) {
String g = m.group();
if (length > 0 && g.length() > length) {
g = g.substring(0, length);
if (suffix != null) {
g += suffix;
}
}
g = m.quoteReplacement(g);
m.appendReplacement(buff, "<a href=\"$1$2\">" + g + "</a>");
}
m.appendTail(buff);
return new String(buff);
}
URL サンプルでは <http://example.com/> を使いましょう。
URL サンプルでは <http://example.com/> を使いましょう。
URL サンプルでは<<a href="http://example.com/>">http://example.com/></a>を使いましょう。
private static Pattern linkHtmlPattern = Pattern.compile(結構面倒くさいです。。色々考えたのですが、今のところこれが一番かなと思います。
"((https?)(://[\\p{Alnum}\\+\\$\\;\\?\\.%,!#~*/:@&=_-]+))|([&<>\"\'])");
public static String linkHtml(String s, int length, String suffix) {
StringBuffer buff = new StringBuffer((int) (s.length() * 1.2f));
Matcher m = linkHtmlPattern.matcher(s);
while (m.find()) {
String g = m.group();
if (g.length() == 1) {
if (g.equals("&")) {
g = "&";
} else if (g.equals("<")) {
g = "<";
} else if (g.equals(">")) {
g = ">";
} else if (g.equals("\"")) {
g = """;
} else if (g.equals("\'")) {
g = "'";
}
m.appendReplacement(buff, g);
continue;
}
if (length > 0 && g.length() > length) {
g = g.substring(0, length);
if (suffix != null) {
g += suffix;
}
}
g = m.quoteReplacement(g);
m.appendReplacement(buff, "<a href=\"$1\">" + g + "</a>");
}
m.appendTail(buff);
return new String(buff);
}
use URI::Find;
my $finder = URI::Find->new(
sub {
my($uri, $orig_uri) = @_;
return qq {<a href="$uri">$orig_uri</a>};
});
$finder->find(\$text);
$text =~ s/>/ __GT__ /g;
$text =~ s/</ __LT__ /g;
$text =~ s/&/ __AMP__ /g;
$text =~ s/"/ __QUOT__ /g;
$text =~ s/'/ __APOS__ /g;
my $finder = URI::Find->new(
sub {
my($uri, $orig_uri) = @_;
return qq {<a href="$uri">$orig_uri</a>};
});
$finder->find(\$text);
$text =~ s/ __GT__ />/g;
$text =~ s/ __LT__ /</g;
$text =~ s/ __AMP__ /&/g;
$text =~ s/ __QUOT__ /"/g;
$text =~ s/ __APOS__ /'/g;
QueryRunner run = new QueryRunner(dataSource);
ResultSetHandler h = new BeanHandler(Person.class);
Person p = (Person) run.query(
"SELECT * FROM Person WHERE name=?", "John Doe", h);
create table person (
id integer not null primary key,
name varchar(20) not null
);
public class Person implements java.io.Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
create table person (
id integer not null primary key,
first_name varchar(20) not null,
last_name varchar(20) not null
);
public class Person implements java.io.Serializable {
private int id;
private String firstName;
private String lastName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName= firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String lastName) {
this.lastName= lastName;
}
// NOTE: for DbUtils
public void setFirst_name(String firstName) {
setFirstName(firstName);
}
public void setLast_name(String lastName) {
setLastName(lastName);
}
}
import java.beans.PropertyDescriptor;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Arrays;
import org.apache.commons.dbutils.BeanProcessor;
public class MyBeanProcessor extends BeanProcessor {
@Override
protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
PropertyDescriptor[] props) throws SQLException {
int cols = rsmd.getColumnCount();
int columnToProperty[] = new int[cols + 1];
Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
for (int col = 1; col <= cols; col++) {
String columnName = rsmd.getColumnName(col);
for (int i = 0; i < props.length; i++) {
// NOTE: 元のコードを
// if (columnName.equalsIgnoreCase(props[i].getName())) {
// NOTE: 次のように変更
if (equalsColumnProperty(columnName, props[i].getName())) {
columnToProperty[col] = i;
break;
}
}
}
return columnToProperty;
}
private boolean equalsColumnProperty(String colName, String propName) {
// NOTE: 頻繁に呼び出されるので実際にはキャッシュを使うなどして
// 高速化したほうがよいです。
return colName.replaceAll("_", "").equalsIgnoreCase(propName);
}
}
RowProcessor rp = new BasicRowProcessor(new MyBeanProcessor());
QueryRunner run = new QueryRunner(dataSource);
ResultSetHandler h = new BeanHandler(Person.class, rp);
Person p = (Person) run.query(
"SELECT * FROM Person WHERE first_name=?", "John Doe", h);