package com.hphoto.server; import java.io.IOException; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.TreeMap; import org.apache.commons.beanutils.BeanUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseAdmin; import org.apache.hadoop.hbase.HScannerInterface; import org.apache.hadoop.hbase.HStoreKey; import org.apache.hadoop.hbase.HTable; import org.apache.hadoop.hbase.RemoteExceptionHandler; import org.apache.hadoop.hbase.filter.PageRowFilter; import org.apache.hadoop.hbase.filter.RegExpRowFilter; import org.apache.hadoop.hbase.filter.RowFilterInterface; import org.apache.hadoop.io.ArrayWritable; import org.apache.hadoop.io.DataInputBuffer; import org.apache.hadoop.io.DataOutputBuffer; import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableComparable; import org.apache.hadoop.io.WritableFactories; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.ipc.RemoteException; import org.apache.log4j.Logger; import com.hphoto.FConstants; import com.hphoto.bean.Album; import com.hphoto.bean.Category; import com.hphoto.bean.Comment; import com.hphoto.bean.Exif; import com.hphoto.bean.Image; import com.hphoto.bean.Tags; import com.hphoto.bean.UserProfile; import com.hphoto.util.KeyUtil; public class TableServer implements FConstants{ private static Logger LOG = Logger.getLogger(TableServer.class.getName()); private UidInterface uisServer; private static String SEPARATOR = "-"; private Configuration conf; private HTable userTable; private HTable imageTable; private HBaseAdmin admin; public TableServer(Configuration conf) throws IOException{ this.conf = conf; try { InitTable.init(new HBaseAdmin(conf)); } catch (IOException e) { LOG.info("Can not init table"); throw e; } userTable = new HTable(conf,UESR_TABLE); imageTable = new HTable(conf,IMAGE_TABLE); String address = conf.get(UID_SERVER_ADDRESS,"0.0.0.0"); int port = conf.getInt(UID_SERVER_PORT,UID_SERVER_PORT_DEFAULT); InetSocketAddress scoket = new InetSocketAddress(address,port); try { this.uisServer = (UidInterface) RPC.waitForProxy( UidInterface.class, UidInterface.versionID, scoket, conf); } catch (IOException e) { if (e instanceof RemoteException) { e = RemoteExceptionHandler.decodeRemoteException((RemoteException) e); } throw e; } } //user attribute public UserProfile[] getUser(String user,int length) throws IOException{ if(user=="" || user == null){ return null; }else{ PageRowFilter rf = new PageRowFilter(length); Text row = new Text(user); UserProfile[] profile = (UserProfile[]) scanTable(userTable,row,USER_FAMILYS,rf,UserProfile.class); if(length == 1){ if(profile != null && profile.length > 0 && profile[0].getNicename().equals(user)){ }else{ return null; } } return profile; } } public void setUser(UserProfile[] ups) throws IOException{ if(ups == null) return; for (UserProfile up :ups){ if(up.getNicename() == null) continue; Text row = new Text(up.getNicename()); DataOutputBuffer out = new DataOutputBuffer(); up.write(out); out.flush(); long id = userTable.startUpdate(row); userTable.put(id, USER_FAMILY, out.getData()); userTable.commit(id); out.close(); } } /** * * @param user user who own the album * @param category tha album name * @return Category or null * @throws IOException */ //image category attribute public Category getCategory(String user,String category) throws IOException{ if(user == null || user.trim().equals("")){ return null; }else{ PageRowFilter rf = new PageRowFilter(1); Text row = new Text(user); Text[] column = new Text[]{ new Text(IMAGE_CATEGORY + user + SEPARATOR + category) }; Category[] categories = (Category[]) scanTable(imageTable,row,column,rf,Category.class); if(categories != null && categories.length > 0 ){ return categories[0]; /* if(categories[0].getLablename().equals(category)&&categories[0].getName().equals(user)){ return categories[0]; } */ } return null; } } /** * * @param user user who own the album * @return an array containing the Category of the list * @throws IOException */ public Category[] getCategories(String user) throws IOException{ if(user == null || user.trim().equals("")){ return null; }else{ PageRowFilter rf = new PageRowFilter(1); Text row = new Text(user); Text[] column = new Text[]{ new Text(IMAGE_CATEGORY + user + SEPARATOR + ".*") }; Category[] categories = (Category[]) scanTable(imageTable,row,column,rf,Category.class); return categories; /* ArrayList<Category> list = new ArrayList<Category>(); if(categories != null && categories.length > 0){ for(Category category:categories){ if(category.getOwner().equals(user)){ list.add(category); } } return list.toArray(new Category[0]); } return new Category[0]; */ } } /** * * @param user user who own the album * @param opened the album is open * @param count least count the album contain photos * @return an array containing the Category of the list * @throws IOException */ public Category[] getCategories(String user,boolean opened,int count) throws IOException{ if(user == null || user.trim().equals("")){ return null; }else{ PageRowFilter rf = new PageRowFilter(1); Text row = new Text(user); Text[] column = new Text[]{ new Text(IMAGE_CATEGORY + user + SEPARATOR + ".*") }; Category[] categories = (Category[]) scanTable(imageTable,row,column,rf,Category.class); ArrayList<Category> list = new ArrayList<Category>(); if(categories != null && categories.length > 0){ for(Category category:categories){ if(category.getOwner().equals(user) && category.isOpened() == opened && category.getCount( ) > count ){ list.add(category); } } } return list.toArray(new Category[0]); } } public void setCategory(String user,Category[] categories) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); for(Category category : categories){ DataOutputBuffer out = new DataOutputBuffer(); if(category.getLablename() == null || category.getLablename().trim().equals("")){ Text key = KeyUtil.getKey(category.getName()); category.setLableName(key.toString()); } category.write(out); out.flush(); imageTable.put(id, new Text(IMAGE_CATEGORY + user + SEPARATOR + category.getLablename()), out.getData()); out.close(); } imageTable.commit(id); } public void deleteCategory(String user,Category[] categories) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); for(Category category: categories){ long id = imageTable.startUpdate(row); String lable = category.getLablename(); //int length = category.getCount(); imageTable.delete(id, new Text(IMAGE_CATEGORY + lable)); imageTable.commit(id); //we also delete the image in table Image[] images = getImages(user,lable); deleteImages(user,images); for(Image image : images){ deleteExif(user,image); deleteAllTags(user,image); deleteAllComment(user,image); deleteAllAlbum(user,image); } } } public Image getImage(String user,String imageid) throws IOException{ Image image = new Image(); if(user == null || user.trim().equals("") ||imageid ==null || imageid.trim().equals("")) return null; Text row = new Text(user); RegExpRowFilter rf = new RegExpRowFilter(".*" +SEPARATOR + imageid); Text[] column = new Text[]{ new Text(IMAGE_INFO + ".*" + SEPARATOR + imageid) ,new Text(IMAGE_EXIF + ".*" + SEPARATOR + imageid) ,new Text(IMAGE_TAGS + ".*" + SEPARATOR + imageid) ,new Text(IMAGE_COMMENT + ".*" + SEPARATOR + imageid) ,new Text(IMAGE_ALBUM + ".*" + SEPARATOR + imageid) }; getImageData(row,column,image); return image.getOwner() == null ? null : image; } /* public Image[] getImages(String user,String id) throws IOException{ if(user == null || user.trim().equals("") ||id ==null || id.trim().equals("")) return null; client.openTable(IMAGE_TABLE); Text row = new Text(user); PageRowFilter rf = new PageRowFilter(1); Text[] column = new Text[]{ new Text(IMAGE_INFO + ".*" + id) }; Image[] infos = (Image[]) scanTable(row,column,rf,Image.class); return infos.length > 0 ? infos[0] : null; } */ //image info attribute //image lable is IMAGE_INFO + category + SEPARATOR + imageid ; public Image[] getImages(String user,String category) throws IOException{ if(user == null || user.trim().equals("") ||category ==null || category.trim().equals("")) return null; Text row = new Text(user); PageRowFilter rf = new PageRowFilter(1); Text[] column = new Text[]{ new Text(IMAGE_INFO + user + SEPARATOR + category + SEPARATOR + ".*") }; return (Image[]) scanTable(imageTable,row,column,rf,Image.class); } public void setImages(String user,Image[] images) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); for(Image image : images){ DataOutputBuffer out = new DataOutputBuffer(); if(image.getId() == null || image.getId().trim().equals("")){ image.setId(Long.toString(this.uisServer.getUid())); } image.write(out); out.flush(); imageTable.put(id, new Text(IMAGE_INFO + user + SEPARATOR + image.getCategory() + SEPARATOR + image.getId()), out.getData()); out.close(); } imageTable.commit(id); } public void deleteImages(String user,Image[] images) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); for(Image image: images){ long id = imageTable.startUpdate(row); imageTable.delete(id, new Text(IMAGE_INFO + user + SEPARATOR + image.getCategory() + SEPARATOR + image.getId())); imageTable.commit(id); // we allso delete tag,comment,album,exif deleteExif(user,image); deleteAllTags(user,image); deleteAllComment(user,image); deleteAllAlbum(user,image); } } //exif public Exif getExif(String user,Image info) throws IOException{ return getExif(user,info.getCategory(),info.getId()); } public Exif getExif(String user,String category,String imageid) throws IOException{ if(user == null || user.trim().equals("") ||category ==null || category.trim().equals("")) return null; Text row = new Text(user); PageRowFilter rf = new PageRowFilter(1); Text[] column = new Text[]{ new Text(IMAGE_EXIF + user + SEPARATOR + category + SEPARATOR + imageid) }; Exif[] exifs = ((Exif[]) scanTable(imageTable,row,column,rf,Exif.class)); return exifs != null && exifs.length > 0 ? exifs[0] :null; } //label is IMAGE_EXIF + category + SEPARATOR + imageId public void setExif(String user,Image image,Exif exif) throws IOException{ setExif(user,image.getCategory(),image.getId(),exif); } public void setExif(String user,String category,String imageid,Exif exif) throws IOException{ if(user == null || user.trim().equals("") ||category ==null || category.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); DataOutputBuffer out = new DataOutputBuffer(); exif.write(out); out.flush(); imageTable.put(id, new Text(IMAGE_EXIF + user + SEPARATOR + category + SEPARATOR + imageid), out.getData()); imageTable.commit(id); out.close(); } public void deleteExif(String user,Image info) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); imageTable.delete(id, new Text(IMAGE_EXIF + user + SEPARATOR + info.getCategory() + SEPARATOR + info.getId())); imageTable.commit(id); } //tags public Tags[] getTags(String user,Image info) throws IOException{ return getTags(user,info.getCategory(),info.getId()); } public Tags[] getTags(String user,String category,String imageid) throws IOException{ if(user == null || user.trim().equals("") ||category ==null || category.trim().equals("")) return null; Text row = new Text(user); byte[][] bytes = imageTable.get(row, new Text(IMAGE_TAGS + user + SEPARATOR + category + SEPARATOR + imageid), 1); if(bytes != null){ Tags[] tags = (Tags[])getWritableClass(Tags.class,bytes[0]); return tags != null && tags.length > 0 ? tags : null; } return null; } public void setTags(String user,Image info,Tags[] tags) throws IOException{ setTags(user,info.getCategory(),info.getId(),tags); } public void setTags(String user,String category,String imageid,Tags[] tags) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); imageTable.put(id, new Text(IMAGE_TAGS + user + SEPARATOR + category + SEPARATOR + imageid),getByteData(Tags.class,tags)); imageTable.commit(id); } public void deleteTags(String user,Image info,Tags tag) throws IOException{ if(user == null || user.trim().equals("")) return; Tags[] tags = getTags(user,info); ArrayList<Tags> list = new ArrayList<Tags>(); for(Tags t:tags){ if(t.equals(tag)){ continue; } list.add(t); } setTags(user,info,(Tags[])list.toArray(new Tags[0])); } public void deleteAllTags(String user,Image info) throws IOException{ if(user == null || user.trim().equals("")) return; setTags(user,info,new Tags[0]); } //comment public Comment[] getComment(String user,Image info) throws IOException{ return getComment(user,info.getCategory(),info.getId()); } public Comment[] getComment(String user,String category,String imageid) throws IOException{ if(user == null || user.trim().equals("") ||category == null || category.trim().equals("")) return null; Text row = new Text(user); byte[][] bytes = imageTable.get(row, new Text(IMAGE_COMMENT + user + SEPARATOR + category + SEPARATOR + imageid), 1); if(bytes != null){ Comment[] comments = (Comment[])getWritableClass(Comment.class,bytes[0]); return comments; //!= null && comments.length > 0 ; } return null; } public void setComment(String user,Image info,Comment[] comments) throws IOException{ SetComment(user,info.getCategory(),info.getId(),comments); } public void SetComment(String user,String category,String imageid,Comment[] comments) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); imageTable.put(id, new Text(IMAGE_COMMENT + user + SEPARATOR + category + SEPARATOR + imageid),getByteData(Comment.class,comments)); imageTable.commit(id); } public void deleteComment(String user,Image info,Comment comment) throws IOException{ if(user == null || user.trim().equals("")) return; Comment[] comments = getComment(user,info); ArrayList<Comment> list = new ArrayList<Comment>(); for(Comment t:comments){ if(t.equals(comment)){ continue; } list.add(t); } setComment(user,info,(Comment[])list.toArray(new Comment[0])); } public void deleteAllComment(String user,Image info) throws IOException{ if(user == null || user.trim().equals("")) return; setComment(user,info,new Comment[0]); } //album public Album[] getAlbum(String user,Image info) throws IOException{ return getAlbum(user,info.getCategory(),info.getId()); } public Album[] getAlbum(String user,String category,String imageid) throws IOException{ if(user == null || user.trim().equals("") ||category == null || category.trim().equals("")) return null; Text row = new Text(user); byte[][] bytes = imageTable.get(row, new Text(IMAGE_ALBUM + user + SEPARATOR + category + SEPARATOR + imageid), 1); if(bytes != null){ return (Album[])getWritableClass(Album.class,bytes[0]); } return null; } public void setAlbum(String user,Image info,Album[] albums) throws IOException{ setAlbum(user,info.getCategory(),info.getId(),albums); } public void setAlbum(String user,String category,String imageid,Album[] albums) throws IOException{ if(user == null || user.trim().equals("")) return; Text row = new Text(user); long id = imageTable.startUpdate(row); imageTable.put(id, new Text(IMAGE_ALBUM + user + SEPARATOR + category + SEPARATOR + imageid),getByteData(Album.class,albums)); imageTable.commit(id); } public void deleteAlbum(String user,Image info,Album album) throws IOException{ if(user == null || user.trim().equals("")) return; Album[] albums = getAlbum(user,info); ArrayList<Album> list = new ArrayList<Album>(); for(Album t:albums){ if(t.equals(album)){ continue; } list.add(t); } setAlbum(user,info,(Album[])list.toArray(new Album[0])); } public void deleteAllAlbum(String user,Image info) throws IOException{ if(user == null || user.trim().equals("")) return; setAlbum(user,info,new Album[0]); } private byte[] getByteData(Class valueClass,Writable[] value) throws IOException{ DataOutputBuffer out = new DataOutputBuffer(); ArrayWritable aw = new ArrayWritable(valueClass,value); aw.write(out); out.flush(); byte[] value1 = out.getData(); out.close(); return value1; } private Object[] getWritableClass(Class valueClass,byte[] bytes) throws IOException{ DataInputBuffer in = new DataInputBuffer(); in.reset(bytes, bytes.length); ArrayWritable aw = new ArrayWritable(valueClass); aw.readFields(in); in.close(); Object[] result = (Object[]) aw.toArray(); //if can comparable,sort it; if(WritableComparable.class.isAssignableFrom(valueClass)){ Arrays.sort(result); } return result; } private Object[] getImageData(Text row, Text[] column,Image image) throws IOException{ PageRowFilter rf = new PageRowFilter(1); HScannerInterface s = imageTable.obtainScanner(column,row,rf); try{ HStoreKey curKey = new HStoreKey(); TreeMap<Text, byte[]> curVals = new TreeMap<Text, byte[]>(); while(s.next(curKey, curVals)) { for(Iterator<Text> it = curVals.keySet().iterator(); it.hasNext(); ) { Text lable = it.next(); Writable writeClass = null; LOG.info("lable:" + lable); byte[] bytes = curVals.get(lable); if(lable.toString().startsWith(IMAGE_INFO.toString())){ writeClass = WritableFactories.newInstance(Image.class); }else if(lable.toString().startsWith(IMAGE_EXIF.toString())){ writeClass = WritableFactories.newInstance(Exif.class); }else if(lable.toString().startsWith(IMAGE_TAGS.toString())){ Tags[] tags = (Tags[]) getWritableClass(Tags.class,bytes); image.setTags(tags); }else if(lable.toString().startsWith(IMAGE_COMMENT.toString())){ Comment[] comments = (Comment[]) getWritableClass(Comment.class,bytes); image.setComments(comments); }else if(lable.toString().startsWith(IMAGE_ALBUM.toString())){ Album[] albums = (Album[]) getWritableClass(Album.class,bytes); image.setAlbum(albums); } if(writeClass != null){ DataInputBuffer in = new DataInputBuffer(); in.reset(bytes, bytes.length); writeClass.readFields(in); in.close(); if(writeClass instanceof Image){ try { BeanUtils.copyProperties(image,(Image)writeClass); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } }else if(writeClass instanceof Exif){ image.setExif((Exif)writeClass); } } } } }finally { s.close(); } return null; } private Object[] scanTable(HTable table,Text row, Text[] column,RowFilterInterface rf,Class valueClass) throws IOException{ ArrayList<Writable> list = new ArrayList<Writable>(); HScannerInterface s = table.obtainScanner(column,row,rf); Writable writeClass = WritableFactories.newInstance(valueClass); try{ HStoreKey curKey = new HStoreKey(); TreeMap<Text, byte[]> curVals = new TreeMap<Text, byte[]>(); boolean next = s.next(curKey, curVals); while(next) { for(Iterator<Text> it = curVals.keySet().iterator(); it.hasNext(); ) { writeClass = WritableFactories.newInstance(valueClass); byte[] bytes = curVals.get(it.next()); DataInputBuffer inbuf = new DataInputBuffer(); inbuf.reset(bytes, bytes.length); writeClass.readFields(inbuf); inbuf.close(); list.add(writeClass); } curVals.clear(); next = s.next(curKey, curVals); } }finally { s.close(); } Object[] result = (Object[]) Array.newInstance(valueClass, list.size()); for (int i = 0; i < list.size(); i++) { Array.set(result, i, list.get(i)); } //if can comparable,sort it; if(WritableComparable.class.isAssignableFrom(valueClass)){ Arrays.sort(result); } return result; } }