renamed Collection to Resource

pull/40/head
Matchman Green 2012-05-19 15:41:21 +08:00
parent 149c1c14b0
commit 50e3091b2a
10 changed files with 171 additions and 214 deletions

View File

@ -128,7 +128,7 @@ Drive::~Drive( )
struct SortCollectionByHref
{
bool operator()( const Collection& c1, const Collection& c2 ) const
bool operator()( const Resource& c1, const Resource& c2 ) const
{
return c1.SelfHref() < c2.SelfHref() ;
}
@ -141,7 +141,7 @@ Drive::FolderListIterator Drive::FindFolder( const std::string& href )
std::equal_range(
m_coll.begin(),
m_coll.end(),
Collection( "", href ),
Resource( "", href ),
SortCollectionByHref() ) ;
return (its.first != its.second) ? its.first : m_coll.end() ;
@ -164,7 +164,7 @@ void Drive::ConstructDirTree( http::Agent *http )
xml::Node resp = xml.Response() ;
assert( m_coll.empty() ) ;
m_coll.push_back( Collection( ".", root_href ) ) ;
m_coll.push_back( Resource( ".", root_href ) ) ;
while ( true )
{
@ -179,7 +179,7 @@ void Drive::ConstructDirTree( http::Agent *http )
if ( e.ParentHrefs().size() == 1 )
{
m_state.OnEntry( e ) ;
m_coll.push_back( Collection( e ) ) ;
m_coll.push_back( Resource( e ) ) ;
}
else
Log( "folder \"%1%\" has multiple parents, ignored", e.Title(), log::warning ) ;
@ -201,7 +201,7 @@ void Drive::ConstructDirTree( http::Agent *http )
for ( FolderListIterator i = m_coll.begin() ; i != m_coll.end() ; ++i )
{
FolderListIterator pit = FindFolder( i->ParentHref() ) ;
Collection *scoll = m_state.FindFolderByHref( i->SelfHref() ) ;
Resource *scoll = m_state.FindFolderByHref( i->SelfHref() ) ;
if ( scoll )
Trace( "found folder %1% in state", scoll->Title() ) ;
else
@ -224,7 +224,7 @@ void Drive::ConstructDirTree( http::Agent *http )
Root()->CreateSubDir( "." ) ;
}
void Drive::UpdateFile( Entry& entry, Collection& parent, http::Agent *http )
void Drive::UpdateFile( Entry& entry, Resource& parent, http::Agent *http )
{
// only handle uploaded files
if ( !entry.Filename().empty() )

View File

@ -19,7 +19,7 @@
#pragma once
#include "Collection.hh"
#include "Resource.hh"
#include "State.hh"
#include "protocol/Json.hh"
@ -45,8 +45,8 @@ class File ;
class Drive
{
public :
typedef std::vector<Collection> FolderList ;
typedef std::vector<Collection>::iterator FolderListIterator ;
typedef std::vector<Resource> FolderList ;
typedef std::vector<Resource>::iterator FolderListIterator ;
public :
Drive( OAuth2& auth ) ;
@ -58,7 +58,7 @@ public :
struct Error : virtual Exception {} ;
private :
void UpdateFile( Entry& file, Collection& parent, http::Agent *http ) ;
void UpdateFile( Entry& file, Resource& parent, http::Agent *http ) ;
void ConstructDirTree( http::Agent *http ) ;

View File

@ -19,7 +19,7 @@
#include "File.hh"
#include "Collection.hh"
#include "Resource.hh"
#include "CommonUri.hh"
#include "http/Download.hh"
@ -37,7 +37,7 @@
namespace gr {
File::File( const Entry& entry, const Collection *parent ) :
File::File( const Entry& entry, const Resource *parent ) :
m_entry ( entry ),
m_parent ( parent )
{

View File

@ -32,12 +32,12 @@ namespace http
class Agent ;
}
class Collection ;
class Resource ;
class File
{
public :
explicit File( const Entry& e, const Collection *parent ) ;
explicit File( const Entry& e, const Resource *parent ) ;
void Update( http::Agent *http, const http::Headers& auth ) ;
void Delete( http::Agent* http, const http::Headers& auth ) ;
@ -51,7 +51,7 @@ private :
private :
Entry m_entry ;
const Collection *m_parent ;
const Resource *m_parent ;
} ;
} // end of namespace

View File

@ -29,7 +29,7 @@ namespace gr {
using namespace details ;
FolderSet::FolderSet( ) :
m_root( new Collection( ".", root_href ) )
m_root( new Resource( ".", root_href ) )
{
m_set.insert( m_root ) ;
}
@ -39,7 +39,7 @@ FolderSet::FolderSet( const FolderSet& fs )
const Set& s = fs.m_set.get<ByIdentity>() ;
for ( Set::const_iterator i = s.begin() ; i != s.end() ; ++i )
{
Collection *c = new Collection( **i ) ;
Resource *c = new Resource( **i ) ;
if ( c->SelfHref() == root_href )
m_root = c ;
@ -54,12 +54,12 @@ FolderSet::~FolderSet( )
std::for_each( s.begin(), s.end(), Destroy() ) ;
}
Collection* FolderSet::Root()
Resource* FolderSet::Root()
{
return m_root ;
}
const Collection* FolderSet::Root() const
const Resource* FolderSet::Root() const
{
return m_root ;
}
@ -76,14 +76,14 @@ FolderSet& FolderSet::operator=( const FolderSet& fs )
return *this ;
}
Collection* FolderSet::FindByHref( const std::string& href )
Resource* FolderSet::FindByHref( const std::string& href )
{
HrefMap& map = m_set.get<ByHref>() ;
HrefMap::iterator i = map.find( href ) ;
return i != map.end() ? *i : 0 ;
}
const Collection* FolderSet::FindByHref( const std::string& href ) const
const Resource* FolderSet::FindByHref( const std::string& href ) const
{
const HrefMap& map = m_set.get<ByHref>() ;
HrefMap::const_iterator i = map.find( href ) ;
@ -91,7 +91,7 @@ const Collection* FolderSet::FindByHref( const std::string& href ) const
}
/// Reinsert should be called when the ID/HREF were updated
bool FolderSet::ReInsert( Collection *coll )
bool FolderSet::ReInsert( Resource *coll )
{
Set& s = m_set.get<ByIdentity>() ;
Set::iterator i = s.find( coll ) ;
@ -105,18 +105,18 @@ bool FolderSet::ReInsert( Collection *coll )
return false ;
}
void FolderSet::Insert( Collection *coll )
void FolderSet::Insert( Resource *coll )
{
m_set.insert( coll ) ;
}
void FolderSet::Erase( Collection *coll )
void FolderSet::Erase( Resource *coll )
{
Set& s = m_set.get<ByIdentity>() ;
s.erase( s.find( coll ) ) ;
}
void FolderSet::Update( Collection *coll, const Entry& e )
void FolderSet::Update( Resource *coll, const Entry& e )
{
coll->Update( e ) ;
ReInsert( coll ) ;

View File

@ -19,7 +19,7 @@
#pragma once
#include "Collection.hh"
#include "Resource.hh"
#include "util/FileSystem.hh"
@ -38,11 +38,11 @@ namespace details
struct ByIdentity {} ;
typedef multi_index_container<
Collection*,
Resource*,
indexed_by<
hashed_non_unique<tag<ByHref>, const_mem_fun<Collection, std::string, &Collection::SelfHref> >,
hashed_non_unique<tag<ByID>, const_mem_fun<Collection, std::string, &Collection::ResourceID> >,
hashed_unique<tag<ByIdentity>, identity<Collection*> >
hashed_non_unique<tag<ByHref>, const_mem_fun<Resource, std::string, &Resource::SelfHref> >,
hashed_non_unique<tag<ByID>, const_mem_fun<Resource, std::string, &Resource::ResourceID> >,
hashed_unique<tag<ByIdentity>, identity<Resource*> >
>
> Folders ;
@ -66,23 +66,23 @@ public :
void Swap( FolderSet& fs ) ;
FolderSet& operator=( const FolderSet& fs ) ;
Collection* FindByHref( const std::string& href ) ;
const Collection* FindByHref( const std::string& href ) const ;
Resource* FindByHref( const std::string& href ) ;
const Resource* FindByHref( const std::string& href ) const ;
bool ReInsert( Collection *coll ) ;
bool ReInsert( Resource *coll ) ;
// void SetID( Collection *coll, const std::string& id ) ;
// void SetHref( Collection *coll, const std::string& href ) ;
void Insert( Collection *coll ) ;
void Erase( Collection *coll ) ;
void Update( Collection *coll, const Entry& e ) ;
void Insert( Resource *coll ) ;
void Erase( Resource *coll ) ;
void Update( Resource *coll, const Entry& e ) ;
Collection* Root() ;
const Collection* Root() const ;
Resource* Root() ;
const Resource* Root() const ;
private :
details::Folders m_set ;
Collection* m_root ;
Resource* m_root ;
} ;
} // end of namespace

View File

@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Collection.hh"
#include "Resource.hh"
#include "CommonUri.hh"
#include "util/OS.hh"
@ -31,19 +31,19 @@
namespace gr {
Collection::Collection( const xml::Node& entry ) :
Resource::Resource( const xml::Node& entry ) :
m_entry ( entry ),
m_parent ( 0 )
{
}
Collection::Collection( const Entry& entry ) :
Resource::Resource( const Entry& entry ) :
m_entry ( entry ),
m_parent ( 0 )
{
}
Collection::Collection(
Resource::Resource(
const std::string& title,
const std::string& href ) :
m_entry ( title, href ),
@ -51,42 +51,42 @@ Collection::Collection(
{
}
void Collection::Update( const Entry& e )
void Resource::Update( const Entry& e )
{
m_entry = e ;
}
std::string Collection::SelfHref() const
std::string Resource::SelfHref() const
{
return m_entry.SelfHref() ;
}
std::string Collection::Title() const
std::string Resource::Title() const
{
return m_entry.Title() ;
}
std::string Collection::ResourceID() const
std::string Resource::ResourceID() const
{
return m_entry.ResourceID() ;
}
const Collection* Collection::Parent() const
const Resource* Resource::Parent() const
{
return m_parent ;
}
Collection* Collection::Parent()
Resource* Resource::Parent()
{
return m_parent ;
}
std::string Collection::ParentHref() const
std::string Resource::ParentHref() const
{
return m_entry.ParentHref() ;
}
void Collection::AddChild( Collection *child )
void Resource::AddChild( Resource *child )
{
assert( child != 0 ) ;
assert( child->m_parent == 0 ) ;
@ -96,12 +96,12 @@ void Collection::AddChild( Collection *child )
m_child.push_back( child ) ;
}
void Collection::AddLeaf( File *file )
void Resource::AddLeaf( File *file )
{
m_leaf.push_back( file ) ;
}
void Collection::Swap( Collection& coll )
void Resource::Swap( Resource& coll )
{
m_entry.Swap( coll.m_entry ) ;
std::swap( m_parent, coll.m_parent ) ;
@ -109,38 +109,32 @@ void Collection::Swap( Collection& coll )
m_leaf.swap( coll.m_leaf ) ;
}
void Collection::CreateSubDir( const fs::path& prefix )
void Resource::CreateSubDir( const fs::path& prefix )
{
fs::path dir = prefix / m_entry.Title() ;
fs::create_directories( dir ) ;
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
for ( std::vector<Resource*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
{
assert( (*i)->m_parent == this ) ;
(*i)->CreateSubDir( dir ) ;
}
}
void Collection::ForEachFile(
Function<void(const std::string&)> callback,
const std::string& prefix )
{
}
fs::path Collection::Dir() const
fs::path Resource::Dir() const
{
assert( m_parent != this ) ;
return m_parent != 0 ? (m_parent->Dir() / m_entry.Title()) : "." ;
}
bool Collection::IsInRootTree() const
bool Resource::IsInRootTree() const
{
return m_parent == 0 ? (SelfHref() == root_href) : m_parent->IsInRootTree() ;
}
Collection* Collection::FindChild( const std::string& title )
Resource* Resource::FindChild( const std::string& title )
{
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
for ( std::vector<Resource*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
{
assert( (*i)->m_parent == this ) ;
if ( (*i)->Title() == title )
@ -153,7 +147,7 @@ Collection* Collection::FindChild( const std::string& title )
namespace std
{
void swap( gr::Collection& c1, gr::Collection& c2 )
void swap( gr::Resource& c1, gr::Resource& c2 )
{
c1.Swap( c2 ) ;
}

View File

@ -21,7 +21,6 @@
#include "Entry.hh"
#include "util/Exception.hh"
#include "util/Function.hh"
#include "util/FileSystem.hh"
#include <string>
@ -31,53 +30,50 @@ namespace gr {
class File ;
class Collection
class Resource
{
public :
explicit Collection( const xml::Node& entry ) ;
explicit Collection( const Entry& entry ) ;
Collection( const std::string& title, const std::string& href ) ;
Collection( const std::string& title, Collection *parent ) ;
explicit Resource( const xml::Node& entry ) ;
explicit Resource( const Entry& entry ) ;
Resource( const std::string& title, const std::string& href ) ;
Resource( const std::string& title, Resource *parent ) ;
// default copy ctor & op= are fine
std::string Title() const ;
std::string SelfHref() const ;
const Collection* Parent() const ;
Collection* Parent() ;
const Resource* Parent() const ;
Resource* Parent() ;
std::string ParentHref() const ;
fs::path Dir() const ;
bool IsInRootTree() const ;
std::string ResourceID() const ;
void AddChild( Collection *child ) ;
void AddChild( Resource *child ) ;
void AddLeaf( File *file ) ;
void Swap( Collection& coll ) ;
void Swap( Resource& coll ) ;
// traversing the tree
void CreateSubDir( const fs::path& prefix ) ;
void ForEachFile(
Function<void(const std::string&)> callback,
const std::string& prefix = "." ) ;
struct Error : virtual Exception {} ;
Collection* FindChild( const std::string& title ) ;
Resource* FindChild( const std::string& title ) ;
void Update( const Entry& e ) ;
private :
Entry m_entry ;
// not owned
Collection *m_parent ;
std::vector<Collection*> m_child ;
std::vector<File*> m_leaf ;
Resource *m_parent ;
std::vector<Resource*> m_child ;
std::vector<File*> m_leaf ;
} ;
} // end of namespace
namespace std
{
void swap( gr::Collection& c1, gr::Collection& c2 ) ;
void swap( gr::Resource& c1, gr::Resource& c2 ) ;
}

View File

@ -19,7 +19,7 @@
#include "State.hh"
#include "Collection.hh"
#include "Resource.hh"
#include "CommonUri.hh"
#include "util/Crypt.hh"
@ -40,82 +40,67 @@ namespace gr {
namespace
{
struct Resource
{
std::string id ;
fs::path path ;
std::string md5sum ;
std::time_t mtime ;
explicit Resource( const fs::path& p ) :
path( p ),
md5sum( crypt::MD5( p ) ),
mtime( fs::last_write_time( p ) )
{
}
explicit Resource( const Json& json ) :
id( json["id"].Str() ),
path( json["path"].Str() ),
md5sum( json["md5"].Str() ),
mtime( json["mtime"].Int() )
{
}
Json Get() const
{
Json entry ;
entry.Add( "id", Json( id ) ) ;
entry.Add( "path", Json( path.string() ) ) ;
entry.Add( "md5", Json( md5sum ) ) ;
entry.Add( "mtime", Json( mtime ) ) ;
return entry ;
}
} ;
struct PathHash
{
std::size_t operator()( const fs::path& p ) const
{
return boost::hash_value( p.string() ) ;
}
} ;
using namespace boost::multi_index ;
struct ByID {} ;
struct ByPath {} ;
typedef multi_index_container<
Resource,
indexed_by<
hashed_non_unique< tag<ByID>, member<Resource, std::string, &Resource::id> >,
hashed_unique< tag<ByPath>,member<Resource, fs::path, &Resource::path>, PathHash >
>
> ResourceSet ;
typedef ResourceSet::index<ByID>::type IDIdx ;
typedef ResourceSet::index<ByPath>::type PathIdx ;
/*
struct ByHref {} ;
struct ByIdentity {} ;
typedef multi_index_container<
Collection*,
indexed_by<
hashed_non_unique<tag<ByHref>, const_mem_fun<Collection, std::string, &Collection::SelfHref> >,
hashed_non_unique<tag<ByID>, const_mem_fun<Collection, std::string, &Collection::ResourceID> >,
hashed_unique<tag<ByIdentity>, identity<Collection*> >
>
> Folders ;
typedef Folders::index<ByHref>::type FoldersByHref ;
typedef Folders::index<ByIdentity>::type FSet ;*/
// struct Resource
// {
// std::string id ;
// fs::path path ;
// std::string md5sum ;
// std::time_t mtime ;
//
// explicit Resource( const fs::path& p ) :
// path( p ),
// md5sum( crypt::MD5( p ) ),
// mtime( fs::last_write_time( p ) )
// {
// }
//
// explicit Resource( const Json& json ) :
// id( json["id"].Str() ),
// path( json["path"].Str() ),
// md5sum( json["md5"].Str() ),
// mtime( json["mtime"].Int() )
// {
// }
//
// Json Get() const
// {
// Json entry ;
// entry.Add( "id", Json( id ) ) ;
// entry.Add( "path", Json( path.string() ) ) ;
// entry.Add( "md5", Json( md5sum ) ) ;
// entry.Add( "mtime", Json( mtime ) ) ;
// return entry ;
// }
// } ;
//
// struct PathHash
// {
// std::size_t operator()( const fs::path& p ) const
// {
// return boost::hash_value( p.string() ) ;
// }
// } ;
//
// using namespace boost::multi_index ;
//
// struct ByID {} ;
// struct ByPath {} ;
//
// typedef multi_index_container<
// Resource,
// indexed_by<
// hashed_non_unique< tag<ByID>, member<Resource, std::string, &Resource::id> >,
// hashed_unique< tag<ByPath>,member<Resource, fs::path, &Resource::path>, PathHash >
// >
// > ResourceSet ;
//
// typedef ResourceSet::index<ByID>::type IDIdx ;
// typedef ResourceSet::index<ByPath>::type PathIdx ;
}
struct State::Impl
{
ResourceSet rs ;
// ResourceSet rs ;
FolderSet folders ;
std::string change_stamp ;
@ -132,13 +117,13 @@ State::State( const fs::path& filename ) :
void State::Read( const fs::path& filename )
{
Trace( "reading %1%", filename ) ;
Json json = Json::ParseFile( filename.string() ) ;
std::vector<Json> res = json["resources"].AsArray() ;
for ( std::vector<Json>::iterator i = res.begin() ; i != res.end() ; ++i )
m_impl->rs.insert( Resource( *i ) ) ;
m_impl->change_stamp = json["change_stamp"].Str() ;
// Json json = Json::ParseFile( filename.string() ) ;
// std::vector<Json> res = json["resources"].AsArray() ;
//
// for ( std::vector<Json>::iterator i = res.begin() ; i != res.end() ; ++i )
// m_impl->rs.insert( Resource( *i ) ) ;
//
// m_impl->change_stamp = json["change_stamp"].Str() ;
}
std::string State::ChangeStamp() const
@ -153,15 +138,10 @@ void State::ChangeStamp( const std::string& cs )
void State::Sync( const fs::path& p )
{
// FoldersByHref& idx = m_impl->folders.get<ByHref>() ;
// FoldersByHref::iterator it = idx.find( root_href ) ;
// Collection *root = m_impl->folders.FindByHref( root_href ) ;
// assert( root != 0 ) ;
Sync( p, m_impl->folders.Root() ) ;
}
void State::Sync( const fs::path& p, Collection *folder )
void State::Sync( const boost::filesystem3::path& p, gr::Resource* folder )
{
assert( folder != 0 ) ;
@ -171,13 +151,13 @@ void State::Sync( const fs::path& p, Collection *folder )
// Trace( "file found = %2% (%1%)", i->path(), i->path().filename() ) ;
if ( fs::is_directory( i->path() ) )
{
Collection *c = new Collection( i->path().filename().string(), "" ) ;
Resource *c = new Resource( i->path().filename().string(), "" ) ;
folder->AddChild( c ) ;
Sync( *i, c ) ;
}
else if ( i->path().filename().string()[0] != '.' )
m_impl->rs.insert( Resource( i->path() ) ) ;
// else if ( i->path().filename().string()[0] != '.' )
// m_impl->rs.insert( Resource( i->path() ) ) ;
}
}
@ -186,14 +166,14 @@ void State::Write( const fs::path& filename ) const
Json result ;
result.Add( "change_stamp", Json( m_impl->change_stamp ) ) ;
IDIdx& idx = m_impl->rs.get<ByID>() ;
std::vector<Json> res ;
std::transform( idx.begin(), idx.end(),
std::back_inserter(res),
boost::bind( &Resource::Get, _1 ) ) ;
result.Add( "resources", Json(res) ) ;
// IDIdx& idx = m_impl->rs.get<ByID>() ;
//
// std::vector<Json> res ;
// std::transform( idx.begin(), idx.end(),
// std::back_inserter(res),
// boost::bind( &Resource::Get, _1 ) ) ;
//
// result.Add( "resources", Json(res) ) ;
// Trace( "%1%", result ) ;
@ -203,18 +183,18 @@ void State::Write( const fs::path& filename ) const
void State::SetId( const fs::path& p, const std::string& id )
{
PathIdx& pidx = m_impl->rs.get<ByPath>() ;
PathIdx::iterator it = pidx.find( p ) ;
if ( it != pidx.end() )
{
Resource r = *it ;
r.id = id ;
pidx.replace( it, r ) ;
}
else
{
Trace( "can't find %1%", p ) ;
}
// PathIdx& pidx = m_impl->rs.get<ByPath>() ;
// PathIdx::iterator it = pidx.find( p ) ;
// if ( it != pidx.end() )
// {
// Resource r = *it ;
// r.id = id ;
// pidx.replace( it, r ) ;
// }
// else
// {
// Trace( "can't find %1%", p ) ;
// }
}
void State::OnEntry( const Entry& e )
@ -263,33 +243,23 @@ std::size_t State::TryResolveEntry()
bool State::Update( const Entry& e )
{
// FoldersByHref& folders = m_impl->folders.get<ByHref>() ;
// FoldersByHref::iterator i = folders.find( e.ParentHref() ) ;
Collection *parent = m_impl->folders.FindByHref( e.ParentHref() ) ;
Resource *parent = m_impl->folders.FindByHref( e.ParentHref() ) ;
if ( parent != 0 )
{
Trace( "found parent of folder %1%: %2%", e.Title(), parent->Title() ) ;
// see if the entry already exist in local
Collection *child = parent->FindChild( e.Title() ) ;
Resource *child = parent->FindChild( e.Title() ) ;
if ( child != 0 )
{
// since we are updating the ID and Href, we need to remove it and re-add it.
m_impl->folders.Update( child, e ) ;
// FSet& fs = m_impl->folders.get<ByIdentity>() ;
// FSet::iterator c = fs.find( child ) ;
//
// if ( c != fs.end() )
// fs.erase( c ) ;
//
// child->Update( e ) ;
// folders.insert( child ) ;
}
// folder entry exist in google drive, but not local.
else
{
child = new Collection( e ) ;
child = new Resource( e ) ;
parent->AddChild( child ) ;
m_impl->folders.Insert( child ) ;
}
@ -299,11 +269,8 @@ bool State::Update( const Entry& e )
return false ;
}
Collection* State::FindFolderByHref( const std::string& href )
Resource* State::FindFolderByHref( const std::string& href )
{
// FoldersByHref& folders = m_impl->folders.get<ByHref>() ;
// FoldersByHref::iterator i = folders.find( href ) ;
// return i != folders.end() ? *i : 0 ;
return m_impl->folders.FindByHref( href ) ;
}

View File

@ -27,7 +27,7 @@
namespace gr {
class Json ;
class Collection ;
class Resource ;
class Entry ;
class State
@ -48,11 +48,11 @@ public :
std::string ChangeStamp() const ;
void ChangeStamp( const std::string& cs ) ;
Collection* FindFolderByHref( const std::string& href ) ;
Collection* FindFolderByID( const std::string& id ) ;
Resource* FindFolderByHref( const std::string& href ) ;
Resource* FindFolderByID( const std::string& id ) ;
private :
void Sync( const fs::path& p, Collection *folder ) ;
void Sync( const fs::path& p, Resource *folder ) ;
bool Update( const Entry& e ) ;
std::size_t TryResolveEntry() ;