github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/dokan/pointertable.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package dokan
     6  
     7  import (
     8  	"sync"
     9  )
    10  
    11  /* Keep Go pointers while passing integers to the C heap.
    12   *
    13   * These tables should only be used through the functions
    14   * defined in this file.
    15   */
    16  
    17  var fsTableLock sync.Mutex
    18  var fsTable = make([]fsTableEntry, 0, 2)
    19  var fiTableLock sync.Mutex      // nolint
    20  var fiTable = map[uint32]File{} // nolint
    21  var fiIdx uint32                // nolint
    22  
    23  type fsTableEntry struct {
    24  	fs        FileSystem
    25  	errChan   chan error
    26  	fileCount uint32
    27  }
    28  
    29  func fsTableStore(fs FileSystem, ec chan error) uint32 {
    30  	fsTableLock.Lock()
    31  	defer fsTableLock.Unlock()
    32  
    33  	for i, c := range fsTable {
    34  		if c.fs == nil {
    35  			fsTable[i] = fsTableEntry{fs: fs, errChan: ec}
    36  			return uint32(i)
    37  		}
    38  	}
    39  
    40  	fsTable = append(fsTable, fsTableEntry{fs: fs, errChan: ec})
    41  	return uint32(len(fsTable) - 1)
    42  }
    43  
    44  func fsTableFree(slot uint32) { // nolint
    45  	fsTableLock.Lock()
    46  	defer fsTableLock.Unlock()
    47  	if int(slot) < len(fsTable) {
    48  		fsTable[slot] = fsTableEntry{}
    49  	}
    50  }
    51  
    52  func fsTableGet(slot uint32) FileSystem { // nolint
    53  	fsTableLock.Lock()
    54  	defer fsTableLock.Unlock()
    55  	return fsTable[slot].fs
    56  }
    57  
    58  func fsTableGetErrChan(slot uint32) chan error { // nolint
    59  	fsTableLock.Lock()
    60  	defer fsTableLock.Unlock()
    61  	return fsTable[slot].errChan
    62  }
    63  
    64  func fsTableGetFileCount(slot uint32) uint32 {
    65  	fsTableLock.Lock()
    66  	defer fsTableLock.Unlock()
    67  	return fsTable[slot].fileCount
    68  }
    69  
    70  func fiTableStoreFile(global uint32, fi File) uint32 { // nolint
    71  	fsTableLock.Lock()
    72  	fsTable[global].fileCount++
    73  	fsTableLock.Unlock()
    74  	fiTableLock.Lock()
    75  	defer fiTableLock.Unlock()
    76  	for {
    77  		// Just use a simple counter (inside the lock)
    78  		// to look for potential free file handles.
    79  		// Overflowing the counter is ok, but skip
    80  		// counter value zero (for better error detection).
    81  		fiIdx++
    82  		if fiIdx == 0 {
    83  			fiIdx++
    84  		}
    85  		_, exist := fiTable[fiIdx]
    86  		if !exist {
    87  			debug("FID alloc", fiIdx, fi)
    88  			fiTable[fiIdx] = fi
    89  			return fiIdx
    90  		}
    91  	}
    92  }
    93  
    94  func fiTableGetFile(file uint32) File { // nolint
    95  	fiTableLock.Lock()
    96  	var fi = fiTable[file]
    97  	fiTableLock.Unlock()
    98  	debug("FID get", file, fi)
    99  	return fi
   100  }
   101  
   102  func fiTableFreeFile(global uint32, file uint32) { // nolint
   103  	fsTableLock.Lock()
   104  	fsTable[global].fileCount--
   105  	fsTableLock.Unlock()
   106  	fiTableLock.Lock()
   107  	defer fiTableLock.Unlock()
   108  	debug("FID free", global, file, "=>", fiTable[file], "# of open files:", len(fiTable)-1)
   109  	delete(fiTable, file)
   110  }