bitcoinleveldb_posix/env_posix.rs
1crate::ix!();
2
3//-------------------------------------------[.cpp/bitcoin/src/leveldb/util/env_posix.cc]
4
5/**
6 | Set by
7 |
8 | EnvPosixTestHelper::SetReadOnlyMMapLimit()
9 | and
10 |
11 | MaxOpenFiles().
12 |
13 */
14lazy_static!{
15 /*
16 int g_open_read_only_file_limit = -1;
17 */
18}
19
20/**
21 | Up to 4096 mmap regions for 64-bit binaries;
22 | none for 32-bit.
23 |
24 */
25pub const DEFAULT_MMAP_LIMIT: i32 = ternary!{size_of::<*mut c_void>() >= 8, 4096, 0};
26
27/**
28 | Can be set using
29 |
30 | EnvPosixTestHelper::SetReadOnlyMMapLimit().
31 |
32 */
33lazy_static!{
34 /*
35 int g_mmap_limit = kDefaultMmapLimit;
36 */
37}
38
39/**
40 | Common flags defined for all posix open
41 | operations
42 |
43 */
44#[cfg(HAVE_O_CLOEXEC)]
45pub const OPEN_BASE_FLAGS: i32 = O_CLOEXEC;
46
47#[cfg(not(HAVE_O_CLOEXEC))]
48pub const OPEN_BASE_FLAGS: i32 = 0;
49
50pub const WRITABLE_FILE_BUFFER_SIZE: usize = 65536;
51
52pub fn posix_error(
53 context: &String,
54 error_number: i32) -> crate::Status {
55
56 todo!();
57 /*
58 if (error_number == ENOENT) {
59 return crate::Status::NotFound(context, std::strerror(error_number));
60 } else {
61 return crate::Status::IOError(context, std::strerror(error_number));
62 }
63 */
64}
65
66/**
67 | Implements sequential read access in a file
68 | using read().
69 |
70 | Instances of this class are thread-friendly but
71 | not thread-safe, as required by the
72 | SequentialFile API.
73 */
74pub struct PosixSequentialFile {
75 fd: i32,
76 filename: String,
77}
78
79impl SequentialFile for PosixSequentialFile { }
80
81impl SequentialFileRead for PosixSequentialFile {
82
83 fn read(&mut self,
84 n: usize,
85 result: *mut Slice,
86 scratch: *mut u8) -> crate::Status {
87
88 todo!();
89 /*
90 crate::Status status;
91 while (true) {
92 ::ssize_t read_size = ::read(fd_, scratch, n);
93 if (read_size < 0) { // Read error.
94 if (errno == EINTR) {
95 continue; // Retry
96 }
97 status = PosixError(filename_, errno);
98 break;
99 }
100 *result = Slice(scratch, read_size);
101 break;
102 }
103 return status;
104 */
105 }
106}
107
108impl SequentialFileSkip for PosixSequentialFile {
109
110 fn skip(&mut self, n: u64) -> crate::Status {
111
112 todo!();
113 /*
114 if (::lseek(fd_, n, SEEK_CUR) == static_cast<off_t>(-1)) {
115 return PosixError(filename_, errno);
116 }
117 return crate::Status::OK();
118 */
119 }
120}
121
122impl GetName for PosixSequentialFile {
123
124 fn get_name(&self) -> &'static str {
125
126 todo!();
127 /*
128 return filename_;
129 */
130 }
131}
132
133impl Drop for PosixSequentialFile {
134 fn drop(&mut self) {
135 todo!();
136 /*
137 close(fd_);
138 */
139 }
140}
141
142impl PosixSequentialFile {
143
144 pub fn new(
145 filename: String,
146 fd: i32) -> Self {
147
148 todo!();
149 /*
150 : fd(fd),
151 : filename(filename),
152
153
154 */
155 }
156}
157
158/**
159 | Implements random read access in a file using
160 | pread().
161 |
162 | Instances of this class are thread-safe, as
163 | required by the RandomAccessFile API. Instances
164 | are immutable and Read() only calls thread-safe
165 | library functions.
166 */
167pub struct PosixRandomAccessFile {
168
169 /**
170 | If false, the file is opened on every
171 | read.
172 |
173 */
174 has_permanent_fd: bool,
175
176 /**
177 | -1 if has_permanent_fd_ is false.
178 |
179 */
180 fd: i32,
181
182 fd_limiter: *const Limiter,
183 filename: String,
184}
185
186impl RandomAccessFile for PosixRandomAccessFile { }
187
188impl Drop for PosixRandomAccessFile {
189 fn drop(&mut self) {
190 todo!();
191 /*
192 if (has_permanent_fd_) {
193 assert(fd_ != -1);
194 ::close(fd_);
195 fd_limiter_->Release();
196 }
197 */
198 }
199}
200
201impl RandomAccessFileRead for PosixRandomAccessFile {
202
203 fn read(&self,
204 offset: u64,
205 n: usize,
206 result: *mut Slice,
207 scratch: *mut u8) -> crate::Status {
208
209 todo!();
210 /*
211 int fd = fd_;
212 if (!has_permanent_fd_) {
213 fd = ::open(filename_.c_str(), O_RDONLY | kOpenBaseFlags);
214 if (fd < 0) {
215 return PosixError(filename_, errno);
216 }
217 }
218
219 assert(fd != -1);
220
221 crate::Status status;
222 ssize_t read_size = ::pread(fd, scratch, n, static_cast<off_t>(offset));
223 *result = Slice(scratch, (read_size < 0) ? 0 : read_size);
224 if (read_size < 0) {
225 // An error: return a non-ok status.
226 status = PosixError(filename_, errno);
227 }
228 if (!has_permanent_fd_) {
229 // Close the temporary file descriptor opened earlier.
230 assert(fd != fd_);
231 ::close(fd);
232 }
233 return status;
234 */
235 }
236}
237
238impl GetName for PosixRandomAccessFile {
239
240 fn get_name(&self) -> &'static str {
241
242 todo!();
243 /*
244 return filename_;
245 */
246 }
247}
248
249impl PosixRandomAccessFile {
250
251 /**
252 | The new instance takes ownership of
253 | fd|. |fd_limiter| must outlive this
254 | instance, and will be used to determine
255 | if .
256 |
257 */
258 pub fn new(
259 filename: String,
260 fd: i32,
261 fd_limiter: *mut Limiter) -> Self {
262
263 todo!();
264 /*
265
266
267 : has_permanent_fd_(fd_limiter->Acquire()),
268 fd_(has_permanent_fd_ ? fd : -1),
269 fd_limiter_(fd_limiter),
270 filename_(std::move(filename))
271 if (!has_permanent_fd_) {
272 assert(fd_ == -1);
273 ::close(fd); // The file will be opened on every read.
274 }
275 */
276 }
277}
278
279/**
280 | Implements random read access in a file using
281 | mmap().
282 |
283 | Instances of this class are thread-safe, as
284 | required by the RandomAccessFile API. Instances
285 | are immutable and Read() only calls thread-safe
286 | library functions.
287 */
288pub struct PosixMmapReadableFile {
289 mmap_base: *const u8,
290 length: usize,
291 mmap_limiter: *const Limiter,
292 filename: String,
293}
294
295impl Drop for PosixMmapReadableFile {
296 fn drop(&mut self) {
297 todo!();
298 /*
299 ::munmap(static_cast<c_void*>(mmap_base_), length_);
300 mmap_limiter_->Release();
301 */
302 }
303}
304
305impl RandomAccessFile for PosixMmapReadableFile { }
306
307impl RandomAccessFileRead for PosixMmapReadableFile {
308
309 fn read(&self,
310 offset: u64,
311 n: usize,
312 result: *mut Slice,
313 scratch: *mut u8) -> crate::Status {
314
315 todo!();
316 /*
317 if (offset + n > length_) {
318 *result = Slice();
319 return PosixError(filename_, EINVAL);
320 }
321
322 *result = Slice(mmap_base_ + offset, n);
323 return crate::Status::OK();
324 */
325 }
326}
327
328impl GetName for PosixMmapReadableFile {
329
330 fn get_name(&self) -> &'static str {
331
332 todo!();
333 /*
334 return filename_;
335 */
336 }
337}
338
339impl PosixMmapReadableFile {
340
341 /**
342 | mmap_base[0, length-1] points to the
343 | memory-mapped contents of the file. It must
344 | be the result of a successful call to
345 | mmap(). This instances takes over the
346 | ownership of the region.
347 |
348 | |mmap_limiter| must outlive this
349 | instance. The caller must have already
350 | aquired the right to use one mmap region,
351 | which will be released when this instance is
352 | destroyed.
353 */
354 pub fn new(
355 filename: String,
356 mmap_base: *mut u8,
357 length: usize,
358 mmap_limiter: *mut Limiter) -> Self {
359
360 todo!();
361 /*
362 : mmap_base_(mmap_base),
363 length_(length),
364 mmap_limiter_(mmap_limiter),
365 filename_(std::move(filename))
366 */
367 }
368}
369
370///-------------------------
371pub struct PosixWritableFile {
372
373 /**
374 | buf_[0, pos_ - 1] contains data to be
375 | written to fd_.
376 |
377 */
378 buf: [u8; WRITABLE_FILE_BUFFER_SIZE],
379
380 pos: usize,
381 fd: i32,
382
383 /**
384 | True if the file's name starts with
385 | MANIFEST.
386 |
387 */
388 is_manifest: bool,
389
390 filename: String,
391
392 /**
393 | The directory of filename_.
394 |
395 */
396 dirname: String,
397}
398
399impl WritableFile for PosixWritableFile {}
400
401impl WritableFileAppend for PosixWritableFile {
402
403 fn append(&mut self, data: &Slice) -> crate::Status {
404
405 todo!();
406 /*
407 size_t write_size = data.size();
408 const char* write_data = data.data();
409
410 // Fit as much as possible into buffer.
411 size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
412 std::memcpy(buf_ + pos_, write_data, copy_size);
413 write_data += copy_size;
414 write_size -= copy_size;
415 pos_ += copy_size;
416 if (write_size == 0) {
417 return crate::Status::OK();
418 }
419
420 // Can't fit in buffer, so need to do at least one write.
421 crate::Status status = FlushBuffer();
422 if (!status.ok()) {
423 return status;
424 }
425
426 // Small writes go to buffer, large writes are written directly.
427 if (write_size < kWritableFileBufferSize) {
428 std::memcpy(buf_, write_data, write_size);
429 pos_ = write_size;
430 return crate::Status::OK();
431 }
432 return WriteUnbuffered(write_data, write_size);
433 */
434 }
435}
436
437impl WritableFileClose for PosixWritableFile {
438
439 fn close(&mut self) -> crate::Status {
440
441 todo!();
442 /*
443 crate::Status status = FlushBuffer();
444 const int close_result = ::close(fd_);
445 if (close_result < 0 && status.ok()) {
446 status = PosixError(filename_, errno);
447 }
448 fd_ = -1;
449 return status;
450 */
451 }
452}
453
454impl WritableFileFlush for PosixWritableFile {
455
456 fn flush(&mut self) -> crate::Status {
457
458 todo!();
459 /*
460 return FlushBuffer();
461 */
462 }
463}
464
465impl Drop for PosixWritableFile {
466 fn drop(&mut self) {
467 todo!();
468 /*
469 if (fd_ >= 0) {
470 // Ignoring any potential errors
471 Close();
472 }
473 */
474 }
475}
476
477impl WritableFileSync for PosixWritableFile {
478
479 fn sync(&mut self) -> crate::Status {
480
481 todo!();
482 /*
483 // Ensure new files referred to by the manifest are in the filesystem.
484 //
485 // This needs to happen before the manifest file is flushed to disk, to
486 // avoid crashing in a state where the manifest refers to files that are not
487 // yet on disk.
488 crate::Status status = SyncDirIfManifest();
489 if (!status.ok()) {
490 return status;
491 }
492
493 status = FlushBuffer();
494 if (!status.ok()) {
495 return status;
496 }
497
498 return SyncFd(fd_, filename_, false);
499 */
500 }
501}
502
503impl GetName for PosixWritableFile {
504
505 fn get_name(&self) -> &'static str {
506
507 todo!();
508 /*
509 return filename_;
510 */
511 }
512}
513
514impl PosixWritableFile {
515 pub fn flush_buffer(&mut self) -> crate::Status {
516
517 todo!();
518 /*
519 crate::Status status = WriteUnbuffered(buf_, pos_);
520 pos_ = 0;
521 return status;
522 */
523 }
524
525 pub fn write_unbuffered(&mut self,
526 data: *const u8,
527 size: usize) -> crate::Status {
528
529 todo!();
530 /*
531 while (size > 0) {
532 ssize_t write_result = ::write(fd_, data, size);
533 if (write_result < 0) {
534 if (errno == EINTR) {
535 continue; // Retry
536 }
537 return PosixError(filename_, errno);
538 }
539 data += write_result;
540 size -= write_result;
541 }
542 return crate::Status::OK();
543 */
544 }
545
546 pub fn sync_dir_if_manifest(&mut self) -> crate::Status {
547
548 todo!();
549 /*
550 crate::Status status;
551 if (!is_manifest_) {
552 return status;
553 }
554
555 int fd = ::open(dirname_.c_str(), O_RDONLY | kOpenBaseFlags);
556 if (fd < 0) {
557 status = PosixError(dirname_, errno);
558 } else {
559 status = SyncFd(fd, dirname_, true);
560 ::close(fd);
561 }
562 return status;
563 */
564 }
565
566 /**
567 | Ensures that all the caches associated with
568 | the given file descriptor's data are flushed
569 | all the way to durable media, and can
570 | withstand power failures.
571 |
572 | The path argument is only used to populate
573 | the description string in the returned crate::Status
574 | if an error occurs.
575 */
576 pub fn sync_fd(
577 fd: i32,
578 fd_path: &String,
579 syncing_dir: bool) -> crate::Status {
580
581 todo!();
582 /*
583 #if HAVE_FULLFSYNC
584 // On macOS and iOS, fsync() doesn't guarantee durability past power
585 // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some
586 // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to
587 // fsync().
588 if (::fcntl(fd, F_FULLFSYNC) == 0) {
589 return crate::Status::OK();
590 }
591 #endif // HAVE_FULLFSYNC
592
593 #if HAVE_FDATASYNC
594 bool sync_success = ::fdatasync(fd) == 0;
595 #else
596 bool sync_success = ::fsync(fd) == 0;
597 #endif // HAVE_FDATASYNC
598
599 if (sync_success) {
600 return crate::Status::OK();
601 }
602 // Do not crash if filesystem can't fsync directories
603 // (see https://github.com/bitcoin/bitcoin/pull/10000)
604 if (syncing_dir && errno == EINVAL) {
605 return crate::Status::OK();
606 }
607 return PosixError(fd_path, errno);
608 */
609 }
610
611 /**
612 | Returns the directory name in a path pointing
613 | to a file.
614 |
615 | Returns "." if the path does not contain any
616 | directory separator.
617 */
618 pub fn dirname(filename: &String) -> String {
619
620 todo!();
621 /*
622 std::string::size_type separator_pos = filename.rfind('/');
623 if (separator_pos == std::string::npos) {
624 return std::string(".");
625 }
626 // The filename component should not contain a path separator. If it does,
627 // the splitting was done incorrectly.
628 assert(filename.find('/', separator_pos + 1) == std::string::npos);
629
630 return filename.substr(0, separator_pos);
631 */
632 }
633
634 /**
635 | Extracts the file name from a path pointing
636 | to a file.
637 |
638 | The returned Slice points to |filename|'s
639 | data buffer, so it is only valid while
640 | |filename| is alive and unchanged.
641 */
642 pub fn basename(filename: &String) -> Slice {
643
644 todo!();
645 /*
646 std::string::size_type separator_pos = filename.rfind('/');
647 if (separator_pos == std::string::npos) {
648 return Slice(filename);
649 }
650 // The filename component should not contain a path separator. If it does,
651 // the splitting was done incorrectly.
652 assert(filename.find('/', separator_pos + 1) == std::string::npos);
653
654 return Slice(filename.data() + separator_pos + 1,
655 filename.length() - separator_pos - 1);
656 */
657 }
658
659 /**
660 | True if the given file is a manifest file.
661 |
662 */
663 pub fn is_manifest(filename: &String) -> bool {
664
665 todo!();
666 /*
667 return Basename(filename).starts_with("MANIFEST");
668 */
669 }
670
671 pub fn new(
672 filename: String,
673 fd: i32) -> Self {
674
675 todo!();
676 /*
677 : pos(0),
678 : fd(fd),
679 : is_manifest(IsManifest(filename)),
680 : filename(std::move(filename)),
681 : dirname(Dirname(filename_)),
682 */
683 }
684}
685
686pub fn lock_or_unlock(
687 fd: i32,
688 lock: bool) -> i32 {
689
690 todo!();
691 /*
692 errno = 0;
693 struct ::flock file_lock_info;
694 std::memset(&file_lock_info, 0, sizeof(file_lock_info));
695 file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK);
696 file_lock_info.l_whence = SEEK_SET;
697 file_lock_info.l_start = 0;
698 file_lock_info.l_len = 0; // Lock/unlock entire file.
699 return ::fcntl(fd, F_SETLK, &file_lock_info);
700 */
701}
702
703/**
704 | Instances are thread-safe because
705 | they are immutable.
706 |
707 */
708pub struct PosixFileLock {
709 fd: i32,
710 filename: String,
711}
712
713impl FileLock for PosixFileLock {
714
715}
716
717impl PosixFileLock {
718
719 pub fn new(
720 fd: i32,
721 filename: String) -> Self {
722
723 todo!();
724 /*
725 : fd(fd),
726 : filename(std::move(filename)),
727 */
728 }
729
730 pub fn fd(&self) -> i32 {
731
732 todo!();
733 /*
734 return fd_;
735 */
736 }
737
738 pub fn filename(&self) -> &String {
739
740 todo!();
741 /*
742 return filename_;
743 */
744 }
745}
746
747/**
748 | Tracks the files locked by
749 | PosixEnv::LockFile().
750 |
751 | We maintain a separate set instead of relying
752 | on fcntl(F_SETLK) because fcntl(F_SETLK) does
753 | not provide any protection against multiple
754 | uses from the same process.
755 |
756 | Instances are thread-safe because all member
757 | data is guarded by a mutex.
758 */
759pub struct PosixLockTable {
760 mu: Mutex<posix_lock_table::Inner>,
761}
762
763pub mod posix_lock_table {
764 use super::*;
765
766 pub struct Inner {
767 locked_files: HashSet<String>,
768 }
769}
770
771impl PosixLockTable {
772
773 #[LOCKS_EXCLUDED(mu_)]
774 pub fn insert(&mut self, fname: &String) -> bool {
775
776 todo!();
777 /*
778 mu_.Lock();
779 bool succeeded = locked_files_.insert(fname).second;
780 mu_.Unlock();
781 return succeeded;
782 */
783 }
784
785 #[LOCKS_EXCLUDED(mu_)]
786 pub fn remove(&mut self, fname: &String) {
787
788 todo!();
789 /*
790 mu_.Lock();
791 locked_files_.erase(fname);
792 mu_.Unlock();
793 */
794 }
795}
796
797///--------------------
798pub struct PosixEnv {
799
800 background_work_mutex: Mutex<posix_env::BackgroundWork>,
801
802 /**
803 | Thread-safe.
804 |
805 */
806 locks: PosixLockTable,
807
808 /**
809 | Thread-safe.
810 |
811 */
812 mmap_limiter: Limiter,
813
814 /**
815 | Thread-safe.
816 |
817 */
818 fd_limiter: Limiter,
819}
820
821impl Env for PosixEnv {
822
823}
824
825impl DeleteFile for PosixEnv {
826
827 fn delete_file(&mut self, filename: &String) -> crate::Status {
828
829 todo!();
830 /*
831 if (::unlink(filename.c_str()) != 0) {
832 return PosixError(filename, errno);
833 }
834 return crate::Status::OK();
835 */
836 }
837}
838
839impl CreateDir for PosixEnv {
840
841 fn create_dir(&mut self, dirname: &String) -> crate::Status {
842
843 todo!();
844 /*
845 if (::mkdir(dirname.c_str(), 0755) != 0) {
846 return PosixError(dirname, errno);
847 }
848 return crate::Status::OK();
849 */
850 }
851}
852
853impl DeleteDir for PosixEnv {
854
855 fn delete_dir(&mut self, dirname: &String) -> crate::Status {
856
857 todo!();
858 /*
859 if (::rmdir(dirname.c_str()) != 0) {
860 return PosixError(dirname, errno);
861 }
862 return crate::Status::OK();
863 */
864 }
865}
866
867impl GetFileSize for PosixEnv {
868
869 fn get_file_size(&mut self,
870 filename: &String,
871 size: *mut u64) -> crate::Status {
872
873 todo!();
874 /*
875 struct ::stat file_stat;
876 if (::stat(filename.c_str(), &file_stat) != 0) {
877 *size = 0;
878 return PosixError(filename, errno);
879 }
880 *size = file_stat.st_size;
881 return crate::Status::OK();
882 */
883 }
884}
885
886impl RenameFile for PosixEnv {
887 fn rename_file(&mut self,
888 from: &String,
889 to: &String) -> crate::Status {
890
891 todo!();
892 /*
893 if (std::rename(from.c_str(), to.c_str()) != 0) {
894 return PosixError(from, errno);
895 }
896 return crate::Status::OK();
897 */
898 }
899}
900
901impl LockFile for PosixEnv {
902
903 fn lock_file(&mut self,
904 filename: &String,
905 lock: *mut *mut Box<dyn FileLock>) -> crate::Status {
906
907 todo!();
908 /*
909 *lock = nullptr;
910
911 int fd = ::open(filename.c_str(), O_RDWR | O_CREAT | kOpenBaseFlags, 0644);
912 if (fd < 0) {
913 return PosixError(filename, errno);
914 }
915
916 if (!locks_.Insert(filename)) {
917 ::close(fd);
918 return crate::Status::IOError("lock " + filename, "already held by process");
919 }
920
921 if (LockOrUnlock(fd, true) == -1) {
922 int lock_errno = errno;
923 ::close(fd);
924 locks_.Remove(filename);
925 return PosixError("lock " + filename, lock_errno);
926 }
927
928 *lock = new PosixFileLock(fd, filename);
929 return crate::Status::OK();
930 */
931 }
932}
933
934impl StartThread for PosixEnv {
935
936 fn start_thread(&mut self,
937 thread_main: fn(thread_main_arg: *mut c_void) -> c_void,
938 thread_main_arg: *mut c_void) {
939
940 todo!();
941 /*
942 std::thread new_thread(thread_main, thread_main_arg);
943 new_thread.detach();
944 */
945 }
946}
947
948impl GetTestDirectory for PosixEnv {
949
950 fn get_test_directory(&mut self, result: *mut String) -> crate::Status {
951
952 todo!();
953 /*
954 const char* env = std::getenv("TEST_TMPDIR");
955 if (env && env[0] != '\0') {
956 *result = env;
957 } else {
958 char buf[100];
959 std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d",
960 static_cast<int>(::geteuid()));
961 *result = buf;
962 }
963
964 // The CreateDir status is ignored because the directory may already exist.
965 CreateDir(*result);
966
967 return crate::Status::OK();
968 */
969 }
970}
971
972impl NewLogger for PosixEnv {
973
974 fn new_logger(&mut self,
975 filename: &String,
976 result: *mut *mut Box<dyn Logger>) -> crate::Status {
977
978 todo!();
979 /*
980 int fd = ::open(filename.c_str(),
981 O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
982 if (fd < 0) {
983 *result = nullptr;
984 return PosixError(filename, errno);
985 }
986
987 std::FILE* fp = ::fdopen(fd, "w");
988 if (fp == nullptr) {
989 ::close(fd);
990 *result = nullptr;
991 return PosixError(filename, errno);
992 } else {
993 *result = new PosixLogger(fp);
994 return crate::Status::OK();
995 }
996 */
997 }
998}
999
1000impl NowMicros for PosixEnv {
1001
1002 fn now_micros(&mut self) -> u64 {
1003
1004 todo!();
1005 /*
1006 static constexpr uint64_t kUsecondsPerSecond = 1000000;
1007 struct ::timeval tv;
1008 ::gettimeofday(&tv, nullptr);
1009 return static_cast<uint64_t>(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec;
1010 */
1011 }
1012}
1013
1014impl SleepForMicroseconds for PosixEnv {
1015
1016 fn sleep_for_microseconds(&mut self, micros: i32) {
1017
1018 todo!();
1019 /*
1020 std::this_thread::sleep_for(std::chrono::microseconds(micros));
1021 */
1022 }
1023}
1024
1025impl UnlockFile for PosixEnv {
1026
1027 fn unlock_file(&mut self, lock: *mut Box<dyn FileLock>) -> crate::Status {
1028
1029 todo!();
1030 /*
1031 PosixFileLock* posix_file_lock = static_cast<PosixFileLock*>(lock);
1032 if (LockOrUnlock(posix_file_lock->fd(), false) == -1) {
1033 return PosixError("unlock " + posix_file_lock->filename(), errno);
1034 }
1035 locks_.Remove(posix_file_lock->filename());
1036 ::close(posix_file_lock->fd());
1037 delete posix_file_lock;
1038 return crate::Status::OK();
1039 */
1040 }
1041}
1042
1043impl GetChildren for PosixEnv {
1044
1045 fn get_children(&mut self,
1046 directory_path: &String,
1047 result: *mut Vec<String>) -> crate::Status {
1048
1049 todo!();
1050 /*
1051 result->clear();
1052 ::DIR* dir = ::opendir(directory_path.c_str());
1053 if (dir == nullptr) {
1054 return PosixError(directory_path, errno);
1055 }
1056 struct ::dirent* entry;
1057 while ((entry = ::readdir(dir)) != nullptr) {
1058 result->emplace_back(entry->d_name);
1059 }
1060 ::closedir(dir);
1061 return crate::Status::OK();
1062 */
1063 }
1064}
1065
1066impl FileExists for PosixEnv {
1067
1068 fn file_exists(&mut self, filename: &String) -> bool {
1069
1070 todo!();
1071 /*
1072 return ::access(filename.c_str(), F_OK) == 0;
1073 */
1074 }
1075}
1076
1077impl NewAppendableFile for PosixEnv {
1078
1079 fn new_appendable_file(&mut self,
1080 filename: &String,
1081 result: *mut *mut Box<dyn WritableFile>) -> crate::Status {
1082
1083 todo!();
1084 /*
1085 int fd = ::open(filename.c_str(),
1086 O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
1087 if (fd < 0) {
1088 *result = nullptr;
1089 return PosixError(filename, errno);
1090 }
1091
1092 *result = new PosixWritableFile(filename, fd);
1093 return crate::Status::OK();
1094 */
1095 }
1096}
1097
1098impl NewWritableFile for PosixEnv {
1099
1100 fn new_writable_file(&mut self,
1101 filename: &String,
1102 result: *mut *mut Box<dyn WritableFile>) -> crate::Status {
1103
1104 todo!();
1105 /*
1106 int fd = ::open(filename.c_str(),
1107 O_TRUNC | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
1108 if (fd < 0) {
1109 *result = nullptr;
1110 return PosixError(filename, errno);
1111 }
1112
1113 *result = new PosixWritableFile(filename, fd);
1114 return crate::Status::OK();
1115 */
1116 }
1117}
1118
1119impl NewRandomAccessFile for PosixEnv {
1120
1121 fn new_random_access_file(&mut self,
1122 filename: &String,
1123 result: *mut *mut Box<dyn RandomAccessFile>) -> crate::Status {
1124
1125 todo!();
1126 /*
1127 *result = nullptr;
1128 int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
1129 if (fd < 0) {
1130 return PosixError(filename, errno);
1131 }
1132
1133 if (!mmap_limiter_.Acquire()) {
1134 *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_);
1135 return crate::Status::OK();
1136 }
1137
1138 uint64_t file_size;
1139 crate::Status status = GetFileSize(filename, &file_size);
1140 if (status.ok()) {
1141 c_void* mmap_base =
1142 ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
1143 if (mmap_base != MAP_FAILED) {
1144 *result = new PosixMmapReadableFile(filename,
1145 reinterpret_cast<char*>(mmap_base),
1146 file_size, &mmap_limiter_);
1147 } else {
1148 status = PosixError(filename, errno);
1149 }
1150 }
1151 ::close(fd);
1152 if (!status.ok()) {
1153 mmap_limiter_.Release();
1154 }
1155 return status;
1156 */
1157 }
1158}
1159
1160impl NewSequentialFile for PosixEnv {
1161
1162 fn new_sequential_file(&mut self,
1163 filename: &String,
1164 result: *mut *mut Box<dyn SequentialFile>) -> crate::Status {
1165
1166 todo!();
1167 /*
1168 int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
1169 if (fd < 0) {
1170 *result = nullptr;
1171 return PosixError(filename, errno);
1172 }
1173
1174 *result = new PosixSequentialFile(filename, fd);
1175 return crate::Status::OK();
1176 */
1177 }
1178}
1179
1180pub mod posix_env {
1181
1182 use super::*;
1183
1184 pub struct BackgroundWork {
1185 background_work_cv: Condvar,
1186 started_background_thread: bool,
1187 background_work_queue: SegQueue<BackgroundWorkItem>,
1188 }
1189
1190 /**
1191 | Stores the work item data in a Schedule()
1192 | call.
1193 |
1194 | Instances are constructed on the thread
1195 | calling Schedule() and used on the background
1196 | thread.
1197 |
1198 | This structure is thread-safe beacuse it is
1199 | immutable.
1200 */
1201 pub struct BackgroundWorkItem {
1202 function: fn(_0: *mut c_void) -> c_void,
1203 arg: *const c_void,
1204 }
1205
1206 impl BackgroundWorkItem {
1207
1208 pub fn new(
1209 function: fn(arg: *mut c_void) -> c_void,
1210 arg: *mut c_void) -> Self {
1211
1212 todo!();
1213 /*
1214 : function(function),
1215 : arg(arg),
1216
1217
1218 */
1219 }
1220 }
1221}
1222
1223impl Drop for PosixEnv {
1224 fn drop(&mut self) {
1225 todo!();
1226 /*
1227 static const char msg[] =
1228 "PosixEnv singleton destroyed. Unsupported behavior!\n";
1229 std::fwrite(msg, 1, sizeof(msg), stderr);
1230 std::abort();
1231 */
1232 }
1233}
1234
1235impl PosixEnv {
1236
1237 pub fn background_thread_entry_point(env: *mut PosixEnv) {
1238
1239 todo!();
1240 /*
1241 env->BackgroundThreadMain();
1242 */
1243 }
1244}
1245
1246/**
1247 | Return the maximum number of concurrent
1248 | mmaps.
1249 |
1250 */
1251pub fn max_mmaps() -> i32 {
1252
1253 todo!();
1254 /*
1255 return g_mmap_limit;
1256 */
1257}
1258
1259/**
1260 | Return the maximum number of read-only
1261 | files to keep open.
1262 |
1263 */
1264pub fn max_open_files() -> i32 {
1265
1266 todo!();
1267 /*
1268 if (g_open_read_only_file_limit >= 0) {
1269 return g_open_read_only_file_limit;
1270 }
1271 struct ::rlimit rlim;
1272 if (::getrlimit(RLIMIT_NOFILE, &rlim)) {
1273 // getrlimit failed, fallback to hard-coded default.
1274 g_open_read_only_file_limit = 50;
1275 } else if (rlim.rlim_cur == RLIM_INFINITY) {
1276 g_open_read_only_file_limit = std::numeric_limits<int>::max();
1277 } else {
1278 // Allow use of 20% of available file descriptors for read-only files.
1279 g_open_read_only_file_limit = rlim.rlim_cur / 5;
1280 }
1281 return g_open_read_only_file_limit;
1282 */
1283}
1284
1285impl Schedule for PosixEnv {
1286
1287 fn schedule(&mut self,
1288 background_work_function: fn(background_work_arg: *mut c_void) -> c_void,
1289 background_work_arg: *mut c_void) {
1290
1291 todo!();
1292 /*
1293 background_work_mutex_.Lock();
1294
1295 // Start the background thread, if we haven't done so already.
1296 if (!started_background_thread_) {
1297 started_background_thread_ = true;
1298 std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this);
1299 background_thread.detach();
1300 }
1301
1302 // If the queue is empty, the background thread may be waiting for work.
1303 if (background_work_queue_.empty()) {
1304 background_work_cv_.Signal();
1305 }
1306
1307 background_work_queue_.emplace(background_work_function, background_work_arg);
1308 background_work_mutex_.Unlock();
1309 */
1310 }
1311}
1312
1313impl Default for PosixEnv {
1314
1315 fn default() -> Self {
1316
1317 todo!();
1318 /*
1319 : background_work_cv(&background_work_mutex_),
1320 : started_background_thread(false),
1321 : mmap_limiter(MaxMmaps()),
1322 : fd_limiter(MaxOpenFiles()),
1323
1324
1325 */
1326 }
1327}
1328
1329impl PosixEnv {
1330 pub fn background_thread_main(&mut self) {
1331
1332 todo!();
1333 /*
1334 while (true) {
1335 background_work_mutex_.Lock();
1336
1337 // Wait until there is work to be done.
1338 while (background_work_queue_.empty()) {
1339 background_work_cv_.Wait();
1340 }
1341
1342 assert(!background_work_queue_.empty());
1343 auto background_work_function = background_work_queue_.front().function;
1344 c_void* background_work_arg = background_work_queue_.front().arg;
1345 background_work_queue_.pop();
1346
1347 background_work_mutex_.Unlock();
1348 background_work_function(background_work_arg);
1349 }
1350 */
1351 }
1352}
1353
1354/**
1355 | Wraps an Env instance whose destructor
1356 | is never created.
1357 |
1358 | Intended usage:
1359 |
1360 | -----------
1361 | @code
1362 |
1363 | using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
1364 | c_void ConfigurePosixEnv(int param) {
1365 | PlatformSingletonEnv::AssertEnvNotInitialized();
1366 | // set global configuration flags.
1367 | }
1368 | Env* Env::Default() {
1369 | static PlatformSingletonEnv default_env;
1370 | return default_env.env();
1371 | }
1372 |
1373 */
1374pub struct SingletonEnv<EnvType> {
1375 __remove_me__: std::marker::PhantomData<EnvType>,
1376
1377 /*
1378 lazy_static!{
1379 /*
1380 typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
1381 env_storage_;
1382 */
1383 }
1384*/
1385}
1386
1387pub mod singleton_env {
1388
1389 use super::*;
1390
1391 #[cfg(not(NDEBUG))]
1392 lazy_static!{
1393 /*
1394 static std::atomic<bool> env_initialized_;
1395 */
1396 }
1397}
1398
1399impl<EnvType> Default for SingletonEnv<EnvType> {
1400
1401 fn default() -> Self {
1402 todo!();
1403 /*
1404
1405
1406 #if !defined(NDEBUG)
1407 env_initialized_.store(true, std::memory_order::memory_order_relaxed);
1408 #endif // !defined(NDEBUG)
1409 const_assert(sizeof(env_storage_) >= sizeof(EnvType),
1410 "env_storage_ will not fit the Env");
1411 const_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
1412 "env_storage_ does not meet the Env's alignment needs");
1413 new (&env_storage_) EnvType();
1414 */
1415 }
1416}
1417
1418impl<EnvType> SingletonEnv<EnvType> {
1419
1420 pub fn env(&mut self) -> Rc<RefCell<dyn Env>> {
1421
1422 todo!();
1423 /*
1424 return reinterpret_cast<Env*>(&env_storage_);
1425 */
1426 }
1427
1428 pub fn assert_env_not_initialized() {
1429
1430 todo!();
1431 /*
1432 #if !defined(NDEBUG)
1433 assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
1434 #endif // !defined(NDEBUG)
1435 */
1436 }
1437}
1438
1439#[cfg(not(NDEBUG))]
1440lazy_static!{
1441 /*
1442 template <typename EnvType>
1443 std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
1444 */
1445}
1446
1447pub type PosixDefaultEnv = SingletonEnv<PosixEnv>;