Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * io/simdisk_file.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002-2003 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2008 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * 00009 * Distributed under the Boost Software License, Version 1.0. 00010 * (See accompanying file LICENSE_1_0.txt or copy at 00011 * http://www.boost.org/LICENSE_1_0.txt) 00012 **************************************************************************/ 00013 00014 #include <stxxl/bits/io/simdisk_file.h> 00015 00016 #if STXXL_HAVE_SIMDISK_FILE 00017 00018 #include <stxxl/bits/io/iostats.h> 00019 #include <stxxl/bits/common/error_handling.h> 00020 00021 00022 __STXXL_BEGIN_NAMESPACE 00023 00024 00025 void DiskGeometry::add_zone(int & first_cyl, int last_cyl, 00026 int sec_per_track, int & first_sect) 00027 { 00028 double rate = 00029 nsurfaces * sec_per_track * bytes_per_sector / 00030 ((nsurfaces - 1) * head_switch_time + 00031 cyl_switch_time + 00032 nsurfaces * revolution_time); 00033 int sectors = 00034 (last_cyl - first_cyl + 00035 1) * nsurfaces * sec_per_track; 00036 zones.insert(Zone(first_sect, sectors, rate)); 00037 first_sect += sectors; 00038 first_cyl = last_cyl + 1; 00039 } 00040 00041 // returns delay in s 00042 double DiskGeometry::get_delay(file::offset_type offset, file::size_type size) 00043 { 00044 #if 0 00045 int first_sect = offset / bytes_per_sector; 00046 int last_sect = (offset + size) / bytes_per_sector; 00047 int sectors = size / bytes_per_sector; 00048 double delay = 00049 cmd_ovh + seek_time + rot_latency + 00050 double(bytes_per_sector) / 00051 double(interface_speed); 00052 00053 std::set<Zone, ZoneCmp>::iterator zone = zones.lower_bound(first_sect); 00054 //std::cout << __PRETTY_FUNCTION__ << " " << (*zone).first_sector << std::endl; 00055 while (1) 00056 { 00057 int from_this_zone = 00058 last_sect - ((*zone).first_sector + 00059 (*zone).sectors); 00060 if (from_this_zone <= 0) 00061 { 00062 delay += sectors * bytes_per_sector / 00063 ((*zone).sustained_data_rate); 00064 break; 00065 } 00066 else 00067 { 00068 delay += from_this_zone * 00069 bytes_per_sector / 00070 ((*zone).sustained_data_rate); 00071 zone++; 00072 stxxl_nassert(zone == zones.end()); 00073 sectors -= from_this_zone; 00074 } 00075 } 00076 00077 return delay; 00078 #else 00079 STXXL_UNUSED(offset); 00080 return double(size) / double(AVERAGE_SPEED); 00081 #endif 00082 } 00083 00084 00085 IC35L080AVVA07::IC35L080AVVA07() 00086 { 00087 std::cout << "Creating IBM 120GXP IC35L080AVVA07" << 00088 std::endl; 00089 00090 nsurfaces = 4; 00091 bytes_per_sector = 512; 00092 cmd_ovh = 0.0002; // in s 00093 seek_time = 0.0082; // in s 00094 rot_latency = 0.00417; // in s 00095 head_switch_time = 0.0015; // in s 00096 cyl_switch_time = 0.002; // in s 00097 revolution_time = 0.0083; // in s 00098 interface_speed = 100000000; // in byte/s 00099 00100 int first_sect = 0; 00101 int last_cyl = 0; 00102 add_zone(last_cyl, 1938, 928, first_sect); 00103 add_zone(last_cyl, 3756, 921, first_sect); 00104 add_zone(last_cyl, 5564, 896, first_sect); 00105 add_zone(last_cyl, 7687, 896, first_sect); 00106 add_zone(last_cyl, 9526, 888, first_sect); 00107 add_zone(last_cyl, 11334, 883, first_sect); 00108 add_zone(last_cyl, 13331, 864, first_sect); 00109 add_zone(last_cyl, 15128, 850, first_sect); 00110 add_zone(last_cyl, 16925, 840, first_sect); 00111 add_zone(last_cyl, 18922, 822, first_sect); 00112 add_zone(last_cyl, 20709, 806, first_sect); 00113 add_zone(last_cyl, 22601, 792, first_sect); 00114 add_zone(last_cyl, 24138, 787, first_sect); 00115 add_zone(last_cyl, 26024, 768, first_sect); 00116 add_zone(last_cyl, 27652, 752, first_sect); 00117 add_zone(last_cyl, 29501, 740, first_sect); 00118 add_zone(last_cyl, 31234, 725, first_sect); 00119 add_zone(last_cyl, 33009, 698, first_sect); 00120 add_zone(last_cyl, 34784, 691, first_sect); 00121 add_zone(last_cyl, 36609, 672, first_sect); 00122 add_zone(last_cyl, 38374, 648, first_sect); 00123 add_zone(last_cyl, 40139, 630, first_sect); 00124 add_zone(last_cyl, 41904, 614, first_sect); 00125 add_zone(last_cyl, 43519, 595, first_sect); 00126 add_zone(last_cyl, 45250, 576, first_sect); 00127 add_zone(last_cyl, 47004, 552, first_sect); 00128 add_zone(last_cyl, 48758, 533, first_sect); 00129 add_zone(last_cyl, 50491, 512, first_sect); 00130 add_zone(last_cyl, 52256, 493, first_sect); 00131 add_zone(last_cyl, 54010, 471, first_sect); 00132 add_zone(last_cyl, 55571, 448, first_sect); 00133 00134 #if 0 00135 set<Zone, ZoneCmp>::iterator it = zones.begin(); 00136 int i = 0; 00137 for ( ; it != zones.end(); it++, i++) 00138 { 00139 //const int block_size = 128*3*1024* 4; // one cylinder 00140 00141 std::cout << "Zone " << i << " first sector: " << (*it).first_sector; 00142 std::cout << " sectors: " << (*it).sectors << " sustained rate: "; 00143 std::cout << (*it).sustained_data_rate / 1024 / 1024 << " MiB/s" << std::endl; 00144 } 00145 00146 std::cout << "Last sector : " << first_sect << std::endl; 00147 std::cout << "Approx. capacity: " << (first_sect / 1024 / 1024) * bytes_per_sector << " MiB" << std::endl; 00148 #endif 00149 00150 std::cout << "Transfer 16 MiB from zone 0 : " << 00151 get_delay(0, 16 * 1024 * 1024) << " s" << std::endl; 00152 std::cout << "Transfer 16 MiB from zone 30: " << 00153 get_delay(file::offset_type(158204036) * file::offset_type(bytes_per_sector), 16 * 1024 * 1024) << " s" << std::endl; 00154 } 00155 00156 //////////////////////////////////////////////////////////////////////////// 00157 00158 void sim_disk_file::serve(const request * req) throw (io_error) 00159 { 00160 scoped_mutex_lock fd_lock(fd_mutex); 00161 assert(req->get_file() == this); 00162 offset_type offset = req->get_offset(); 00163 void * buffer = req->get_buffer(); 00164 size_type bytes = req->get_size(); 00165 request::request_type type = req->get_type(); 00166 double op_start = timestamp(); 00167 00168 stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE); 00169 00170 void * mem = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, file_des, offset); 00171 if (mem == MAP_FAILED) 00172 { 00173 STXXL_THROW2(io_error, 00174 " Mapping failed." << 00175 " Page size: " << sysconf(_SC_PAGESIZE) << 00176 " offset modulo page size " << (offset % sysconf(_SC_PAGESIZE))); 00177 } 00178 else if (mem == 0) 00179 { 00180 stxxl_function_error(io_error); 00181 } 00182 else 00183 { 00184 if (type == request::READ) 00185 { 00186 memcpy(buffer, mem, bytes); 00187 } else { 00188 memcpy(mem, buffer, bytes); 00189 } 00190 stxxl_check_ge_0(munmap(mem, bytes), io_error); 00191 } 00192 00193 double delay = get_delay(offset, bytes); 00194 00195 delay = delay - timestamp() + op_start; 00196 00197 assert(delay > 0.0); 00198 00199 int seconds_to_wait = static_cast<int>(floor(delay)); 00200 if (seconds_to_wait) 00201 sleep(seconds_to_wait); 00202 00203 usleep((unsigned long)((delay - seconds_to_wait) * 1000000.)); 00204 } 00205 00206 const char * sim_disk_file::io_type() const 00207 { 00208 return "simdisk"; 00209 } 00210 00211 //////////////////////////////////////////////////////////////////////////// 00212 00213 void sim_disk_file::set_size(offset_type newsize) 00214 { 00215 scoped_mutex_lock fd_lock(fd_mutex); 00216 if (newsize > _size()) 00217 { 00218 stxxl_check_ge_0(::lseek(file_des, newsize - 1, SEEK_SET), io_error); 00219 stxxl_check_ge_0(::write(file_des, "", 1), io_error); 00220 } 00221 } 00222 00223 __STXXL_END_NAMESPACE 00224 00225 #endif // #if STXXL_HAVE_SIMDISK_FILE 00226 // vim: et:ts=4:sw=4