2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * Synopsis: Implements virtual file protocol operations 2N/A * This module implements the "Virtual File protocol" operations. These 2N/A * operations are intended to provide very fast access to file data, 2N/A * allowing a file to be accessed in very efficient ways with extremely 2N/A * low-cpu intensive operations. If possible file data is mapped directly 2N/A * into memory allowing the data to be accessed directly. If the data 2N/A * cannot be mapped directly into memory, memory will be allocated and 2N/A * the file data read directly into memory. If that fails currently the 2N/A * file data is not accessible. Other methods of making the file could 2N/A * be implemented in the future (e.g. stdio if all else fails). 2N/A * In general any code that uses stdio to access a file can be changed 2N/A * to use the various "vfp" operations to access a file, with a resulting 2N/A * increase in performance and decrease in cpu time required to access 2N/A * the file contents. 2N/A * vfpCheckpointFile - Create new VFP that checkpoints existing VFP 2N/A * vfpCheckpointOpen - open file, allocate storage, return pointer to VFP_T 2N/A * vfpClose - close file associated with vfp 2N/A * vfpDecCurrPtr - decrement current character pointer 2N/A * vfpGetBytesRemaining - get number of bytes remaining to read 2N/A * vfpGetCurrCharPtr - get pointer to current character 2N/A * vfpGetCurrPtrDelta - get number of bytes between current and specified char 2N/A * vfpGetFirstCharPtr - get pointer to first character 2N/A * vfpGetLastCharPtr - get pointer to last character 2N/A * vfpGetModifiedLen - get highest modified byte (length) contained in vfp 2N/A * vfpGetPath - get the path associated with the vfp 2N/A * vfpGetc - get current character and increment to next 2N/A * vfpGetcNoInc - get current character - do not increment 2N/A * vfpGets - get a string from the vfp into a fixed size buffer 2N/A * vfpIncCurrPtr - increment current character pointer 2N/A * vfpIncCurrPtrBy - increment current pointer by specified delta 2N/A * vfpOpen - open file on vfp 2N/A * vfpPutBytes - put fixed number of bytes to current character and increment 2N/A * vfpPutFormat - put format one arg to current character and increment 2N/A * vfpPutInteger - put integer to current character and increment 2N/A * vfpPutLong - put long to current character and increment 2N/A * vfpPutc - put current character and increment to next 2N/A * vfpPuts - put string to current character and increment 2N/A * vfpRewind - rewind file to first byte 2N/A * vfpSeekToEnd - seek to end of file 2N/A * vfpSetCurrCharPtr - set pointer to current character 2N/A * vfpSetFlags - set flags that affect file access 2N/A * vfpSetSize - set size of file (for writing) 2N/A * vfpTruncate - truncate file 2N/A * vfpWriteToFile - write data contained in vfp to specified file 2N/A * These are internal flags that occupy the high order byte of the VFPFLAGS_T 2N/A * flags element of the vfp. These flags may only occupy the high order order 2N/A * 16 bits of the 32-bit unsigned vfp "flags" object. 2N/A/* path name given to "anonymous" (string) vfp */ 2N/A/* minimum size file to mmap (64mb) */ 2N/A * ***************************************************************************** 2N/A * global external (public) functions 2N/A * ***************************************************************************** 2N/A * Description: Open file on vfp, allocate storage, return pointer to VFP_T 2N/A * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T 2N/A * char *a_path - path of file to open and associate with this VFP. 2N/A * - if the path is (char *)NULL then no file is associated 2N/A * with this VFP - this is a way to create a fixed length 2N/A * string that can be manipulated with the VFP operators. 2N/A * Before the VFP can be used "vfpSetSize" must be called 2N/A * to set the size of the string buffer. 2N/A * char *a_mode - fopen mode to open the file with 2N/A * VFPFLAGS_T a_flags - one or more flags to control the operation: 2N/A * - VFP_NONE - no special flags 2N/A * - VFP_NEEDNOW - file data needed in memory now 2N/A * - VFP_SEQUENTIAL - memory will be sequentially accessed 2N/A * - VFP_RANDOM - memory will be randomly accessed 2N/A * - VFP_NOMMAP - do not use mmap to access file 2N/A * - VFP_NOMALLOC - do not use malloc to buffer file 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp 2N/A * which can be used with the various vfp functions. 2N/A * errno -- contains system error number if return is != 0 2N/A /* allocate pre-zeroed vfp object */ 2N/A /* create "string" vfp if no path specified */ 2N/A * no path specified - no open file associated with vfp 2N/A * The vfp is initialized to all zeros - initialize just those 2N/A * values that need to be non-zero. 2N/A * path specified - associate open file with vfp; 2N/A * return an error if no path or mode specified 2N/A /* return an error if an empty path or mode specified */ 2N/A /* Get the file size */ 2N/A * Obtain access to existing file contents: 2N/A * -> plan a: map contents file into memory 2N/A * -> plan b: on failure just read into large buffer 2N/A /* attempt to mmap file if mmap is allowed */ 2N/A * if file is a regular file, and if mmap allowed, 2N/A * and (malloc not forbidden or size is > minumum size to mmap) 2N/A /* set size to current size of file */ 2N/A * compute proper size for mapping for the file contents; 2N/A * add in one extra page so falling off end when file size is 2N/A * exactly modulo page size does not cause a page fault to 2N/A * guarantee that the end of the file contents will always 2N/A * contain a '\0' null character. 2N/A * mmap allowed: mmap file into memory 2N/A * first allocate space on top of which the mapping can be done; 2N/A * this way we can guarantee that if the mapping happens to be 2N/A * an exact multiple of a page size, that there will be at least 2N/A * one byte past the end of the mapping that can be accessed and 2N/A * that is guaranteed to be zero. 2N/A /* allocate backing space */ 2N/A /* guarantee first byte after end of data is zero */ 2N/A /* map file on top of the backing space */ 2N/A /* if mmap succeeded set mmap used flag in vfp */ 2N/A /* if map failed (or not allowed) attempt malloc (if allowed) */ 2N/A /* mmap failed - plan b: read directly into memory */ 2N/A * compute proper size for allocating storage for file contents; 2N/A * add in one extra page so falling off end when file size is 2N/A * exactly modulo page size does not cause a page fault to 2N/A * guarantee that the end of the file contents will always 2N/A * contain a '\0' null character. 2N/A /* allocate buffer to hold file data */ 2N/A /* read the file into the buffer */ 2N/A /* assure last byte+1 is null character */ 2N/A /* set malloc used flag in vfp */ 2N/A /* if no starting address all read methods failed */ 2N/A /* no mmap() - no read() - cannot allocate memory */ 2N/A * initialize vfp contents 2N/A /* _vfpCurr -> next byte to read */ 2N/A /* _vfpEnd -> last data byte */ 2N/A /* _vfpHighWater -> last byte written */ 2N/A /* _vfpFile -> associated FILE* object */ 2N/A /* set flags as appropriate */ 2N/A /* retain path name */ 2N/A /* set return vfp pointer */ 2N/A * Description: Close an open vfp, causing any modified data to be written out 2N/A * to the file associated with the vfp. 2N/A * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T returned by vfpOpen 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A * Side Effects: r_vfp is set to (VFP_T)NULL 2N/A /* return error if NULL VFP_T** provided */ 2N/A /* localize access to VFP_T */ 2N/A /* return successful if NULL VFP_T* provided */ 2N/A /* reset return VFP_T* handle */ 2N/A * if closing a file that is open for writing, commit all data if the 2N/A * backing memory is volatile and if there is a file open to write 2N/A /* determine number of bytes to write */ 2N/A /* if modified bytes present commit data to the file */ 2N/A /* unmap the file mapping */ 2N/A /* free the backing allocation */ 2N/A /* close the file */ 2N/A /* deallocate the vfp itself */ 2N/A /* if the fclose() failed, return error and errno */ 2N/A * Description: Modify operation of VFP according to flags specified 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set flags 2N/A * VFPFLAGS_T a_flags - one or more flags to control the operation: 2N/A * - VFP_NEEDNOW - file data needed in memory now 2N/A * - VFP_SEQUENTIAL - file data sequentially accessed 2N/A * - VFP_RANDOM - file data randomly accessed 2N/A * Any other flags specified are silently ignored. 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A /* return if no vfp specified */ 2N/A /* if file data mapped into memory, apply vm flags */ 2N/A /* mmap succeeded: properly advise vm system */ 2N/A /* advise vm system data is needed now */ 2N/A /* advise vm system data access is sequential */ 2N/A /* advise vm system data access is random */ 2N/A * Description: Reset default pointer for next read/write to start of file data 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to rewind 2N/A * Operation is always successful 2N/A /* return if no vfp specified */ 2N/A /* set high water mark of last modified data */ 2N/A /* reset next character pointer to start of file data */ 2N/A * Description: Set size of in-memory image associated with VFP 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set 2N/A * size_t a_size - number of bytes to associatge with VFP 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A * Currently only a file that is in malloc()ed memory can 2N/A * have its in-memory size changed. 2N/A * An error is returned If the file is mapped into memory. 2N/A * A file cannot be decreased in size - if the specified 2N/A * size is less than the current size, the operation is 2N/A * successful but no change in file size occurs. 2N/A * If no file is associated with the VFP (no "name" was 2N/A * given to vfpOpen) the first call to vfpSetSize allocates 2N/A * the initial size of the file data - effectively calling 2N/A * "malloc" to allocate the initial memory for the file data. 2N/A * Once an initial allocation has been made, subsequent calls 2N/A * to vfpSetSize are effectively a "realloc" of the existing 2N/A * All existing file data is preserved. 2N/A /* return if no vfp specified */ 2N/A /* if malloc not used don't know how to set size right now */ 2N/A /* adjust size to reflect extra page of data maintained */ 2N/A /* if size is not larger than current nothing to do */ 2N/A /* remember new size */ 2N/A /* make sure last allocated byte is a null */ 2N/A * adjust all pointers to account for buffer address change 2N/A /* _vfpCurr -> next byte to read */ 2N/A /* _vfpHighWater -> last byte written */ 2N/A /* _vfpEnd -> last data byte */ 2N/A /* _vfpStart -> first data byte */ 2N/A * Description: Truncate data associated with VFP 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to truncate 2N/A * Operation is always successful. 2N/A * In memory data associated with file is believed to be empty. 2N/A * Actual memory associated with file is not affected. 2N/A * If a file is associated with the VFP, it is truncated. 2N/A /* return if no vfp specified */ 2N/A * reset all pointers so that no data is associated with file 2N/A /* current byte is start of data area */ 2N/A /* last byte written is start of data area */ 2N/A /* current character is NULL */ 2N/A /* if file associated with VFP, truncate actual file */ 2N/A * Name: vfpWriteToFile 2N/A * Description: Write data associated with VFP to specified file 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to write 2N/A * char *a_path - path of file to write file data to 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A /* return if no vfp specified */ 2N/A /* on buffer overflow generate error */ 2N/A /* open file to write data to */ 2N/A /* determine number of bytes to write */ 2N/A * if there is data associated with the file, write it out; 2N/A * if an error occurs, close the file and return failure. 2N/A /* error comitting data - return failure */ 2N/A /* close the file */ 2N/A /* data committed to backing store - clear the modified flag */ 2N/A /* return success */ 2N/A * Name: vfpCheckpointFile 2N/A * Description: Create new VFP that checkpoints existing VFP, can be used by 2N/A * subsequent call to vfpCheckpointOpen to open a file using the 2N/A * existing in-memory cache of the contents of the file 2N/A * Arguments: VFP_T **r_cpVfp - pointer to pointer to VFP_T to be filled in 2N/A * with "checkpointed file" VFP (backing store) 2N/A * VFP_T **a_vfp - pointer to pointer to VFP_T returned by vfpOpen 2N/A * representing the VFP to checkpoint 2N/A * char *a_path - path to file that is the backing store for the 2N/A * in-memory data represented by a_vfp - used to verify 2N/A * that the data in memory is not out of date with respect 2N/A * to the backing store when vfpCheckpointOpen is called 2N/A * == (char *)NULL - use path associated with a_vfp 2N/A * that is, the backing store file in use 2N/A * Returns: int == 0 - operation was successful 2N/A * - r_destVfp contains a pointer to a new VFP that 2N/A * may be used in a subsequent call to 2N/A * - the VFP referenced by *a_vfp is free()ed and 2N/A * must no longer be referenced 2N/A * != 0 - operation failed, errno contains reason 2N/A * - the VFP referenced by *a_vfp is not affected; 2N/A * the caller may continue to use it 2N/A * Notes: If the data of a VFP to checkpoint is mmap()ed then this method 2N/A * returns failure - only malloc()ed data VFPs can be 2N/A /* return error if NULL VFP_T** to checkpoint provided */ 2N/A /* reset return checkpoint VFP pointer */ 2N/A /* return error if no VFP to checkpoint specified */ 2N/A /* localize reference to a_vfp */ 2N/A /* return error if no VFP to checkpoint specified */ 2N/A /* on buffer overflow generate error */ 2N/A /* no checkpointing is possible if the existing VFP is mmap()ed */ 2N/A /* if no path specified, grab it from the VFP to checkpoint */ 2N/A /* backing store required: if VFP is "string" then this is an error */ 2N/A /* Get the VFP to checkpoint (backing store) file size */ 2N/A /* allocate storage for checkpointed VFP (to return) */ 2N/A * close any file that is on the VFP to checkpoint (backing store); 2N/A * subsequent processes can modify the backing store data, and 2N/A * then when vfpCheckpointOpen is called, either the in-memory 2N/A * cached data will be used (if backing store unmodified) or else 2N/A * the in-memory data is released and the backing store is used. 2N/A /* free any path associated with VFP to checkpoint (backing store) */ 2N/A /* copy contents of VFP to checkpoint to checkpointed VFP */ 2N/A /* free contents of VFP to checkpoint */ 2N/A /* reset pointer to VFP that has been free'd */ 2N/A /* remember path associated with the checkpointed VFP (backing store) */ 2N/A /* save tokens that identify the backing store for the in-memory data */ 2N/A /* pass checkpointed VFP to caller */ 2N/A * Name: vfpCheckpointOpen 2N/A * Description: Open file on vfp, allocate storage, return pointer to VFP_T 2N/A * a checkpointed VFP is passed in, and the in memory contents of 2N/A * the VFP are not out of date with respect to the backing store 2N/A * file, use the existing in-memory contents - otherwise, discard 2N/A * the in-memory contents and reopen and reread the file. 2N/A * Arguments: VFP_T **a_cpVfp - pointer to pointer to VFP_T that represents 2N/A * checkpointed VFP to use to open the file IF the contents 2N/A * of the backing store are identical to the in-memory data 2N/A * VFP_T **r_vfp - pointer to pointer to VFP_T to open file on 2N/A * char *a_path - path of file to open and associate with this VFP. 2N/A * - if the path is (char *)NULL then no file is associated 2N/A * with this VFP - this is a way to create a fixed length 2N/A * string that can be manipulated with the VFP operators. 2N/A * Before the VFP can be used "vfpSetSize" must be called 2N/A * to set the size of the string buffer. 2N/A * char *a_mode - fopen mode to open the file with 2N/A * VFPFLAGS_T a_flags - one or more flags to control the operation: 2N/A * - VFP_NONE - no special flags 2N/A * - VFP_NEEDNOW - file data needed in memory now 2N/A * - VFP_SEQUENTIAL - memory will be sequentially accessed 2N/A * - VFP_RANDOM - memory will be randomly accessed 2N/A * - VFP_NOMMAP - do not use mmap to access file 2N/A * - VFP_NOMALLOC - do not use malloc to buffer file 2N/A * Returns: int == 0 - operation was successful 2N/A * != 0 - operation failed, errno contains reason 2N/A * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp 2N/A * which can be used with the various VFP functions. 2N/A * a_cpVfp -- contents reset to zero if used to open the file 2N/A * errno -- contains system error number if return is != 0 2N/A VFP_T *
vfp;
/* new VFP open on checkpointed backing store */ 2N/A * if no source VFP, or source VFP empty, 2N/A * or no backing store, just open file 2N/A /* localize access to checkpointed VFP_T (*a_cpVfp) */ 2N/A /* if no path specified, grab it from the checkpointed VFP */ 2N/A /* return error if no path specified and no path in checkpointed VFP */ 2N/A /* if no backing store path, then just open file */ 2N/A * if backing store tokens do not match checkpointed VFP, 2N/A * the backing store has been updated since the VFP was checkpointed; 2N/A * release the in-memory data, and open and read the backing store 2N/A * backing store has not been updated since the VFP was checkpointed; 2N/A * use the in-memory data without re-reading the backing store; open the 2N/A * backing store file (if no file already open on the checkpointed VFP) 2N/A * so there is an open file associated with the in-memory data 2N/A /* allocate new VFP object to return as open VFP */ 2N/A /* copy cached checkpointed VFP to new VFP to return */ 2N/A * initialize VFP to return contents 2N/A /* FILE -> file opened on the VFPs backing store */ 2N/A /* release any existing path associated with the VFP */ 2N/A /* path associated with the backing store for this VFP */ 2N/A * data pointers associated with in memory copy of backing store 2N/A * (such as _vfpHighWater, _vfpEnd, _vfpStart, etc.) 2N/A * do not need to be modified because we are using the same backing 2N/A * store as was checkpointed in cpVfp that is pointed to by vfp. 2N/A /* _vfpCurr -> next byte to read */ 2N/A /* free checkpointed VFP as it is now open on "vfp" */ 2N/A /* reset callers -> checkpointed VFP */ 2N/A /* set return VFP pointer */ 2N/A * Name: vfpClearModified 2N/A * Description: Clear the "data is modified" indication from the VFP 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to clear 2N/A * the "data is modified" indication 2N/A * Returns: int - previous setting of "data is modified" indication 2N/A * == 0 - "data is modified" was NOT previously set 2N/A * != 0 - "data is modified" WAS previously set 2N/A /* save current flags settings */ 2N/A /* clear "data is modified" flag */ 2N/A /* return previous "data is modified" flag setting */ 2N/A * Name: vfpSetModified 2N/A * Description: Set the "data is modified" indication from the VFP 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set 2N/A * the "data is modified" indication 2N/A * Returns: int - previous setting of "data is modified" indication 2N/A * == 0 - "data is modified" was NOT previously set 2N/A * != 0 - "data is modified" WAS previously set 2N/A /* save current flags settings */ 2N/A /* set "data is modified" flag */ 2N/A /* return previous "data is modified" flag setting */ 2N/A * Name: vfpGetModified 2N/A * Description: Get the "data is modified" indication from the VFP 2N/A * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to get 2N/A * the "data is modified" indication 2N/A * Returns: int - current setting of "data is modified" indication 2N/A * == 0 - "data is modified" is NOT set 2N/A * != 0 - "data is modified" IS set 2N/A /* return current "data is modified" flag setting */ 2N/A * Name: vfpSafeWrite 2N/A * Description: write data to open file safely 2N/A * Arguments: a_fildes - file descriptor to write data to 2N/A * a_buf - pointer to buffer containing data to write 2N/A * a_nbyte - number of bytes to write to open file 2N/A * < 0 - error, errno set 2N/A * NOTE: unlike write(2), vfpSafeWrite() handles partial writes, and will 2N/A * ----- restart the write() until all bytes are written, or an error occurs. 2N/A /* write bytes to file */ 2N/A /* return error on failure of write() */ 2N/A /* EAGAIN: try again */ 2N/A /* EINTR: interrupted - try again */ 2N/A /* return total bytes written on success */ 2N/A /* partial write, adjust pointers, call write again */ 2N/A * Name: vfpSafePwrite 2N/A * Description: write data to open file safely 2N/A * Arguments: a_fildes - file descriptor to write data to 2N/A * a_buf - pointer to buffer containing data to write 2N/A * a_nbyte - number of bytes to write to open file 2N/A * a_offset - offset into open file to write the first byte to 2N/A * < 0 - error, errno set 2N/A * NOTE: unlike pwrite(2), vfpSafePwrite() handles partial writes, and will 2N/A * ----- restart the pwrite() until all bytes are written, or an error occurs. 2N/A /* write bytes to file */ 2N/A /* return error on failure of write() */ 2N/A /* EAGAIN: try again */ 2N/A /* EINTR: interrupted - try again */ 2N/A /* return total bytes written on success */ 2N/A /* partial write, adjust pointers, call write again */