- Main Page
- Classes
- Files

- File List

# services/FileService.hpp

    00001 // ---------------------------------------------------------------------
    00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
    00003 // ---------------------------------------------------------------------
    00004 // Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_FILESERVICE_HEADER__
    00011 #define __PION_FILESERVICE_HEADER__
    00012
    00013 #include <boost/shared_ptr.hpp>
    00014 #include <boost/functional/hash.hpp>
    00015 #include <boost/filesystem/path.hpp>
    00016 #include <boost/thread/once.hpp>
    00017 #include <boost/thread/mutex.hpp>
    00018 #include <boost/shared_array.hpp>
    00019 #include <pion/config.hpp>
    00020 #include <pion/logger.hpp>
    00021 #include <pion/hash_map.hpp>
    00022 #include <pion/http/plugin_service.hpp>
    00023 #include <pion/http/request.hpp>
    00024 #include <pion/http/response_writer.hpp>
    00025 #include <pion/http/server.hpp>
    00026 #include <string>
    00027 #include <map>
    00028
    00029
    00030 namespace pion {        // begin namespace pion
    00031 namespace plugins {     // begin namespace plugins
    00032
    00033
    00037 class DiskFile {
    00038 public:
    00040     DiskFile(void)
    00041         : m_file_size(0), m_last_modified(0) {}
    00042
    00044     DiskFile(const boost::filesystem::path& path,
    00045              char *content, unsigned long size,
    00046              std::time_t modified, const std::string& mime)
    00047         : m_file_path(path), m_file_content(content), m_file_size(size),
    00048         m_last_modified(modified), m_mime_type(mime)
    00049     {}
    00050
    00052     DiskFile(const DiskFile& f)
    00053         : m_file_path(f.m_file_path), m_file_content(f.m_file_content),
    00054         m_file_size(f.m_file_size), m_last_modified(f.m_last_modified),
    00055         m_last_modified_string(f.m_last_modified_string), m_mime_type(f.m_mime_type)
    00056     {}
    00057
    00059     void update(void);
    00060
    00062     void read(void);
    00063
    00069     bool checkUpdated(void);
    00070
    00072     inline const boost::filesystem::path& getFilePath(void) const { return m_file_path; }
    00073
    00075     inline char *getFileContent(void) { return m_file_content.get(); }
    00076
    00078     inline bool hasFileContent(void) const { return m_file_content; }
    00079
    00081     inline unsigned long getFileSize(void) const { return m_file_size; }
    00082
    00084     inline std::time_t getLastModified(void) const { return m_last_modified; }
    00085
    00087     inline const std::string& getLastModifiedString(void) const { return m_last_modified_string; }
    00088
    00090     inline const std::string& getMimeType(void) const { return m_mime_type; }
    00091
    00093     inline void setFilePath(const boost::filesystem::path& p) { m_file_path = p; }
    00094
    00096     inline void appendFilePath(const std::string& p) { m_file_path /= p; }
    00097
    00099     inline void setMimeType(const std::string& t) { m_mime_type = t; }
    00100
    00102     inline void resetFileContent(unsigned long n = 0) {
    00103         if (n == 0) m_file_content.reset();
    00104         else m_file_content.reset(new char[n]);
    00105     }
    00106
    00107
    00108 protected:
    00109
    00111     boost::filesystem::path     m_file_path;
    00112
    00114     boost::shared_array<char>   m_file_content;
    00115
    00117     std::streamsize             m_file_size;
    00118
    00120     std::time_t                 m_last_modified;
    00121
    00123     std::string                 m_last_modified_string;
    00124
    00126     std::string                 m_mime_type;
    00127 };
    00128
    00129
    00133 class DiskFileSender :
    00134     public boost::enable_shared_from_this<DiskFileSender>,
    00135     private boost::noncopyable
    00136 {
    00137 public:
    00146     static inline boost::shared_ptr<DiskFileSender>
    00147         create(DiskFile& file,
    00148                pion::http::request_ptr& http_request_ptr,
    00149                pion::tcp::connection_ptr& tcp_conn,
    00150                unsigned long max_chunk_size = 0)
    00151     {
    00152         return boost::shared_ptr<DiskFileSender>(new DiskFileSender(file, http_request_ptr,
    00153                                                                     tcp_conn, max_chunk_size));
    00154     }
    00155
    00157     virtual ~DiskFileSender() {}
    00158
    00162     void send(void);
    00163
    00165     inline void set_logger(logger log_ptr) { m_logger = log_ptr; }
    00166
    00168     inline logger get_logger(void) { return m_logger; }
    00169
    00170
    00171 protected:
    00172
    00181     DiskFileSender(DiskFile& file,
    00182                    pion::http::request_ptr& http_request_ptr,
    00183                    pion::tcp::connection_ptr& tcp_conn,
    00184                    unsigned long max_chunk_size);
    00185
    00192     void handle_write(const boost::system::error_code& write_error,
    00193                      std::size_t bytes_written);
    00194
    00195
    00197     logger                              m_logger;
    00198
    00199
    00200 private:
    00201
    00203     DiskFile                                m_disk_file;
    00204
    00206     pion::http::response_writer_ptr        m_writer;
    00207
    00209     boost::filesystem::ifstream             m_file_stream;
    00210
    00212     boost::shared_array<char>               m_content_buf;
    00213
    00219     unsigned long                           m_max_chunk_size;
    00220
    00222     unsigned long                           m_file_bytes_to_send;
    00223
    00225     unsigned long                           m_bytes_sent;
    00226 };
    00227
    00229 typedef boost::shared_ptr<DiskFileSender>       DiskFileSenderPtr;
    00230
    00231
    00235 class FileService :
    00236     public pion::http::plugin_service
    00237 {
    00238 public:
    00239
    00240     // default constructor and destructor
    00241     FileService(void);
    00242     virtual ~FileService() {}
    00243
    00254     virtual void set_option(const std::string& name, const std::string& value);
    00255
    00257     virtual void operator()(pion::http::request_ptr& http_request_ptr,
    00258                             pion::tcp::connection_ptr& tcp_conn);
    00259
    00261     virtual void start(void);
    00262
    00264     virtual void stop(void);
    00265
    00267     inline void set_logger(logger log_ptr) { m_logger = log_ptr; }
    00268
    00270     inline logger get_logger(void) { return m_logger; }
    00271
    00272
    00273 protected:
    00274
    00276     typedef PION_HASH_MAP<std::string, DiskFile, PION_HASH_STRING >     CacheMap;
    00277
    00279     typedef PION_HASH_MAP<std::string, std::string, PION_HASH_STRING >  MIMETypeMap;
    00280
    00286     void scanDirectory(const boost::filesystem::path& dir_path);
    00287
    00298     std::pair<CacheMap::iterator, bool>
    00299         addCacheEntry(const std::string& relative_path,
    00300                       const boost::filesystem::path& file_path,
    00301                       const bool placeholder);
    00302
    00309     static std::string findMIMEType(const std::string& file_name);
    00310
    00311     void sendNotFoundResponse(pion::http::request_ptr& http_request_ptr,
    00312                               pion::tcp::connection_ptr& tcp_conn);
    00313
    00315     logger                  m_logger;
    00316
    00317
    00318 private:
    00319
    00321     static void createMIMETypes(void);
    00322
    00323
    00325     static const std::string    DEFAULT_MIME_TYPE;
    00326
    00328     static const unsigned int   DEFAULT_CACHE_SETTING;
    00329
    00331     static const unsigned int   DEFAULT_SCAN_SETTING;
    00332
    00334     static const unsigned long  DEFAULT_MAX_CACHE_SIZE;
    00335
    00337     static const unsigned long  DEFAULT_MAX_CHUNK_SIZE;
    00338
    00340     static boost::once_flag     m_mime_types_init_flag;
    00341
    00343     static MIMETypeMap *        m_mime_types_ptr;
    00344
    00345
    00347     boost::filesystem::path     m_directory;
    00348
    00350     boost::filesystem::path     m_file;
    00351
    00353     CacheMap                    m_cache_map;
    00354
    00356     boost::mutex                m_cache_mutex;
    00357
    00364     unsigned int                m_cache_setting;
    00365
    00373     unsigned int                m_scan_setting;
    00374
    00379     unsigned long               m_max_cache_size;
    00380
    00386     unsigned long               m_max_chunk_size;
    00387
    00391     bool                        m_writable;
    00392 };
    00393
    00394
    00395 }   // end namespace plugins
    00396 }   // end namespace pion
    00397
    00398 #endif