We expect developers to live in their tiny tiny cubes 24-7
我們希望程序員7*24小時工作在自己的小隔間里面
This is a support position
We don’t allow our developers to have a life outside of work
我們不希望員工有工作之外的生活
You will work closely with the PM, DBA and QA
Our environment is highly political, riddled with ridiculous rules
made by people who don’t understand software, and we get very little
done
我們的環境是高政治的,由很多不懂軟件的人制定了很多荒謬的制度。我們還有很多沒有達標。
This position involves working with our real-time application
I don’t know what real-time means but it sounds good
Great opportunity for growth
Only a desperate person would deal with this shit
只有絕望的人才會做這種狗屎的工作。
Job candidate must be resourceful, responsible and able to work well
under pressure.
Our corporate culture is basically the ‘Lord of the Flies
我們的管理方式就是“蟻王和工蟻”的方式。
加入特定限制條件「[]」
[a-z] 條件限制在小寫a to z范圍中一個字符
[A-Z] 條件限制在大寫A to Z范圍中一個字符
[a-zA-Z] 條件限制在小寫a to z或大寫A to Z范圍中一個字符
[0-9] 條件限制在小寫0 to 9范圍中一個字符
[0-9a-z] 條件限制在小寫0 to 9或a to z范圍中一個字符
[0-9[a-z]] 條件限制在小寫0 to 9或a to z范圍中一個字符(交集)
[]中加入^后加再次限制條件「[^]」
[^a-z] 條件限制在非小寫a to z范圍中一個字符
[^A-Z] 條件限制在非大寫A to Z范圍中一個字符
[^a-zA-Z] 條件限制在非小寫a to z或大寫A to Z范圍中一個字符
[^0-9] 條件限制在非小寫0 to 9范圍中一個字符
[^0-9a-z] 條件限制在非小寫0 to 9或a to z范圍中一個字符
[^0-9[a-z]] 條件限制在非小寫0 to 9或a to z范圍中一個字符(交集)
/**
* Thread Pool Manager.
*
* Use a fixed number of threads and process requests.
*/
public class ThreadPool
{
/**
* @param nThread
* number of threads to create.
*/
public ThreadPool( int nThread ) {
for( int i=0; i<nThread; i++ )
new WorkerThread().start();
}
/** list of tasks waiting for execution */
private final List tasks = new LinkedList();
/** list of lower-priority tasks waiting for execution */
private final List backgroundTasks = new LinkedList();
/**
* Adds a new 'task' to the pool.
* Assigned task will be eventually processed by one of the threads
* in the pool.
*/
public synchronized void addTask( Runnable task ) {
tasks.add(task);
notify(); // notify any thread waiting for a task
}
/**
* Adds a new low-priority 'task' to the pool.
* Assigned task will be eventually processed by one of the threads
* in the pool.
*/
public synchronized void addBackgroundTask( Runnable task ) {
backgroundTasks.add(task);
}
/**
* Obtains a task from the queue.
*/
private synchronized Runnable getTask() {
while(true) {
if(!tasks.isEmpty())
return (Runnable)tasks.remove(0);
public class CacheManagerImpl implements CacheManager
{
/**
* Set to non-null to see debug traces.
*/
private PrintStream debug = System.out;
/**
* The number of bytes in the cache.
* This field is accessed by the Janitor.
*/
long usedCacheSize = 0;
private Object usedCacheSizeLock = new Object();
/** Atomically modify the value of usedCacheSize. */
private void modifyUsedCacheSize( long offset ) {
synchronized(usedCacheSizeLock) {
usedCacheSize += offset;
}
}
private final long cacheLimit;
protected final TreeMap map=new TreeMap();
protected final TreeSet fileSet=new TreeSet();
/** The directory in which all cached objects are placed. */
private final File dir = new File("cache");
public final File getCacheDir() { return dir; }
private final CachePolicy policy;
/**
* Constructor:
* Load cache file information into CacheFileInfo objects.
* Include: filename, lastModified time, file length in byte.
* Add these objects to a TreeSet object, make them ordered
* by lastModified time.
* get current used cache size (in Bytes)
*/
public CacheManagerImpl(long limit, CachePolicy _policy) throws IOException
{
this.policy = _policy;
this.cacheLimit=limit; //in bytes
// launch the janitor
new Thread(new CacheJanitor(this)).start();
}
/**
* Put HttpResponse object into proxy cache.
* Write HttpResponse to a cache file if it is "toBeCached":
* 1. use request URL as a base of filename
* 2. the structure of the cache file contains two parts
* a. Request URL (String)
* b. HttpResponse object
*/
public void put( HttpRequest request, HttpResponse response ) {
long reservedSize;
try {
// if(debug!=null)
// debug.println("trying to store:"+request.getPath());
if(policy.toBeCached(request,response))
{
reservedSize = response.getBodySize()+2000;
// TODO: check if this object fits into the memory
// if(...)
// return;
// allocate the space before we actually use it
modifyUsedCacheSize(reservedSize);
// allocate physical space if it's necessary
if(!compactCache()) {
File f = getCacheFileName(request);
ObjectOutputStream fileOut=new ObjectOutputStream(
new FileOutputStream(f));
fileOut.writeObject(request.getPath());
try {
fileOut.writeObject(response.getHeaderAsDate("Expires"));
} catch( java.text.ParseException e ) {
fileOut.writeObject(null); // write a dummy
}
fileOut.writeObject(response);
fileOut.close();
long actualSize = f.length();
synchronized(fileSet) { // use one lock for both objects
CacheFileInfo cfi = new CacheFileInfo(f);
fileSet.add( cfi );
map.put( cfi.fname, cfi );
}
modifyUsedCacheSize(actualSize-reservedSize);
if(debug!=null)
debug.println("stored :"+request.getPath());
}
} catch( IOException e ) {
// TODO: possibly return the reservedSize.
reservedSize=-0;
modifyUsedCacheSize(reservedSize);
e.printStackTrace();
// TODO: remove any corrupted file
}
}
/**
* Get requested object from proxy cache.
* if (URL in file)==(request URL), and object not expired, then
* return object to callee. else return null
*/
public HttpResponse get( HttpRequest request )
{
try {
File f = getCacheFileName(request);
if(f.exists()) {
ObjectInputStream oi=new ObjectInputStream(
new FileInputStream(f));
String fURL=(String)oi.readObject();
if(fURL.equals(request.getPath())) {
Date now = new Date();
// we won't use it, but we need to read this object
// to get to the body
Date expires = (Date)oi.readObject();
// parse the body
HttpResponse resp=(HttpResponse)oi.readObject();
oi.close();
//check if the object expired
try {
Date d = resp.getHeaderAsDate("Expires");
if(d==null || d.after(now)) {
// not expired. use this object.
// touch this file for LRU purpose, and
// modify fileSet and map content
Util.setLastModified(f,now.getTime());
// maintain the control data structure
synchronized(fileSet) {
//remove this object first
fileSet.remove(map.get(f.getName()));
map.remove(f.getName());
//add this object with current attributes
CacheFileInfo new_cfi=new CacheFileInfo(f);
fileSet.add(new_cfi);
map.put(f.getName(),new_cfi);
}
return resp;
}
} catch( ParseException e ) { ; }
// we'll return null, so the caller will go ahead
// and fetch a new one, then store that new object
// into the cache.
// so we don't need to remove the old item now.
}
oi.close();
}
} catch( IOException e ) {
e.printStackTrace();
} catch( ClassNotFoundException e ) {
e.printStackTrace();
}
if(debug!=null)
debug.println("miss :"+request.getPath());
return null;
}
public boolean contains( HttpRequest request ) {
try {
File f = getCacheFileName(request);
if(!f.exists()) return false;
ObjectInputStream oi=new ObjectInputStream(
new FileInputStream(f));
String fURL=(String)oi.readObject();
boolean r = fURL.equals(request.getPath());
oi.close();
return r;
} catch( Exception e ) {
return false;
}
}
/**
* Compacts the cache so that the total size fell below the limit.
*
* @return
* true if the operation is successful and our used size is
* now lower then the limit.
*/
public boolean compactCache() {
synchronized(fileSet) {
/**
* Remove LRU cache file until get enough free space
* LRU strategy
*/
CacheFileInfo cFile;
/**
* Deletes the object represented by a given CacheFileInfo.
*
* To remove something from the cache, you need to call this method
* so that the cache manager can maintain the proper data structure.
*/
protected void removeCacheItem( CacheFileInfo cfi ) {
File tmp = new File(dir,"_"+cfi.fname);
new File(dir,cfi.fname).renameTo(tmp);
if(debug!=null) {
try {
// open the file just to print the name of URL
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(tmp));
debug.println("delete :"+ois.readObject());
ois.close();
} catch( Exception e ) {
// it's OK if we fail to print the debug message.
// so just ignore the error
}
}