Sophie

Sophie

distrib > Mandriva > cooker > i586 > media > contrib-release-debug > by-pkgid > 29b07848f1f0d261023b5d8e39188a60 > files > 198

glame-debug-2.0.2-0.20070607.rc1.4mdv2011.0.i586.rpm

#ifndef _SWAPFILE_H
#define _SWAPFILE_H

/*
 * swapfile.h
 *
 * Copyright (C) 1999, 2000, 2001, 2004 Richard Guenther
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/* There are some generic issues for an implementation of the
 * swapfile API to make it efficient for the desired tasks:
 * - blocks need to be able to be shared between files
 * - blocks need to be able to be split and continue to be
 *   shared between files
 * Those requirements result in the following difficulties
 * an implementation will run into:
 * - maintaining a simple bitmask of unallocated blocks is not
 *   possible, as blocks may be shared, i.e. sort of an usage
 *   count is needed, not just a true/false state
 * - mmapping a file is usually not (efficient) possible - only
 *   one block at a time can be mmapped due to block splitting
 *   block start offsets are not aligned to a minimum block size
 *   and block sizes are not multiples of a minimum block size
 * - organizing files block allocation table as a simple linear
 *   list or as extends is not efficient because of the same
 *   block alignment/size issues, so a tree-like structure needs
 *   to be used for this - and in this tree the size of the blocks
 *   or their offsets in the file need to be stored
 * - because of the splitting requirement one need information
 *   about which files use a given block - i.e. a reverse block
 *   allocation table needs to be maintained (optimize for the
 *   single file case, O(n) operations are acceptable)
 * So an efficient implementation with respect to speed _and_
 * storage requirement for metadata is quite difficult.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>



typedef long swfd_t;                  /* open file cookie, like fd/FILE */
typedef struct { int dummy; } SWDIR;  /* cookie for open directory, like DIR */

struct sw_stat {
	long name;           /* file name */
	size_t size;         /* file size in bytes */
	int mode;            /* active protection */
	off_t offset;        /* current file pointer position */
	off_t cluster_start; /* start of current cluster */
	off_t cluster_end;   /* end of current cluster */
	size_t cluster_size; /* size of current cluster */
};



#ifdef __cplusplus
extern "C" {
#endif


/**********************************************************************
 * Initialization/cleanup
 */

/* Registers a handler that gets executed if the swapfile subsystem
 * is about to commit suicide. The message may be a hint to the user. */
void swapfile_register_panic_handler(void (*handler)(const char *));

/* Tries to open an existing swap file/partition.
 * Returns 0 on success, -1 on failure.
 * Failures can be
 *  - missing swap file/parition
 *  - in use swap
 *  - unclean swap */
int swapfile_open(const char *name, int flags);

/* Syncs the in memory caches and metadata to disk. Does not sync
 * exisiting memory mappings. */
void swapfile_sync();

/* Closes and updates a previously opened swap file/partition
 * and marks it clean. */
void swapfile_close();

/* Tries to create an empty swapfile on name of size size. */
int swapfile_creat(const char *name, size_t size);

/* Tries to recover from unclean shutdown. Returns -1, if fsck
 * cannot be performed or failed, 0 if swapfile is clean, 1 if
 * swapfile was modified. Provide force == 1 to force a complete
 * fsck, even if swapfile is clean. */
int swapfile_fsck(const char *name, int force);



/**********************************************************************
 * Operations on the swapfile namespace. Unlike a unix filesystem
 * the swapfile filesystem has names composed out of a single "long".
 * Also the swapfile name hierarchy is flat - i.e. no directories.
 * Names are >=0, negative values are reserved.
 * All namespace operations are atomic (i.e. thread safe) and not
 * undoable (well - just sw_unlink is not undoable).
 */

/* Deletes a name from the filesystem. Like unlink(2). */
int sw_unlink(long name);

/* Open the (flat) swapfile directory for reading. The stream
 * is positioned at the first file. Like opendir(3), but w/o
 * directory specification for obvious reason. */
SWDIR *sw_opendir();

/* As the namespace is rather simple the equivalent to readdir(3) is
 * just returning the names, no directory entry. Anything else
 * is like readdir(3). If no further entries are available, -1 is returned. */
long sw_readdir(SWDIR *dir);

/* Like closedir(3). */
int sw_closedir(SWDIR *d);


/**********************************************************************
 * Operations on a single file. Files are organized in variable sized
 * clusters. Access to the file is limited to mapping those clusters.
 */

/* Open a file like open(2) - flags can be O_CREAT, O_EXCL,
 * O_RDWR, O_RDONLY, O_WRONLY with same semantics as open(2).
 * Returns a file descriptor on success, -1 on error. */
swfd_t sw_open(long name, int flags);

/* Closes a file descriptor. Like close(2). */
int sw_close(swfd_t fd);

/* Changes the size of the file fd like ftruncate(2). */
int sw_ftruncate(swfd_t fd, off_t length);

/* Tries to copy count bytes from the current position of in_fd
 * to the current position of out_fd (updating both file pointer
 * positions). The actual number of copied bytes is returned, or
 * -1 on an error.
 * Two different modes are supported (may be or'ed together):
 * - SWSENDFILE_INSERT inserts into, rather than overwrites/extends
 *   the destination file
 * - SWSENDFILE_CUT removes copied data from the source file
 * The destination file descriptor may be SW_NOFILE, in that case
 * no data is actually written (useful with SWSENDFILE_CUT). */
#define SW_NOFILE ((swfd_t)-1)
#define SWSENDFILE_INSERT 1
#define SWSENDFILE_CUT 2
ssize_t sw_sendfile(swfd_t out_fd, swfd_t in_fd, size_t count, int mode);

/* Update the file pointer position like lseek(2). */
off_t sw_lseek(swfd_t fd, off_t offset, int whence);

/* Like read(2), read count bytes from the current filepointer
 * position to the array pointed to by buf. */
ssize_t sw_read(swfd_t fd, void *buf, size_t count);

/* Like write(2), write count bytes from buf starting at the current
 * filepointer position. */
ssize_t sw_write(swfd_t fd, const void *buf, size_t count);

/* Obtain information about the file - works like fstat(2), but
 * with different struct stat. Also included is information about
 * the actual (file pointer position, see sw_lseek) cluster which
 * can be mapped using sw_mmap. */
int sw_fstat(swfd_t fd, struct sw_stat *buf);

/* Maps the actual (file pointer position, see sw_lseek and sw_fstat)
 * cluster into memory with parameters like mmap(2) - no size/offset
 * as they are determined by the actual cluster offset/size. */
void *sw_mmap(void *start, int prot, int flags, swfd_t fd);

/* Unmaps a previously mapped part of a file. Like munmap(2). */
int sw_munmap(void *start);


#ifdef __cplusplus
}
#endif

#endif