Most of the time, people will think of an IP adress as a String. Especially in Java, most of the time, developers will deal with IP address either with URL or String class. However, representing an IP adress with String has several disadvantages. First a String usually takes more memory comparing to the "same" value int or long, and it will be difficult to compare with other IP addresses with a String. And more importantly, it will not be possible for people to easily determine whether an IP address is in the range of another two IP addresses.
Since IP addresses (IPv4) are composed by four integers ranging from 0 - 255, it will be obviously easy to convert an String IP address to an numerical form which can also uniquely represent the IP address. That's how Long IP address emerges.
A simple method to convert the String IP address to a Long IP address (A.B.C.D) would be:
256*256*256*A + 256*256*B + 256*C + D
Using Long IP address will be helpful in certain scenarios, one is when you dealing with IP-Location mapping in Google App Engine. A very popular data called GeoIP created by MaxMind is heavily used in a lot of different projects. However, when parsing the IP addresses, what they have done in the Java library is first transform the IP String into an InetAddress, and then using getAddress() to get its byte[], and finally get the Long value. There will be no problem when you using this library in other platforms. But in Google App Engine, things will got stuck because of the InetAddress is on the black-list of GAE, which means you will not be able to play with this class. The workaround here would be using the converting method above, you can directly get the Long value which is what they have calculated all the way along.
There might be some other places Long IP addresses is useful, especially when dealing with range query of IP addresses.
Showing posts with label Google App Engine. Show all posts
Showing posts with label Google App Engine. Show all posts
Wednesday, July 7, 2010
Long IP Address
Labels:
Converting,
GAE,
GeoIP,
Google App Engine,
InetAddress,
Long IP,
MaxMind
Monday, May 3, 2010
Using GAE python to bulk load CSV data into Java datastore
The official document is here: http://code.google.com/appengine/docs/python/tools/uploadingdata.html, more details will be covered here with Java applications.
1. Using any Windows environment to download Python SDK 2.5.X, preferably 2.5.4 since it is the last stable version with Windows Installer. Avoid to download 2.6.X and 3.X.X because GAE doesn't officially support these.
2. Download Google App Engine SDK for Python. Current version is 1.3.3. You may download GAE launcher which is only available in Windows.
3. Create a new project, naming it uploaddata (or whatever you like), add an app.yaml file
application: XXX
version: 1
runtime: python
api_version: 1
handlers:
-url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
Add above code to the app.yaml file. Use the correct application name and version, do not change the script of the handler.
4. Generate a python class, which can mapping the datastore table into a class. An example is:
(Student.py)
from google.appengine.ext import db
class Student(db.Model):
studentId = db.StringProperty()
name = db.StringProperty()
address = db.StringProperty()
......
5. Create a data loader file used by the handler. Here is another example:
(loader.py)
import datetime
from google.appengine.ext import db
from google.appengine.tools import bulkloader
import Student
class StudentLoader(bulkloader.Loader):
def __init__(self):
bulkloader.Loader.__init__(self, 'Student',
[('studentId', str), ('name', str), ('address', str)])
loaders = [StudentLoader]
Pay attention to those columns may contain characters in French Accent or Asian languages, use proper unicode to convert.
4. With command line, using the following command to upload data. With previous example, a sample command would look like:
appcfg.py upload_data --config_file=loader.py --filename=data.csv --kind=Student uploaddata
1. Using any Windows environment to download Python SDK 2.5.X, preferably 2.5.4 since it is the last stable version with Windows Installer. Avoid to download 2.6.X and 3.X.X because GAE doesn't officially support these.
2. Download Google App Engine SDK for Python. Current version is 1.3.3. You may download GAE launcher which is only available in Windows.
3. Create a new project, naming it uploaddata (or whatever you like), add an app.yaml file
application: XXX
version: 1
runtime: python
api_version: 1
handlers:
-url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
Add above code to the app.yaml file. Use the correct application name and version, do not change the script of the handler.
4. Generate a python class, which can mapping the datastore table into a class. An example is:
(Student.py)
from google.appengine.ext import db
class Student(db.Model):
studentId = db.StringProperty()
name = db.StringProperty()
address = db.StringProperty()
......
5. Create a data loader file used by the handler. Here is another example:
(loader.py)
import datetime
from google.appengine.ext import db
from google.appengine.tools import bulkloader
import Student
class StudentLoader(bulkloader.Loader):
def __init__(self):
bulkloader.Loader.__init__(self, 'Student',
[('studentId', str), ('name', str), ('address', str)])
loaders = [StudentLoader]
Pay attention to those columns may contain characters in French Accent or Asian languages, use proper unicode to convert.
4. With command line, using the following command to upload data. With previous example, a sample command would look like:
appcfg.py upload_data --config_file=loader.py --filename=data.csv --kind=Student uploaddata
Wednesday, April 21, 2010
App Engine SDK 1.3.3 released
Although the Eclipse plug-in has not updated yet, I have tried to download the zip file. This is only a minor updated version with limited features. One of the most important thing worth to pay attention is the SQLite support for Python. Despite of the official word "Note that this feature does not add SQL support to the App Engine SDK or service", it is a great advantage for developers to harness the benefits of SQLite. Just wondering when will they expand the support to Java field. It seems Java is always a step backward compared to the development team of Python.
Tuesday, April 20, 2010
New Warning Message on Google App Engine
I just noticed a pretty new warning appears in the log of App Engine:
"This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application."
Previously, there is no such thing highlighted the reason why sometimes a simple operation might take longer CPU hours than expected. Now with this handy warning, things are much clear and you don't have to worry about any internal coding issues with your project.
However, if Google can solve this issue, it will be much better. Currently, in order to avoid such re-loading time waste, I have to reduce my cron job frequency to once per minute. Yep, when it runs in 2/min, App Engine will complain every time, and the overall CPU cost is even higher than the more frequently job. Ironically, Ridiculously, huh?
I know some guys are working this issue now, hopefully it can be fixed in the near future.
"This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application."
Previously, there is no such thing highlighted the reason why sometimes a simple operation might take longer CPU hours than expected. Now with this handy warning, things are much clear and you don't have to worry about any internal coding issues with your project.
However, if Google can solve this issue, it will be much better. Currently, in order to avoid such re-loading time waste, I have to reduce my cron job frequency to once per minute. Yep, when it runs in 2/min, App Engine will complain every time, and the overall CPU cost is even higher than the more frequently job. Ironically, Ridiculously, huh?
I know some guys are working this issue now, hopefully it can be fixed in the near future.
Monday, March 22, 2010
Warning in JDO lazy fetch with App Engine
If you consistently meets the warning "org.datanucleus.store.appengine.MetaDataValidator warn: Meta-data warning for ****: The datastore does not support joins and therefore cannot honor requests to place related objects in the default fetch group. The field will be fetched lazily on first access. You can modify this warning by setting the datanucleus.appengine.ignorableMetaDataBehavior property in your config. A value of NONE will silence the warning. A value of ERROR will turn the warning into an exception." like this, please add the following line into your jdoconfig.xml:
<property name="datanucleus.appengine.ignorableMetaDataBehavior" value="NONE" />
Although it is quite obvious, but it's the problem where you put it might confuse many people.
<property name="datanucleus.appengine.ignorableMetaDataBehavior" value="NONE" />
Although it is quite obvious, but it's the problem where you put it might confuse many people.
Wednesday, March 17, 2010
Using memcache in GAE/J
Actually memcache is not a brand new concept, it has been utilized in many large scale projects. The most famous memcache event will be the Whale in Twitter's front page. To understand the background knowledge of memcache, please Google it. In one sentence, memcache is a way to cache those frequently used data internal or external to reduce the cost of database query and remote invocation. This is a very classical way in dealing with all kinds of database, however since most of the codes are written in low level , most of the developers are out of touch. Here, with the help of memcache, to transplant this idea into the application level, which will definitely be a great boost to large scale applications.
Google App Engine supports memcache for a long time, which should be one of its born advantage. Here I'd like to briefly introduce how to use memcache in GAE/J. Sorry for those who are interested in Python.
First, let's construct a scenario. There is a university system in GAE/J which stores information for around 10k students. Such a system includes all kinds of information for students to use, such as enrollment, study blackboard, course selection and so on. As a result, there will be a huge demand on the database query. However, such kind of demand always falls in two parts, which part of the students who really like the system and would like to log in everyday, another part students who can be considered as "lazy" seldom care about this. As a result, to improve the efficiency of the system. to cache those frequently used information will be a good help. Here we assume there is a table called Student, no matter what kind of action to happen, there is always the need to query the data in Student table. Let's see how memcache to store the Student information.
First we generate a JDO POJO class to store Student information. As an example, the fields in the class are pretty simple.
[java]@PersistenceCapable(identityType = IdentityType.APPLICATION)
@Inheritance(customStrategy = “complete-table”)
public class Student implements Serializable{
@PrimaryKey
@Persistent
private String uuid;
@Persistent
private String name;
@Persistent
private String email;
@Persistent
private String address;
public Student(){
this.uuid = UUID.randomUUID().toString();
//setter&getter
}[/java]
Then we need to construct a Cache class which will in charge of the operations in Cache layer.
[java]
public class QueryCache {
private static final Logger log = Logger.getLogger(QueryCache.class
.getName());
private static QueryCache instance;
private Cache cache;
private QueryCache(){
try{
CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
cache = cacheFactory.createCache(Collections.emptyMap());
}catch(CacheException e){
log.severe(”Error in creating the cache”);
}
}
public static synchronized QueryCache getInstance(){
if(instance==null){
instance = new QueryCache();
}
return instance;
}
public void putInCache(String address, String student){
cache.put(address, student);
}
public String findInCache(String address){
if(cache.containsKey(address)){
return (String)cache.get(address);
}else{
return null;
}
}
}
[/java]
Inside this class, we generate a new Cache instance under the Singleton pattern. A map resides in this class. At the same time, we define two methods, one to put the student information into the cache and another to get the information out of the cache.
Finally, we construct a servlet to query the student information.
public class QueryServlet extends HttpServlet{
private static final Logger log = Logger.getLogger(QueryServlet.class.getName());
@Override
protected void doGet(HttpServletRequest req, HttpServletResposne resp) throws ServletException, IOException{
log.info(”Now start……”);
QueryCache cache = QueryCache.getInstance();
String studentC = cache.findInCache(”Address7694″);
if(studentC!=null){
resp.getWriter().write(”Found the item in cache!”);
}else{
resp.getWriter().write(”No hit in cache!”);
PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(Student.class);
query.setFilter(”address==’Address7694′”);
List students = List query.execute();
if(students.iterator().hasNext()){
log.info(”Found one:”+student.toString());
resp.getWriter().write(”Found one:”+student.toString());
cache.putInCache(”Address7694″, student.toString());
}else{
log.info(”None found!”);
resp.getWriter().write(”None Found!”);
}
}
}
This is a very simple example to briefly show how to use memcache in GAE/J. However, a lot more things need to think about in reality such as where to use memcache, how to set the expire time of each cache, etc.
Google App Engine supports memcache for a long time, which should be one of its born advantage. Here I'd like to briefly introduce how to use memcache in GAE/J. Sorry for those who are interested in Python.
First, let's construct a scenario. There is a university system in GAE/J which stores information for around 10k students. Such a system includes all kinds of information for students to use, such as enrollment, study blackboard, course selection and so on. As a result, there will be a huge demand on the database query. However, such kind of demand always falls in two parts, which part of the students who really like the system and would like to log in everyday, another part students who can be considered as "lazy" seldom care about this. As a result, to improve the efficiency of the system. to cache those frequently used information will be a good help. Here we assume there is a table called Student, no matter what kind of action to happen, there is always the need to query the data in Student table. Let's see how memcache to store the Student information.
First we generate a JDO POJO class to store Student information. As an example, the fields in the class are pretty simple.
[java]@PersistenceCapable(identityType = IdentityType.APPLICATION)
@Inheritance(customStrategy = “complete-table”)
public class Student implements Serializable{
@PrimaryKey
@Persistent
private String uuid;
@Persistent
private String name;
@Persistent
private String email;
@Persistent
private String address;
public Student(){
this.uuid = UUID.randomUUID().toString();
//setter&getter
}[/java]
Then we need to construct a Cache class which will in charge of the operations in Cache layer.
[java]
public class QueryCache {
private static final Logger log = Logger.getLogger(QueryCache.class
.getName());
private static QueryCache instance;
private Cache cache;
private QueryCache(){
try{
CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
cache = cacheFactory.createCache(Collections.emptyMap());
}catch(CacheException e){
log.severe(”Error in creating the cache”);
}
}
public static synchronized QueryCache getInstance(){
if(instance==null){
instance = new QueryCache();
}
return instance;
}
public void putInCache(String address, String student){
cache.put(address, student);
}
public String findInCache(String address){
if(cache.containsKey(address)){
return (String)cache.get(address);
}else{
return null;
}
}
}
[/java]
Inside this class, we generate a new Cache instance under the Singleton pattern. A map resides in this class. At the same time, we define two methods, one to put the student information into the cache and another to get the information out of the cache.
Finally, we construct a servlet to query the student information.
public class QueryServlet extends HttpServlet{
private static final Logger log = Logger.getLogger(QueryServlet.class.getName());
@Override
protected void doGet(HttpServletRequest req, HttpServletResposne resp) throws ServletException, IOException{
log.info(”Now start……”);
QueryCache cache = QueryCache.getInstance();
String studentC = cache.findInCache(”Address7694″);
if(studentC!=null){
resp.getWriter().write(”Found the item in cache!”);
}else{
resp.getWriter().write(”No hit in cache!”);
PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(Student.class);
query.setFilter(”address==’Address7694′”);
List students = List query.execute();
if(students.iterator().hasNext()){
log.info(”Found one:”+student.toString());
resp.getWriter().write(”Found one:”+student.toString());
cache.putInCache(”Address7694″, student.toString());
}else{
log.info(”None found!”);
resp.getWriter().write(”None Found!”);
}
}
}
This is a very simple example to briefly show how to use memcache in GAE/J. However, a lot more things need to think about in reality such as where to use memcache, how to set the expire time of each cache, etc.
Monday, December 7, 2009
How to invoke a remote web service in GAE
Well, with GAE it is easy to develop applications on the cloud. But various limitations sometimes make people feel really uncomfortable when their usual behavior being considered as illegal according to the Google Laws.
You are not allowed to use any library related to .net package which may possibly generate more threads. But in order to make any invocation of other RESTful web services, we need to do something to both satisfy the requirement of Google and us.
In the official document, GAE recommends to use the HttpURLConnection class, which is a little bit too simpler to use, which means it brings various problems when dealing with complicated data types.
Here I will invoke a remote RESTful web service which will accept the format of JSON. Here is the code:
try {
URL url = new URL("http://localhost:8183/users/" +user+"/content");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
String json = content.toJSON().toString();
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(json);
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
System.out.println("sssssss");
} else {
System.out.println(connection.getResponseMessage());
System.out.println("ffffffff");
}
} catch (Exception e) {
e.printStackTrace();
}
Looks easy, ha, yep, quite straightforward. Remember to add those content-type in the connection for the receiver to recognize the format you are sending. While you are only allowed to send String or Char[], so hurry up and write your own parsing functions.
You are not allowed to use any library related to .net package which may possibly generate more threads. But in order to make any invocation of other RESTful web services, we need to do something to both satisfy the requirement of Google and us.
In the official document, GAE recommends to use the HttpURLConnection class, which is a little bit too simpler to use, which means it brings various problems when dealing with complicated data types.
Here I will invoke a remote RESTful web service which will accept the format of JSON. Here is the code:
try {
URL url = new URL("http://localhost:8183/users/" +user+"/content");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
String json = content.toJSON().toString();
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(json);
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
System.out.println("sssssss");
} else {
System.out.println(connection.getResponseMessage());
System.out.println("ffffffff");
}
} catch (Exception e) {
e.printStackTrace();
}
Looks easy, ha, yep, quite straightforward. Remember to add those content-type in the connection for the receiver to recognize the format you are sending. While you are only allowed to send String or Char[], so hurry up and write your own parsing functions.
Subscribe to:
Posts (Atom)