00001 /* 00002 * Copyright 2008, 2009 Alexandros Frantzis, Michael Iatrou 00003 * 00004 * This file is part of libbls. 00005 * 00006 * libbls is free software: you can redistribute it and/or modify it under the 00007 * terms of the GNU Lesser General Public License as published by the Free Software 00008 * Foundation, either version 3 of the License, or (at your option) any later 00009 * version. 00010 * 00011 * libbls is distributed in the hope that it will be useful, but WITHOUT ANY 00012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00014 * details. 00015 * 00016 * You should have received a copy of the GNU General Public License along with 00017 * libbls. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 /** 00021 * @file data_object.c 00022 * 00023 * Implementation of the base data_object_t ADT and interface mechanism. 00024 */ 00025 00026 #include <stdlib.h> 00027 #include <errno.h> 00028 00029 #include "data_object.h" 00030 #include "data_object_internal.h" 00031 #include "debug.h" 00032 00033 struct data_object { 00034 void *impl; 00035 struct data_object_funcs *funcs; 00036 int usage; 00037 }; 00038 00039 /********************** 00040 * Internal functions * 00041 **********************/ 00042 00043 /** 00044 * Creates a data_object_t using a specific implementation. 00045 * 00046 * This functions is for use by the various data_object_t implementations. 00047 * 00048 * @param[out] obj the created data_object_t 00049 * @param impl the implementation private data 00050 * @param funcs function pointers to the implementations' functions 00051 * 00052 * @return the operation status code 00053 */ 00054 int data_object_create_impl(data_object_t **obj, void *impl, 00055 struct data_object_funcs *funcs) 00056 { 00057 if (obj == NULL) 00058 return_error(EINVAL); 00059 00060 *obj = malloc(sizeof(data_object_t)); 00061 00062 if (*obj == NULL) 00063 return_error(ENOMEM); 00064 00065 (*obj)->impl = impl; 00066 (*obj)->funcs = funcs; 00067 (*obj)->usage = 0; 00068 00069 return 0; 00070 00071 } 00072 00073 /** 00074 * Gets the private implementation data of a data_object_t, 00075 */ 00076 void *data_object_get_impl(data_object_t *obj) 00077 { 00078 return obj->impl; 00079 } 00080 00081 /***************** 00082 * API functions * 00083 *****************/ 00084 00085 00086 /** 00087 * Gets a pointer to data from the data object. 00088 * 00089 * This function provides a pointer that points to a location that contains 00090 * the data range requested. It is possible that a call to this function 00091 * retrieves only some of the requested data. Subsequent calls may be needed to 00092 * complete the whole operation. 00093 * 00094 * Furthermore, the pointer returned is valid only as long as no other access 00095 * is made to the data object (watch out for concurrency issues!). 00096 * 00097 * @param obj the obj to get the data from 00098 * @param[out] buf the location that will contain the data 00099 * @param offset the offset in the data object to get data from 00100 * @param[in,out] length the length of the data to get, on return will contain 00101 * the length of the data that was actually retrieved. 00102 * The returned length always fits in an ssize_t variable. 00103 * @param flags whether the data will be read or written to (or both) 00104 * 00105 * @return the operation error code 00106 */ 00107 00108 int data_object_get_data(data_object_t *obj, void **buf, off_t offset, 00109 off_t *length, data_object_flags flags) 00110 { 00111 return (*obj->funcs->get_data)(obj, buf, offset, length, flags); 00112 } 00113 00114 /** 00115 * Frees the data object and its resources. 00116 * 00117 * @param obj the data object to free 00118 * 00119 * @return the operation error code 00120 */ 00121 int data_object_free(data_object_t *obj) 00122 { 00123 int err = (*obj->funcs->free)(obj); 00124 00125 if (err) 00126 return_error(err); 00127 00128 free(obj); 00129 00130 return 0; 00131 } 00132 00133 /** 00134 * Updates the usage count of this data object. 00135 * 00136 * If the usage count falls to zero (or below) the data object 00137 * is freed. This function is to be called by the memory management 00138 * system of segment_t. 00139 * 00140 * @param obj the data object 00141 * @param change the change in the usage count or 0 to reset the count 00142 * 00143 * @return the operation error code 00144 */ 00145 int data_object_update_usage(void *obj, int change) 00146 { 00147 if (obj == NULL) 00148 return_error(EINVAL); 00149 00150 data_object_t *data_obj = (data_object_t *) obj; 00151 00152 if (change == 0) { 00153 data_obj->usage = 0; 00154 return 0; 00155 } 00156 00157 data_obj->usage += change; 00158 00159 if (data_obj->usage <= 0) { 00160 int err = data_object_free(data_obj); 00161 if (err) 00162 return_error(err); 00163 } 00164 00165 return 0; 00166 } 00167 /** 00168 * Gets the size of the data object. 00169 * 00170 * @param obj the data object to get the size of 00171 * @param[out] size the size of the data object 00172 * 00173 * @return the operation error code 00174 */ 00175 int data_object_get_size(data_object_t *obj, off_t *size) 00176 { 00177 return (*obj->funcs->get_size)(obj, size); 00178 } 00179 00180 /** 00181 * Compares the data held by two data objects. 00182 * 00183 * Note that the compare is based on reference equality (eg for memory 00184 * data objects if their data is located at the same memory area, for file 00185 * objects if they are associated with the same file) not byte by byte 00186 * comparison. 00187 * 00188 * @param[out] result 0 if they are equal, 1 otherwise 00189 * @param obj1 one of the data objects to compare 00190 * @param obj2 the other data object to compare 00191 * 00192 * @return the operation error code 00193 */ 00194 int data_object_compare(int *result, data_object_t *obj1, data_object_t *obj2) 00195 { 00196 if (obj1 == NULL || obj2 == NULL || result == NULL) 00197 return_error(EINVAL); 00198 00199 /* Check if they are of the same type */ 00200 if (obj1->funcs != obj2->funcs) { 00201 *result = 1; 00202 return 0; 00203 } 00204 00205 return (*obj1->funcs->compare)(result, obj1, obj2); 00206 }