Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5c47c65

Browse files
committed
Refactor parse_filename_for_nontemp_relation to parse more.
Instead of returning the number of characters in the RelFileNumber,return the RelFileNumber itself. Continue to return the fork number,as before, and additionally return the segment number.parse_filename_for_nontemp_relation now rejects a RelFileNumber orsegment number that begins with a leading zero. Before, we acceptedsuch cases as relation filenames, but if we continued to do so afterthis change, the function might return the same values for twodifferent files (e.g. 1234.5 and 001234.5 or 1234.005) which could beannoying for callers. Since we don't actually ever generate filenameswith leading zeroes in the names, any such files that we find musthave been created by something other than PostgreSQL, and it istherefore reasonable to treat them as non-relation files.Along the way, change unlogged_relation_entry to store a RelFileNumberrather than an OID. This update should have been made in851f4cc, but it was overlooked.It's trivial to make the update as part of this commit, perhaps moretrivial than it would have been without it, so do that.Patch by me, reviewed by David Steele.Discussion:http://postgr.es/m/CA+TgmoZNVeBzoqDL8xvr-nkaepq815jtDR4nJzPew7=3iEuM1g@mail.gmail.com
1 parentb6f1cca commit5c47c65

File tree

3 files changed

+93
-64
lines changed

3 files changed

+93
-64
lines changed

‎src/backend/backup/basebackup.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,9 +1197,9 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
11971197
{
11981198
intexcludeIdx;
11991199
boolexcludeFound;
1200-
ForkNumberrelForkNum;/* Type of fork if file is a relation */
1201-
intrelnumchars;/* Chars in filename that are the
1202-
* relnumber */
1200+
RelFileNumberrelNumber;
1201+
ForkNumberrelForkNum;
1202+
unsignedsegno;
12031203

12041204
/* Skip special stuff */
12051205
if (strcmp(de->d_name,".")==0||strcmp(de->d_name,"..")==0)
@@ -1249,23 +1249,20 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
12491249

12501250
/* Exclude all forks for unlogged tables except the init fork */
12511251
if (isDbDir&&
1252-
parse_filename_for_nontemp_relation(de->d_name,&relnumchars,
1253-
&relForkNum))
1252+
parse_filename_for_nontemp_relation(de->d_name,&relNumber,
1253+
&relForkNum,&segno))
12541254
{
12551255
/* Never exclude init forks */
12561256
if (relForkNum!=INIT_FORKNUM)
12571257
{
12581258
charinitForkFile[MAXPGPATH];
1259-
charrelNumber[OIDCHARS+1];
12601259

12611260
/*
12621261
* If any other type of fork, check if there is an init fork
12631262
* with the same RelFileNumber. If so, the file can be
12641263
* excluded.
12651264
*/
1266-
memcpy(relNumber,de->d_name,relnumchars);
1267-
relNumber[relnumchars]='\0';
1268-
snprintf(initForkFile,sizeof(initForkFile),"%s/%s_init",
1265+
snprintf(initForkFile,sizeof(initForkFile),"%s/%u_init",
12691266
path,relNumber);
12701267

12711268
if (lstat(initForkFile,&statbuf)==0)

‎src/backend/storage/file/reinit.c

Lines changed: 84 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static void ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname,
3131

3232
typedefstruct
3333
{
34-
Oidreloid;/* hash key */
34+
RelFileNumberrelnumber;/* hash key */
3535
}unlogged_relation_entry;
3636

3737
/*
@@ -195,23 +195,22 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
195195
while ((de=ReadDir(dbspace_dir,dbspacedirname))!=NULL)
196196
{
197197
ForkNumberforkNum;
198-
intrelnumchars;
198+
unsignedsegno;
199199
unlogged_relation_entryent;
200200

201201
/* Skip anything that doesn't look like a relation data file. */
202-
if (!parse_filename_for_nontemp_relation(de->d_name,&relnumchars,
203-
&forkNum))
202+
if (!parse_filename_for_nontemp_relation(de->d_name,
203+
&ent.relnumber,
204+
&forkNum,&segno))
204205
continue;
205206

206207
/* Also skip it unless this is the init fork. */
207208
if (forkNum!=INIT_FORKNUM)
208209
continue;
209210

210211
/*
211-
* Put the OID portion of the name into the hash table, if it
212-
* isn't already.
212+
* Put the RelFileNumber into the hash table, if it isn't already.
213213
*/
214-
ent.reloid=atooid(de->d_name);
215214
(void)hash_search(hash,&ent,HASH_ENTER,NULL);
216215
}
217216

@@ -235,12 +234,13 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
235234
while ((de=ReadDir(dbspace_dir,dbspacedirname))!=NULL)
236235
{
237236
ForkNumberforkNum;
238-
intrelnumchars;
237+
unsignedsegno;
239238
unlogged_relation_entryent;
240239

241240
/* Skip anything that doesn't look like a relation data file. */
242-
if (!parse_filename_for_nontemp_relation(de->d_name,&relnumchars,
243-
&forkNum))
241+
if (!parse_filename_for_nontemp_relation(de->d_name,
242+
&ent.relnumber,
243+
&forkNum,&segno))
244244
continue;
245245

246246
/* We never remove the init fork. */
@@ -251,7 +251,6 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
251251
* See whether the OID portion of the name shows up in the hash
252252
* table. If so, nuke it!
253253
*/
254-
ent.reloid=atooid(de->d_name);
255254
if (hash_search(hash,&ent,HASH_FIND,NULL))
256255
{
257256
snprintf(rm_path,sizeof(rm_path),"%s/%s",
@@ -285,14 +284,14 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
285284
while ((de=ReadDir(dbspace_dir,dbspacedirname))!=NULL)
286285
{
287286
ForkNumberforkNum;
288-
intrelnumchars;
289-
charrelnumbuf[OIDCHARS+1];
287+
RelFileNumberrelNumber;
288+
unsignedsegno;
290289
charsrcpath[MAXPGPATH*2];
291290
chardstpath[MAXPGPATH];
292291

293292
/* Skip anything that doesn't look like a relation data file. */
294-
if (!parse_filename_for_nontemp_relation(de->d_name,&relnumchars,
295-
&forkNum))
293+
if (!parse_filename_for_nontemp_relation(de->d_name,&relNumber,
294+
&forkNum,&segno))
296295
continue;
297296

298297
/* Also skip it unless this is the init fork. */
@@ -304,11 +303,12 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
304303
dbspacedirname,de->d_name);
305304

306305
/* Construct destination pathname. */
307-
memcpy(relnumbuf,de->d_name,relnumchars);
308-
relnumbuf[relnumchars]='\0';
309-
snprintf(dstpath,sizeof(dstpath),"%s/%s%s",
310-
dbspacedirname,relnumbuf,de->d_name+relnumchars+1+
311-
strlen(forkNames[INIT_FORKNUM]));
306+
if (segno==0)
307+
snprintf(dstpath,sizeof(dstpath),"%s/%u",
308+
dbspacedirname,relNumber);
309+
else
310+
snprintf(dstpath,sizeof(dstpath),"%s/%u.%u",
311+
dbspacedirname,relNumber,segno);
312312

313313
/* OK, we're ready to perform the actual copy. */
314314
elog(DEBUG2,"copying %s to %s",srcpath,dstpath);
@@ -327,26 +327,27 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
327327
dbspace_dir=AllocateDir(dbspacedirname);
328328
while ((de=ReadDir(dbspace_dir,dbspacedirname))!=NULL)
329329
{
330+
RelFileNumberrelNumber;
330331
ForkNumberforkNum;
331-
intrelnumchars;
332-
charrelnumbuf[OIDCHARS+1];
332+
unsignedsegno;
333333
charmainpath[MAXPGPATH];
334334

335335
/* Skip anything that doesn't look like a relation data file. */
336-
if (!parse_filename_for_nontemp_relation(de->d_name,&relnumchars,
337-
&forkNum))
336+
if (!parse_filename_for_nontemp_relation(de->d_name,&relNumber,
337+
&forkNum,&segno))
338338
continue;
339339

340340
/* Also skip it unless this is the init fork. */
341341
if (forkNum!=INIT_FORKNUM)
342342
continue;
343343

344344
/* Construct main fork pathname. */
345-
memcpy(relnumbuf,de->d_name,relnumchars);
346-
relnumbuf[relnumchars]='\0';
347-
snprintf(mainpath,sizeof(mainpath),"%s/%s%s",
348-
dbspacedirname,relnumbuf,de->d_name+relnumchars+1+
349-
strlen(forkNames[INIT_FORKNUM]));
345+
if (segno==0)
346+
snprintf(mainpath,sizeof(mainpath),"%s/%u",
347+
dbspacedirname,relNumber);
348+
else
349+
snprintf(mainpath,sizeof(mainpath),"%s/%u.%u",
350+
dbspacedirname,relNumber,segno);
350351

351352
fsync_fname(mainpath, false);
352353
}
@@ -371,52 +372,82 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
371372
* This function returns true if the file appears to be in the correct format
372373
* for a non-temporary relation and false otherwise.
373374
*
374-
* NB: If this function returns true, the caller is entitled to assume that
375-
* *relnumchars has been set to a value no more than OIDCHARS, and thus
376-
* that a buffer of OIDCHARS+1 characters is sufficient to hold the
377-
* RelFileNumber portion of the filename. This is critical to protect against
378-
* a possible buffer overrun.
375+
* If it returns true, it sets *relnumber, *fork, and *segno to the values
376+
* extracted from the filename. If it returns false, these values are set to
377+
* InvalidRelFileNumber, InvalidForkNumber, and 0, respectively.
379378
*/
380379
bool
381-
parse_filename_for_nontemp_relation(constchar*name,int*relnumchars,
382-
ForkNumber*fork)
380+
parse_filename_for_nontemp_relation(constchar*name,RelFileNumber*relnumber,
381+
ForkNumber*fork,unsigned*segno)
383382
{
384-
intpos;
383+
unsigned longn,
384+
s;
385+
ForkNumberf;
386+
char*endp;
385387

386-
/* Look for a non-empty string of digits (that isn't too long). */
387-
for (pos=0;isdigit((unsignedchar)name[pos]);++pos)
388-
;
389-
if (pos==0||pos>OIDCHARS)
388+
*relnumber=InvalidRelFileNumber;
389+
*fork=InvalidForkNumber;
390+
*segno=0;
391+
392+
/*
393+
* Relation filenames should begin with a digit that is not a zero. By
394+
* rejecting cases involving leading zeroes, the caller can assume that
395+
* there's only one possible string of characters that could have produced
396+
* any given value for *relnumber.
397+
*
398+
* (To be clear, we don't expect files with names like 0017.3 to exist at
399+
* all -- but if 0017.3 does exist, it's a non-relation file, not part of
400+
* the main fork for relfilenode 17.)
401+
*/
402+
if (name[0]<'1'||name[0]>'9')
403+
return false;
404+
405+
/*
406+
* Parse the leading digit string. If the value is out of range, we
407+
* conclude that this isn't a relation file at all.
408+
*/
409+
errno=0;
410+
n=strtoul(name,&endp,10);
411+
if (errno||name==endp||n <=0||n>PG_UINT32_MAX)
390412
return false;
391-
*relnumchars=pos;
413+
name=endp;
392414

393415
/* Check for a fork name. */
394-
if (name[pos]!='_')
395-
*fork=MAIN_FORKNUM;
416+
if (*name!='_')
417+
f=MAIN_FORKNUM;
396418
else
397419
{
398420
intforkchar;
399421

400-
forkchar=forkname_chars(&name[pos+1],fork);
422+
forkchar=forkname_chars(name+1,&f);
401423
if (forkchar <=0)
402424
return false;
403-
pos+=forkchar+1;
425+
name+=forkchar+1;
404426
}
405427

406428
/* Check for a segment number. */
407-
if (name[pos]=='.')
429+
if (*name!='.')
430+
s=0;
431+
else
408432
{
409-
intsegchar;
433+
/* Reject leading zeroes, just like we do for RelFileNumber. */
434+
if (name[0]<'1'||name[0]>'9')
435+
return false;
410436

411-
for (segchar=1;isdigit((unsignedchar)name[pos+segchar]);++segchar)
412-
;
413-
if (segchar<=1)
437+
errno=0;
438+
s=strtoul(name+1,&endp,10);
439+
if (errno||name+1==endp||s<=0||s>PG_UINT32_MAX)
414440
return false;
415-
pos+=segchar;
441+
name=endp;
416442
}
417443

418444
/* Now we should be at the end. */
419-
if (name[pos]!='\0')
445+
if (*name!='\0')
420446
return false;
447+
448+
/* Set out parameters and return. */
449+
*relnumber= (RelFileNumber)n;
450+
*fork=f;
451+
*segno= (unsigned)s;
421452
return true;
422453
}

‎src/include/storage/reinit.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020

2121
externvoidResetUnloggedRelations(intop);
2222
externboolparse_filename_for_nontemp_relation(constchar*name,
23-
int*relnumchars,
24-
ForkNumber*fork);
23+
RelFileNumber*relnumber,
24+
ForkNumber*fork,
25+
unsigned*segno);
2526

2627
#defineUNLOGGED_RELATION_CLEANUP0x0001
2728
#defineUNLOGGED_RELATION_INIT0x0002

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp