1 /***************************************************************************
2  *  foxxll/io/fileperblock_file.cpp
3  *
4  *  Part of FOXXLL. See http://foxxll.org
5  *
6  *  Copyright (C) 2008, 2009 Johannes Singler <singler@ira.uka.de>
7  *  Copyright (C) 2008 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
8  *
9  *  Distributed under the Boost Software License, Version 1.0.
10  *  (See accompanying file LICENSE_1_0.txt or copy at
11  *  http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 #include <cassert>
15 #include <cstdio>
16 #include <iomanip>
17 #include <sstream>
18 #include <string>
19 
20 #include <tlx/counting_ptr.hpp>
21 #include <tlx/logger/core.hpp>
22 #include <tlx/unused.hpp>
23 
24 #include <foxxll/common/aligned_alloc.hpp>
25 #include <foxxll/common/error_handling.hpp>
26 #include <foxxll/common/exceptions.hpp>
27 #include <foxxll/config.hpp>
28 #include <foxxll/io/disk_queued_file.hpp>
29 #include <foxxll/io/file.hpp>
30 #include <foxxll/io/fileperblock_file.hpp>
31 #include <foxxll/io/mmap_file.hpp>
32 #include <foxxll/io/request.hpp>
33 #include <foxxll/io/serving_request.hpp>
34 #include <foxxll/io/syscall_file.hpp>
35 #include <foxxll/io/ufs_platform.hpp>
36 #include <foxxll/io/wincall_file.hpp>
37 
38 namespace foxxll {
39 
40 template <class base_file_type>
fileperblock_file(const std::string & filename_prefix,int mode,int queue_id,int allocator_id,unsigned int device_id)41 fileperblock_file<base_file_type>::fileperblock_file(
42     const std::string& filename_prefix,
43     int mode,
44     int queue_id,
45     int allocator_id,
46     unsigned int device_id)
47     : file(device_id),
48       disk_queued_file(queue_id, allocator_id),
49       filename_prefix_(filename_prefix),
50       mode_(mode),
51       current_size_(0)
52 { }
53 
54 template <class base_file_type>
~fileperblock_file()55 fileperblock_file<base_file_type>::~fileperblock_file()
56 {
57     if (lock_file_)
58         lock_file_->close_remove();
59 }
60 
61 template <class base_file_type>
filename_for_block(offset_type offset)62 std::string fileperblock_file<base_file_type>::filename_for_block(offset_type offset)
63 {
64     std::ostringstream name;
65     //enough for 1 billion blocks
66     name << filename_prefix_ << "_fpb_" << std::setw(20) << std::setfill('0') << offset;
67     return name.str();
68 }
69 
70 template <class base_file_type>
serve(void * buffer,offset_type offset,size_type bytes,request::read_or_write op)71 void fileperblock_file<base_file_type>::serve(
72     void* buffer, offset_type offset,
73     size_type bytes, request::read_or_write op)
74 {
75     base_file_type base_file(filename_for_block(offset), mode_, get_queue_id(),
76                              NO_ALLOCATOR, DEFAULT_DEVICE_ID, file_stats_);
77     base_file.set_size(bytes);
78     base_file.serve(buffer, 0, bytes, op);
79 }
80 
81 template <class base_file_type>
lock()82 void fileperblock_file<base_file_type>::lock()
83 {
84     if (!lock_file_)
85     {
86         lock_file_ = tlx::make_counting<base_file_type>(
87                 filename_prefix_ + "_fpb_lock", mode_, get_queue_id()
88             );
89 
90         //create lock file and fill it with one page, an empty file cannot be locked
91         const int page_size = BlockAlignment;
92         void* one_page = aligned_alloc<BlockAlignment>(page_size);
93 #if FOXXLL_WITH_VALGRIND
94         memset(one_page, 0, page_size);
95 #endif
96         lock_file_->set_size(page_size);
97         request_ptr r = lock_file_->awrite(one_page, 0, page_size);
98         r->wait();
99         aligned_dealloc<BlockAlignment>(one_page);
100     }
101     lock_file_->lock();
102 }
103 
104 template <class base_file_type>
discard(offset_type offset,offset_type length)105 void fileperblock_file<base_file_type>::discard(offset_type offset, offset_type length)
106 {
107     tlx::unused(length);
108 #ifdef FOXXLL_FILEPERBLOCK_NO_DELETE
109     if (::truncate(filename_for_block(offset).c_str(), 0) != 0)
110         TLX_LOG1 << "truncate() error on path=" << filename_for_block(offset)
111                  << " error=" << strerror(errno);
112 #else
113     if (::remove(filename_for_block(offset).c_str()) != 0)
114         TLX_LOG1 << "remove() error on path=" << filename_for_block(offset)
115                  << " error=" << strerror(errno);
116 #endif
117 
118     TLX_LOG << "discard " << offset << " + " << length;
119 }
120 
121 template <class base_file_type>
export_files(offset_type offset,offset_type length,std::string filename)122 void fileperblock_file<base_file_type>::export_files(offset_type offset, offset_type length, std::string filename)
123 {
124     std::string original(filename_for_block(offset));
125     filename.insert(0, original.substr(0, original.find_last_of("/") + 1));
126     if (::remove(filename.c_str()) != 0)
127         TLX_LOG1 << "remove() error on path=" << filename
128                  << " error=" << strerror(errno);
129 
130     if (::rename(original.c_str(), filename.c_str()) != 0)
131         TLX_LOG1 << "rename() error on path=" << filename
132                  << " to=" << original << " error=" << strerror(errno);
133 
134 #if !FOXXLL_WINDOWS
135     //TODO: implement on Windows
136     if (::truncate(filename.c_str(), as_signed(length)) != 0) {
137         FOXXLL_THROW_ERRNO(io_error, "Error doing truncate()");
138     }
139 #else
140     tlx::unused(length);
141 #endif
142 }
143 
144 template <class base_file_type>
io_type() const145 const char* fileperblock_file<base_file_type>::io_type() const
146 {
147     return "fileperblock";
148 }
149 
150 ////////////////////////////////////////////////////////////////////////////
151 
152 template class fileperblock_file<syscall_file>;
153 
154 #if FOXXLL_HAVE_MMAP_FILE
155 template class fileperblock_file<mmap_file>;
156 #endif
157 
158 #if FOXXLL_HAVE_WINCALL_FILE
159 template class fileperblock_file<wincall_file>;
160 #endif
161 
162 } // namespace foxxll
163 
164 /******************************************************************************/
165 
166 /**************************************************************************/
167