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>;