• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

RecMessage.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Record message definitions
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "libts.h"
00025 
00026 #include "P_RecCore.h"
00027 #include "P_RecFile.h"
00028 #include "P_RecMessage.h"
00029 #include "P_RecUtils.h"
00030 #include "P_RecCore.h"
00031 #include "I_Layout.h"
00032 
00033 static RecMessageRecvCb g_recv_cb = NULL;
00034 static void *g_recv_cookie = NULL;
00035 
00036 //-------------------------------------------------------------------------
00037 // RecMessageAlloc
00038 //-------------------------------------------------------------------------
00039 RecMessage *
00040 RecMessageAlloc(RecMessageT msg_type, int initial_size)
00041 {
00042   RecMessage *msg;
00043 
00044   msg = (RecMessage *)ats_malloc(sizeof(RecMessageHdr) + initial_size);
00045   memset(msg, 0, sizeof(RecMessageHdr) + initial_size);
00046   msg->msg_type = msg_type;
00047   msg->o_start = sizeof(RecMessageHdr);
00048   msg->o_write = sizeof(RecMessageHdr);
00049   msg->o_end = sizeof(RecMessageHdr) + initial_size;
00050   msg->entries = 0;
00051 
00052   return msg;
00053 }
00054 
00055 //-------------------------------------------------------------------------
00056 // RecMessageFree
00057 //-------------------------------------------------------------------------
00058 
00059 int
00060 RecMessageFree(RecMessage * msg)
00061 {
00062   ats_free(msg);
00063   return REC_ERR_OKAY;
00064 }
00065 
00066 //-------------------------------------------------------------------------
00067 // RecMessageMarshal_Realloc
00068 //-------------------------------------------------------------------------
00069 RecMessage *
00070 RecMessageMarshal_Realloc(RecMessage * msg, const RecRecord * record)
00071 {
00072   int msg_ele_size;
00073   int rec_name_len = -1;
00074   int rec_data_str_len = -1;
00075   int rec_data_def_str_len = -1;
00076   int rec_cfg_chk_len = -1;
00077   RecMessageEleHdr *ele_hdr;
00078   RecRecord *r;
00079   char *p;
00080 
00081   // find out how much space we need
00082   msg_ele_size = sizeof(RecMessageEleHdr) + sizeof(RecRecord);
00083   if (record->name) {
00084     rec_name_len = strlen(record->name) + 1;
00085     msg_ele_size += rec_name_len;
00086   }
00087   if (record->data_type == RECD_STRING) {
00088     if (record->data.rec_string) {
00089       rec_data_str_len = strlen(record->data.rec_string) + 1;
00090       msg_ele_size += rec_data_str_len;
00091     }
00092     if (record->data_default.rec_string) {
00093       rec_data_def_str_len = strlen(record->data_default.rec_string) + 1;
00094       msg_ele_size += rec_data_def_str_len;
00095     }
00096   }
00097   if (REC_TYPE_IS_CONFIG(record->rec_type) && (record->config_meta.check_expr)) {
00098     rec_cfg_chk_len = strlen(record->config_meta.check_expr) + 1;
00099     msg_ele_size += rec_cfg_chk_len;
00100   }
00101   // XXX: this is NOT 8 byte alignment
00102   // msg_ele_size = 5;
00103   // (msg_ele_size + 7) & ~7 == 5 !!!
00104   // msg_ele_size = (msg_ele_size + 7) & ~7;       // 8 byte alignmenet
00105 
00106   msg_ele_size = INK_ALIGN_DEFAULT(msg_ele_size);  // 8 byte alignmenet
00107   // get some space in our buffer
00108   while (msg->o_end - msg->o_write < msg_ele_size) {
00109     int realloc_size = (msg->o_end - msg->o_start) * 2;
00110     msg = (RecMessage *)ats_realloc(msg, sizeof(RecMessageHdr) + realloc_size);
00111     msg->o_end = msg->o_start + realloc_size;
00112   }
00113   ele_hdr = (RecMessageEleHdr *) ((char *) msg + msg->o_write);
00114   // The following memset() is pretty CPU intensive, replacing it with something
00115   // like the below would reduce CPU usage a fair amount. /leif.
00116   // *((char*)msg + msg->o_write) = 0;
00117   memset((char *) msg + msg->o_write, 0, msg->o_end - msg->o_write);
00118   msg->o_write += msg_ele_size;
00119 
00120   // store the record
00121   ele_hdr->magic = REC_MESSAGE_ELE_MAGIC;
00122   ele_hdr->o_next = msg->o_write;
00123   p = (char *) ele_hdr + sizeof(RecMessageEleHdr);
00124   memcpy(p, record, sizeof(RecRecord));
00125   r = (RecRecord *) p;
00126   p += sizeof(RecRecord);
00127   if (rec_name_len != -1) {
00128     ink_assert((msg->o_end - ((uintptr_t) p - (uintptr_t) msg)) >= (uintptr_t) rec_name_len);
00129     memcpy(p, record->name, rec_name_len);
00130     r->name = (char *) ((uintptr_t) p - (uintptr_t) r);
00131     p += rec_name_len;
00132   }
00133   if (rec_data_str_len != -1) {
00134     ink_assert((msg->o_end - ((uintptr_t) p - (uintptr_t) msg)) >= (uintptr_t) rec_data_str_len);
00135     memcpy(p, record->data.rec_string, rec_data_str_len);
00136     r->data.rec_string = (char *) ((uintptr_t) p - (uintptr_t) r);
00137     p += rec_data_str_len;
00138   }
00139   if (rec_data_def_str_len != -1) {
00140     ink_assert((msg->o_end - ((uintptr_t) p - (uintptr_t) msg)) >= (uintptr_t) rec_data_def_str_len);
00141     memcpy(p, record->data_default.rec_string, rec_data_def_str_len);
00142     r->data_default.rec_string = (char *) ((uintptr_t) p - (uintptr_t) r);
00143     p += rec_data_def_str_len;
00144   }
00145   if (rec_cfg_chk_len != -1) {
00146     ink_assert((msg->o_end - ((uintptr_t) p - (uintptr_t) msg)) >= (uintptr_t) rec_cfg_chk_len);
00147     memcpy(p, record->config_meta.check_expr, rec_cfg_chk_len);
00148     r->config_meta.check_expr = (char *) ((uintptr_t) p - (uintptr_t) r);
00149   }
00150 
00151   msg->entries += 1;
00152 
00153   return msg;
00154 }
00155 
00156 //-------------------------------------------------------------------------
00157 // RecMessageUnmarshalFirst
00158 //-------------------------------------------------------------------------
00159 
00160 int
00161 RecMessageUnmarshalFirst(RecMessage * msg, RecMessageItr * itr, RecRecord ** record)
00162 {
00163   itr->ele_hdr = (RecMessageEleHdr *) ((char *) msg + msg->o_start);
00164   itr->next = 1;
00165 
00166   return RecMessageUnmarshalNext(msg, NULL, record);
00167 }
00168 
00169 //-------------------------------------------------------------------------
00170 // RecMessageUnmarshalNext
00171 //-------------------------------------------------------------------------
00172 
00173 int
00174 RecMessageUnmarshalNext(RecMessage * msg, RecMessageItr * itr, RecRecord ** record)
00175 {
00176   RecMessageEleHdr *eh;
00177   RecRecord *r;
00178 
00179   if (itr == NULL) {
00180     if (msg->entries == 0) {
00181       return REC_ERR_FAIL;
00182     } else {
00183       eh = (RecMessageEleHdr *) ((char *) msg + msg->o_start);
00184     }
00185   } else {
00186     if (itr->next >= msg->entries) {
00187       return REC_ERR_FAIL;
00188     }
00189     itr->ele_hdr = (RecMessageEleHdr *) ((char *) (msg) + itr->ele_hdr->o_next);
00190     itr->next += 1;
00191     eh = itr->ele_hdr;
00192   }
00193 
00194   ink_assert(eh->magic == REC_MESSAGE_ELE_MAGIC);
00195 
00196   // If the file is corrupt, ignore the the rest of the file.
00197   if (eh->magic != REC_MESSAGE_ELE_MAGIC) {
00198     Warning("Persistent statistics file records.stat is corrupted. Ignoring the rest of the file\n");
00199     return REC_ERR_FAIL;
00200   }
00201 
00202   r = (RecRecord *) ((char *) eh + sizeof(RecMessageEleHdr));
00203 
00204   if (r->name) {
00205     r->name = (char *) r + (intptr_t) (r->name);
00206   }
00207   if (r->data_type == RECD_STRING) {
00208     if (r->data.rec_string) {
00209       r->data.rec_string = (char *) r + (intptr_t) (r->data.rec_string);
00210     }
00211     if (r->data_default.rec_string) {
00212       r->data_default.rec_string = (char *) r + (intptr_t) (r->data_default.rec_string);
00213     }
00214   }
00215   if (REC_TYPE_IS_CONFIG(r->rec_type) && (r->config_meta.check_expr)) {
00216     r->config_meta.check_expr = (char *) r + (intptr_t) (r->config_meta.check_expr);
00217   }
00218 
00219   *record = r;
00220 
00221   return REC_ERR_OKAY;
00222 }
00223 
00224 //-------------------------------------------------------------------------
00225 // RecMessageRegisterRecvCb
00226 //-------------------------------------------------------------------------
00227 
00228 int
00229 RecMessageRegisterRecvCb(RecMessageRecvCb recv_cb, void *cookie)
00230 {
00231   if (g_recv_cb) {
00232     return REC_ERR_FAIL;
00233   }
00234   g_recv_cookie = cookie;
00235   g_recv_cb = recv_cb;
00236 
00237   return REC_ERR_OKAY;
00238 }
00239 
00240 //-------------------------------------------------------------------------
00241 // RecMessageRecvThis
00242 //-------------------------------------------------------------------------
00243 
00244 void *
00245 RecMessageRecvThis(void * /* cookie */, char *data_raw, int /* data_len */)
00246 {
00247   RecMessage *msg = (RecMessage *) data_raw;
00248   g_recv_cb(msg, msg->msg_type, g_recv_cookie);
00249   return NULL;
00250 }
00251 
00252 //-------------------------------------------------------------------------
00253 // RecMessageReadFromDisk
00254 //-------------------------------------------------------------------------
00255 
00256 RecMessage *
00257 RecMessageReadFromDisk(const char *fpath)
00258 {
00259   RecMessageHdr msg_hdr;
00260   RecMessage *msg = NULL;
00261   RecHandle h_file;
00262   int bytes_read;
00263 
00264   if ((h_file = RecFileOpenR(fpath)) == REC_HANDLE_INVALID) {
00265     goto Lerror;
00266   }
00267   if (RecFileRead(h_file, (char *) (&msg_hdr), sizeof(RecMessageHdr), &bytes_read) == REC_ERR_FAIL) {
00268     goto Lerror;
00269   }
00270   msg = (RecMessage *)ats_malloc((msg_hdr.o_end - msg_hdr.o_start) + sizeof(RecMessageHdr));
00271   memcpy(msg, &msg_hdr, sizeof(RecMessageHdr));
00272   if (RecFileRead(h_file, (char *) (msg) + msg_hdr.o_start,
00273                   msg_hdr.o_end - msg_hdr.o_start, &bytes_read) == REC_ERR_FAIL) {
00274     goto Lerror;
00275   }
00276 
00277   goto Ldone;
00278 
00279 Lerror:
00280   ats_free(msg);
00281   msg = NULL;
00282 
00283 Ldone:
00284   if (h_file != REC_HANDLE_INVALID) {
00285     RecFileClose(h_file);
00286   }
00287 
00288   return msg;
00289 }
00290 
00291 //-------------------------------------------------------------------------
00292 // RecMessageWriteToDisk
00293 //-------------------------------------------------------------------------
00294 
00295 int
00296 RecMessageWriteToDisk(RecMessage *msg, const char *fpath)
00297 {
00298   int msg_size;
00299   RecHandle h_file;
00300   int bytes_written;
00301 
00302   // Cap the message (e.g. when we read it, o_end should reflect the
00303   // size of the new buffer that we write to disk, not the size of the
00304   // buffer in memory).
00305   msg->o_end = msg->o_write;
00306 
00307   msg_size = sizeof(RecMessageHdr) + (msg->o_write - msg->o_start);
00308   if ((h_file = RecFileOpenW(fpath)) != REC_HANDLE_INVALID) {
00309     if (RecFileWrite(h_file, (char *) msg, msg_size, &bytes_written) == REC_ERR_FAIL) {
00310       RecFileClose(h_file);
00311       return REC_ERR_FAIL;
00312     }
00313     RecFileClose(h_file);
00314   }
00315 
00316   return REC_ERR_OKAY;
00317 }

Generated by  doxygen 1.7.1