in src/generic/filecounter.c [329:540]
int nextSeqNo(Tcl_Interp * interp, SeqNoGenerator * seqnogen, int *seqno, int next)
{
/* if next == 1: incr filecounter, if next == 0: just get current value of filecounter */
int currentSeqNo = -1;
Tcl_Channel channel;
Tcl_Obj *lineObj = NULL;
int bytesRead = -1;
int newfile = 0;
if (seqnogen == NULL)
return TCL_ERROR;
Tcl_SetResult(interp, "", TCL_STATIC);
/* ----------------------------------------------------------------------
* Try to create file
* ------------------------------------------------------------------- */
if ((channel = Tcl_OpenFileChannel(interp,
seqnogen->fileName,
"CREAT RDWR", seqnogen->mask)) == NULL) {
LOG_MSG(interp, WRITE_LOG,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
(char *) Tcl_GetStringResult(interp), NULL);
return TCL_ERROR;
}
/* --------------------------------------------------------------------
* Try to lock file
* ----------------------------------------------------------------- */
if (lock_TclChannel(interp, channel) == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR, "error getting lock", NULL);
return TCL_ERROR;
}
/* --------------------------------------------------------------------
* Try to read file
* ----------------------------------------------------------------- */
lineObj = Tcl_NewObj();
Tcl_IncrRefCount(lineObj);
if ((bytesRead = Tcl_GetsObj(channel, lineObj)) < 0) {
if (!Tcl_Eof(channel)) {
/* failed -> unlock and close */
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
"error reading file: ", Tcl_ErrnoMsg(Tcl_GetErrno()),
NULL);
Tcl_DecrRefCount(lineObj);
return TCL_ERROR;
}
else {
bytesRead = 0;
}
}
/* --------------------------------------------------------------------
* new file
* ----------------------------------------------------------------- */
if (bytesRead == 0) {
LOG_MSG(interp, WRITE_LOG,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_INFO, "new file", NULL);
currentSeqNo = seqnogen->seed;
newfile = 1;
}
else {
/* --------------------------------------------------------------------
* have read
* ----------------------------------------------------------------- */
if (Tcl_GetIntFromObj(interp, lineObj, ¤tSeqNo) != TCL_OK) {
/* ----------------------------------------------------------------
* ... but cannot understand what I read
* ------------------------------------------------------------- */
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
"file \"", seqnogen->fileName,
"\" contains invalid data: ",
Tcl_GetStringResult(interp), NULL);
Tcl_DecrRefCount(lineObj);
return TCL_ERROR;
}
/* --------------------------------------------------------------------
* get value (and wrap)
* ----------------------------------------------------------------- */
if (next == 1) {
currentSeqNo += seqnogen->incrValue;
if (currentSeqNo > seqnogen->maxValue) {
if (seqnogen->doWrap) {
currentSeqNo = seqnogen->minValue;
}
else {
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
"counter overflow", NULL);
Tcl_DecrRefCount(lineObj);
return TCL_ERROR;
}
}
}
}
/* ------------------------------------------------------------------------
* set result to return
* --------------------------------------------------------------------- */
*seqno = currentSeqNo;
/* ------------------------------------------------------------------------
* write new value, but only if we need to:
* either next == 1 (i.e. we have a new value)
* or newfile == 1 (we have a new file to write)
* --------------------------------------------------------------------- */
if (next == 1 || newfile == 1) {
Tcl_SetIntObj(lineObj, *seqno);
if (Tcl_Seek(channel, 0, SEEK_SET) < 0) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
"error rewinding channel", NULL);
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
Tcl_DecrRefCount(lineObj);
return TCL_ERROR;
}
Tcl_AppendToObj(lineObj, "\n", 1);
{
int written = 0;
int expected = 0;
written = Tcl_WriteObj(channel, lineObj);
expected = Tcl_GetCharLength(lineObj);
/* printf("DBG written: %d, expected: %d\n",written,expected); fflush(stdout); */
/* if ( (written = Tcl_WriteObj(channel,lineObj)) != Tcl_GetCharLength(lineObj)) */
if (written < expected) {
/*we try to close the file */
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::filecounter", WEBLOG_ERROR,
"error writing to file \"",
seqnogen->fileName, "\": ", Tcl_GetStringResult(interp),
NULL);
Tcl_DecrRefCount(lineObj);
return TCL_ERROR;
}
}
/* ------------------------------------------------------------------------
* that's it
* --------------------------------------------------------------------- */
Tcl_Flush(channel);
}
unlock_TclChannel(interp, channel);
Tcl_Close(interp, channel);
Tcl_DecrRefCount(lineObj);
seqnogen->currValue = *seqno;
seqnogen->hasCurrent = 1;
return TCL_OK;
}