Make storage and lock configurable for Index

1.  `storage` become a `Storage` object;
1.  Inside `Index`, raw dictionary accesses of `storage` are replaced
with method calls of `storage`, so that when we use some other class
(probably a subclass of `Storage`) of
object for `storage`, behaviors of these operations can be easily
redefined.

If we want a `index` that can be accessed across multiple machines, we can create a `index` like this:

```python
index = Index(curddir, MemcachedStorage())
```